What cause a Diecimila or Uno to reboot.

Good day,

I have code that reads a upc from a barcode scanner and then uses an ethernet shield to retrieve the data from the Interent.
I notice that it reboots occassionally. I may scan 5 items then reboot, perhaps scan 3 items and then it reboots.
I can tell that it reboots because it displays a message that I have at the end of the setup. ( in the serial monitor)
Reading some posts gave some ideas but I'm wondering if there is more.

  1. RAM (2048), exceeding that will reboot?
  2. What about supply voltage? Too high or too low will cause a reboot? Perhaps powering from my USB the controller, scanner and ethernet shield may casue this?
  3. Too much current? Too little?
  4. I use #ifdef statement so I can keep my troubleshooting messages when I'm done. Does it take memory or skipped at compile?
  5. Stopping or starting the serial monitor causes a reboot.
  6. Math overflow of some kind would cause a reboot?
  7. Array pointers?
    8....

Thanks
Randy

Well, all of those are reasons it would reboot.

Without any code or hardware schematics to look over, that's all that can be said.

On that list, because you said "retrieve information from the internet" the most likely culprit is either a) RAM exhaustion and/or b) running past the end of a buffer.

RandyMan:
I have code that ... reboots occassionally.

I have a dream, that people who have problems with their code will post that code.

Ha ha... I understand but my intentions is for me to solve the problem and use the form as a last option.
I have been working with Ardunio for a few years now but still learning. I put the list together to identify the possible issues and was wondering if someone could add to my list.
Perhaps if it was upside down turning counterclockwise on a Sunday would casue it to reboot or if the supply voltage drops below 3.8 volts you would get a reboot.
I understand things better if I can figure it out myself but may need some help occasionally. :slight_smile:

Thank you for the comments, this form has always been an excellent resource because of the people.

I would happy to post my code if you are curious or would like to comment.

Randy

i know that the arduino runs happily at 16MHz on 3.3 volts, that i can answer :slight_smile:

RandyMan:
Ha ha... I understand but my intentions is for me to solve the problem and use the form as a last option.
...
Perhaps if it was upside down turning counterclockwise on a Sunday would casue it to reboot or if the supply voltage drops below 3.8 volts you would get a reboot.

Lots of things can cause a reboot. A couple more to add:

  • The watchdog timer might fire.
  • The brown-out detector might fire.
  • Spikes in the power line might do it.
  • You might write software to deliberately do it.
  • You might recursively call a function until it consumes all the stack

The question is too general. If you want help you need to post some code, or describe your hardware. If it happens frequently, but directly after you scan something (as it seems to) it is more likely some sort of data-related problem.

I tried a few things but without success.
I tried increasing the supply voltage to 7.2 volts. Adding a delay, perhaps the site was slow to respond.
The scanner and scanner code appears to be working correctly. I think the issue is pointing to the ethernet shield. Perhaps the web site?

Code and sample of the output is in the next two post.

I had to exclude the scan code becasue of the 9500 character limit.

#define DEBUGETHER        0xFF                         // Debug Print.  Set to FF to debug ethernet shield.
#define DEBUGSD           0xFF                         // Debug of the SD code.

//Ethernet
IPAddress server(174,122,37,98);                       // Delete this
char serverName[] = "upcdata.info";                    // 
byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x98, 0x13};     // MAC address of the arduino. Arduino does not have it's own MAC address.                

#define COMP "&comp=no"                           

// eeprom 
#define SEQ 0                                           // Address of seq data in eeprom. (High Byte & Low Byte)

#define COMMA ','                                       // Start & end of the data - CSV format.
#define QUOTE '"'                                       // Number of char before I save the data for the valid field
#define STAT 3                                          // Number of char before I save the data for the item name field
#define DESCRIPTCNT 11                                  // Number of char before I save the data for the description field
#define FIELD_LENGTH 40                                 // Length of the data fields. In case of too much data.

EthernetClient client;


//Scanner
int SCAN_ENTER = 0x5a;                                  // ASCI Character '^'
int SCAN_BREAK = 0xf0;
int breakActive = 0;
int clockPin = 3;                                       // Clock is only output. 
int dataPin = 2;                                        // The data pin is bi-directional, but at the moment we are only interested in receiving   
int ledPin = 13;                                        // When a SCAN_ENTER scancode is received the LED blink
int clockValue = 0; 

byte scanCodes[10] = {0x45,0x16,0x1e,0x26,0x25,0x2e,0x36,0x3d,0x3e,0x46}; 
char characters[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
int quantityCodes = 10;
char buffer[64] = {};	                                // This saves the characters (for now only numbers) 
int bufferPos = 0; 
int bufferLength = 64;

String upc  = "";                                      // The upc code. Rasins - "0041143028704", rice "071429097056" 

int x = 0;

void setup() {
pinMode(dataPin, INPUT);                                               
pinMode(clockPin, INPUT);                                              
pinMode(ledPin, OUTPUT);     
//pinMode(10, OUTPUT);
Serial.begin(9600);  

if (Ethernet.begin(mac) == 0) {
 #ifdef DEBUGETHER
   Serial.println("Failed to configure Ethernet using DHCP");
 #endif
 
   while(true); // Can't continue so do nothing.
   }
  
 // Give the Ethernet shield a second to initialize:

#ifdef DEBUGETHER
  Serial.println("Connecting...");
#endif
delay(3000);                                            //Wait three seconds before we start.
upc = "";


} // End of Setup.

//---------------------------------------------

void loop() {
 
upc = ""; 
while(upc == ""){
  upc =  translateScan();  
} // End of While. 


if (upc != "" && (upc.length() == 8 || upc.length() == 12 || upc.length() == 13))  {
  beginethernet(upc); 
  delay(500);  
} // End of if upc !=""

                             
} // End of loop.

//-------------------------------------------

void beginethernet(String scanUpc){

// Start the Ethernet connection:

client.flush();

#ifdef DEBUGETHER
  Serial.print("ScanUpc = ");
  Serial.println(scanUpc);
  Serial.print("DHCP = ");
#endif



 // We have a connection?
if (client.connect(serverName, 80)) {

  #ifdef DEBUGETHER
    Serial.println("Connected");
  #endif

 // Make a HTTP request:
   client.println("GET http://upcdata.info/feed.php?keycode=B3074E924F1C8998&mode=csv&find=" + scanUpc + COMP);
   client.println();
  
   receiveEvent();
  } 
  else {
    // Connection to server failed
    #ifdef DEBUGETHER
      Serial.println("Connection failed");
    #endif
    
    client.flush();
    client.stop(); 
  }  
  
  #ifdef DEBUGETHER
      Serial.println("Connection Done");
  #endif
  
}


void receiveEvent(){

delay(3000);                                           // Waiting 3 seconds, perhaps the data is not ready.
  
  // Data received from HTTP post.  

String csv_value = ""; 
String sub_upc = "";                                    // UPC Submited
String query_status = "";                               // 200 = success, 404 = not found, 400 & 500 = error
String upc13 = "";                                      // 13 Digit EAN-13 Code
String product = "";                                    // The item name.
String description = "";                                // Size, weight, count, color etc
String category_no = "";                                // Numeric category code.
String category_text = "";                              // Text version of the category.

int csv_position[] = {2,3,6,9,10,11,12, 3000}; //(client.available() + 1)
int counter = 0;

// Scan data from web site.
// If there are incoming bytes available from the server.

  delay(1000);
  
  #ifdef DEBUGETHER
    Serial.println("Receive Start");
    Serial.print("Available = ");
    Serial.println(client.available());
   // Serial.print("Read = ");
   // Serial.println(client.read());
  #endif
  
  for (int i =0; i < 8; i++) {
    
    while (client.available()) {                      //csv_position[]
      char c = client.read();
           
      if (c == COMMA)
       counter++;
    
      if (counter == csv_position[i]) {                                // Reads the CSV ag and then we'll see if we need it.
        c = client.read();
        
       while(c != COMMA) {  
        if (c != QUOTE) 
          csv_value = csv_value + c;
        c = client.read();  
       }

       switch (csv_position[i]) {
        case 2:
         sub_upc = csv_value;
         csv_value = "";
         break;
        case 3:  
         query_status = csv_value;
         csv_value = "";
         break;
        case 6:  
         upc13 = csv_value;
         csv_value = "";
         break; 
        case 9:  
         product = csv_value;
         csv_value = "";
         break; 
        case 10:  
         description = csv_value;
         csv_value = "";
         break;
        case 11:  
         category_no = csv_value;
         csv_value = "";
         break;
        case 12:  
         category_text = csv_value;
         csv_value = "";
             
        } // End of Swirch  
        counter++; 
        break;  
      } // End of counter == csv_position[i]
      
    } // End of While

  } // End of for statement.
  
  // If the server's disconnected, stop the client:
if (!client.connected()) {
    
  // Stop the client and flush the data. We have completed parsing the input from
  // the web site so we are done.
    client.stop();
    client.flush();
      
    #ifdef DEBUGETHER
      Serial.println();
      Serial.println("disconnecting.");
      Serial.print("Submitted Item - ");
      Serial.println(sub_upc);
      Serial.print("Status - ");
      Serial.println(query_status);
      Serial.print("13 Digit UPC - ");
      Serial.println(upc13);
      Serial.print("Product - ");
      Serial.println(product);
      Serial.print("Description - ");
      Serial.println(description);
      Serial.print("Cat No: - ");
      Serial.println(category_no);
      Serial.print("Cat Text - ");
      Serial.println(category_text);
    #endif
} 
   
   // while(true){}
  
  
// if (query_status == "200") {
//   if (StartSD){
 //    Write_Record(upc13, product, description, category_no, category_text );
//   }
// }
 
 
 #ifdef DEBUGETHER
   Serial.println("End of Rcvd Event");
 #endif
}
At the end of the output you will see "Connecting...".  
The "connecting..." is at the end is in the setup so it must be rebooting after the scan. The ethernet shield?

Thanks
Randy

[code
disconnecting.
Submitted Item - 034000315000
Status - 200
13 Digit UPC - 0034000315000
Product - Herseys Genuine Chocolate Syrup
Description - 16Oz
Cat No: - 0
Cat Text - 
End of Rcvd Event
Connection Done
ScanUpc = 032076561871
DHCP = Connected
Receive Start
Available = 261

disconnecting.
Submitted Item - 032076561871
Status - 200
13 Digit UPC - 0032076561871
Product - HST-187 3/16-3/32 SHRINK TUBE
Description - 
Cat No: - 0
Cat Text - 
End of Rcvd Event
Connection Done
ScanUpc = 034000315000
DHCP = CoConnecting...
]

You are using the String class. I would put in some checks you haven't run out of memory.

Yeah, with all of those strings, you are very likely running out of RAM.

Three general comments:

  1. Don't use the String class. Use the traditional "character arrays".
    Strings in an environment with such little RAM requires more care. By forcing yourself to use character arrays you can monitor how much memory you are using. Since the Arduino/ATmega328 has no memory manager, it is up to you to manage that 2048 bytes of RAM.

  2. Move all of the strings used with Serial and Client.prints to PROGMEM.
    If you are using 1.0, you can use the macro F():
    Serial.println(F("Connection failed"))

If not using 1.0, then search for "PROGMEM" on the arduino site for a example of how to use it.

It isn't obvious, but each of those character arrays actually consumes RAM at run time. They add up quickly. Keeping your strings in PROGMEM reduces their RAM footprint significantly.

  1. Don't use "concat" of the String class, ever. So don't do this: client.println("GET http://upcdata.info/feed.php?keycode=B3074E924F1C8998&mode=csv&find=" + scanUpc + COMP);
    I haven't looked to see if this is fixed in 1.0, but concatting strings in the legacy String class meant making copies of the existing string and a buffer as large as the new one. A string like you are doing here can be problematic very quickly.
    Instead you are better off doing multiple client.print() with a final client.println(""), along with the fixed portion coming out of PROGMEM.

Thanks gentlemen.
I will remove the strings and look at PROGMEM which I'm not familiar with.
Let you know if this solves the problem.
Good lesson on memory managment.

Randy

Thanks for the advice.
Your recommendations resolved the issue.
I use PROGMEM and changed the strings to array of characters and I have been unable to make it fail.
Returns the data each time and no reboot.
Lesson learned is to make tight code and I'm learning.
Well done.
Thanks again.