Issues with ethershield

I'm running into some issues with the ethershield. I've got the program listed below as well as the circuit running. The included image is a seperate shield so imagine that in the stack of shields. This was fairly stable in my test environment running via USB. I've since moved it into a kegerator and it's running on a 7v switching wall-wort. It's incredibly unstable and usually locks up and can't be seen on the network. I've also noted that the board is quite warm while running off the 7v wall wort. Is this normal and do you have any ideas?

Thanks in advance!

/// This is a collection of code snippits found  ///
/// from around the web as well as code written  ///
/// by yours truly. This is a very rough         ///
/// version 0.1                                  /// 
///                                              ///
/// Last compiled on Arduino version 17          ///
///                                              ///
/// 
///
///


///  FLOW METER STUFF HERE
volatile int state = LOW;
float keg1_liter_count = 8; // This is used for counting liters drank, drunk, sipped, nursed, etc!
float keg2_liter_count = 0; // This is used for counting liters drank, drunk, sipped, nursed, etc!
int flow[] = {0, 0}; // This var is attached to the interupt and gets incremented on each flow count used for both kegs
float keg1_liters_full = 29; // this value will store the number of liters of a full keg (default as pony keg)
float keg2_liters_full = 29; // this value will store the number of liters of a full keg (default as pony keg)
///  END FLOW METER STUFF


#include <EEPROM.h>


///  TEMPERATURE CONFIG STUFF HERE
#include <OneWire.h>
OneWire therm1(8); // initiate OneWire on pin 8 (Thermometer 1)
OneWire therm2(9); // initiate OneWire on pin 9 (Thermometer 2)
byte present = 0, data[12], therm1_addr[8], therm2_addr[8];
int intPostDecimal, boolSign, intHexTempReading, intTempReadingBeforeSplit, preDecimal, i;
float fltPostDecimal, intHexTempReadingerature;
char sign[2] = "-"; // in the rare event we're dealing with negative numbers...if we are...OH NOES
float temp1 = 111.11; // this is the DSB18S20 attached to digital pin 8
float temp2 = 222.22; // this is the DSB18S20 attached to digital pin 9
//int insigtemp; // pretty sure this isn't used
int count; // This is used to determine which thermometer we're working on 
/// END TEMPERATURE STUFF

///  ETHERSHIELD STUFF HERE
#include <Ethernet.h>
#include <String.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Set the MAC address...more than 1 kegbot requires this to be diff on each
byte ip[] = { 192, 168, 1, 36 }; // IP address for the ethernet shield

Server server(80); // This is the port that we're serving up the webpages on
/// END EITHERSHIELD STUFF

void setup() {
  //  Flow Meter stuff
    pinMode(5, OUTPUT); // no fucking clue what I was doing here
    attachInterrupt(0, count_beer1, RISING); // setup the interrupt for keg1 digital pin 2
    attachInterrupt(1, count_beer2, RISING); // setup the interrupt for keg2 digital pin 3
  //  END FLOW METER STUFF  //
  
  Ethernet.begin(mac, ip);
  server.begin();
  /// END EITHERSHIELD STUFF
}

void loop() {

  if (flow[0] > 2200) { // This is used for counting liters instead of pulses on keg1
      keg1_liter_count += 1; // increment the liter count
      flow[0] = flow[0] - 2200;
      //EEPROM.write(10, keg1_liter_count);  // Write it to eeprom in case we lose power
  }
  if (flow[1] > 2200) { // This is used for counting liters instead of pulses on keg2
      keg2_liter_count += 1; // increment the liter count
      flow[1] = flow[1] - 2200;
     // EEPROM.write(20, keg2_liter_count);  // Write it to eeprom in case we lose power
  }
      printTemperature();
//  delay(5000);
Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if we've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so we can send a reply
        if (c == '\n' && current_line_is_blank) {

          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          break;
        }
        if (c == '\n') {
          // we're starting a new line
          current_line_is_blank = true;
        } else if (c != '\r') {
          // we've gotten a character on the current line
          current_line_is_blank = false;
        }
      }
    }
        if(boolSign) {
          client.print(sign); // god I hope we never need this
        }
        client.print(temp1); // print value of temp sensor 1 (digitl pin 8)
        client.print(","); // comma seperate the values for prettyness (think explode in php)
 
        if(boolSign) {
          client.print(sign); // god I hope we never need this
        }
        client.print(temp2); // print value of temp sensor 2 (digitl pin 9)
        // DONE PRINTING TEMPS  ///
        client.print(","); // comma seperate the values for prettyness (think explode in php)

        client.print(((keg1_liters_full - keg1_liter_count) / keg1_liters_full) * 100); // Print percent left in Keg 1
        client.print(","); // comma seperate the values for prettyness (think explode in php)
        //client.println("Ounces left in Keg #2 -- ");
        client.println(((keg2_liters_full - keg2_liter_count) / keg2_liters_full) * 100); // Print percent left in Keg 1
        
    // give the web browser time to receive the data
    delay(1);
    count = 0;
    client.stop();
  }  
}



///  Flow Meter Intterrupt stuff  ///

void count_beer1() {
  flow[0] += 1;
}

void count_beer2() {
  flow[1] += 1;
}


///////////////////////////////////////
///   BEGIN TEMPERATURE FUNCTIONS   ///
///////////////////////////////////////
int getTemperature(int low_Byte, int high_Byte) {
  intHexTempReading = (high_Byte << 8) + low_Byte;
  boolSign = intHexTempReading & 0x8000;
  if(boolSign) {
    intHexTempReading = (intHexTempReading ^ 0xffff) + 1;
  }
  intTempReadingBeforeSplit = 6.25 * intHexTempReading; // multiply by (100 * precision) = (100 * 0.0625) = 6.25 = 12-bit precision
  preDecimal = intTempReadingBeforeSplit / 100;
  intPostDecimal = intTempReadingBeforeSplit % 100;
  fltPostDecimal = intPostDecimal;
  if(intPostDecimal<10) {
    intHexTempReadingerature = preDecimal+(fltPostDecimal/1000);
  }
  else {
    intHexTempReadingerature = preDecimal+(fltPostDecimal/100);
  }

  if(boolSign) {
    //Serial.print(sign);
  }
  //Serial.println(convert_c_to_f(intHexTempReadingerature));
  if(count == 1) {
    temp1 = convert_c_to_f(intHexTempReadingerature);
    //Serial.println(temp1);
  }
  else if(count == 2) {
    temp2 = convert_c_to_f(intHexTempReadingerature);
    //Serial.println(temp2);
  }
  else {
      //Serial.println("no data to print");
  }

  return 0;
}

float convert_c_to_f(int celsius) {
  return((celsius*1.8)+32); // (Celsius * 9/5) + 32 = Fahrenheit
}

int printTemperature(void) {  
  if(!therm1.search(therm1_addr)) { // No more addresses
    therm1.reset_search();
  }
  
  if(!therm2.search(therm2_addr)) { // No more addresses
    therm2.reset_search();
  }
  
  if(OneWire::crc8(therm1_addr,7)!=therm1_addr[7]) { // Checksum invalid
    //Serial.println("Thermometer #1 CRC checksum invalid");
  }
  
  if(OneWire::crc8(therm2_addr,7)!=therm2_addr[7]) { // Checksum invalid
    //Serial.println("Thermometer #2 CRC checksum invalid");
  }
  
  therm1.reset();
  therm1.select(therm1_addr);
  therm1.write(0x44, 1); // start conversation w/ parasite power
  delay(1000);
  
  therm2.reset();
  therm2.select(therm2_addr);
  therm2.write(0x44, 1); // start conversation w/ parasite power
  delay(1000);
  
  present = therm1.reset();
  therm1.select(therm1_addr);
  therm1.write(0xBE); // read scratchpad  
  for(i=0;i<9;i++) { // need 9 bytes
    data[i] = therm1.read();
  }
  
  //Serial.print("Thermometer #1: ");
  count = 1;
  getTemperature(data[0], data[1]);
//  temp1 = getTemperature(data[0], data[1]);
  
  present = therm2.reset();
  therm2.select(therm2_addr);
  therm2.write(0xBE); // read scratchpad
  for(i=0;i<9;i++) { // need 9 bytes
    data[i] = therm2.read();
  }
  
  //Serial.print("Thermometer #2: ");
  count = 2;
  getTemperature(data[0], data[1]);
  count = 0;
//  temp2 = getTemperature(data[0], data[1]);
  return 0;
}

//////////////////////////////////////
///  END OF TEMPERATURE FUNCTIONS  ///
//////////////////////////////////////

... it's running on a 7v switching wall-wort

Where do you connect the 7 Volts?
I only see 5 Volts power on you circuit diagramm.

I've also noted that the board is quite warm while running off the 7v

I would check the 5 volt signal on your board. If you have 7 volts on the 5 volt power that could be the reason why your board is quite warm.

the 7v is coming in from the power jack on the arduino board. So I think it should be OK from reading this... http://arduino.cc/en/Main/ArduinoBoardDuemilanove

I'll check the 5v though..

It's incredibly unstable and usually locks up and can't be seen on the network.

How do you know it's locked up? Maybe it's just pinin' for the fjords :slight_smile:

When you say "unstable", it implies that the system works part of the time. Does it actually run for a while, and then stop? Or does it not run at all sometimes?

Several people (including me) have had problems with the Wiznet module not resetting reliably. It looks like it may depend on the timing of the system reset pulse. I followed the suggestion I found on another forum thread, and moved the Ethernet shield reset to a digital I/O pin. Then I added a little code to do the reset "manually":

      pinMode(WIZNET_RESET_PIN, OUTPUT);
      digitalWrite(WIZNET_RESET_PIN, HIGH);
      delay(50);
      digitalWrite(WIZNET_RESET_PIN, LOW);
      delay(50);
      digitalWrite(WIZNET_RESET_PIN, HIGH);
      delay(100);

      Ethernet.begin(mac, my_ip, gateway);

The size of the delay() times is probably overkill, but I haven't felt the need to do the experimenting required to find out the minimums required: a couple hundred extra mS at startup is no big deal when the system is supposed to run for months at a time.

Ran

I just did some more testing and I think my issue is power supply related.

Ethernet is my only way to test this as I've disabled all serial out.

with a 7v wall wort plugged into the barrel jack I the ethernet is flaky. Usually means it works for awhile then quits

with a usb adapter made for an iphone the ethernet doesn't work at all

with usb plugged into a computer it works beautifully. (unless you make a lot of requests very fast which seems to crash it)

So I guess my next tests are to build a super stable 5v power supply or try and find a way to get the 7v in from the barrel connector to not suck....

any ideas on the new found info?

Unless you have a low-dropout regulator, 7V sucks by definition: normal manufacturing tolerances on power supplies mean that you could be getting dropouts.

Rather than trying for a super-stable 5V supply, I'd be looking for a "so-so-or-better" one that's 8V or so.

Ran

I think you're right on the reset pin. I was having issues getting the program running again and I hit the reset button on the ethershield. This gets ethernet up and running again and all is good. So I think there is something going on during a fresh boot up when the power is applied sometimes I'll see if it stays up and running now that it's going. Thanks for all the input. I'll let you know hoe it goes.

16 hours and still running strong...

It dies between 20 and 28 hours. There's got to be a bug in there somewhere I'm not seeing.

Did you solve the bug allready?

There is at least one (small) bug I see in your code:

In the main loop you reset the flow counters, but there is a chance that there is an interrupt during execution of this line.

(A) flow[0] = flow[0] - 2200;

in pseudo assembly this will be executed something like:

LDA flow[0]        load register with value of flow[0]
SUB 2200           subtract 2200
STA flow[0]        store the result back in flow[0]

In the interrupt you state:

flow[0] += 1;

This interrupt code can occur at any place during the execution of line (A) so at any place in the pseudo assembly code. Suppose it happens after the LDA and before the STA then you would miss an interrupt.

This is a concurrency problem. the solution is to adjust flow[0] within the IRQ so it is done as one atomic (but slightly longer) action.

However it can't cause the sudden dead after 20-28 hours afaik.

Thanks for the reply, that is a great point. I did a major complete re-design of the code and am about to begin testing it. I ended up reconfiguring the arduino to run as a webclient. It is constantly posting it's 4 variables to a web server and the web server is doing all of the back end processing. We'll see how it goes...