w5500 freezes arduino mega

Hello,

I'm building a weather station with Mega 2560 R3 as my first arduino project. I'm using a W5500 network module. Everything works perfectly with days without problems without ethernet. Even sending data to Wunderground works but ... Mega always freezes while sending sample # 56, every time. I tried changing the delay between sending, nothing changes. I tried not using DHCP and setting ip address in router to avoid end of lease time ... nothing change.

I'm using IDE 1.6.9 (1.6.10 does not work with my RTC library) and the Wiznet library 1.5 which was copied over the Arduino Ethernet library. Sketch occupies 12 % program space and 20 % memory space. It should not be a problem. I also ensured power supply voltage was ok.

As my sketch is close to 900 lines, as it perfectly works if I comment the main loop line calling the function sending data, I will only include the lines related to ethernet, it should be easier this way.

Define part, etc ...

#include <SPI.h>                // Ethernet module communication
#include <Ethernet.h>          // wiznet library
EthernetClient client; 
byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };     // Enter a MAC address for your controller 
IPAddress SERVER = { 38,102,137,157 };                  // numeric IP for "weatherstation.wunderground.com"  
//char SERVER [] = "weatherstation.wunderground.com" ;  // name address for uploading data 
char ID [] =         "IQUBECVI10"  ;                    // wunderground id
char PASSWORD [] =   "XXXXX"    ;                    // wunderground password
char WEBPAGE []  =   "GET /weatherstation/updateweatherstation.php?" ;
int wundgCycles ;   // delay before sending Wunderground data
unsigned int Sample = 0;           // Data sent sample number
#define IDLE_TIMEOUT_MS  5000      // Amount of time to wait (in milliseconds) with no data

Setup, initEther(), wundgSendData()

Mega freezes at that line : if (!client.connect(SERVER, 80))

// --- setup ---- 
  initEther() ;                      //  initialize W5500   

// ----- initEther function ----

void initEther()
 {
  if (Ethernet.begin(mac) == 0) 
    { Serial.println(F("Failed to configure Ethernet using DHCP"));
      lcd.print(F("Ethernet failed"));  
      delay(10000);  // this will trigger the watchdog timer
    } 
  delay(1000) ; 
  Serial.print(F("Connected - IP address is : "));  // print your local IP address:
  lcd.setCursor(0,0);
  Serial.print(Ethernet.localIP()) ;
  lcd.print(F("Ethernet OK"));
  Serial.println();
 }

// ------ wundgSendData function ------

 void sendWundgData(void)
{ Serial.println(F("in SendWundgData()"));
  Sample ++;    // to check # sent  
  float windSpdMph = (windSpdKmH_avg2m* kmhToMph) ; 
  float windGustMph = (windGustKmh_10m * kmhToMph) ; 
  float tempF = ((outTempC*1.8)+32);
  float dewF =  ((dewptC*1.8)+32);
  float pressIn = (pressSea*0.0295299830714) ;
  float rainIn = (dailyRainmm * mmToInch);
  float rainLastHrin = (rainLastHrmm * mmToInch);
  long start = millis() ;                               //  to monitor time delay to send data
  Serial.println(F("before if connect ")); 

  if (!client.connect(SERVER, 80))    //  mega freezes here 

     {Serial.println(F("Connection failed"));
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(F("Connection failed"));
      delay(2000); 
      initEther() ;   
     }
  else  
     {
      Serial.println(F("connected "));
      Serial.print(F("Sample # "));     
      Serial.println(Sample);      
      client.print(WEBPAGE);      
      client.print(F("ID="));
      client.print(ID);      
      client.print(F("&PASSWORD="));
      client.print(PASSWORD); 
      client.print(F("&dateutc=now"));          
      client.print(F("&windspeedmph=")); 
      client.print(windSpdMph,2);
      Serial.print(F("&windspeedmph = "));       
      Serial.println(windSpdMph,2);       
      if (windGust)
         { client.print(F("&windgustmph="));
           client.print(windGustMph,2);
         }        
      client.print(F("&dailyrainin="));
      client.print(rainIn,3) ;
      client.print(F("&rainin="));
      client.print(rainLastHrin,3) ;  
      client.print(F("&tempf="));
      client.print(tempF,2);      
      client.print(F("&baromin="));   
      client.print(pressIn,2);    
      client.print(F("&dewptf="));
      client.print(dewF);   
      client.print(F("&humidity="));
      client.print(humidity,1);            
      client.print(F("&action=updateraw"));
      client.println();
      Serial.println(F("&action=updateraw"));                     
      digitalWrite(LED, LOW);
      Serial.print (F("duree envoi : ")); 
      Serial.println(millis()- start ); 
     } 

 Serial.println(F("-------------"));  
 Serial.println(F("Server Responce!"));
 unsigned long lastRead = millis();
 while (client.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) 
    {
     while (client.available()) 
        {
         char c = client.read();
         Serial.print(c);
         lastRead = millis();
        }
    }
 Serial.println(F("---------------------------"));   
 client.stop();

 secondRTC = second(RTC.get() ) ;  // To restart complete cycle next second
}

Main Loop code. The only part for Ethernet is the call to wundgSendData(). No problem at all if commented.

void loop()
{  
 secondRTC = second(RTC.get()) ;
 minuteRTC = minute(RTC.get()) ;  
 dayRTC = day(RTC.get()) ;  
 if (secondRTC != lastSecondRTC)      // to start retreiving data each new second
    { // digitalWrite(LED,HIGH);      // internal LED on when cycle begins 
     if (lcdView> 2)                  // executes view0() or view1() or view2()
         lcdView = 0;       
     if (lcdView == 0)
         view0(); 
     if (lcdView == 1)
         view1();  
     if (lcdView == 2)
         view2();            
     lastSecondRTC = secondRTC;        // to start loop each new second  
     if (lastDayRTC != dayRTC )        // reset/change daily values
        { resetMaxMin() ;              // min & max temp
          lastDayRTC = dayRTC ; }                  
     if(secondRTC == 0)
        { if(++min10Count > 9) min10Count = 0;   // increment min10Count 
          rainHour[minuteRTC] = 0;               // Zero out this minute's rainfall amount
          windGustMax_10m[min10Count] = 0;       // Zero out this minute's gust 
          windLullMin_10m[min10Count] = 99 ; }   // Zero out this minute's lull                                         
     rainProcess();                 // Calculates rain data
     tempProcess();                 // Calculates temp and Humidity data 
     pressureProcess();             // Calculates atmospheric pressure data
     if(secondRTC == 59 )  
       {pOld[minuteRTC] = pressSea;}  
     windSpeedProcess();                              // Calculates wind speed data 
     if(windSpeed > windGustToday)                    // Check to see if this is a gust for the day
       {windGustToday = windSpeed;}                           
     if(windSpeed > windGustMax_10m[min10Count])      // Check to see if this is a gust for the minute
       {windGustMax_10m[min10Count] = windSpeed;}
     if(windSpeed < windLullMin_10m[min10Count])      // Check to see if this is a lull for the minute
       {windLullMin_10m[min10Count] = windSpeed;}
     windSpdAvg[sec120Count] = (int)windSpeed;
     if(++sec120Count > 119)                     // increment sec120Count to store wind speed every second for 120 seconds   
       { sec120Count = 0; 
       }
     wundgCycles ++ ;   
     if(wundgCycles >59) 
       {Serial.println("Avant sendWundgData()");
        sendWundgData();         // upload data to wunderground 
        wundgCycles = 0 ;   
       }
      tempFeelProcess();             // Calculates Windchill or Humidex         
      buttonProcess();               // Process button actions          
      // serialPrintWeather();       // optional to serial monitor all readings every second   
      // digitalWrite(LED,LOW);      // internal led OFF after 1 cylce calc is done       
      wdt_reset();                   // reset watchdog
    }      
  delay(5);    // delay to wait for second to change in RTC  
}              // end of main loop

Thanks in advance, I'm quite sure it's a stupid logic error as I'm not an expert with network and even Arduino ..

J Guy

Maybe you are running out of SRAM? I wouldn't think so with a Mega, but I can't see your whole sketch.

Do you have a SD card in the shield's slot?

How do you have it wired to the Mega?

I can't test it because I don't have the LCD library, but here is the SRAM check function.

int freeRam() {
  extern int __heap_start,*__brkval;
  int v;
  return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval);  
}

// then call it like this
Serial.print(F("SRAM = "));
Serial.println(freeRam());

Thank Tim,

I was just checking the memory. I check it just here :
Serial.print(F("FREE RAM = ")) ;
Serial.println(freeRam());
if (!client.connect(SERVER, 80))

It's 6326 at the beginning and 6326 at the end. So, no memory leak.

It's wired with jumper. I didn't suspect any problem on this side as it works for 55 times ... and ALWAYS 55 times. A bad connection problem would not create such a regular failure. Unless one wire is really broken. I will change the jumpers just to see.

It really looks as a software problem with !client.connect(SERVER,80) : it's not time dependant as I changed sending delay from 2 minutes to 30 seconds and it still blocks at 56th trial.

I also set the router to dedicate the 168.192.2.121 to the ethernet mac module to ensure it was not a end of lease for the IP address ... I also removed the if to test : nothing changed.

So problem is really with client.connect(). As it looks not related to a timeout, could there be something else asking for reset somewhere ? Could it be a library problem ???

J Guy

I'm not where I can check your code, bit I would check to insure you are not overflowing an array.

Thanks Tim,

I did another trial in commenting 6 lines of data sent to Wunderground. Nothing changes, so it's neither related to volume of data sent over internet.

I will look at arrays but my knowledge is very limited. Your offer is more than welcomed !

J Guy

I may have found something. Ethernet fails connecting after a while: client.connect() problem [imported] · Issue #15 · arduino-libraries/Ethernet · GitHub

client.connect does not work properly when frequently opening a Ethernet connection (Once a minute). After a while, Wiznet is no longer able to open connection. That's exactly my problem ! That could also explain why so many people complain that they cannot upload data to Wunderground without regularly freezing.

Go at the bottom of the page where it's said problem is back with W5500. Another work around was found. I replaced my client.close with the work around but doesn't compile. I will try to find where is the ctime it may be somewhere in the library.

Tim : do not lose you time looking at arrays in my sketch, this problem is too similar. Solution is probably there.

Thanks in advance J Guy

BTW : is there another library I could use for the W5500 ?

I don't think that is it. I have opened a connection every 30 seconds for a couple weeks straight without a fail. I'm using a w5100 tho. I use this library. I think it is the one you are using.

Have you checked the socket status during your tests? Here is what I use. Mine shows 4 sockets, yours should show 8. If you do not have a socket with the status of 0x0, any connection attempt will fail. Call this function after each connection.

#include <utility/w5100.h>

byte socketStat[MAX_SOCK_NUM];

void ShowSockStatus()
{
  for (int i = 0; i < MAX_SOCK_NUM; i++) {
    Serial.print(F("Socket#"));
    Serial.print(i);
    uint8_t s = W5100.readSnSR(i);
    socketStat[i] = s;
    Serial.print(F(":0x"));
    Serial.print(s,16);
    Serial.print(F(" "));
    Serial.print(W5100.readSnPORT(i));
    Serial.print(F(" D:"));
    uint8_t dip[4];
    W5100.readSnDIPR(i, dip);
    for (int j=0; j<4; j++) {
      Serial.print(dip[j],10);
      if (j<3) Serial.print(".");
    }
    Serial.print(F("("));
    Serial.print(W5100.readSnDPORT(i));
    Serial.println(F(")"));
  }
}

Status list:
0x0 = available.
0x14 = socket waiting for a connection
0x17 = socket connected to a client or server.
0x1C = open socket waiting for close
0x22 = UDP

Tim,

I wanted to be sure not missing anything, so I call the function before client.connect and after client.close.

This way, I understand I should have 8 times 0x0 and that's what I got but you may be interested in something else.

Here's the status before first connection : Socket#0:0x0 68 D:255.255.255.255(67)
after first connection : Socket#0:0x0 1025 D:38.102.137.157(80)
after second connection : Socket#0:0x0 1026 D:38.102.137.157(80)

last time it worked :

Socket#0:0x0 1079 D:38.102.137.157(80)
Socket#1:0x0 0 D:0.0.0.0(0)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)
Socket#4:0x0 0 D:0.0.0.0(0)
Socket#5:0x0 0 D:0.0.0.0(0)
Socket#6:0x0 0 D:0.0.0.0(0)
Socket#7:0x0 0 D:0.0.0.0(0)

I see that the number right after 0x0 (SnPort if I'm correct) grows by one after each connection. It's easy to ask if there is a maximum value to that number ? What does it represent ?

Thanks again J Guy

That looks ok. That is the source port (client port). It will roll over at some point. I've never checked to see when it does it. It appears to be in the Wiznet firmware.

So you get "before if connect" but never get the "connection failed" or "connected" message on the serial monitor?

When it connects, I get the "connected" but when it freezes, it doesn't go after the line " if (!client.connect(SERVER, 80). Problem is really there as I never get "connection failed". I did a serial print before and after that line just to validate that problem was there.

For your information, I also posted in the Wiznet forum but no answer. I imagine they are in vacation as the website is even down right now.

Thank you so much for the support !

J Guy

Have you tried a simplified version of your sketch? Just the ethernet client part?

I would guess that something is corrupting the ethernet section of your sketch. Just a guess. My only suggestion is break your code into sections and reassemble it, testing thoroughly as you add each section.

edit: Are you calling Ethernet.maintain() anywhere in your loop to renew your network settings?

Congratulations for you 10 000 posts ! With your post's quality, you're a great value to the Arduino world !

Maintain() is not in my sketch. I discover it while looking at library code and I think I checked it with no success and removed it. I tested so many things that I'm not sure. I will do it first.

For a simplest sketch, I developed the ethernet part that way : started from scratch with static values for temp, humidity, etc ... but, when it was working, after 5-10 sending, I integrated it in the main sketch. I will test ethernet code only for a longer time, just sending static data.

These are excellent ideas !

Thanks J Guy

This previous post was removed as my Wunderground password was not deleted in the attachement.

For the SRAM, this would mean that it's "eaten" by the ethernet module sending data because, with everything in the sketch, there's no problem when I don't send data to Wunderground (I just comment the main loop SendWungData(). This way, it works days without any problem. I will search to see if there's a way to validate SRAM usage with serial print.

It's not a shield, it's what they call a network module and there's not SD card.

For the complete sketch, even If I split it 2 parts, I hit the 9000 characters maximum. So find it included.

You will see that I implemented a watchdog timer just in case it could solve the problem but when Arduino freezes even the hardware reset doesn't work, I need to power off. When frozen, I can ping the W5500 from the pc.

Thanks in advance J Guy

JGV_14_aug_PM_w5500.ino (33.1 KB)

Tim,

YOU GOT IT ! Thank you so much for your excellent and super fast support !

Complete sketch with maintain() didn't work BUT a basic sketch to upload static values to Wunderground worked over 55 times ! I couldn't believe it. I will now rebuilt my sketch piece by piece to find out the culprit part. Finding it should be easy, solving it may be another question.

Easy or not easy to solve (I may need you again !), I will be back soon to complete the story. I may not be the only one with such a problem as many people try unsuccessfully to upload their weather station data to wunderground (sensors list and libraries are quite limited).

I'll be back soon with the culprit !

J Guy

Hello,

I did some test and it was a real mess ... Problem was there as soon as I added few sensors, even with completely different sensors. I did another test without any sensor and started with RTC ... problem still there. I started thinking about a memory problem. To make a long story short, I finally got the freeze 3 seconds after sample 56. I thought it could be a memory problem (Sainsmart Mega) and decided to try another one.

So far, it still blocks (no freeze) at sample 55 but with this mega, the watchdog works and mega restarts by itself. Not good for a weather station as you will loose data like accumulated rain in a day, but that's a step forward !

So, I think I had 2 problems : a memory problem (?) and a library problem. Memory or something else being cleared by changing Mega, I will start from scratch to find out the other problem that could be a library one.

Btw, is there a way to check memory ????

J Guy

The SRAM check I posted in reply #3, but that checked out ok (maybe).

I get the impression it is an array overflow, but I could be wrong.

Thanks Tim

Yes the memory check was OK but I think the function checks for free memory. What I had in mind for the trouble was a few defective bytes in memory.

Here are the results of the tests I did in starting from scratch and adding equipment one by one with the second Mega : HTU21D, BMP180, Anemometer and Rain meter do not produce the freeze problem. I'm currently testing RTC. If this one creates the freeze, your impression may be good as almost all arrays are managed by RTC and they were not tested before. I'll have a look at arrays while waiting.

J Guy

I had probles with w5500 also, i fixed it updating the libary here and my code worked