Ethernet / UDP controlled Motors and Servo

Hi,
This is my first go at using Arduino and I don't think I've done to bad,
I can program in VB 6, but I could never get on with C so I have shocked myself.

I am trying to program the Arduino with a Ethernet shield, and Motor shield.

As you can see below I have a basic code written but I am having trouble getting UDP data, I would like to be able to send 'A123', 'DHIGH' and/or 'E255' and have the Arduino decode this to
A = Servo 1 and 123 = Servo Placement
the same as 'DHIGH' would be D = Motor Drive 1 A and HIGH = Output HIGH

#include <SPI.h>                                             // needed for Arduino versions later than 0018
#include <Ethernet.h>                                        // Ethernet board connected - Uses A0, A1, (D2 or D4), D10, D11, D12, D13
#include <EthernetUdp.h>                                     // UDP library from: bjoern@cs.stanford.edu 12/30/2008
#include <Servo.h>                                           // Servo Library - Can be used on D3 D5 D6 D9

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };         // MAC Address
IPAddress ip(192, 168, 1, 177);                              // IP Address
unsigned int localPort = 8888;                               // Local IP port to listen on
byte gateway[] = { 192, 168, 1, 1 };                         // internet access via router
byte subnet[] = { 255, 255, 255, 0 };                        // Subnet Address

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];                   //buffer to hold incoming packet
EthernetUDP Udp;                                             // An EthernetUDP instance to let us send and receive packets over UDP

Servo myservoA;                                              // create servo object to control a servo 
Servo myservoB;                                              // a maximum of eight servo objects can be created 

int dir1PinA = 7;                                            // motor A Dir 1
int dir2PinA = 8;                                            // motor A Dir 2
int speedPinA = 6;                                           // motor A Speed
int dir1PinB = 2;                                            // motor B Dir Pin 1
int dir2PinB = 4;                                            // motor B Dir Pin 2
int speedPinB = 9;                                           // motor B Speed

const int TempIn = A0;                                       // Temp sensor on A0
int TempValue = 0;                                           // Setup val for temp
int Servo1 = 90;                                             // Setup for servo1
int Servo2 = 90;                                             // Setup for servo2
int SpeedA = 0;                                              // Setup for motor speed A
int SpeedB = 0;                                              // Setup for motor speed B
int Dir1A = 0;                                               // Setup for motor A dir 1
int Dir2A = 0;                                               // Setup for motor A dir 2
int Dir1B = 0;                                               // Setup for motor B dir 1
int Dir2B = 0;                                               // Setup for motor B dir 2

void setup() {                                               // run setup only once on boot

  Ethernet.begin(mac,ip);                                    // Enable Ethernet 
  Udp.begin(localPort);                                      // Start UDP Connection

  myservoA.attach(3);                                        // attaches the servo on pin 9 to the servo object 
  myservoB.attach(5);                                        // attaches the servo on pin 6 to the servo object 
  pinMode(dir1PinA, OUTPUT);                                 // attaches the motor drive dir 1
  pinMode(dir2PinA, OUTPUT);                                 // attaches the motor drive dir 2
  pinMode(speedPinA, OUTPUT);                                // attaches the motor drive speed
  pinMode(dir1PinB, OUTPUT);                                 // attaches the motor drive dir 1
  pinMode(dir2PinB, OUTPUT);                                 // attaches the motor drive dir 2
  pinMode(speedPinB, OUTPUT);                                // attaches the motor drive speed

  Serial.begin(9600);                                        // Start Serial Output
  Serial.write("SYSTEM BOOT");                               // Send Power on to serial

  myservoA.write(Servo1);                                    // tell servo to go to position 90
  myservoB.write(Servo2);                                    // tell servo to go to position 90
  analogWrite(speedPinA, SpeedA);                            // tell the motor A drive to stop
  analogWrite(speedPinB, SpeedB);                            // tell the motor B drive to stop
  digitalWrite(dir1PinA, LOW);                               // tell the motor drive A to brake
  digitalWrite(dir2PinA, LOW);                               // tell the motor drive A to brake
  digitalWrite(dir1PinB, LOW);                               // tell the motor drive B to brake
  digitalWrite(dir2PinB, LOW);                               // tell the motor drive B to break
             }                                               // end of setup

void loop()                                                  // Start Running System
{
  int packetSize = Udp.parsePacket();                        // if there's data available, read a packet
  if(packetSize)
  {
Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);               // read the packet into packetBufffer
char ch = packetBuffer[0];

switch(ch)
{
 case '0':                                                   // if 0 is sent via udp then do this -->>
  myservoA.write(90);                                        // tell servo to go to position
  myservoB.write(90);                                        // tell servo to go to position
  analogWrite(speedPinA, 0);                                 // tell the motor A drive to stop
  analogWrite(speedPinB, 0);                                 // tell the motor B drive to stop
  digitalWrite(dir1PinA, LOW);                               // tell the motor drive A to brake
  digitalWrite(dir2PinA, LOW);                               // tell the motor drive A to brake
  digitalWrite(dir1PinB, LOW);                               // tell the motor drive B to brake
  digitalWrite(dir2PinB, LOW);                               // tell the motor drive B to break
 break;                                                      // end of case 0

// place to put cases
 
 default :                                                   // if recived info vai udp and not found in the case do this -->>
    Serial.print("No Case Found for: ");                     // if case not found send info via serial
    Serial.print(ch);                                        // send udp info back to serial
    Serial.print(" - ");                                     // send udp info back to serial
    Serial.print(packetBuffer);                              // send udp info back to serial
 break;                                                      // end of case not found
}
    TempValue = analogRead(TempIn);                          // Read temp value
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());       // open udp on address that has connected to arduino to send feed back to
    Udp.write("Dir1 A = " );                                   
    Udp.println(Dir1A);                                      // send Dir 1 A value back via udp
    Udp.write("\nDir 2 A = ");
    Udp.println(Dir2A);                                      // send Dir 2 A value back via udp
    Udp.write("\nSpeed A = ");
    Udp.println(SpeedA);                                     // send Speed A value back via udp
    Udp.write("\nDir 1 B = ");
    Udp.println(Dir1B);                                      // send Dir 1 B value back via udp
    Udp.write("\nDir 2 B = ");
    Udp.println(Dir2B);                                      // send Dir 2 B value back via udp
    Udp.write("\nSpeed B = ");
    Udp.println(SpeedB);                                     // send Speed B value back via udp
    Udp.write("\nServo 1 = ");
    Udp.println(Servo1);                                     // send Servo 1 value back via udp
    Udp.write("\nServo 2 = ");
    Udp.println(Servo2);                                     // send Servo 2 value back via udp
    Udp.write("\nTemp = ");
    Udp.println(TempValue);                                  // send temp value back via udp
    Udp.endPacket();                                         // close udp
}
  char packetBuffer[] = "                                 "; //Clear the buffers so as not to leave text behind from one messag to the next
  delay(15);                                                 // waits 15ms for the servo to reach the position and/or udp input wait ...
}                                                            // end system run, but now loop and start system run again

Any help on this would be great,
Thanks

I haven't read all your code, but I have found some problems. See my comments below.

//...

void loop()                                                  // Start Running System
{
  int packetSize = Udp.parsePacket();                        // if there's data available, read a packet
  if(packetSize)
  {
    // the following line has been modified
    int read = Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);               // read the packet into packetBufffer
    // null-terminating the string so Serial.print knows the length
    packetBuffer[read] = 0;
    char ch = packetBuffer[0];
    // ...
  }
  // the following line defines a variable and doesn't "clear" a buffer
  char packetBuffer[] = "                                 "; //Clear the buffers so as not to leave text behind from one messag to the next
  delay(15);                                                 // waits 15ms for the servo to reach the position and/or udp input wait ...
}                                                            // end system run, but now loop and start system run again

Thanks for the input, I can see what you have changed, but ... to tell the truth, I can not understand why?

I have also noticed the line

char packetBuffer[] = " ";

don't work but I have not found a fix for it, as I don't understand why it will not work.

richard1982:
Thanks for the input, I can see what you have changed, but ... to tell the truth, I can not understand why?

richard1982:
I have also noticed the line char packetBuffer[] = "                                 "; don't work but I have not found a fix for it, as I don't understand why it will not work.

As I said, that statement doesn't "clear" the buffer. It declares a variable and assigns a literal string to it.

Why do you need to "clear" the buffer anyway?

Right, I see what error I had made, thank you, I also have learned something new, what is good.
I want to clear the buffer as for some reason when I send data via UDP and it is forwarded to the serial it dose not seam to dump the old data.

For example if I send a UDP of "The Quick Brown Fox Jumps" and then send a UDP of "Test Test" the serial prints out "Test Test Brown Fox Jumps"

richard1982:
I want to clear the buffer as for some reason when I send data via UDP and it is forwarded to the serial it dose not seam to dump the old data.

For example if I send a UDP of "The Quick Brown Fox Jumps" and then send a UDP of "Test Test" the serial prints out "Test Test Brown Fox Jumps"

I thought that was what you were thinking. You don't have to clear the buffer. You just need to know where the end of the string is. You can either store the length in a separate variable or null-termiate the string. And when it becomes time to send the string just send the bytes in the string and not the entire buffer.

It is always the simply things, why didn't I think of that :~
Thanks, that should also help with me decoding information sent via UDP as it only need to decode what I want and not the complete buffer.

Me again,
I'm really have trouble with this here, If I was writing in VB I would not have this trouble,

Can someone help me decode a string and split it in to individual variables,
E.G -> getting a string "A255" via the packet buffer and then spiltting it into variables, "A" and "255"
then using the "A" for a Case to select the output pin
and use the "255" to set the the value for the pin
E.G 2 -> "B080" would be "B" and "080"
thanks

If your data is in packetBuffer, then getting the first character is easy.

char pin = packetBuffer[0];

Then, to get the value, replace the 1st character with a space, and pass the array to atoi().

packetBuffer[0] = ' ';
int val = atoi(packetBuffer);

Then, using the data is pretty simple:

switch(pin)
{
   case 'A':
      analogWrite(aPin, val);
      break;
   // Some other cases go here
}

Of course, you need to use the correct pin in the 'A' case.

Thanks for your help, but I have been trying to use 'atoi' but not having luck and with the line of code you supplied I'm also getting a error

UDP_Receive_String:88: error: crosses initialization of 'int val'

I just don't understand it. Thanks

I just don't understand it.

Well, I have no clue where you put the bits I suggested, so I have no idea why you are getting the message, either. (Although I know what it means.)

The code is as above but with the added help of you thanks, but here is the upto date code

#include <SPI.h>                                             // needed for Arduino versions later than 0018
#include <Ethernet.h>                                        // Ethernet board connected - Uses A0, A1, (D2 or D4), D10, D11, D12, D13
#include <EthernetUdp.h>                                     // UDP library from: bjoern@cs.stanford.edu 12/30/2008
#include <Servo.h>                                           // Servo Library - Can be used on D3 D5 D6 D9

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };         // MAC Address
IPAddress ip(192, 168, 1, 177);                              // IP Address
unsigned int localPort = 8888;                               // Local IP port to listen on
byte gateway[] = { 192, 168, 1, 1 };                         // internet access via router
byte subnet[] = { 255, 255, 255, 0 };                        // Subnet Address

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];                   // buffer to hold incoming packet
EthernetUDP Udp;                                             // An EthernetUDP instance to let us send and receive packets over UDP

Servo myservoA;                                              // create servo object to control a servo 
Servo myservoB;                                              // a maximum of eight servo objects can be created 

int dir1PinA = 7;                                            // motor A Dir 1
int dir2PinA = 8;                                            // motor A Dir 2
int speedPinA = 6;                                           // motor A Speed
int dir1PinB = 2;                                            // motor B Dir Pin 1
int dir2PinB = 4;                                            // motor B Dir Pin 2
int speedPinB = 9;                                           // motor B Speed

const int TempIn = A0;                                       // Temp sensor on A0
int TempValue = 0;                                           // Setup val for temp
int Servo1 = 90;                                             // Setup for servo1
int Servo2 = 90;                                             // Setup for servo2
int SpeedA = 0;                                              // Setup for motor speed A
int SpeedB = 0;                                              // Setup for motor speed B
int Dir1A = 0;                                               // Setup for motor A dir 1
int Dir2A = 0;                                               // Setup for motor A dir 2
int Dir1B = 0;                                               // Setup for motor B dir 1
int Dir2B = 0;                                               // Setup for motor B dir 2

void setup() {                                               // run setup only once on boot

  Ethernet.begin(mac,ip);                                    // Enable Ethernet 
  Udp.begin(localPort);                                      // Start UDP Connection

  myservoA.attach(3);                                        // attaches the servo on pin 9 to the servo object 
  myservoB.attach(5);                                        // attaches the servo on pin 6 to the servo object 
  pinMode(dir1PinA, OUTPUT);                                 // attaches the motor drive dir 1
  pinMode(dir2PinA, OUTPUT);                                 // attaches the motor drive dir 2
  pinMode(speedPinA, OUTPUT);                                // attaches the motor drive speed
  pinMode(dir1PinB, OUTPUT);                                 // attaches the motor drive dir 1
  pinMode(dir2PinB, OUTPUT);                                 // attaches the motor drive dir 2
  pinMode(speedPinB, OUTPUT);                                // attaches the motor drive speed

  Serial.begin(9600);                                        // Start Serial Output
  Serial.write("SYSTEM BOOT");                               // Send Power on to serial

  myservoA.write(Servo1);                                    // tell servo to go to position 90
  myservoB.write(Servo2);                                    // tell servo to go to position 90
  analogWrite(speedPinA, SpeedA);                            // tell the motor A drive to stop
  analogWrite(speedPinB, SpeedB);                            // tell the motor B drive to stop
  digitalWrite(dir1PinA, LOW);                               // tell the motor drive A to brake
  digitalWrite(dir2PinA, LOW);                               // tell the motor drive A to brake
  digitalWrite(dir1PinB, LOW);                               // tell the motor drive B to brake
  digitalWrite(dir2PinB, LOW);                               // tell the motor drive B to break
             }                                               // end of setup

void loop()                                                  // Start Running System
{
  int packetSize = Udp.parsePacket();                        // if there's data available, read a packet
  if(packetSize)
  {
  int read = Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);  // read the packet into packetBufffer
    packetBuffer[read] = 0;
    char ch = packetBuffer[0];

switch(ch)
{
 case '0':                                                   // if 0 is sent via udp then do this -->>
  myservoA.write(90);                                        // tell servo to go to position
  myservoB.write(90);                                        // tell servo to go to position
  analogWrite(speedPinA, 0);                                 // tell the motor A drive to stop
  analogWrite(speedPinB, 0);                                 // tell the motor B drive to stop
  digitalWrite(dir1PinA, LOW);                               // tell the motor drive A to brake
  digitalWrite(dir2PinA, LOW);                               // tell the motor drive A to brake
  digitalWrite(dir1PinB, LOW);                               // tell the motor drive B to brake
  digitalWrite(dir2PinB, LOW);                               // tell the motor drive B to break
 break;                                                      // end of case 0
 
 case 'A':
  packetBuffer[0] = ' ';                                     // replace the 1st character with a space
  int Servo1 = atoi(packetBuffer);                           // and pass the array to atoi() to convert string to int
  myservoA.write(Servo1);                                    // tell servo to go to position
 break;
 
  case 'B':
  packetBuffer[0] = ' ';                                     // replace the 1st character with a space
  int Servo2 = atoi(packetBuffer);                           // and pass the array to atoi() to convert string to int
  myservoB.write(Servo2);                                    // tell servo to go to position
 break;
 
// place to put other cases
 
 default :                                                   // if recived info via udp and not found in the case do this -->>
    Serial.print("No Case Found for: ");                     // if case not found send info via serial
    Serial.print(ch);                                        // send udp info back to serial
    Serial.print(" - ");                                     // send udp info back to serial
    Serial.print(packetBuffer);                  // send udp info back to serial
 break;                                                      // end of case not found
}
    TempValue = analogRead(TempIn);                          // Read temp value
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());       // open udp on address that has connected to arduino to send feed back to
    Udp.write("Dir1 A = " );                                   
    Udp.println(Dir1A);                                      // send Dir 1 A value back via udp
    Udp.write("\nDir 2 A = ");
    Udp.println(Dir2A);                                      // send Dir 2 A value back via udp
    Udp.write("\nSpeed A = ");
    Udp.println(SpeedA);                                     // send Speed A value back via udp
    Udp.write("\nDir 1 B = ");
    Udp.println(Dir1B);                                      // send Dir 1 B value back via udp
    Udp.write("\nDir 2 B = ");
    Udp.println(Dir2B);                                      // send Dir 2 B value back via udp
    Udp.write("\nSpeed B = ");
    Udp.println(SpeedB);                                     // send Speed B value back via udp
    Udp.write("\nServo 1 = ");
    Udp.println(Servo1);                                     // send Servo 1 value back via udp
    Udp.write("\nServo 2 = ");
    Udp.println(Servo2);                                     // send Servo 2 value back via udp
    Udp.write("\nTemp = ");
    Udp.println(TempValue);                                  // send temp value back via udp
    Udp.endPacket();                                         // close udp
}

  delay(15);                                                 // waits 15ms for the servo to reach the position and/or udp input wait ...
}                                                            // end system run, but now loop and start system run again

Declaring local variables in case is not allowed, unless the local variables are in a block.

 case 'A':
{
  packetBuffer[0] = ' ';                                     // replace the 1st character with a space
  int Servo1 = atoi(packetBuffer);                           // and pass the array to atoi() to convert string to int
  myservoA.write(Servo1);                                    // tell servo to go to position
}
 break;

Of course, then you can't print them later. Make them global, instead.

Works like a dream, it has now killed my feedback for the servos and motor drives (not sure why YET... but this is really not any trouble) Thank you very much for your help!!!!

it has now killed my feedback for the servos and motor drives (not sure why YET

Because the values are stored in variables that are local to the switch statement. After the switch statement ends, the variables go out of scope. Since you have global variables of the same name, you don't really need (and should not have) local variables. Change the case to look like:

 case 'A':
  packetBuffer[0] = ' ';                                     // replace the 1st character with a space
  Servo1 = atoi(packetBuffer);                           // and pass the array to atoi() to convert string to int
  myservoA.write(Servo1);                                    // tell servo to go to position
  break;

Oh I see, and understand it all, Thanks for the help.

Here is a code update,
It is now to large to post, so it has been attached ...
I'm not sure if it is any good to anyone else, its for a wifi controlled tank all working apart from I think I am out of PWM outputs as I can not control no more then 3 PWM outputs, can anyone tell me why?

And before someone tells me its because I have left servo 2 out, I have done it to make the code work, as if I use PWM 3, 10 or 11 the Arduino stops working,

Thanks

wifi_tank.ino (11.4 KB)