Arduino + Wishield + Servos

Hi, I posted this in the hardware section but couldn't get a reply for the past few days. Sorry for posting again but thought I might have better luck on here.

here is my original post.


Hi,

Anyone have any experience with this combination?..

Essentially I want the Arduino to act like a webserver with the help of the Wishield. With this I want to create a website with buttons to control the servos. Thing is the Wishield and the Arduino seem to work but when I add the Servos to the Arduino using the Wishield extender pins and upload Servo code to the Arduino the Wishield stops working. I am using a breadboard for all the wiring.

I have concluded that this might be due to the fact that I am uploading Servo and Webserver code seperately to the Arduino. Am I correct in saying that this renders one these components i.e. the servos or the Wishield to not work as the previous code on the Arduino gets deleted/replaced?. Is it possible to merge Servo and Webserver code into the same sketch and upload it?

P.S. I have tried merging the two codes and it didn't work for me. I believe this is due to me being a complete newbie at programming.

Any help would be greatly appreciated.


I have concluded that this might be due to the fact that I am uploading Servo and Webserver code seperately to the Arduino. Am I correct in saying that this renders one these components i.e. the servos or the Wishield to not work as the previous code on the Arduino gets deleted/replaced?. Is it possible to merge Servo and Webserver code into the same sketch and upload it?

Yes, that is correct and yes it will be.

If you can post the merged code that you tried then we could have a looksie and try to work out why it is not working for you.

Mowcius

Hi,

Thanks for the reply.

Here is the codes that I merged together. I tried to merge the servo code into the Webserver files and upload it at once to the Arduino but it didn’t work.


The following is the WebServer.pde and the webserver.c files. Both these files are in one sketch


WebServer.pde

/*
 * Web Server
 *
 * A simple web server example using the WiShield 1.0
 */
#include <Servo.h> // Included to make the servos turn 
Servo leftServo; // Telling the above library we have this servo 
Servo rightServo; // Telling the above library we have this servo

#include <WiShield.h>

#define WIRELESS_MODE_INFRA      1
#define WIRELESS_MODE_ADHOC      2

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {192,168,1,200};      // IP address of WiShield
unsigned char gateway_ip[] = {192,168,1,254};      // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0};      // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"BeBox"};            // max 32 bytes

unsigned char security_type = 0;      // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"14CCAACB88"};      // max 64 characters

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = {      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,      // Key 0
                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      0x00,      // Key 1
                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      0x00,      // Key 2
                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      0x00      // Key 3
                                                };

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
//---------------------------------------------------------------------------

    void setup()
    {
          WiFi.init();
    
    leftServo.attach(5); // Enables the use of this servo  
      rightServo.attach(6); // Enables the use of this servo 
    }
    
    // This is the webpage that is served up by the webserver
    const prog_char webpage[] PROGMEM = {"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<center><h1>Hello World!! I am WiShield</h1><form method=\"get\" action=\"0\">Toggle LED:<input type=\"submit\" name=\"0\" value=\"LED1\"></input></form></center>"};
    
    void loop()
    {
      WiFi.run();
        int choice = random(2); // Declare a random 1 or 2 number  
        int duration = random(2000); // Declare a random number between 1 and 2000

        goForward(); // Use the goForward code below  
        delay(duration); // Use a delay that turns the servos for the random duration in milliseconds 
      
        // After the above delay has finished let's turn the robot  
        if (choice == 1) // If the random number is 1 then go right  
          { 
            goLeft(); // Use the goLeft code below  
          } 
          
          else // If the random number is not 1 it must be 2 so...  
            { 
              goRight(); // Use the goRight code below  
            } 
    
      delay(duration); // Use a delay that turns the servos for the random duration in milliseconds  

    }
    
    void goForward() // This makes the bot go forward by turning a servo: 
    { 
    
      leftServo.write(110); // One way  
      rightServo.write(50); // And the other way 
    } 
    
    void goRight() // This makes the bot turn by making the servos: 
    { 
      leftServo.write(50); // Turn the same way lower than 90 (center) 
      rightServo.write(50); // Turn the same way lower than 90 (center) 
    } 
    
    void goLeft() // This makes the bot turn by making the servos: 
    { 
      leftServo.write(110); // Turn the same way higher than 90 (center) 
      rightServo.write(110); // Turn the same way higher than 90 (center) 
    }

webserver.c

/******************************************************************************

  Filename:            webserver.h
  Description:      Webserver app for the WiShield 1.0

 ******************************************************************************

  TCP/IP stack and driver for the WiShield 1.0 wireless devices

  Copyright(c) 2009 Async Labs Inc. All rights reserved.

  This program is free software; you can redistribute it and/or modify it
  under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation.

  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  more details.

  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 59
  Temple Place - Suite 330, Boston, MA  02111-1307, USA.

  Contact Information:
  <asynclabs@asynclabs.com>

   Author               Date        Comment
  ---------------------------------------------------------------
   AsyncLabs                  05/29/2009      Initial version

 *****************************************************************************/

#include "uip.h"
#include <string.h>
#include "webserver.h"
#include "config.h"

static int handle_connection(struct webserver_state *s);

void webserver_init(void)
{
      uip_listen(HTONS(80));
}

void webserver_appcall(void)
{
      struct webserver_state *s = &(uip_conn->appstate);

      if(uip_connected()) {
            PSOCK_INIT(&s->p, s->inputbuf, sizeof(s->inputbuf));
      }

      handle_connection(s);
}

#define ISO_nl      0x0a
#define ISO_space   0x20
#define ISO_slash   0x2f

const char http_get[5] = {0x47, 0x45, 0x54, 0x20, };      /* "GET " */

unsigned short fill_buf(void* blk)
{
      unsigned short webpage_len;

      webpage_len = (strlen_P(webpage)>uip_mss())?uip_mss():strlen_P(webpage);

      memcpy_P(uip_appdata, webpage, webpage_len);
      return webpage_len;
}

static int handle_connection(struct webserver_state *s)
{
      PSOCK_BEGIN(&s->p);

      // the incoming GET request will have the following format:
      // GET / HTTP/1.1 ....
      // we have to parse this string to determine the resource being requested
      // if the requested resource is not the root webpage ('/') then,
      // GET /<resource name> HTTP/1.1 ....
      // we should parse the specific resource and react appropriately

      // read incoming data until we read a space character
      PSOCK_READTO(&s->p, ISO_space);

      // parse the data to determine if it was a GET request
      if(strncmp(s->inputbuf, http_get, 4) != 0) {
            PSOCK_CLOSE_EXIT(&s->p);
      }

      // continue reading until the next space character
      PSOCK_READTO(&s->p, ISO_space);

      // determine the requested resource
      // in this case, we check if the request was for the '/' root page
      // AKA index.html
      if(s->inputbuf[0] != ISO_slash) {
            // request for unknown webpage, close and exit
            PSOCK_CLOSE_EXIT(&s->p);
      }

      if(s->inputbuf[1] != ISO_space) {
            // request for unavailable resource
            // not supported, modify to add support for additional resources
            PSOCK_CLOSE_EXIT(&s->p);
      }

      //PSOCK_SEND_STR(&s->p, "HTTP/1.1 200 OK\r\n");
      //PSOCK_SEND_STR(&s->p, "Content-Type: text/html\r\n");
      //PSOCK_SEND_STR(&s->p, "\r\n");
      //PSOCK_SEND_STR(&s->p, "Hello World, I am WiShield");
      //PSOCK_SEND_STR(&s->p, "<center><h1>Hello World!! I am WiShield</h1></center>");
      PSOCK_GENERATOR_SEND(&s->p, fill_buf, 0);
      PSOCK_CLOSE(&s->p);
      PSOCK_END(&s->p);
}

By the way, I know my servo code is lacking. I don’t know how to go about writing code that triggers functions such as left,right,forward and backward at the click of a button.

Please do not PM me when I have not replied. I am notified every time someone replies to a thread I have posted in, I have just been rather busy and was hoping someone else might take a look :P

Anyway now I have a bit more time...

I presume you have been getting some errors. The webserver.c code should stay exactly as it is. Where you have added in new 'program sections' (goLeft(); and goRight() etc) you have to define them in the code.

Below the servo code (Servo rightServo; // Telling the above library we have this servo), you need to define each one by putting

void goLeft();
void goRight();
void goForward();

etc

After that I would need to know what is not working...

Mowcius

Oh ok, sorry mate. It just been quite a while, and I thought you had forgotten. Really, thanks a lot for your help, I'll post back once I have done the changes.

Hi mate I have modified the code to reflect your advice, but can’t really test it as I am getting the following errors -

error: expected constructor, destructor, or type conversion before ‘=’ token In function ‘void setSpeedRight(int)’:
In function ‘void goForward()’:
In function ‘void goBackward()’:
In function ‘void goRight()’:
In function ‘void goLeft()’:


Here is my modified code.


/*
 * Web Server
 *
 * A simple web server example using the WiShield 1.0
 */

#include <WiShield.h>
#define WIRELESS_MODE_INFRA      1
#define WIRELESS_MODE_ADHOC      2
#define FORWARD 70 //F
#define BACKWARD 66 //B
#define LEFT 76 //L
#define RIGHT 82 //R
#define SETSPEED 83 //S
#define STOP 67 //C
#define SETSPEEDLEFT 88 //X
#define SETSPEEDRIGHT 89 //Y

/*The three check bytes (used to keep the robot from responding to random serial *data) currently "AAA" */
#define checkByte1 65 // "A"
#define checkByte2 65 // "A"
#define checkByte3 65 // "A" 

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {192,168,1,2};      // IP address of WiShield
unsigned char gateway_ip[] = {192,168,1,1};      // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0};      // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"ASYNCLABS"};            // max 32 bytes

unsigned char security_type = 0;      // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"12345678"};      // max 64 characters

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = {      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,      // Key 0
                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      0x00,      // Key 1
                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      0x00,      // Key 2
                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      0x00      // Key 3
                                                };

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
//---------------------------------------------------------------------------

// START OF ARDUINO CONTROLLED SERVO ROBOT (SERB) PREAMBLE
#include <Servo.h>
#define LEFTSERVOPIN 5 //The pin the left servo is connected to
#define RIGHTSERVOPIN 6 //The pin the right servo is connected to

Servo leftServo; 
Servo rightServo; 

int leftSpeed = 50;     //holds the speed of the robots leftServo 
                        //a percentage between 0 and 100int 
rightSpeed = 100;       //holds the speed of the robots rightServo 
                        //a percentage between 0 and 100

// END OF ARDUINO CONTROLLED SERVO ROBOT (SERB) PREAMBLE
//--------------------------------------------------------------------------

void setup()
  {
    WiFi.init();
    Serial.begin(9600);   //Starts the serial port 
    serbSetup();          //sets the state of all neccesary 
                          //pins and adds servos to your sketch 
  }

// This is the webpage that is served up by the webserver
const prog_char webpage[] PROGMEM = {"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<center><h1>Hello World!! I am WiShield</h1><form method=\"get\" action=\"0\">Toggle LED:<input type=\"submit\" name=\"0\" value=\"LED1\"></input></form></center>"};

//The main program loop
void loop()
  {
    WiFi.run();
    serbPollSerialPort();   //continuously looks to the serial port 
                            //if there is data it processes it
  }

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

//START OF ARDUINO SERIAL SERVER ROUTINES

/* * Processes commands delivered to the arduino's serial port */
void serbPollSerialPort()
  { 
    int dta; //variable to hold the serial byte 
      if ( Serial.available() >= 5) 
    { 
      //if 5 bytes are in the buffer (length pf a full request) 
      dta = Serial.read(); 
      if ( dta = checkByte1)
      { //Checks for first check byte 
        dta = Serial.read(); 
  
        if ( dta = checkByte2)
        { //Checks for second check byte 
        dta = Serial.read(); 
  
          if ( dta = checkByte3)
          { //Checks for third check byte 
  
            int command = Serial.read(); //Fourth byte is the command 
            int param1 = Serial.read(); //Fifth byte is param1 
            interpretCommand(command, param1); //sends the parsed request to it's handler 
          } 
        } 
      } 
    }
  }

/* * Takes the command and parameter and passes it to the robot */
void interpretCommand(int command, int param1)
  {
    if (command == FORWARD)
      {
        goForward(); 
        delay(param1 * 100); 
        goStop();
      } //if forward
      
      else if(command == BACKWARD)
      {
        goBackward(); 
        delay(param1 * 100); 
        goStop();
      } //if backwards

      else if(command == LEFT)
      {
        goLeft(); 
        delay(param1 * 100); 
        goStop();
      } //if left

      else if(command == RIGHT)
      {
        goRight();
        delay(param1 * 100); 
        goStop();
      } //if right 

      else if(command == SETSPEED)
      {
        setSpeed(param1);
      } //if setting speed 
      
      else if(command == STOP)
      {
        goStop();
      } //if stop 
      
      else if(command == SETSPEEDLEFT)
      {
        setSpeedLeft(param1);
      } //if setting left speed 
      
      else if(command == SETSPEEDRIGHT)
      {
        setSpeedRight(param1);
      } //if setting right speed 

      else
      { //if unrecognized command do a little shimmey 
        goLeft(); 
        delay(150); 
        goRight(); 
        delay(150); 
        goStop(); 
      }
  }

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

//START OF ARDUINO CONTROLLED SERVO ROBOT (SERB) ROUTINES

/* * sets up your arduino to address your SERB using the included routines*/
void serbSetup()
  { 
    setSpeed(leftSpeed); 
    pinMode(LEFTSERVOPIN, OUTPUT); //sets the left servo signal pin 
                                   //to output 
    pinMode(RIGHTSERVOPIN, OUTPUT); //sets the right servo signal pin 
                                    //to output 
    leftServo.attach(LEFTSERVOPIN); //attaches left servo 
    rightServo.attach(RIGHTSERVOPIN); //attaches right servo 
    goStop();
  }

/* * sets the speed of the robot between 0-(stopped) and 100-(full speed) * NOTE: speed will not change the current speed you must change speed * then call one of the go methods before changes occur.*/ 
void setSpeed(int newSpeed)
  { 
    setSpeedLeft(newSpeed); //sets left speed 
    setSpeedRight(newSpeed); //sets right speed
  }

/* * Sets the speed of the left wheel */
void setSpeedLeft(int newSpeed)
  { 
    if(newSpeed >= 100) 
      {
        newSpeed = 100;   //if speed is greater than 100
      }                   //make it 100 if(newSpeed <= 0)
                           
      {
        newSpeed = 0;     //if speed is less than 0 make
      }                   //it 0  
                          
      leftSpeed = newSpeed * 0.9; //between 0 and 90
  }

/* * Sets the speed of the right wheel */
void setSpeedRight(int newSpeed)
  { 
    if(newSpeed >= 100) 
      {
        newSpeed = 100;     //if speed is greater than 100 //make it 100 
      } 
  
    if(newSpeed <= 0) 
      {
        newSpeed = 0;      //if speed is less than 0 make 
      }                    //it 0
    
      rightSpeed = newSpeed * 0.9; //scales the speed to be 
  }
  
/* * sends the robot forwards */
void goForward()
  { 
    leftServo.write(90 + leftSpeed); 
    rightServo.write(90 - rightSpeed);
  } 

/* * sends the robot backwards */
void goBackward()
  { 
    leftServo.write(90 - leftSpeed); 
    rightServo.write(90 + rightSpeed);
  } 

/* * sends the robot right */
void goRight()
  { 
    leftServo.write(90 + leftSpeed);
    rightServo.write(90 + rightSpeed);
  }

/* * sends the robot left */
void goLeft()
  { 
    leftServo.write(90 - leftSpeed); 
    rightServo.write(90 - rightSpeed);
  }

/* * stops the robot */
void goStop()
  { 
    leftServo.write(90); 
    rightServo.write(90);
  }
//END OF ARDUINO CONTROLLED SERVO ROBOT (SERB) ROUTINES//---------------------------------------------------------------------------


Any idea why I am getting these?.. Propably something simple but can’t figure it out.

Thanks.

Nur

[edit]Sorry one more question. Is it true that controlling Servo motors directly on the Arduino pins can cause irreparable damage to it?.. Is it essential to use a Motor Controller?.. I ask because I have seen other projects where they do not use a motor controller for their robots. Does servo.h library/header require a motor controller?.. Sorry that was several questons, lol ;D[/edit]

Ok, I'm not sure what you have done there! It looks like you completely upended your code....

Ok, lets go back to where we were before:

Here is the codes that I merged together. I tried to merge the servo code into the Webserver files and upload it at once to the Arduino but it didn't work.

What did not work with this? What code did you have before you tried to add in the servo code?

Sorry one more question. Is it true that controlling Servo motors directly on the Arduino pins can cause irreparable damage to it?.. Is it essential to use a Motor Controller?.. I ask because I have seen other projects where they do not use a motor controller for their robots. Does servo.h library/header require a motor controller?

Umm, well I never have, running any motor directly from the arduino pins is not a good idea but for your servo you only have the control pin from the arduino. The power pins are from your arduino. Some servos can draw a lot of current requiring you to have them plugged into an external power source as the arduino regulator can only provide 400mA (including what the atmega and FTDI chip, and anything else, use).

Mowcius

Ok, lets go back to where we were before:

> Here is the codes that I merged together. I tried to merge the servo code into the Webserver files and upload it at once to the Arduino but it didn’t work.

What did not work with this?

It compiled but didn’t do anything. Both my Servos and Wishield were non functional.

What code did you have before you tried to add in the servo code?


Here is the original, before adding the Servo code -


/*
 * Web Server
 *
 * A simple web server example using the WiShield 1.0
 */

#include <WiShield.h>

#define WIRELESS_MODE_INFRA      1
#define WIRELESS_MODE_ADHOC      2

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {192,168,1,2};      // IP address of WiShield
unsigned char gateway_ip[] = {192,168,1,1};      // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0};      // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"ASYNCLABS"};            // max 32 bytes

unsigned char security_type = 0;      // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"12345678"};      // max 64 characters

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = {      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,      // Key 0
                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      0x00,      // Key 1
                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      0x00,      // Key 2
                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      0x00      // Key 3
                                                };

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
//---------------------------------------------------------------------------

void setup()
{
      WiFi.init();
}

// This is the webpage that is served up by the webserver
const prog_char webpage[] PROGMEM = {"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<center><h1>Hello World!! I am WiShield</h1><form method=\"get\" action=\"0\">Toggle LED:<input type=\"submit\" name=\"0\" value=\"LED1\"></input></form></center>"};

void loop()
{
      WiFi.run();
}

Ok I'm afraid I will not now be able to look at that til tomorrow as I have to go do some other stuff now.

In the meantime I would suggest that you add in the servo defines and try to get the servo to move...

Then when you can get the servo moving while the webserver code still runs, you can then try to add in the other parts.

Mowcius

this is a little bit of an old thread but since I was doing this same thing just last night, i thought i would throw down my take on it.

i have not used the “WebServer” sketch but I did use the “SimpleServer” sketch. The difference is how it runs the wifi stuff. the setup and loop look something like
the include has wiserver.h rather than wishield,h

#include <WiServer.h>

my setup method uses WiServer rather than wifi

void setup() {
  WiServer.init(adjustServos);
  servoX.attach(14);
  servoY.attach(15);
}
void loop(){
  WiServer.server_task();
  delay(10);
}

and the method to run the task takes a url

boolean adjustServos(char* URL) {
    if (URL[1] == '?' && URL[2] == '1' && URL[6] == '2') {// l ooking for 1xxx2xxx where xxx is the axis 0 to 100 for x and y
      ... 
    }
}