Arduino sensor network - reset problem

Hi, (sorry for my english :p)

Project short: I'm making a wireless sensor network, for communication I use the XBee Series 2 modules, these are connected to the arduino with an XBee shield. Also, I have an ethernet shield with build on SD card reader for data logging and later putting it on a server. this is the coördinator of my network, i'm using a arduino mega 1280. For the routers in my network I use the arduino FIO who have a direct connection for XBee modules.

Problem: When running the Coördinator with USB cable connected, it recieves data from a router and respons to it by looking for his adress. Then the router respons back to know it succeeded (this is just a test to be able to get serial and pan adresses from my network)
This all works but for some reason, after some time the arduino just randomly resets. There are no external signals that disturb the arduino.

Does anybody know a solution for this problem?

Fixes I tried: Arduino Playground - DisablingAutoResetOnSerialConnection , the 120ohm fix, and replace my arduino uno with a mega to get more ram, I thought it might be a stack overflow or something.


Later I brought this more outside so i can easly reach it, with wire. Because when programming, this auto-reset is handy.

Modifications:
What i had to change to connect the ethernet board to the mega: http://mcukits.com/2009/04/06/arduino-ethernet-shield-mega-hack/

  • MEGA pin 50 (MISO) to Arduino Ethernet Shield pin 12.
  • MEGA pin 51 (MOSI) to Arduino Ethernet Shield pin 11.
  • MEGA pin 52 (SCK) to Arduino Ethernet Shield pin 13.
  • MEGA pin 53 (SS) to Arduino Ethernet Shield pin 10.


What i had to do to connect th arduino, ethernet shield and xbee shield:

What it looks like:

I hope there is a easy or detailed sollution to this problem, I'm new in this stuff. Thanks for the help already!

(I will put the code in my next post)

Code Coördinator:

#define VERSION "1.00a0"
#include <SD.h>
//************ HELP VARIABLES ************//
int Found;        
int SBFOUND = 0;  
int Find = 99;    //Position in API frame (99 impossible)
int o = 0;

//************ ADRESSING ************//
int SER1;         //MSB Serial adres 
int SER2;         //                 
int SER3;         //LSB Serial adres
int PAN1;         //MSB PAN adres
int PAN2;         //LSB PAN adres
int CS;           //Checksum

int ReCount = 0;  //Look for the response
int Response;     //Response from Router

//************ SD CARD ************//
const int sd_cs = 4; 
const int ethernet_cs = 10;
File myFile;
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
#define error(s) error_P(PSTR(s))
// store error strings in flash to save RAM
void error_P(const char* str) {
  PgmPrint("error: ");
  SerialPrintln_P(str);
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}

//************ SETUP ************//
void setup()
{
  Serial.begin(9600);
  
  pinMode(sd_cs, OUTPUT);
  pinMode(ethernet_cs, OUTPUT); // !!!!!!
  
   digitalWrite(sd_cs, LOW);
  
  //SD card info, instellen, controleren...
  PgmPrint("Free RAM: ");
  Serial.println(FreeRam()); 
  
  digitalWrite(ethernet_cs, HIGH);                    // but turn off the W5100 chip!

  if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!");
  
  // initialize a FAT volume
  if (!volume.init(&card)) error("vol.init failed!");

  PgmPrint("Volume is FAT");
  Serial.println(volume.fatType(),DEC);
  Serial.println();
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  
  myFile = SD.open("logfile.txt", FILE_WRITE);
  myFile.close();
    
  if (!root.openRoot(&volume)) error("openRoot failed");

  // list file in root with date and size
  PgmPrintln("Files found in root:");
  root.ls(LS_DATE | LS_SIZE);
  Serial.println();
  
  // Recursive list of all directories
  PgmPrintln("Files found in all dirs:");
  root.ls(LS_R);
  
  Serial.println();
  PgmPrintln("Done");
}

void loop() 
{
    if (Serial.available() > 0) //recieved?
    { 
       for (int i = 0; i<Serial.available(); i++) //whole frame
        {
  Serial.print("(( ");
  Serial.print(Find);
  Serial.print(" ))");
          Found = Serial.read();    //Found serial
          //Serial.write(Found);   //Debugging 
          
          //First Recieve
          if (Found == 0x7E)        //Startbyte found?
            {
              SBFOUND = 1;          //YES
              Serial.write("    StartByte gevonden    "); //Debugging
              Find = 0;          //Reset position in frame
            }
          if (Find == 10)        //position 10 SER1
            {              SER1 = Found;            }
          if (Find == 11)        //position 11 SER2
            {              SER2 = Found;            }
          if (Find == 12)        //position 12 SER3
            {              SER3 = Found;            }
          if (Find == 13)        //position 13 PAN1
            {              PAN1 = Found;            }
          if (Find == 14)        //position 14 PAN2
            {              PAN2 = Found;            }   
            
          Find = Find + 1;    //Position in frame
          
          //Second Recieve - Response on Answer
          //                 (/@(RESPONSE))))
          if (ReCount == 4)
            {
              ReCount = 0;       //Reset the locater
              Response = Found;  //Save the Response
              Find = 0;          //Reset positie in frame   
              Serial.write("    Found the Response:  "); //Debugging  
              Serial.write(Response); //Debugging    
              
              //Write to logfile
              recordConditions();  
              
            }
          if (Found == 0x28)        //Response incoming?
            {                       
            if (ReCount == 3) {ReCount++; /*Serial.write("Last  (");*/}        //Last  (
            else {
                  if (ReCount == 0) {ReCount++; /*Serial.write("First (");*/}  //First (
                  else {ReCount = 0;}
                 }
            }
          if (Found == 0x2F)        
            {
            if (ReCount == 1) {ReCount++; /*Serial.write("2nd   /");*/}        //2nd   /
            else {ReCount = 0;}
            } 
          if (Found == 0x40)        
            {
            if (ReCount == 2) {ReCount++; /*Serial.write("3th   @");*/}        //3th   @
            else {ReCount = 0;}
            } 
        }  
  }
  else
  {
   if (PAN1 == 0 & PAN2 == 0) {}    //Both '0' -> bad adress
   else
   {
    if (SBFOUND == 1){              //Startbyte Found
    Serial.write("    Zend naar Router    "); //Debugging
              
              //Answer - on First Recieve   
           
              // 7E 00 0F 10 01 0000 0000 0000 FFFF XXXX 00 00 2B CS -> Frame to be send
              // Checksum calc:
              CS = 0xFF-((0x10+0x01+0xFF+0xFF+PAN1+PAN2+0x2B)%256); //16² = 256
              char nul = 0x00;      //To send NUL

              
              Serial.write(0x7E);   //Startbyte
              
              Serial.write(nul);    //Lengte    
              Serial.write(0x0F); 
              
              Serial.write(0x10);   //Frame type / ID
              Serial.write(0x01); 
              
              Serial.write(nul);    //64-bit destination address
              Serial.write(nul);    
              Serial.write(nul);    
              Serial.write(nul);    
              Serial.write(nul);    
              Serial.write(nul);
              Serial.write(0xFF);
              Serial.write(0xFF);
                        
              Serial.write(PAN1);   //16-bit destination address         
              Serial.write(PAN2);            
              
              Serial.write(nul);    //Extra options 
              Serial.write(nul);   
              
              Serial.write(0x2B);   //Information  
             
              Serial.write(CS);     //Checksum
           
                            
          SBFOUND = 0;              //Startbyte resetten 
          }
         else 
          {
            delay(1000);            
            Serial.write("-");
          }
   }
  }
}

void recordConditions()
{
  digitalWrite(ethernet_cs, HIGH);
  digitalWrite(sd_cs, LOW);
  myFile = SD.open("logfile.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to logfile.txt...");
    String dataString = "";
    dataString += String("Serial (Fixed): " );
    dataString += SER1;                dataString += String(",");              
    dataString += SER2;                dataString += String(",");    
    dataString += SER3;
    dataString += String(" - PAN ID (Variable): ");
    dataString += PAN1;                dataString += String(",");    
    dataString += PAN2;
    dataString += String(" - Response: ");     dataString += Response;           
    Serial.print(dataString);
    myFile.println(dataString);
    // close the file:
    myFile.close();
    Serial.println("done.");
  } 
  else {
    // if the file didn't open, print an error:
    Serial.println("error opening logfile.txt");
  }
}

Thank you for the well-documented question.

The code looks well-thought and well-written. One concern I would eliminate immediately is the use of the String class in recordConditions(), because there is a well-known memory fragmentation issue that it causes. The symptom is random behavior, like you are seeing.

If you rewrite this function to use char arrays I believe it will help with the reliability issues you are seeing.

Good luck with your project,

-br

Thanks for the fast reply.

If it works that would be the easy sollution I was looking for. I'm gonna try it out now and will update this post if it works out!

As billroy says, get rid of the String class but another question is how are you powering this? Maybe your sucking to much power with Ethernet & XBee.

Thank you for the reply!

Right now I'm in a testfase so I'm just powering over USB. Later I will just use an adapter I found on antratek: http://www.antratek.nl/pdf/hnp06.pdf

The XBee is very low power consuming. The ethernet board is only used for the sd card part for now.

Edit
I tried the adapter now, still has the problem. Doh it doesn't reset anymore, but this happends because of the 120ohm resistor I discribed above, it just gets stuck now, I have to reset it myself. I'm writing the char array now, but I find this hard because it doesn't have a fixed number of chars and some of them are hexadecimal values. any inside on this could be helpfull

Thanks so far guys!

Disabling the auto reset is not going to stop it resetting unless the reset is caused by the the opening and closing of the serial port.

Once you have disabled the serial port's reset you have two ways in which the arduino can be being reset:-

  1. Interference from the other modules or an external source like thermostat motor and so on.
  2. Through the software, either through some sort of memory overflow or watchdog timeout.

Thanks for the reply mike.

Is there a way to see if there is some sort of overflow? I've already been looking around the net for this and not really finding detailed information about this.

Also looked into the watchdog, but I don't understand how this works with the arduino, and why it would run for some thim without problems and after a random time stop working, triggering this watchdog. Also, I could find something to like monitor this timer or to see if it is triggered.

About the resetting, it's doing that again now, don't know why just some time ago it just stopped doing anything without the resetting.

billroy

If you rewrite this function to use char arrays I believe it will help with the reliability issues you are seeing.

I'm not sure about how to do this, it might be stupid but always had a hard time with using arrays, surely when I have other types of values like HEX. So I have to rewrite the understanding code to place it in array instead of the datastring.

void recordConditions()
{
  digitalWrite(ethernet_cs, HIGH);
  digitalWrite(sd_cs, LOW);
  myFile = SD.open("logfile.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to logfile.txt...");
  
    String dataString = "";
    dataString += String("Serial (Fixed): " );
    dataString += SER1;                dataString += String(",");              
    dataString += SER2;                dataString += String(",");    
    dataString += SER3;
    dataString += String(" - PAN ID (Variable): ");
    dataString += PAN1;                dataString += String(",");    
    dataString += PAN2;
    dataString += String(" - Response: ");     dataString += Response;           
    Serial.print(dataString);
    myFile.println(dataString);
    // close the file:
    myFile.close();
    Serial.println("done.");
  } 
  else {
    // if the file didn't open, print an error:
    Serial.println("error opening logfile.txt");
  }
}

This is what i tried, but it's just bad and i knew it wouldn't work:

    char* dataArray[ ] = {"Serial (Fixed): ", SER1, SER2, SER3, " - PAN ID (Variable): ", PAN1, PAN2, " - Response: ", Response};

How can I get these HEX values to be inserted in the array on a correct way, and the array doesn't have a fixed lenght, I'm really confused atm :stuck_out_tongue:

I'm writing the char array now, but I find this hard because it doesn't have a fixed number of chars and some of them are hexadecimal values. any inside on this could be helpfull

Figure out the maximum size a string could be and then make your char array at least this size+1. You should also try and do bounds checking on the array so if at some point a longer string arrives you don't corrupt memory. You should post some examples of the strings with hex values or describe them in more detail so we know what to do next.

Thank you for the response Riva.

This is what I had so far, when not using the array yet.

Serial (Fixed): 148,83,227 - PAN ID (Variable): 155,45 - Response: 43

As you can see this is in decimal, I wanted to get this in hexadecimal but it wouldn't work straight away.
This is what I would love to have in my array:

Serial (Fixed): 94,53,E3 - PAN ID (Variable): 9B,2D - Response: 2B

These values are read in directly from the frame I recieve. And i suppose they are saved in HEX because I use the serial and PAN to respond to the frame.

I may have sent you astray. Get rid of the String, yes. Maybe you don't need char arrays.

Couldn't you "just" myFile.print() what you want, one piece at a time?

-br

Thanks again billroy,

I'm doing this now but I get the error: "Error while compiling"
Not sure why, no further information was given. I'm gonna try rewriting this and rebooting my pc to see if the prob is solved. If this works i'll update the post.

void recordConditions()
{
  digitalWrite(ethernet_cs, HIGH);
  digitalWrite(sd_cs, LOW);
  myFile = SD.open("logfile.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to logfile.txt...");

    myFile.print("Serial (Fixed): ");
    myFile.print(String(SER1));
    myFile.print(","); 
    myFile.print(String(SER2));
    myFile.print(",");   
    myFile.print(String(SER3));
    myFile.print(" - PAN ID (Variable): ");
    myFile.print(String(PAN1));
    myFile.print(",");
    myFile.print(String(PAN2));
    myFile.print(" - Response: ");
    myFile.println(String(Response));
                                                    
    // close the file:
    myFile.close();
    Serial.println("done.");
  } 
  else {
    // if the file didn't open, print an error:
    Serial.println("error opening logfile.txt");
  }
}

So I modified it and it still keeps on resetting.
I monitored this in X-CTU (program used to program XBEEs)

The moment of the reset is still random.

I also tried to monitor this with CoolTerm and I get a warning (I didn't get this warning before I switched to the MEGA and modified the hardware)

It sais:
Coolterm - Warning
A Serial Port Error Occured
103: No Stop Bit recieved
or
104: Stop Bit recieved too early

But I didn't get this before, but before I did get the reset error aswel. So this might be a problem but I suppose it's not related to the reset problem.

    myFile.print(String(SER1));

Your still using the String class.

Your still using the String class.

You're right, were was I and were the hell was my brain :stuck_out_tongue: So bad :stuck_out_tongue:

I'm gonna try it out tomorow. Tnx for pointing out my fail Riva :slight_smile:

Also looked into the watchdog, but I don't understand how this works with the arduino, and why it would run for some thim without problems

A watchdog times out if not reset or kicked in a certain time. If something takes a bit longer than the writer of the code expected, like a packet arriving a bit late, the the watchdog can kick in. Find out if your code is using and try extending the period. This can be a cause of random reaseting.
Also given your hardware tower it could be that there are some loose connections. Does it reset more when you physically move the stack of cards?

BR and Riva
So now I made this out of it:

    myFile.print("Serial (Fixed): ");
    myFile.print(SER1);
    myFile.print(","); 
    myFile.print(SER2);
    myFile.print(",");   
    myFile.print(SER3);
    myFile.print(" - PAN ID (Variable): ");
    myFile.print(PAN1);
    myFile.print(",");
    myFile.print(PAN2);
    myFile.print(" - Response: ");
    myFile.println(Response);

But I still get the random reset.

Grumpy Mike
Tried to move the hardware around to see if it has any effect on the resets, also tried it in other buildings/on other pc's, the reset still happends + there is no increase of times it does so. It could still be hardware related if i made a wrong modifiction of some sort.

Looked after a watchdog timer. I didn't set 1 myself, is there 1 internal in the arduino that is configured bij arduino itself?

I also think there is no loop were he could hang or a place that takes to long to complete. Everything seems to go at the right pace, until it resets that is :stuck_out_tongue:

Any other possibilities or insights on this problem are very welcome.
Thanks allot for helping me.

Looked after a watchdog timer. I didn't set 1 myself, is there 1 internal in the arduino that is configured bij arduino itself?

The built in watchdog timer is disabled by default. If you have not enabled it and any library you use has not enabled it then it is not the problem.

Maybe your serial read parsing routine is sometimes entering a deadlock loop condition. To debug you could try turning LED's on and off when entering/leaving parts of the code and see if it locks up within a specific place. Also try commenting out the recordConditions call to see if problem is in main loop of the SD card routines.

Thanks for the idea Riva, I'm gonna try this on monday. I'll keep you posted.