Ethernet diagnosis help

The EtherTen combines an Uno-equivalent Arduino-compatible board and Wiznet-based Ethernet support, along with a microSD card slot and Power-over-Ethernet support. [Product page]
drewgarth
Posts: 14
Joined: Thu Apr 25, 2013 10:07 pm

Ethernet diagnosis help

Post by drewgarth » Thu Apr 25, 2013 10:34 pm

Hi guys, im looking for some ideas to help diagnose a problem i have with an etherten board.

Background
Im running a remote power supply monitoring system with an etherten. Basically measuring voltage, current, power etc and uploading to cosm. The location is on a bush block with a shed that I get to a few times a year.

I've been running the code on an arduino uno with an ethernet shield with out any issues. At easter i visited the site and swapped in an Etherten, that I had been testing a few code tweaks on in my home, where it had run for 10 days without any issues.

My code uses a watchdog timer set for 2s. This is used to allow the board to "reboot" once per day, to a) help avoid any problems with timers/memory rolling over after x days and
b), to hopefully create a more reliable platform in case of any trouble.

The etherten is powered by a dc-dc converter from the battery bank, set at 9.5v

I have a lan to lan VPN to the site between my home router and a router with a 3g connection on the site. This is working fine and my remote weather station continues to function so I know that internet is up and working and so to is my lan/vpn

Problem
After the etherten was running for 5 days when i was at the location last, i returned home and it ran for another 5 days. It then went "offline". This surprised me because i figured whatever cased the problem should disappear on the next days watchdog timeout. That didnt happen. The board is not uploading to cosm, but it's also NOT responding to ping.

Initially i assumed it must have been a hardware failure of either the board itself or something like the dc-dc power supply. However i noticed that the router still had it listed in it's arp cache, after I remotely rebooted the router. I cleared the arp cache. and after a few seconds the arp listing re-appeared. I manually deleted the arp listing using the router's SSH interface and again,a few seconds later the ARP listing re-appeared. Yet I still cant ping the etherten (either over the vpn, or through the router interface directly).

So it appears that the etherten ethernet interface appears to be "alive" at one level.

Given i only get to the site a few times a year, I would welcome any thoughts on what might be causing this. I can swap out the etherten for a replacement, but i dont want to do so only to have it fail again after another random time period.

I did notice the item on the etherten page titled "Ethernet Reset IC Delay"
It made me wonder whether on one of the watchdog resets it triggered this condition.
and since then triggers this condition each time?

Does my observation of responding to ARP, but not ping match the expected behaviour of the above?

Any thoughts, comments, suggestions would be appreciated.

cheers
Andrew

ngp99
Posts: 49
Joined: Sat Jul 14, 2012 1:53 am
Location: Dee Why NSW

Re: Ethernet diagnosis help

Post by ngp99 » Sun Apr 28, 2013 4:02 pm

Very interesting, but it sounds like the watchdog is more trouble than it's worth, and is due for retirement.

Why don't you use the code that worked before on the Uno? With additional backup to the SD card.

Sleurhutje
Posts: 28
Joined: Thu Mar 01, 2012 9:18 am

Re: Ethernet diagnosis help

Post by Sleurhutje » Mon Apr 29, 2013 12:29 pm

The watchdog reset does not reset the WizNet 5100 chip. Only a true hardware reset does. You need an external watchdog/reset circuit to reset both the ATmega and WizNet 5100.

See http://arduino.cc/forum/index.php?topic=58234.0

drewgarth
Posts: 14
Joined: Thu Apr 25, 2013 10:07 pm

Re: Ethernet diagnosis help

Post by drewgarth » Mon Apr 29, 2013 8:00 pm

Hi guys and thanks for the replies,
That does definitely give me a bit more to look at.

Its definitely proved to be quite a challenge to keep an arduino up and online over a period of many months when i cant just go and power cycle it. I will look into an external reset circuit.

cheers
Andrew

angusgr
Freetronics Staff
Freetronics Staff
Posts: 853
Joined: Tue Apr 09, 2013 11:19 pm
Location: Melbourne, Australia
Contact:

Re: Ethernet diagnosis help

Post by angusgr » Tue Apr 30, 2013 12:29 am

Hi Andrew,

What a frustrating problem.

As Sleurhutje points out, the watchdog timer won't assert the hardware RESET pin on the W5100 the same way a hard reset will.

However, at startup the Arduino Ethernet library does perform a software reset of the W5100 (which will happen on both WDT resets and hard resets.) To me the symptoms feel like a possible problem with software (either the software running on the Arduino or on the W5100), rather than the underlying ethernet hardware (which would seem to be working OK if you're seeing ARP responses.)

A couple more questions:

- Are you sure the watchdog timer is triggering every day with the new code you're running?

- What specifically did you tweak when you swapped from the Uno & Ethernet Shield to the EtherTen? Any chance of posting some code? Did you change Arduino IDE versions or anything else?

If you do get to physically see the EtherTen while it is malfunctioning, you may learn something by watching the Ethernet status LEDs next to the microSD card slot. For example you can see if the LNK LED is not solidly on (which would indicate a hardware or network problem.)

Cheers,

Angus

drewgarth
Posts: 14
Joined: Thu Apr 25, 2013 10:07 pm

Re: Ethernet diagnosis help

Post by drewgarth » Tue Apr 30, 2013 2:38 am

Hi Angus,
thanks for your response. I will attempt to answer and provide background on each.

Firstly, should also note that the since Sleurhutje's post i have also been able to find more details on the reset behaviour (soft vs electric reset) in an older post on this forum. For completeness the following is in interesting read viewtopic.php?t=24

In response to 1). Until the fault occured (and during my testing), I am 100% sure that the watchdog was triggering. I know that because i post back to Cosm the summed up amp hours of energy use/input. This grows and at 9am each day when the watchdog triggers it starts counting from zero again.

2) with respect to what i specifically tweaked was
a) to add software averaging to the voltage and current values. The combination of inverter noise, and PWM switching of the solar regulator were causing "noise".
b) I was also forced to use the linux version of the IDE when I was on-site as I only had my work laptop which is locked down, so i booted using a linux pendrive
c) I discovered that for some reason either the linux version of the IDE was somehow not allowing me to use an 8s watchdog timeout, so i was forced to change this to 2s

Though that said, when i returned to Melbourne i used the linux ide and same code on my testing Etherten and it ran fine...

I will only get to the site in June, and im looking forward to assessing the physical state!


Interestingly, since Sleurhutje's post I also found the following "hack" to do a self electrical reset. Im implemented this this morning on my test device and it reset OK this morning.
This should force a full electrical reset of both the Arduino and the W5100.
http://weblog.jos.ph/development/arduino-reset-hack/
Though anyone things this is a bad idea, let me know :) but it seems to be working.

The following code may assist (or be of interest to someone else) Though don't be too critical of my coding skills..im not a software developer by any stretch of the imagination ;)

cheers
Andrew

Code: Select all

/*
This program reads the analogue inputs and computes voltage and current from sensors.

On boot, it connects to the Net, reads the NTP time.
If unavailable it sets the time to be the reset time.

The system employs a watchdog reset system so that if a particular line item hangs it resets.

The watchdog is also used to reset the system once daily. At Reset time the system lets the watchdog expire.
This causes the system to reboot and zero's all variables.
Again if the time isnt available via NTP it sets it to be the reset time on the basis that will be close to when the watchdog forced the reset.
If the reset is triggered accidentally, then the "Reset-time" is as good as any other arbiarty time to bases further logic on 
*/



#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Time.h>
#include <avr/wdt.h> //Watchdog Timer Suitable for Uno only....2s max timer on Linux
#include <utility/w5100.h> // Allows tailoring of ethernet timeout. Important for watchdog
#include <Dns.h>


//Variables
int reset_hour=9;  //time used to reset Summed Amps
int day_reset=0; // Used to toggle whether or not the system has been through the reset loop.
int current_hour; // used to store the hour using the hour() function so logic is based on a variable rather than a function
float Vref=5.07; // reference voltage
float sty_h=.010; //V / amp   sensitivity of 200a sensor
float sty_l=.040; //V / amp   sensitivity of 50a sensor
unsigned long elapsed_time_start=0;
unsigned long last_interval_calculated;
float summed_amps;
float amp_hours;
unsigned long elapsed_time;
unsigned long loop_timer;
unsigned long loop_counter_day;
float voltage; // voltage of battery
float power;
float current_best; // current based on most useful sensor
float current_l; // calculated current from 50amp sensor
float current_h; // caluculated current from 200amp sensor

// Definition of variables for averaging
const int numReadings = 10; 

int readingsVolt[numReadings];
int readingsCurrent_l[numReadings];// the readings from the analog input
int readingsCurrent_h[numReadings];
int index = 0;                  // the index of the current reading
int totalVolt = 0;             // the running total
int totalCurrent_l=0;
int totalCurrent_h=0;
int averageVolt = 0;                // the average
int averageCurrent_l =0;
int averageCurrent_h =0;



#define APIKEY "cosm key here" // your cosm api key ** modified for online posting
#define FEEDID         cosm feed id   // your feed ID ** modified for online posting
#define USERAGENT      "Cosm Arduino Example (xxxx)" // user agent is the project name ** modified for online posting
static char dtostrfbuffer[15]; // used to convert float to string
byte mac[] = {xxx, xxx, xxx, xxxx, xx, xx}; //** modified for online posting
IPAddress ip(192,168,3,211);

//TIME Related SETUP Info
unsigned int localPort = 8888;      // local port to listen for UDP packets
//IPAddress timeServer(192, 43, 244, 18); // time.nist.gov NTP server
IPAddress timeServer;
const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 
time_t prevDisplay = 0; // when the digital clock was displayed
const  long timeZoneOffset = 36000L; // set this to the offset in seconds to your local time;
// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
// initialize the library instance:
EthernetClient client;


char server[] = "api.cosm.com";      // of using DNS instead
unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 15*1000; //delay between updates to Cosm.com



void setup() {
  // start serial port:
  Serial.begin(9600);
 
 //Initialise averaging array to 0 
   for (int thisReading = 0; thisReading < numReadings; thisReading++)
     {
    readingsVolt[thisReading] = 0;     
    readingsCurrent_l[thisReading] = 0; 
    readingsCurrent_h[thisReading] = 0; 
     }
  
  

 //Start Ethernet connection using Fixed IP
 Ethernet.begin(mac, ip);
  Udp.begin(localPort);
 
 // lookup time server ip
   DNSClient dns;
  dns.begin(Ethernet.dnsServerIP());
  
  if(dns.getHostByName("pool.ntp.org",timeServer)) {
    Serial.print(F("NTP server ip :"));
    Serial.println(timeServer);
  }
  else Serial.print(F("dns lookup failed"));
 
//time set to be the reset_time for example 9am on an arbitrary date
//this might help, if the system reboots using a watchdog at the reset time, then this 
//will ensure that an approximately useful time is provided in-case ntp fails.
setTime(reset_hour,0,0,11,11,1980);
digitalClockDisplay();
                    sendNTPpacket(timeServer); // send an NTP packet to a time server
                    // wait to see if a reply is available
                    delay(1000); 
                    if ( Udp.parsePacket() ) {  
                    // We've received a packet, read the data from it
                    Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer
                    //the timestamp starts at byte 40 of the received packet and is four bytes,
                    // or two words, long. First, esxtract the two words:
                    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
                    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
                    // combine the four bytes (two words) into a long integer
                    // this is NTP time (seconds since Jan 1 1900):
                    unsigned long secsSince1900 = highWord << 16 | lowWord;              
                    // now convert NTP time into everyday time:
                    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
                    const unsigned long seventyYears = 2208988800UL;     
                    // subtract seventy years:
                    unsigned long epoch = secsSince1900 - seventyYears + timeZoneOffset;  
                    time_t t = epoch;
                    setTime(t); 
                    Serial.println("ran through time loop");
                    }   
digitalClockDisplay();
current_hour=hour();
//these lines reduce the ethernet timeout from 30 seconds to about 3 seconds http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1287775341 
 //important for watchdog timer.
W5100.setRetransmissionTime(0x07D0); // Set the ethernet timeout
W5100.setRetransmissionCount(3);      //set the number of attempts
wdt_enable(WDTO_2S); // Enable watchdog timer Reset every 4 seconds
}






void loop() {
wdt_reset(); //Reset the watchdog timeout..
  float a2_l; // used in current caluclation low
float a3_h; // used in current calculation high
int SensorValue_l;
int SensorValue_h;
int sensorValue;

unsigned long av_reset;
float temp_value;

/* Calculations based on millis()...reset is based on time */

if(millis() > loop_timer){
     loop_timer=millis()+200; //1000 = 1 second...eg read once per second
//     sensorValue = analogRead(A0); //read voltage sensor
//     SensorValue_l=analogRead(A2); // 50a sensor +1 for zero offset
//     SensorValue_h=analogRead(A3); // 200a sensor +1 for zero offset

  // subtract the last reading:
  totalVolt = totalVolt - readingsVolt[index];   
  totalCurrent_l = totalCurrent_l - readingsCurrent_l[index]; 
  totalCurrent_h = totalCurrent_h - readingsCurrent_h[index]; 
  
  // read from the sensor:  
  readingsVolt[index] = analogRead(A0); 
  readingsCurrent_l[index] = analogRead(A2); //read 50a sensor
  readingsCurrent_h[index] = analogRead(A3); //read 200a sensor

  // add the reading to the total:
  totalVolt= totalVolt + readingsVolt[index];  
  totalCurrent_l= totalCurrent_l + readingsCurrent_l[index]; 
  totalCurrent_h= totalCurrent_h + readingsCurrent_h[index];   
  // advance to the next position in the array:  
  index = index + 1;       
  
    // if we're at the end of the array...
  if (index >= numReadings)              
    // ...wrap around to the beginning: 
    index = 0;  
    
  // calculate the average:
  averageVolt = totalVolt / numReadings;
  sensorValue = averageVolt;
 // Serial.println(averageVolt);
  averageCurrent_l = totalCurrent_l / numReadings;
  SensorValue_l=averageCurrent_l;
 // Serial.println(SensorValue_l);
  averageCurrent_h = totalCurrent_h / numReadings; 
  SensorValue_h=averageCurrent_h; 
 // Serial.println(SensorValue_h);
  
     
     
     a2_l=Vref/1023; // reference volts per count
     a3_h=a2_l; // reference volts per count
     voltage=a2_l; // reference volts per count

     a2_l=a2_l*SensorValue_l;
     a3_h=a3_h*SensorValue_h;
     current_l=Vref/2;
     current_h=current_l;
     current_l=a2_l-current_l;
     current_h=a3_h - current_h;
     current_l=current_l/sty_l; // current in amps
     current_h=current_h/sty_h; // current in amps

     voltage = voltage*sensorValue;
     voltage = voltage*  (19.93+2.98) / 2.98; // based on measured resistance of voltage divider


    //pick which sensor to use and base current_best on that
    //positive currents
      if(current_l > 40){
          current_best=current_h;
          }
          else{
            if(current_l >= 0)
            {
            current_best=current_l;
            }
          }
    //negative currents
      if(current_l < -40){
          current_best=current_h;
          }
          else{
            if(current_l < 0)
            {
            current_best=current_l;
            }
          }
     
     //Calculate the power based on the best current
     power = voltage * current_best;



    loop_counter_day = loop_counter_day +1;

    elapsed_time=millis()-elapsed_time_start;
    elapsed_time=elapsed_time/1000; //in seconds
    summed_amps=summed_amps+current_best;
    temp_value=summed_amps/loop_counter_day;
    amp_hours=temp_value*elapsed_time/3600;



/***********RESET**********
If the current hour is the reset_hour  then if the system timer has been running for more than two hours
then perform a reset. In that way if the system has just booted at the reset hour...the system timer will not have run long enough to allow a reboot.
Otherwise it would reboot continuously during the reset hour. The downside is that if it is booted just prior to the reset hour, it wont reset until the following day...big deal :)
*/
current_hour=hour();
Serial.println(current_hour);
Serial.println(millis());
//Serial.println("current");
//Serial.println(analogRead(A2));
//Serial.println(analogRead(A3));
// if(millis() > 60000)
//{    USE THIS ONE TO RESET EVERY 1 Minute for TESTING
//  delay(3000);
//}
        if(current_hour == reset_hour){ 
  
          if(millis() > 3600000){   // 3600000 1 hour hours in milliseconds
                Serial.println("in reset loop");
                delay(3000);
            }
         }
         
         

}   /////End IF for calculations

wdt_reset();
/////Now Create COSM String for upload


      dtostrf(voltage,4,2, dtostrfbuffer); //convert float to string
        String dataString="Voltage,";
      dataString +=  dtostrfbuffer;
//      dataString += "\nCurrentL,";
//     dtostrf(current_l,4,2, dtostrfbuffer);
//     dataString += dtostrfbuffer;
//     dataString += "\nCurrentH,";
//     dtostrf(current_h,4,2, dtostrfbuffer);
//      dataString += dtostrfbuffer;
     dataString += "\nCurrentBest,";
     dtostrf(current_best,4,2, dtostrfbuffer);
      dataString += dtostrfbuffer;
      dataString += "\nPower,";
   dtostrf(power,5,2, dtostrfbuffer);
      dataString += dtostrfbuffer;
        dataString += "\nAmpHours,";
     dtostrf(amp_hours,4,2, dtostrfbuffer);
      dataString += dtostrfbuffer;
       dataString += "\nHour,";
     dtostrf(current_hour,4,2, dtostrfbuffer);
      dataString += dtostrfbuffer;


  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
    wdt_reset();
  }
  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {
    
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    wdt_reset();
  }

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    wdt_reset();
    wdt_disable(); //disable watchdog to allow for DNS and network issues
    
    sendData(dataString);
    
    wdt_enable(WDTO_2S); //re-enable watchdog timer
    wdt_reset();

  }
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();


}

// this method makes a HTTP connection to the server:
void sendData(String thisData) {
  // if there's a successful connection:
 
  if (client.connect(server, 80)) {
    Serial.println("connecting...");
    // send the HTTP PUT request:
    client.print("PUT /v2/feeds/");
    client.print(FEEDID);
    client.println(".csv HTTP/1.1");
    client.println("Host: api.cosm.com");
    client.print("X-ApiKey: ");
    client.println(APIKEY);
    wdt_reset();
    client.print("User-Agent: ");
    client.println(USERAGENT);
    client.print("Content-Length: ");
    client.println(thisData.length());
    // last pieces of the HTTP PUT request:
    client.println("Content-Type: text/csv");
    client.println("Connection: close");
    client.println();

    // here's the actual content of the PUT request:
    
    client.println(thisData);

  }
  else {
    // if you couldn't make a connection:
    wdt_reset();
    Serial.println("connection failed");
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
   // note the time that the connection was made or attempted:
  lastConnectionTime = millis();
}

// This method calculates the number of digits in the
// sensor reading.  Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:

int getLength(int someValue) {
  // there's at least one byte:
  int digits = 1;
  // continually divide the value by ten,
  // adding one to the digit count for each
  // time you divide, until you're at 0:
  int dividend = someValue /10;
  while (dividend > 0) {
    dividend = dividend /10;
    digits++;
  }
  // return the number of digits:
  return digits;
}

// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(IPAddress& address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 		   
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket(); 
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

ngp99
Posts: 49
Joined: Sat Jul 14, 2012 1:53 am
Location: Dee Why NSW

Re: Ethernet diagnosis help

Post by ngp99 » Tue Apr 30, 2013 8:05 am

I'm struggling to see why you need a watchdog, but I had never heard of the term until a couple of days ago and it may not be a bad precaution. Now that the code is posted, I recognise the goal but I don't understand the method, i.e. the code for transmission to cosm.

Cosm underwent something of a palace revolution a few months ago and new libraries were published. It seems that any problems with cosm being flakey since then are fixed by using those libraries, but you aren't.

Maybe that is where the real problem lies. The watchdog is innocent, but cosm moved the goalposts when you weren't looking.

drewgarth
Posts: 14
Joined: Thu Apr 25, 2013 10:07 pm

Re: Ethernet diagnosis help

Post by drewgarth » Tue Apr 30, 2013 11:35 am

Hi ngp99,
thanks for the feedback. Yeah, i have to admit i had missed the changes in the cosm example code and i picked up on that the other day.

Having said that, in this case i don't think that it's related to a cosm issue, because the etherten is locking up to the point where it wont even respond to ping. (Btw, just to be clear i dont necessarily believe that what i am seeing is an etherten specific issue, as i use plenty of them for other automation applications around my place in Melbourne without issue :)

This issue seems to be at a lower level, though i am happy to learn if I have missed where it could be in the cosm code.....

It's definitely worth reading further into Watchdog's its a really useful feature. Especially when you need to leave a bit of hardware running and your not quite sure what might cause it to "lockup" In this case i started using a watchdog, actually hoping to avoid exactly this scenario where some sort of IP issues caused the system to become non responsive...the theory being that it might persist for a day, but then reset itself.

The other advantage of the watchdog in this case was me being lazy. When summing numbers they will eventually exceed the limit of the variable....and when millis() roles over and re-zeros I didnt want to find out the hard way 40 days in that my logic was flawed in dealing with the rollover....Hence resetting once a day means that any logic errors will be revealed in a day. If it works for 24 hours and resets, it should work indefinitely.....obviously unless some other problem gets in the way! :)

drewgarth
Posts: 14
Joined: Thu Apr 25, 2013 10:07 pm

Re: Ethernet diagnosis help

Post by drewgarth » Tue Apr 30, 2013 8:02 pm

Ive posted a seperate reply to ngp99 thats waiting for moderation (What triggers the need for moderation?).

In some other reading i've realised I could have also implemented a watchdog timer reset in a much more simple way, (specifically for resetting) by creating a reset function that enables the watchdog and then triggers it, This is only done when the reset is called.
In my example code, I have to keep "patting the dog" to prevent the reset when it isnt wanted. http://arduino.cc/forum/index.php/topic,12874.0.html
Though implementing the watchdog in this way doesn't help prevent against other code or processes that may inadvertently hang.....

Also, as covered early in this thread, it also doesn't reset the Ethernet,

angusgr
Freetronics Staff
Freetronics Staff
Posts: 853
Joined: Tue Apr 09, 2013 11:19 pm
Location: Melbourne, Australia
Contact:

Re: Ethernet diagnosis help

Post by angusgr » Tue Apr 30, 2013 11:25 pm

drewgarth wrote: Firstly, should also note that the since Sleurhutje's post i have also been able to find more details on the reset behaviour (soft vs electric reset) in an older post on this forum. For completeness the following is in interesting read viewtopic.php?t=24http://forum.freetron ... c.php?t=24
Yes, it is an interesting read. Jon did a good job of explaining the reset controller (MPU Supervisor) chip.

Just to be pedantic, all the resetting of the W5100 discussed in that thread is hardware resetting - it's just that in some circumstances the hardware reset pulse may not be long enough to cleanly reset the W5100, hence the MPU Supervisor chip that stretches that pulse out.

On the other hand, a software reset is the microcontroller explicitly sending a software reset command to the W5100 (over the SPI bus.)
drewgarth wrote:In response to 1). Until the fault occured (and during my testing), I am 100% sure that the watchdog was triggering. I know that because i post back to Cosm the summed up amp hours of energy use/input. This grows and at 9am each day when the watchdog triggers it starts counting from zero again.
Excellent!

drewgarth wrote: 2) with respect to what i specifically tweaked was
a) to add software averaging to the voltage and current values. The combination of inverter noise, and PWM switching of the solar regulator were causing "noise".
b) I was also forced to use the linux version of the IDE when I was on-site as I only had my work laptop which is locked down, so i booted using a linux pendrive
Does this mean you changed Arduino IDE versions (which would mean different Arduino Ethernet library versions), as well? Do you know what the two versions were?
drewgarth wrote: Interestingly, since Sleurhutje's post I also found the following "hack" to do a self electrical reset. Im implemented this this morning on my test device and it reset OK this morning.
This should force a full electrical reset of both the Arduino and the W5100.
http://weblog.jos.ph/development/arduino-reset-hack/
Though anyone things this is a bad idea, let me know :) but it seems to be working.
There are a few posts on the internet recommending this solution, and a few more posts exclaiming "Atmel says don't do this!".

The "don't do this" reason is that it's out of spec for the AVR chip on the Arduino. If you look at page 48 of the ATmega328p Complete datasheet, you'll see that there's a minimum reset pulse width of 2.5us. "Shorter periods may not generate a reset."

The catch is that resetting doesn't quite happen all at once, and one of the first things may be the output pins (including the pin you're using to assert reset) will go back into their default high impedance (INPUT) state and de-asserting RESET.

I just wired this up on my EtherTen and looked at the reset pulse on my oscilloscope. It's only held low for about 400ns (0.4us, ie 1/6th of the minimum reset pulse.)

So as a result you might get an incomplete reset or some other weird partial state. I haven't been able to find the document (referred to by various internet posts) where Atmel explicitly say "don't do that", but from reading the datasheet you're at least in a bit of a grey area. It might work perfectly every time for years, or it might not...

This is actually the same problem Jon talks about in the other thread. If you want to ensure the reset pulse is always long enough, you could use a reset controller (MPU Supervisor) like the APX811, or you could wire something up using a 555 one-shot timer or similar.

You could even program the ATmegaU2 on the EtherTen to act like an external Watchdog for the main ATmega328p, using one of the digital pins on its programming header to wire back to Reset. But that might be unnecessarily complex. :)
drewgarth wrote:The following code may assist (or be of interest to someone else) Though don't be too critical of my coding skills..im not a software developer by any stretch of the imagination ;)
Code looks nice and straightforward to me. I can't see anything immediately that made me think "mmm maybe this will lock up the W5100", unfortunately.

I'll be very interested to hear how you end up progressing.

Post Reply