Webserver with leds switching off automatically after clicking

Hello all,

I.m trying to setup a simple webserver with about 20x2 buttons to switch 20 track changers (don't know the exact word for it) in a model railway. I used some code I found on internet and changed it to how I want it to work but it doesn't work like I want it (-; . It is not switching 1 but 2 pins. Can someone have a look at what I have been doing wrong? Thanks in advance... Also I can use some help on adding the code.

If you share neither your code nor your circuitry, how are we supposed to help?

//zoomkat 8-04-12
//simple button GET server code to control servo and arduino pins 5, 6, 7 and 8
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use ' instead of " in the html 
//address will look like http://192.168.177.250:80 when submited
//for use with W5100 based ethernet shields
///note that the below bug fix may be required
// http://code.google.com/p/arduino/issues/detail?id=605 

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 177, 250 }; // ip in lan
EthernetServer server(80); //server port

String readString; 

//////////////////////

void setup(){

  pinMode(5, OUTPUT); //pin selected to control
  pinMode(6, OUTPUT); //pin selected to control
  pinMode(7, OUTPUT); //pin selected to control
  pinMode(8, OUTPUT); //pin selected to control
  pinMode(22, OUTPUT); //pin selected to control
  pinMode(23, OUTPUT); //pin selected to control
  pinMode(24, OUTPUT); //pin selected to control
  pinMode(25, OUTPUT); //pin selected to control  
  //start Ethernet
  Ethernet.begin(mac, ip);
  server.begin();

  //enable serial data print 
  Serial.begin(9600); 
  Serial.println("server multi pin button test 1.0"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string 
          readString += c; 
          //Serial.print(c);
        } 

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging 

          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();

          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<TITLE>Wisselschakelaarpagina</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");

          //client.println("<H1>Zoomkat's simple Arduino button</H1>");
          
          // For simple testing, pin 5, 6, 7, and 8 are used in buttons
          // DIY buttons
          client.println("<p></p>");
          client.println("<a href=/?on2 >W 1 rechtuit</a>"); 
          client.println("<a href=/?on4 >W 1 afslaan</a>");
          //client.println("<p>Wissel 2</p>"); 
          client.println("<a href=/?on6 >W 2 rechtuit</a>");
          client.println("<a href=/?on8 >W 2 afslaan</a>");
          //client.println("<p></p>");
          client.println("<a href=/?on10 >W 3 rechtuit</a>"); 
          client.println("<a href=/?on12 >W 3 afslaan</a>");
          //client.println("<p></p>"); 
          client.println("<a href=/?on14 >W 4 rechtuit</a>");
          client.println("<a href=/?on16 >W 4 afslaan</a>");                     

          client.println("</BODY>");
          client.println("</HTML>");
 
          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf('2') >0)//checks for 2
          {
            digitalWrite(5, HIGH);    // set pin 5 high
            Serial.println("Led 5 On");
            delay(500);
            digitalWrite(5,LOW);
          }
          
          if(readString.indexOf('4') >0)//checks for 4
          {
            digitalWrite(6, HIGH);    // set pin 6 high
            Serial.println("Led 6 On");
            delay(500);
            digitalWrite(6,LOW);            
          }
          
           if(readString.indexOf('6') >0)//checks for 6
          {
            digitalWrite(7, HIGH);    // set pin 7 high
            Serial.println("Led 7 On");
            delay(500);
            digitalWrite(7,LOW);            
          }
          
            if(readString.indexOf('8') >0)//checks for 8
          {
            digitalWrite(8, HIGH);    // set pin 8 high
            Serial.println("Led 8 On");
            delay(500);
            digitalWrite(8,LOW);
          }
          if(readString.indexOf('10') >0)//checks for 10
          {
            digitalWrite(22, HIGH);    // set pin 5 high
            Serial.println("Led 22 On");
            delay(500);
            digitalWrite(22,LOW);
          }
          
          if(readString.indexOf('12') >0)//checks for 12
          {
            digitalWrite(23, HIGH);    // set pin 6 high
            Serial.println("Led 23 On");
            delay(500);
            digitalWrite(23,LOW);            
          }
          
           if(readString.indexOf('14') >0)//checks for 14
          {
            digitalWrite(24, HIGH);    // set pin 7 high
            Serial.println("Led 24 On");
            delay(500);
            digitalWrite(24,LOW);            
          }
          
            if(readString.indexOf('16') >0)//checks for 16
          {
            digitalWrite(25, HIGH);    // set pin 8 high
            Serial.println("Led 25 On");
            delay(500);
            digitalWrite(25,LOW);
          }          

             
          //clearing string for next read
          readString="";

        }
      }
    }
  }
}

Didn't understand how to add the code but the forum is helpfull

String readString="";

If you send, for example, a "14", this will also be true:

          if(readString.indexOf('4') >0)//checks for 4

After all, 14 does contain a 4.

So this way you can't create 40 buttons?

No, you have to do proper string equality checks.

readString.indexOf('10')

10 is not a symbol. change ' to "

I.m totally newbie and only looking for this to get working. How does one do the checks or isn't there a simple answer for that?

//zoomkat 8-04-12
//simple button GET server code to control servo and arduino pins 5, 6, 7 and 8
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use ' instead of " in the html
//address will look like http://192.168.177.250:80 when submited
//for use with W5100 based ethernet shields
///note that the below bug fix may be required
// http://code.google.com/p/arduino/issues/detail?id=605

#include <SPI.h>
#include <Ethernet.h>

const byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
const byte ip[] = { 192, 168, 177, 250 }; // ip in lan
EthernetServer server(80); //server port
String readString = "";
const byte Pages = 8;
const byte PageToPins[Pages][2] = {
  2, 5,
  4, 6,
  6, 7,
  8, 8,
  10, 22,
  12, 23,
  14, 24,
  16, 25
};
//////////////////////

void setup() {
  pinMode(5, OUTPUT); //pin selected to control
  pinMode(6, OUTPUT); //pin selected to control
  pinMode(7, OUTPUT); //pin selected to control
  pinMode(8, OUTPUT); //pin selected to control
  pinMode(22, OUTPUT); //pin selected to control
  pinMode(23, OUTPUT); //pin selected to control
  pinMode(24, OUTPUT); //pin selected to control
  pinMode(25, OUTPUT); //pin selected to control
  //start Ethernet
  Ethernet.begin(mac, ip);
  server.begin();

  //enable serial data print
  Serial.begin(9600);
  Serial.println("server multi pin button test 1.0"); // so I can keep track of what is loaded
}

void loop() {
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string
          readString += c;
          //Serial.print(c);
        }

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging

          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();
          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<TITLE>Wisselschakelaarpagina</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");

          //client.println("<H1>Zoomkat's simple Arduino button</H1>");

          // For simple testing, pin 5, 6, 7, and 8 are used in buttons
          // DIY buttons
          client.println("<p></p>");
          client.println("<a href=/?on2 >W 1 rechtuit</a>");
          client.println("<a href=/?on4 >W 1 afslaan</a>");
          //client.println("<p>Wissel 2</p>");
          client.println("<a href=/?on6 >W 2 rechtuit</a>");
          client.println("<a href=/?on8 >W 2 afslaan</a>");
          //client.println("<p></p>");
          client.println("<a href=/?on10 >W 3 rechtuit</a>");
          client.println("<a href=/?on12 >W 3 afslaan</a>");
          //client.println("<p></p>");
          client.println("<a href=/?on14 >W 4 rechtuit</a>");
          client.println("<a href=/?on16 >W 4 afslaan</a>");

          client.println("</BODY>");
          client.println("</HTML>");

          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          for (byte i = 0; i < Pages; i++) {
            if (readString.indexOf((String)PageToPins[i][0]) > 0) {
              digitalWrite(PageToPins[i][1], HIGH);
              Serial.print("LedOn ");
              Serial.println(PageToPins[i][1]);
              delay(500);
              digitalWrite(PageToPins[i][1], LOW);
            }
          }
          readString = "";  //clearing string for next read
        }
      }
    }
  }
}

Given that "readString" contains an entire HTTP request, extracting the switch id from it is not exactly trivial but something like this might do (put this directly after "client.stop()"):

int firstLineEnd = readString.indexOf("\n");
if (firstLineEnd <= 0) {
    firstLineEnd = readString.length();
}
// readString will look like this: "GET /?on2"
string pointsId = readString.substr(8, firstLineEnd);

Then, change all the "if" conditions from that point on to look like this:

if (pointsId == "2") {

instead of this:

if (readString.indexOf('2') > 0) {

(Code is untested, may have off-by-one errors)

Also, please just ignore kolaha's code, I am pretty certain it'll show the exact same bug as your current code does.)

Hi Taschi,

Thanks for your effort! I added the adjusted code according to your message. I get the following error:

Arduino:1.8.13 (Windows 10), Board:"Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)"

C:\Users\Ernie\Documents\Arduino\hopelijk-simpeler\hopelijk-simpeler.ino: In function 'void loop()':

hopelijk-simpeler:101:39: error: 'class String' has no member named 'substr'; did you mean 'c_str'?

          String pointsId = readString.substr(8, firstLineEnd);

                                       ^~~~~~

                                       c_str

exit status 1

'class String' has no member named 'substr'; did you mean 'c_str'?

The other code of Kaloha was giving the same errors as my original code however adjusting and tweaking it a bit gave me 10 pins I could use. (But I want 40 (-; )



Dit rapport zou meer informatie bevatten met
"Uitgebreide uitvoer weergeven tijden compilatie"
optie aan in Bestand -> Voorkeuren.

Seems like you need to use "substring" instead of "substr", sorry!

Hello Taschi,

Checking the serial output when clicking on the first button of the webpage gives an: GET /?on2 HTTP/1.1 etc.etc . Unfortunately no Leds are working now but the problem with the substring is solved. Looks like the Arduino doesn't respond or receive the code correctly.

Right, I assumed that the first line of the request would just be "GET /?on2". Usually I have at least some kind of parser between me and raw HTTP requests so I don't know off the top of my head how to "manually" parse them.

Try this on for size:

// readString will look like this: "GET /?on2 HTTP/1.1"
int endOfUrl = readString.indexOf("HTTP") - 1;
string pointsId = readString.substr(8, endOfUrl);

(What this code is doing - or at least what it is supposed to do - is just extract the switch/points number from the HTTP request.)

Hi Taschi,

Works like a charm!! Can I extend this code to 40 pins? If so what is important to keep in mind. Again many thanks!

I suppose you can, as long as your Arduino has at least 40 output pins. This code should work as long as all your URLs (in the <a href=...> tags) are formatted as /onXXX, with XXX being any number (letters probably also would work).

In this line

string pointsId = readString.substring(8, endOfUrl);

the 8 tells the substring function to ignore the first 8 characters of "readString". So, if your HTTP request looks like GET /?on17 HTTP/1.1, it just ignores everything before the 17. If you change those URLs, you also need to change the substring call's parameters to match it.

You may also want to use an array or map to define which switch corresponds to which I/O pin, so you don't duplicate the same code over and over again, but that's an advanced topic.

Ok, great. I will proceed tomorrow and will follow your instructions. Thanks again and goodnight!

Hi Taschi,

Thanks for helping me with the code and the good explanation. I managed to change the buttons and replicate the code so I have added more buttons.

Groet,
Ernie