Go Down

Topic: server/ RGB controller (Read 491 times) previous topic - next topic

Developing a 3-channel lighting controller to run off a server hosted by the arduino ethernet. I have a server operational and more-or-less functioning.

One problem I have is that if I enter in invalid data into the URL to pull up the browser-based software, the controller hangs and I must reset the controller.

Examples:

1. I type in the IP address to open the controller interface
http://192.168.24.253/

2. I make setting adjustments to different channels
http://192.168.24.253/?r=255&g=255&b=255&H=Program
sets r, g, & b values. Program button applies the data

Everything works fine in this fashion

3. If erroneous data is sent to the controller like this:
http://192.168.24.253/blahblahblah

the controller hangs.

Is there a way I can safeguard against bad data? Or at least prevent the controller from hanging and needing a reset?

If I have to deal with it hanging, would a watchdog timer work in resetting the controller?

I suspect the problem in the code is within this section, but honestly I'm confused as to how this portion of the code works.

Portion of "Loop"

Code: [Select]
void loop()
{
  // Serial.println(str);

  //   Serial.print("freeMemory()=");
  //   Serial.println(freeMemory());
  //   delay(2000);


  int bufLength;
  Client client = server.available();
  if (client) {
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (inString.length() < maxLength) {
          //inString.append(c);
          inString += c;
        }     

        if (c == '\n' && current_line_is_blank) {
          if (inString.indexOf("?") > -1) {
            int Pos_r = inString.indexOf("r");
            int Pos_g = inString.indexOf("g", Pos_r);
            int Pos_b = inString.indexOf("b", Pos_g);
            int End = inString.indexOf("H", Pos_b);
            if(End < 0){
              End =  inString.length() + 1;
            }
            bufLength = ((Pos_g) - (Pos_r+2));
            if(bufLength > 4){  //dont overflow the buffer
              bufLength = 4;
            }   
            inString.substring((Pos_r+2), (Pos_g-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            r = atoi(colorBuff);
            bufLength = ((Pos_b) - (Pos_g+2));
            if(bufLength > 4){  //dont overflow the buffer
              bufLength = 4;
            }     
            inString.substring((Pos_g+2), (Pos_b-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            g = atoi(colorBuff);
            bufLength = ((End) - (Pos_b+2));
            if(bufLength > 4){  //dont overflow the buffer
              bufLength = 4;
            }     
            inString.substring((Pos_b+2), (End-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            b = atoi(colorBuff);


This is based off an individuals code here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238498454


#1
Feb 15, 2012, 06:55 pm Last Edit: Feb 15, 2012, 06:59 pm by jstamour802 Reason: 1
The entire code won't fit in a single message, so here it is in 2 parts:

Includes, Variables, Functions, and Setup:

I'm using the Arduino Ethernet, and v0022 of the compiler

Code: [Select]

/* Advanced Illumination
LEDLink
*/

#include <EEPROM.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#define maxLength 25
#include <memoryFree.h>


// these values are saved in EEPROM

const byte CH_EEPROM_ID = 0x99;   // used to identify if valid data in EEPROM

byte mac[] = {
 0x00, 0x22, 0xFE, 0x10, 0x00, 0x00 }; //update with factory MAC settings
byte default_ip[] = {
 192, 168, 24, 253};
byte default_gate[] = {
 192,168,24,1};
byte default_subnet[4];


String inString = String(maxLength);
int val;

byte r;               //initial values to hold channel settings
byte g;              
byte b;
//byte w;

char colorBuff[5];
Server server(80);    //server port, HTML

const byte ch0Pin = 5;                // channel0 output PWM pin
const byte ch1Pin = 6;                // channel1 output PWM pin
const byte ch2Pin = 9;                // channel2 output PWM pin

const byte strb0Pin = 4;              // channel0 STRB enable pin
const byte strb1Pin = 7;              // channel1 STRB enable pin
const byte strb2Pin = 8;              // channel2 STRB enable pin

// TODO reserve pins 2 & 3 for hardware interrupts

const char swVer[]="0.02a - Alpha";  //ethernet software version number
const char fwVer[]="010-100";        //controller firmware version number
const char serialNum[]="000001";     //controller serial number


//constants used to identify EEPROM addresses
const int CH_ID_ADDR = 0;            // pointer to the EEPROM address used to store the user channel settings
const int R_PIN_ADDR = 1;            // the EEPROM address used to store the pin
const int G_PIN_ADDR = 2;            // ""
const int B_PIN_ADDR = 3;            // ""
const int CH_INTERVAL_ADDR = 4;      // the EEPROM address used to store the interval

const int IP_ADDR_ID = 5;            //pointer to the EEPROM address used to store the user IP ADDRESS
const int IP_ADDR[] = {
 6,7,8,9};

//FUNCTIONS*********

//------------------------------setChannelPower--------------------------------------
void setChannelPower()
{
 analogWrite(ch0Pin, r);
 analogWrite(ch1Pin, g);
 analogWrite(ch2Pin, b);
 delay(5);
 // analogWrite(ch3Pin, w);       //remnant from 4 channels
 // delay(5);

 EEPROM.write(CH_ID_ADDR, 0x99);
 EEPROM.write(R_PIN_ADDR, r);
 EEPROM.write(G_PIN_ADDR, g);
 EEPROM.write(B_PIN_ADDR, b);
 delay(5);
}

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

//------------------------------setMode----------------------------------------------
void setMode()
{
 //TODO: add continuous and strobe modes
 // User will switch between modes using software
 // strobe mode will need to shut off the light and enable
 //the high current sense resistor
}
//-----------------------------------------------------------------------------------

//------------------------------setFactoryDefault------------------------------------
void setFactoryDefault()
{
 //TODO: add code to write all 0x00 to EEPROM
 // When controller first boots, it will set default values when it sees that
 // EEPROM_IDs are 00 and assign default variables accordingly

 for(unsigned int i = 0; i < 512; i++)
 {
   EEPROM.write(i, 0x00);
 }
}  
//----------------------------------------------------------------------------------

//-----------------------------configureDHCP----------------------------------------

/* void configureDHCP()
{
// start the Ethernet connection:
if (Server.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
for(;;)
;
}
// print your local IP address:
Serial.print("My IP address: ");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(".");
}
Serial.println();
*/

//-----------------------------displayInfo------------------------------------------

void displayInfo()
{

 Serial.print("\n<Channel Settings>");    
 Serial.println();  
 Serial.print("Channel 0: ");
 Serial.println(r,DEC);
 Serial.print("Channel 1: ");
 Serial.println(g,DEC);
 Serial.print("Channel 2: ");
 Serial.println(b,DEC);


 Serial.print("\n<TCP/IP settings>");    
 Serial.println();
 Serial.print("IP Address: ");
 for (byte i = 0; i <4; i++)
 {
   Serial.print(default_ip[i], DEC);    
   Serial.print(".");
 }

 Serial.println();
 Serial.print("Gateway: ");
 for (byte i = 0; i <4; i++)
 {
   Serial.print(default_gate[i], DEC);    
   Serial.print(".");

 }  
 Serial.println();
 Serial.print("Subnet: ");
 for (byte i = 0; i <4; i++)
 {
   Serial.print(default_subnet[i], DEC);    
   Serial.print(".");

 }
 Serial.println();

 Serial.print("\n<Hardware Information>");
 Serial.println();
 // Serial.println("Software Version: ");
 // Serial.print(swVer);
 Serial.print("Firmware Version: ");
 Serial.println(fwVer);
 Serial.print("Serial Number: ");
 Serial.println(serialNum);



 //TODO-- add more stuff to display here

}
//----------------------------------------------------------------------------------

//*******************************SETUP**********************************************

void setup()
{
 Serial.begin(115200);

 //read EEPROM and determine if channel data and setup data has been written
 //
 byte id = EEPROM.read(CH_ID_ADDR);     // read the first byte from the EEPROM
 if( id == CH_EEPROM_ID)                //looks for 0x99 in ID_ADDR 0
 {
   // here if the id value read matches the value saved when writing eeprom
   Serial.println("Using channel data from EEPROM");

   r = EEPROM.read(R_PIN_ADDR);
   g = EEPROM.read(G_PIN_ADDR);
   b = EEPROM.read(B_PIN_ADDR);

   delay(50);

   analogWrite(ch0Pin, r);    //write EEPROM channel data to output pins
   analogWrite(ch1Pin, g);
   analogWrite(ch2Pin, b);


 }
 else
 {
   // here if the ID is not found,  write the default data
   Serial.println("Writing default channel data to controller");
   analogWrite (ch0Pin, 255);            //default is 255 = 100% output
   analogWrite (ch1Pin, 255);
   analogWrite (ch2Pin, 255);
   // analogWrite (ch3Pin, 255);          //channel 4 remnant

 }

 Ethernet.begin(mac, default_ip);
 server.begin();
 displayInfo();


}

Loop

Code: [Select]

//***************************************LOOP**********************************************
void loop()
{
 // Serial.println(str);

 //   Serial.print("freeMemory()=");
 //   Serial.println(freeMemory());
 //   delay(2000);


 int bufLength;
 Client client = server.available();
 if (client) {
   boolean current_line_is_blank = true;
   while (client.connected()) {
     if (client.available()) {
       char c = client.read();
       if (inString.length() < maxLength) {
         //inString.append(c);
         inString += c;
       }      

       if (c == '\n' && current_line_is_blank) {
         if (inString.indexOf("?") > -1) {
           int Pos_r = inString.indexOf("r");
           int Pos_g = inString.indexOf("g", Pos_r);
           int Pos_b = inString.indexOf("b", Pos_g);
           int End = inString.indexOf("H", Pos_b);
           if(End < 0){
             End =  inString.length() + 1;
           }
           bufLength = ((Pos_g) - (Pos_r+2));
           if(bufLength > 4){  //dont overflow the buffer
             bufLength = 4;
           }    
           inString.substring((Pos_r+2), (Pos_g-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
           r = atoi(colorBuff);
           bufLength = ((Pos_b) - (Pos_g+2));
           if(bufLength > 4){  //dont overflow the buffer
             bufLength = 4;
           }      
           inString.substring((Pos_g+2), (Pos_b-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
           g = atoi(colorBuff);
           bufLength = ((End) - (Pos_b+2));
           if(bufLength > 4){  //dont overflow the buffer
             bufLength = 4;
           }      
           inString.substring((Pos_b+2), (End-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
           b = atoi(colorBuff);



           /* remnant from having 4 channels
            if (c == '\n' && current_line_is_blank) {
            if (inString.indexOf("?") > -1) {
            int Pos_r = inString.indexOf("r");
            int Pos_g = inString.indexOf("g", Pos_r);
            int Pos_b = inString.indexOf("b", Pos_g);
            int Pos_w = inString.indexOf("w", Pos_b);
            int End = inString.indexOf("H", Pos_w);
            if(End < 0){
            End =  inString.length() + 1;
            }
            bufLength = ((Pos_g) - (Pos_r+2));
            if(bufLength > 5){  //dont overflow the buffer
            bufLength = 5;
            }    
            inString.substring((Pos_r+2), (Pos_g-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            r = atoi(colorBuff);
            bufLength = ((Pos_b) - (Pos_g+2));
            if(bufLength > 5){  //dont overflow the buffer
            bufLength = 5;
            }      
            inString.substring((Pos_g+2), (Pos_b-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            g = atoi(colorBuff);
            bufLength = ((Pos_w) - (Pos_b+2));
            if(bufLength > 5){  //dont overflow the buffer
            bufLength = 5;
            }      
           
            inString.substring((Pos_b+2), (Pos_w-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            b = atoi(colorBuff);
            bufLength = ((End) - (Pos_w+2));
            if(bufLength > 5){  //dont overflow the buffer
            bufLength = 5;
            }  
            inString.substring((Pos_w+2), (End-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            w = atoi(colorBuff);
            //    if(bufLength > 5){  //dont overflow the buffer
            //      bufLength = 5;
            */


         }

         client.println("<html>");
         client.println("<head>");
         client.print("<title> LEDLink GUI</title>");
         client.println("</head>");

         client.println();
         client.println("<body>");

         //         client.println("<center>");
         client.print("<h2><font face=verdana color=green>LEDLink</font></h2>   ");
         client.println();

         client.print("<font face=verdana>");
         client.print("<h3><a href=\"http://www.advill.com\"<"
           "target=\"_blank\">Advanced Illumination</a></h3>");
         //          client.println("</center>");
         client.println();


         client.println("<fieldset style=width:275>");
         client.println("<legend>Channel Settings</legend>");
         client.println("<table>");
         client.println("<tr></td>Enter Values 0-255<td></tr></td>");

         client.println();
         client.println("<br>");
         client.println("<br>");


         client.println("<tr><td><form method=get>Channel 0: <input type=text size=10 name=r />""</tr></td>");
         client.println("<tr><td><form method=get>Channel 1: <input type=text size=10 name=g />""</tr></td>");
         client.println("<tr><td><form method=get>Channel 2: <input type=text size=10 name=b />""</tr></td>");
         //        client.println("<tr><td><form method=get>Channel 3: <input type=text size=10 name=w/>""</tr></td>");

         client.println("<tr><td>&nbsp;<input name=H type=submit value=Program align=RIGHT></form></tr></table>");

         setChannelPower();

         // TODO: Move this to a function to set channel power
         // function should check for value between 0-255
         // if >255, set value to 255

         client.println("</fieldset>");
         client.println("<br>");
         client.println();


         client.println("<fieldset style=width:275>");
         client.println("<legend>Status/Information</legend>");
         client.println("<br>");
         client.println();


         client.println("Channel 0:    ");
         client.print(r,DEC);
         client.println("<br>");
         client.println();

         client.println("Channel 1:    ");
         client.print(g,DEC);
         client.println("<br>");
         client.println();

         client.println("Channel 2:    ");
         client.print(b,DEC);
         client.println("<br>");
         client.println();
         client.println("<br>");
         client.println();

         /*          
          client.println("Channel 3:    ");
          client.print(w);
          client.println("<br>");
          client.println();
          client.println("<br>");
          client.println();
          */

         client.println(" Software Version: ");
         client.print(swVer);
         client.println("<br>");
         client.println();

         client.println(" Firmware Version: ");
         client.print(fwVer);
         client.println("<br>");
         client.println();


         client.println(" Serial Number: ");
         client.print(serialNum);
         client.println("<br>");
         client.println();


         client.println("</fieldset>");
         client.print("</font>");

         client.println("</body></html>");
         break;
       }
       if (c == '\n') {
         current_line_is_blank = true;
       }
       else if (c != '\r') {
         current_line_is_blank = false;
       }
     }
   }
   delay(1);
   inString = "";
   client.stop();


 }
}

PaulS

Code: [Select]
            bufLength = ((Pos_g) - (Pos_r+2));
What happens here if Pos_g or Pos_r is -1?

Code: [Select]
            inString.substring((Pos_r+2), (Pos_g-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
Or here? Or the other places where you do not properly check the values used in the substring() function?

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy