Go Down

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

jstamour802

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


jstamour802

#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();


}

jstamour802

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