Ethernet Shield, Servo control with textfield in webpage

Hey,

I try to hook up a servo to an ethernet shield because I want to control the servo with an textfield over the internet. Since I am new to the ethernet shield I still have some problems regarding the code.

I manage to put up a string i.e. 192.168.0.3/?servo=123 by using the GET command but I have some problems reading it with the arduino and put it in an int. In the end I want the arduino to read sthg like: int servo = 123 which i can send to the servo. Is there any easy way to do this?

I was also thinking of some read command which searches the readString for “?servo=” and puts whatever comes afterwards in a special variable. do you know any special command for this? After this I also want to light an LED while doing this so dont mind the LED parts.

Thanks in advance!

#include <SPI.h>  
#include <Ethernet.h>
#include <Servo.h> 
 
byte mac[] = { 0x54, 0x55, 0x58, 0x10, 0x00, 0x24 };  
byte ip[]  = { 192, 168, 0, 3 };                  
byte subnet[]  = { 255, 255, 255, 0 };

EthernetServer server(80);
Servo myservo;

int Pin3 = 3;
char Data[4];
int i;
int x;
int servo;
String readString=String(100);      // string for fetching data from address

void setup(){
  
Ethernet.begin(mac, ip, subnet);
server.begin();
myservo.attach(9);
pinMode(Pin3, OUTPUT);
Serial.begin(9600); }

void loop(){
EthernetClient client = server.available();
if (client) 
{
while (client.connected()) 
{
if (client.available()) 
{
char c = client.read();
if (readString.length() < 100) {readString = readString + c;}
if (c == '\n') 
{  
Serial.print(readString); //I get something like "100GET ?servo=xxx" Where does the 100 come from?
do { 
if(readString>0)
{ Data[x] = readString[x+13]; i++; } //Problem is probably here! :)
}
while(x<4);
x=0;
servo = atof(Data);
Serial.print("Received: ");
Serial.print(servo);
Serial.println();
myservo.writeMicroseconds(servo);     
delay(1000);    
myservo.writeMicroseconds(1400);  
} 

/*if(readString.indexOf("") > -1){
 digitalWrite(Pin3, LOW);
 Serial.println("LED off");
 Pin3ON = false;
}
*/


//--------------------------HTML------------------------
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><head>");
client.print("<title>Servotest</title>");
client.println("</head>");
client.print("<body bgcolor='#444444'>");
client.println("
<hr />");
client.println("<h1><div align='center'><font color='#2076CD'>Servotest</font color></div></h1>");
client.println("<hr />
");
client.println("<tr bgColor='#222222'>");
client.println("<td bgcolor='#222222'><font face='Verdana' color='#CFCFCF' size='2'>Servo Test
</font></td>");
client.println("<td align='center' bgcolor='#222222'><form method=get><input type='text' name='servo'><input type='submit' value='Drehen'></form></td>");
client.println("<td align='center' bgcolor='#222222'><form method=get><input type=submit name='servo' value='90'></form></td>");
client.println("<td align='center'><font color='green' size='5'>Servovalue: ");
client.print(servo);
client.println("</tr>");
client.println("</tr>");
client.println("</table>");
client.println("</body></html>");
readString="";
client.stop();
}}}}
String readString=String(100);      // string for fetching data from address

This is creating a String object bu converting the value 100 to a string, and then wrapping that string in the String object. It then copies that String to readString, wasting more memory. What did you think it was doing?

Serial.print(readString); //I get something like "100GET ?servo=xxx" Where does the 100 come from?

Well, now you know.

do { 
if(readString>0)
{ Data[x] = readString[x+13]; i++; } //Problem is probably here! :)
}
while(x<4);

A for loop is so much easier to understand…

If you printed out Data after filling it, you’d see that it contained ‘=’, ‘x’, ‘x’, and ‘x’. Which, by the way, is not the same as “=xxx”.

servo = atof(Data);

The atof() function (Why are you converting what you expect to be an int to a float?) expects a NULL terminated array of characters. You are not passing it a NULL terminated array of characters.

I was also thinking of some read command which searches the readString for “?servo=”

Like maybe String::indexOf()?

and puts whatever comes afterwards in a special variable.

An ordinary variable won’t do?

Thanks!

I rewrote some parts after I found out about the indexof command… Its still not working thou… do you know why ServoString is empty?

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

byte mac[] = { 0x54, 0x55, 0x58, 0x10, 0x00, 0x24 }; 
byte ip[]  = { 192, 168, 0, 3 };                 
byte subnet[]  = { 255, 255, 255, 0 };

EthernetServer server(80);
Servo myservo;

int Pin3 = 3;
int servo;
String readString;
String InputString;      
String ServoString;
int ind1 = 0;
int ind2 = 0;
int pos = 0;


void setup(){
  
Ethernet.begin(mac, ip, subnet);
server.begin();
myservo.attach(9);
pinMode(Pin3, OUTPUT);
Serial.begin(9600); }

void loop(){
EthernetClient client = server.available();
if (client) 
{
while (client.connected()) 
{
if (client.available()) 
{
char c = client.read();
if (readString.length() < 100) {readString = readString + c;}
if (c == '\n') 
{  
  ind1 = readString.indexOf("=");
  ServoString = readString.substring(ind1, ind1+4);
  Serial.println(ServoString);
    }
  }

/*if(readString.indexOf("") > -1){
 digitalWrite(Pin3, LOW);
 Serial.println("Alles ausgeschaltet");
 Pin3ON = false;
}
*/


//--------------------------HTML------------------------
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><head>");
client.print("<title>Servotest</title>");
client.println("</head>");
client.print("<body bgcolor='#444444'>");
client.println("
<hr />");
client.println("<h1><div align='center'><font color='#2076CD'>Servotest</font color></div></h1>");
client.println("<hr />
");
client.println("<tr bgColor='#222222'>");
client.println("<td bgcolor='#222222'><font face='Verdana' color='#CFCFCF' size='2'>Servo Test
</font></td>");
client.println("<td align='center' bgcolor='#222222'><form method=get><input type='text' name='servo'><input type='submit' value='Drehen'></form></td>");
client.println("<td align='center' bgcolor='#222222'><form method=get><input type=submit name='servo' value='90'></form></td>");
client.println("<td align='center'><font color='green' size='5'>Servovalue: ");
client.print(ServoString);
client.println("</tr>");
client.println("</tr>");
client.println("</table>");
client.println("</body></html>");

InputString="";
ServoString="";
readString="";  

client.stop();
}}}

do you know why ServoString is empty?

Because readString doesn't contain an = sign? I don't know. I can't see that you are printing readString, or what you are doing to cause readString to be valued. You've got to help out a little...

And to preempt the next problem - As you are running a shield and a servo, you should consider separate power as this will likely cause you problems soon if not already.

See the links in my signature for a demonstration why

Duane B

rcarduino.blogspot.com

Ah, ok sry I mean this part:
it looks like I dont get any chars in readString but I dont know where i did the mistake… :frowning:

void loop(){
EthernetClient client = server.available();
if (client) 
{
while (client.connected()) 
{
if (client.available()) 
{
char c = client.read();
if (readString.length() < 100) readString = readString + c; //read chars one by one and store them in readString
if (c == '\n') //...till the end of line 
{  
  Serial.println(readString); //I forgot this in my previous post
  ind1 = readString.indexOf("=");
  ServoString = readString.substring(ind1, ind1+4); //I wonder if thats going to work :-P
  Serial.println(ServoString);
    }
  }

it looks like I dont get any chars in readString

Then, you need to figure out why.

if (readString.length() < 100) readString = readString + c; //read chars one by one and store them in readString

This implies that you have a maximum length command in mind. In which case, you should ditch the String class, and use a static char array. If you persist in this folly (and you might be able to), at least minimize the amount of thrashing that goes on by using the += operator.

readString += c;

Snippets don’t tell us anything.

But, before you paste any more code, use the Tools + Auto Format option. That random indenting is quite unprofessional.

I got it working, this is the code…
thanks for the help!

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

byte mac[] = { 
  0x54, 0x55, 0x58, 0x10, 0x00, 0x24 }; 
byte ip[]  = { 
  192, 168, 0, 3 };                 
byte subnet[]  = { 
  255, 255, 255, 0 };

EthernetServer server(80);
Servo myservo;

int Pin3 = 3;
int servo;
String readString;
String InputString;    
String ServoString;
String OutputString;
int ind1 = 0;
int ind2 = 0;
boolean error = false;

void setup(){

  Ethernet.begin(mac, ip, subnet);
  server.begin();
  myservo.attach(9);
  pinMode(Pin3, OUTPUT);
  Serial.begin(9600); 
}

void loop(){
  EthernetClient client = server.available();
  if (client) 
  {
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        if (readString.length() < 100) {
          readString = readString + c;
        }
        if (c == '\n') {  
          Serial.println(readString);
          ind1 = readString.indexOf("=");
          ind2 = readString.indexOf("&");
          ServoString = readString.substring(ind1+1, ind2);
          char servochar[ServoString.length()];
          ServoString.toCharArray(servochar, ServoString.length()+1);
          servo = atof(servochar);
          if (servo >= 500 && servo <= 2700) {
            myservo.writeMicroseconds(servo);
            OutputString = ServoString; 
          } 
          else {
            OutputString ="Type in a value between 500 and 2700";
          }


          //--------------------------HTML------------------------
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          client.print("<html><head>");
          client.print("<title>Hendrik's Servotest</title>");
          client.println("</head>");
          client.print("<body bgcolor='black'>");
          client.println("
<hr />");
          client.println("<h1><div align='center'><font color='#FFFFFF'>Servotest</font color></div></h1>");
          client.println("<hr />
");
          client.println("<tr bgColor='#222222'>");
          client.println("<td bgcolor='#222222'><font face='Verdana' color='#FFFFFF' size='2'>Type in value between 500 and 2700  microseconds
</font></td>");
          client.println("<td align='center' bgcolor='#222222'><form method=get><input type='text' name='servo'><input type='hidden' name='!'><input type='submit' value='Turn'></form></td>");
          client.println("<td align='center' bgcolor='#222222'><form method=get><input type='hidden' name='servo' value='1500'><input type='hidden' name='!'><input type='submit' value='1500'></form></td>");
          client.println("<td align='center'><font color='green' size='5'>Servovalue: ");
          client.print(OutputString);
          client.println("</tr>");
          client.println("</tr>");
          client.println("</table>");
          client.println("</body></html>");

          InputString="";
          ServoString="";
          readString="";  

          client.stop();
        }
      }
    }
  }
}
          ind1 = readString.indexOf("=");
          ind2 = readString.indexOf("&");
          ServoString = readString.substring(ind1+1, ind2);
          char servochar[ServoString.length()];
          ServoString.toCharArray(servochar, ServoString.length()+1);
          servo = atof(servochar);

Suppose readString does not contain = or &. Then, what was it you just stuffed into ServoString?

Why are you converting the value to a float, and then storing the resulting float in an int? You got something against atoi()?