Problems with the Ethernet library

I've got an arduino board that has sensors tied into it. The code i've written is pretty simple. It loops through all the sensors once a minute and writes the data in an XML document out to a server that is running on a PC. The server takes the XML and stores all the data in mySQL for analysis and graphing later.

I coded the thing first using Serial and it works fine. I then added an ethernet shield board and had the code output to the serial and over a socket connection back to my server.

Now, i'm getting weird behavior from the connection. It seems like if I write too much data out each cycle, that random characters are added to the output stream. Also, after a few cycles through the loop, i stop getting output on the socket. I thought maybe there was some sort of buffer overrun. i tried throughing in some delays to maybe allow the output buffer to clear (a guess). This seemed to help, but the problem persists.

Another odd behavoir i've seen is that if I start the serial monitor on the ide, it seems to free something up and i get a few more messages from the ethernet port.

has anyone seen anything similar to this. I'm so close to finishing this code and keep running into weird problems.

Michael

If I just do serial, it works great. And the ethernet c

Hard to say for sure without seeing your code, but if I had to take a guess I'd say you are running out of RAM. I think the Ethernet library uses more RAM and this would explain why you did not see the issue when using only serial.

I figured it was some sort of memory problem. I'm pretty sure I'm not stepping on anything, i've done this several times. How robust is the memory management for the arduino.

I simplified the code. I wrote a string class that used malloc to manage the string memory. I got rid of this code and do it all now with local variables, also reduced the amount of data written, and it works better, but still hangs after a while. Here's the code if anyone wants to look at it.

#include <Client.h>
#include <Ethernet.h>

#define SERVER_PORT 14822
#define NUMBER_SAMPLES 8

#define roomId 1
#define boardId 1

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 200, 200 };
byte gateway[] = { 192, 168, 200, 1 };
byte netmask[] = { 255, 255, 255, 0 };
byte server[] = { 192, 168, 200, 110 };

int reportInterval = 60; // temperature readings interval in seconds.

unsigned long startTime = 0;
unsigned long minuteTimer = 0;

#define NO_SENSOR 0
#define SENSOR_TEMP 1
#define SENSOR_LIGHT 2

#define NUMBER_SENSORS 6
int sensors[NUMBER_SENSORS];

void
ConvertInt(char *data, int value, int size)
{
int length;
if ( size == 0 )
{
if ( value == 0 )
length = 1;
else
{
int newvalue = value;
length = 0;
while ( newvalue > 0 )
{
newvalue /= 10;
length++;
}
}
}
else
length = size;
for ( int i = 0; i < length; i++ )
{
int mod = value % 10;
data[length - i - 1] = (char)mod + '0';
value = value / 10;
}
data[length] = '\0';
}

int
ConvertDouble( char *data, double value, int decimalPlaces)
{
char wholeString[10];
char fractionString[10];
ConvertInt(wholeString, (int)value, 0);

double dec = value - (double)((int)value);
for ( int i = 0; i < decimalPlaces; i++ )
dec = dec * 10.0;

ConvertInt(fractionString, (int)dec, decimalPlaces);

int n = 0;
for (n = 0; n < wholeString[n] != '\0'; n++)
data[n] = wholeString[n];
data[n++] = '.';
for (int i = 0; fractionString != '\0'; i++)
_ data[n++] = fractionString*;_
_
data[n] = '\0';_
_
}_
double ReadValue( int sensorId )
_
{_
_
double value = 0.0;_
_
//_
_
// Read a number of samples and average them to get a more accurate value._
_
//_
for (int i = 0; i < NUMBER_SAMPLES; i++)
_
value += (double)analogRead(sensorId);_
value = value / (double)NUMBER_SAMPLES;
_
return value;_
_
}_
double
ReadTemp(int sensorId)
_
{_
_
double tempc = ReadValue(sensorId);_
_
// The temperate is 10mv per degree, 1024 is 5.0V, so scale this to degress._
_ tempc = ( 5.0 * tempc * 100.0) / 1024.0;_
_
//_
_
// Convert to Fahrenheit*_
_ return ((tempc * 9.0)/5.0) + 32.0;_
}
void
WriteMessageHeader(Print *stream )
{
// stream->println("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
// stream->println("<Message");
// stream->println(" xmlns="urn:sol.bosque.com:Solar:Arduino"");
// stream->println(" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance\"");
// stream->print(" xsi:schemaLocation="urn:sol.bosque.com:Solar:Arduino");
// stream->println(" http://winserv/Schemas/ArduinoData.xsd\">");
* stream->println("<?xml version=\"1.0\"?>");*
* stream->println("");*
}
void
WriteMessageEnd(Print *stream)
{
* stream->println("");*
* stream->println("</?xml>");*
}
void
WriteLocation(Print *stream, int sensorId)
{
* stream->print(" \n");*
* stream->print(" ");*
* stream->print(roomId);*
* stream->print("\n");*
* stream->print(" ");*
* stream->print(boardId);*
* stream->print("\n");*
* stream->print(" ");*
* stream->print(sensorId);*
* stream->print("\n");*
* stream->print(" \n");*
}
void WriteLight(Print *stream, int id)
{
* int time = (millis() - startTime)/1000;*
* WriteMessageHeader(stream);*
* stream->print(" \n");*
* stream->print(" ");*
* stream->print((int)ReadValue(id));*
* stream->println("");*
* stream->print(" ");*
* stream->print(time);*
* stream->println("");*
* stream->println(" Light");*
* WriteLocation(stream, id);*
* stream->print(" \n");*
* WriteMessageEnd(stream);*
}
void WriteTemperature(Print *stream, int id)
{
* int time = (millis() - startTime)/1000;*
* double temp = ReadTemp(id);*

* WriteMessageHeader(stream);*
* stream->print(" \n");*
* stream->print( " "); *

* char s[20];*
* ConvertDouble(s, temp, 2);*
* stream->print(s);*

* stream->print("\n F\n ");*
_ stream->print((int)(temp100.0));_
_
stream->print("\n");_
_
stream->println(" Temperature");_
_
WriteLocation(stream, id);_
_
stream->print(" \n");_
_
WriteMessageEnd(stream);_
_
}_
void WriteSensors()
_
{_
Client client( server, SERVER_PORT);
_
int connected = 0;_
_
if (client.connect() != 0)_
_
{_
_
connected = 1;_
_
}_
for ( int i = 0; i < NUMBER_SENSORS; i++)
_
{_
_ switch ( sensors )
{_
case SENSOR_TEMP:
_// WriteTemperature(&Serial, i);
if (connected == 1)
WriteTemperature(&client, i);
break;_
case SENSOR_LIGHT:
_// WriteLight( &Serial, i);
if (connected == 1)
WriteLight(&client, i);
break;
default:
break;
}
delay(10);
}
if (connected == 1)
{
client.stop();
}*_

}
void setup()
*{ *
* Serial.begin(115200);*
* Ethernet.begin( mac, ip, gateway, netmask );*

* startTime = millis();*
* minuteTimer = millis();*

// for (int n=0; n < 5; n++)
// command[n] = '\0';

* for ( int i = 0; i < NUMBER_SENSORS; i++)
_ {
sensors = NO_SENSOR;
}_

sensors[1] = SENSOR_TEMP;
// sensors[2] = SENSOR_TEMP;
// sensors[3] = SESNOR_TEMP;
sensors[5] = SENSOR_LIGHT;
_ WriteSensors();
}
void loop()
{
unsigned long delta = ( millis() - minuteTimer ) / 1000;
if ( delta > reportInterval )
{
minuteTimer = millis();
WriteSensors();
}
// checkSerial();
}*_

How robust is the memory management for the arduino.

There is none. The stack will grow until it wraps and trashes the bottom of the address space, hence weird problems seemingly out of the blue.

you have a large number of constant strings - see if you can move them to program memory. This is a pretty typical problem/solution.

-j

How do I move them to program memory?

My guess would be instead of

void printa()
{
stream->print("aaaaa");
}

use

const char *s = "aaaaa";

void
printa()
{
stream->print(s);
}

Thanks for the help. So far so good. I changed the code to the following like it showed in the example and it's working.

It's been running for 30 minutes, no problem.

PROGMEM const prog_char xmStartTag[] = "</?xml?>";
PROGMEM const prog_char messageStartTag[] = "";

PGM_P StringTable[] PROGMEM = {
xmlStartTag,
messageStartTag, };

#define XML_START_TAG 0
#define MESSAGE_START_TAG 1

void
WriteString(Print stream, int id, int newline)
{
char buffer[80];
strcpy_P(buffer, (char
)pgm_read_word(&(StringTable[id])));
if ( newline == 0 )
stream->print(buffer);
else
stream->println(buffer);
}

I spoke too soon. It's working better, but still hangs after about 30 or 40 loops. The serial code has run for days no problem, but now that the ethernet has been added, it hangs.

The weird thing is that if it's hung and i turn on the ide serial monitor, it spits out another message.

Opening the serial monitor resets the Arduino, so it would make sense that things start working again.

Can you reproduce the problem with a simpler program?

Now it makes sense while the serial monitor makes it work again.

I think I found the problem. I found this post about problems with Client in the Ethernet library

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1227735530

I made this change and made the _srcport static and it's been working for over an hour versus about 4 minutes before.

Michael