Wireless control system problem

[quote author=Nick Gammon link=topic=89212.msg675103#msg675103 date=1328161089] This works with what I presume is your data:

/*

Author: Nick Gammon
Date:   2nd February 2012

 example input: .123,100,92,42,99/

*/

// how much serial data we expect before a terminator
const unsigned int MAX_INPUT = 100;
const char TERMINATOR = '/';
const char STARTER = '.';

void setup ()
{
  Serial.begin(115200);
} // end of setup

int middle, thumb, ring, pointer, rotation;

// here to process incoming serial data after a terminator received
void process_data (char * data)
  {

  // convert strings into numbers:

  middle = atoi (strtok (data, ","));
  thumb = atoi (strtok (NULL, ","));
  ring = atoi (strtok (NULL, ","));
  pointer = atoi (strtok (NULL, ","));
  rotation = atoi (strtok (NULL, ","));
  
// control the servos here! 

// for now I am displaying what I got ...

  Serial.print ("middle = ");
  Serial.println (middle);
  Serial.print ("thumb = ");
  Serial.println (thumb);
  Serial.print ("ring = ");
  Serial.println (ring);
  Serial.print ("pointer = ");
  Serial.println (pointer);
  Serial.print ("rotation = ");
  Serial.println (rotation);
  
  }  // end of process_data
  

void loop()
{
static char input_line [MAX_INPUT];
static unsigned int input_pos = 0;

  if (Serial.available () > 0) 
    {
    char inByte = Serial.read ();

    switch (inByte)
      {

      case TERMINATOR:   // end of text
        input_line [input_pos] = 0;  // terminating null byte
        
        // terminator reached! process input_line here ...
        process_data (input_line);
        
        // reset buffer for next time
        input_pos = 0;  
        break;
  
      case STARTER:  
        // reset buffer 
        input_pos = 0;        
        break;
  
      default:
        // keep adding if not full ... allow for terminating null byte
        if (input_pos < (MAX_INPUT - 1))
          input_line [input_pos++] = inByte;
        break;

      }  // end of switch

  }  // end of incoming data

  // do other stuff here like testing digital input (button presses) ...

}  // end of loop

if (Serial.available () > 0) *change this to something like: if (Serial.available () > 8) because there are 9 characters *

No. It gets a byte at a time. That's the WHOLE idea.

char inByte = Serial.read (); *times this by 9? *

No. It adds to a buffer. You don't do 9 reads. How do you know it is 9? How do you know in advance if you are getting 1-digit, 2-digit, 3-digit numbers? Try to think through what you are sending. [/quote] Alright. So do i even need to send the commas? So i am sending 5 sensor values, once it reads those it store them in a buffer? but then how do i access them and move the servos with them?

So do i even need to send the commas? So i am sending 5 sensor values, once it reads those it store them in a buffer? but then how do i access them and move the servos with them?

Yes, you need to send the commas. If you didn't, how would you know where one value ended and the next began. Here is a string of servo values. Move your servos to the correct positions: 125678011

Now, here is another string: 125,67,8,0,11

The second string allows you to know where to break it, using strtok() to get tokens. With the tokens, you can call atoi() to get integer values that the servos can be moved to.

[quote author=Nick Gammon link=topic=89212.msg675103#msg675103 date=1328161089] This works with what I presume is your data:

/*

Author: Nick Gammon
Date:   2nd February 2012

 example input: .123,100,92,42,99/

*/

// how much serial data we expect before a terminator
const unsigned int MAX_INPUT = 100;
const char TERMINATOR = '/';
const char STARTER = '.';

void setup ()
{
  Serial.begin(115200);
} // end of setup

int middle, thumb, ring, pointer, rotation;

// here to process incoming serial data after a terminator received
void process_data (char * data)
  {

  // convert strings into numbers:

  middle = atoi (strtok (data, ","));
  thumb = atoi (strtok (NULL, ","));
  ring = atoi (strtok (NULL, ","));
  pointer = atoi (strtok (NULL, ","));
  rotation = atoi (strtok (NULL, ","));
  
// control the servos here! 

// for now I am displaying what I got ...

  Serial.print ("middle = ");
  Serial.println (middle);
  Serial.print ("thumb = ");
  Serial.println (thumb);
  Serial.print ("ring = ");
  Serial.println (ring);
  Serial.print ("pointer = ");
  Serial.println (pointer);
  Serial.print ("rotation = ");
  Serial.println (rotation);
  
  }  // end of process_data
  

void loop()
{
static char input_line [MAX_INPUT];
static unsigned int input_pos = 0;

  if (Serial.available () > 0) 
    {
    char inByte = Serial.read ();

    switch (inByte)
      {

      case TERMINATOR:   // end of text
        input_line [input_pos] = 0;  // terminating null byte
        
        // terminator reached! process input_line here ...
        process_data (input_line);
        
        // reset buffer for next time
        input_pos = 0;  
        break;
  
      case STARTER:  
        // reset buffer 
        input_pos = 0;        
        break;
  
      default:
        // keep adding if not full ... allow for terminating null byte
        if (input_pos < (MAX_INPUT - 1))
          input_line [input_pos++] = inByte;
        break;

      }  // end of switch

  }  // end of incoming data

  // do other stuff here like testing digital input (button presses) ...

}  // end of loop

if (Serial.available () > 0) *change this to something like: if (Serial.available () > 8) because there are 9 characters *

No. It gets a byte at a time. That's the WHOLE idea.

char inByte = Serial.read (); *times this by 9? *

No. It adds to a buffer. You don't do 9 reads. How do you know it is 9? How do you know in advance if you are getting 1-digit, 2-digit, 3-digit numbers? Try to think through what you are sending. [/quote] So luckily i was reading this over and i saw that there was more code that you posted. code doesnt seem to be very mobile friendly. I added in the servo part and everything. does this look good? do i need the flash(); function if im going to send at 9600?

#include 

Servo myservo1;  // create servo object to control a servo
Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;
Servo myservo6;
Servo myservo7;

// how much serial data we expect before a terminator
const unsigned int MAX_INPUT = 100;
const char TERMINATOR = '/';
const char STARTER = '.';

void setup ()
{
  Serial.begin(9600);
  
   myservo1.attach(2); //middle
   myservo2.attach(3); //thumb
   myservo3.attach(4); //ring
   myservo4.attach(5); //pinky
   myservo5.attach(6); //pointer
   myservo7.attach(7); //swivel
} // end of setup

int middle, thumb, ring, pointer, rotation;

// here to process incoming serial data after a terminator received
void process_data (char * data)
  {

  // convert strings into numbers:

  middle = atoi (strtok (data, ","));
  thumb = atoi (strtok (NULL, ","));
  ring = atoi (strtok (NULL, ","));
  pointer = atoi (strtok (NULL, ","));
  rotation = atoi (strtok (NULL, ","));
  
    myservo1.write(middle);
    myservo2.write(thumb);
    myservo3.write(ring);
    myservo4.write(ring);
    myservo5.write(pointer);
    myservo7.write(rotation);

// for now I am displaying what I got ...

  Serial.print ("middle = ");
  Serial.println (middle);
  Serial.print ("thumb = ");
  Serial.println (thumb);
  Serial.print ("ring = ");
  Serial.println (ring);
  Serial.print ("pointer = ");
  Serial.println (pointer);
  Serial.print ("rotation = ");
  Serial.println (rotation);
  
  }  // end of process_data
  

void loop()
{
static char input_line [MAX_INPUT];
static unsigned int input_pos = 0;

  if (Serial.available () > 0) 
    {
    char inByte = Serial.read ();

    switch (inByte)
      {

      case TERMINATOR:   // end of text
        input_line [input_pos] = 0;  // terminating null byte
        
        // terminator reached! process input_line here ...
        process_data (input_line);
        
        // reset buffer for next time
        input_pos = 0;  
        break;
  
      case STARTER:  
        // reset buffer 
        input_pos = 0;        
        break;
  
      default:
        // keep adding if not full ... allow for terminating null byte
        if (input_pos < (MAX_INPUT - 1))
          input_line [input_pos++] = inByte;
        break;

      }  // end of switch

  }  // end of incoming data

  // do other stuff here like testing digital input (button presses) ...

}  // end of loop

njkl44: So luckily i was reading this over and i saw that there was more code that you posted. code doesnt seem to be very mobile friendly.

It was indeed lucky that you read the code I posted. Otherwise my time would have been wasted.

[quote author=Nick Gammon link=topic=89212.msg677637#msg677637 date=1328332324]

njkl44: So luckily i was reading this over and i saw that there was more code that you posted. code doesnt seem to be very mobile friendly.

It was indeed lucky that you read the code I posted. Otherwise my time would have been wasted. [/quote] So does everything look good in that code then? It's still not working :/ the receiving LED comes on but in the serial monitor of the receiving side there is nothing.

[quote author=Nick Gammon link=topic=89212.msg677637#msg677637 date=1328332324]

njkl44: So luckily i was reading this over and i saw that there was more code that you posted. code doesnt seem to be very mobile friendly.

It was indeed lucky that you read the code I posted. Otherwise my time would have been wasted. [/quote] Do I still use that flash function if im sending at 9600? Does the code look like it has everything there?

Can you explain to me in your own words what you think the flash() function does? Here, I'll reproduce it:

void flash ()
  {
  digitalWrite (LED, HIGH);
  digitalWrite (LED, LOW);
  }  // end of flash

Once you have told me what it does, can you tell me if your program needs it to do that or not?

[quote author=Nick Gammon link=topic=89212.msg682041#msg682041 date=1328648730] Can you explain to me in your own words what you think the flash() function does? Here, I'll reproduce it:

void flash ()
  {
  digitalWrite (LED, HIGH);
  digitalWrite (LED, LOW);
  }  // end of flash

Once you have told me what it does, can you tell me if your program needs it to do that or not? [/quote] It just slows it down so you can get all 5 values at the same time. Because i am using 9600 i believe i do. This is just what i understood from the pictures a few pages back and your website.

No. I put it there to flash the LED. That's all. I did that to show how fast the data is coming in. That's all.

If I had thought it necessary to put it in, I would have in the code I pasted on the previous page.

You seem to have incorporated the servo controls into the code. Well, does it work or not? If not, what does it do?

[quote author=Nick Gammon link=topic=89212.msg682056#msg682056 date=1328649563] No. I put it there to flash the LED. That's all. I did that to show how fast the data is coming in. That's all.

If I had thought it necessary to put it in, I would have in the code I pasted on the previous page.

You seem to have incorporated the servo controls into the code. Well, does it work or not? If not, what does it do? [/quote] No servos move or anything but the receiving light does turn on. So its receiving something but i dont know what.

Here is my sending code:

int pwm_a = 3;  //PWM control for motor outputs 1 and 2 is on digital pin 3
int dir_a = 12;  //direction control for motor outputs 1 and 2 is on digital pin 12

int Finger1 = 2;
int Finger2 = 3;
int Finger3 = 4;
int Finger4 = 5;
int Rotation =  0;


void setup()
{
   Serial.begin(9600);
  pinMode(pwm_a, OUTPUT);  //Set control pins to be outputs
  pinMode(dir_a, OUTPUT);
  digitalWrite(dir_a, LOW);
  
}

void loop()
{  

   int FingerV1 = analogRead(Finger1);
   int FingerV2 = analogRead(Finger2);
   int FingerV3 = analogRead(Finger3);
   int FingerV4 = analogRead(Finger4);
   int RotationV1 = analogRead(Rotation);
   
   if (FingerV1 < 30) FingerV1 = 30;
   else if (FingerV1 > 80) FingerV1 = 80;
   
   if (FingerV2 < 45) FingerV2 = 45;
   else if (FingerV2 > 69) FingerV2 = 69;
   
   if (FingerV3 < 22) FingerV3 = 22;
   else if (FingerV3 > 87) FingerV3 = 87;
   
   if (FingerV4 < 12) FingerV4 = 12;
   else if (FingerV4 > 62) FingerV4 = 62;
   
   if (RotationV1 < 300) RotationV1 = 300;
   else if (RotationV1 > 600) RotationV1 = 600;
  
   byte servoVal1 = map(FingerV1,30, 80, 0, 255);//middle
   byte servoVal2 = map(FingerV2,69, 45, 0, 100);//thumb
   byte servoVal3 = map(FingerV3,87, 22, 0, 255);//ring
   byte servoVal4 = map(FingerV4,12, 62, 0, 255);//pointer
   byte servoVal5 = map(RotationV1,300, 600, 0, 255);//Rotation
   
   Serial.print(".");
   Serial.print(servoVal1);
   Serial.print(",");
   Serial.print(servoVal2);
   Serial.print(",");
   Serial.print(servoVal3);
   Serial.print(",");
   Serial.print(servoVal4);
   Serial.print(",");
   Serial.print(RotationV1);
   Serial.print("/");
   
   delay(10);
}

On the receiving end, what do the serial prints show?

[quote author=Nick Gammon link=topic=89212.msg682093#msg682093 date=1328651249] On the receiving end, what do the serial prints show? [/quote] This is a small bit of what i get.

middle = 163
thumb = 4
ring = 23
pointer = 255
rotation = 5883
middle = 1555
thumb = 441
ring = 0
pointer = 0
rotation = 0
middle = 435
thumb = 0

Those values are way way way off. My sending code keeps all of them between 0 and 100 and the rotation is between 300 and 600.

Can you post your current sending code please?

[quote author=Nick Gammon link=topic=89212.msg682113#msg682113 date=1328652389] Can you post your current sending code please? [/quote] Sending:

int pwm_a = 3;  //PWM control for motor outputs 1 and 2 is on digital pin 3
int dir_a = 12;  //direction control for motor outputs 1 and 2 is on digital pin 12

int Finger1 = 2;
int Finger2 = 3;
int Finger3 = 4;
int Finger4 = 5;
int Rotation =  0;


void setup()
{
   Serial.begin(9600);
  pinMode(pwm_a, OUTPUT);  //Set control pins to be outputs
  pinMode(dir_a, OUTPUT);
  digitalWrite(dir_a, LOW);
  
}

void loop()
{  

   int FingerV1 = analogRead(Finger1);
   int FingerV2 = analogRead(Finger2);
   int FingerV3 = analogRead(Finger3);
   int FingerV4 = analogRead(Finger4);
   int RotationV1 = analogRead(Rotation);
   
   if (FingerV1 < 30) FingerV1 = 30;
   else if (FingerV1 > 80) FingerV1 = 80;
   
   if (FingerV2 < 45) FingerV2 = 45;
   else if (FingerV2 > 69) FingerV2 = 69;
   
   if (FingerV3 < 22) FingerV3 = 22;
   else if (FingerV3 > 87) FingerV3 = 87;
   
   if (FingerV4 < 12) FingerV4 = 12;
   else if (FingerV4 > 62) FingerV4 = 62;
   
   if (RotationV1 < 300) RotationV1 = 300;
   else if (RotationV1 > 600) RotationV1 = 600;
  
   byte servoVal1 = map(FingerV1,30, 80, 0, 255);//middle
   byte servoVal2 = map(FingerV2,69, 45, 0, 100);//thumb
   byte servoVal3 = map(FingerV3,87, 22, 0, 255);//ring
   byte servoVal4 = map(FingerV4,12, 62, 0, 255);//pointer
   byte servoVal5 = map(RotationV1,300, 600, 0, 255);//Rotation
   
   Serial.print(".");
   Serial.print(servoVal1);
   Serial.print(",");
   Serial.print(servoVal2);
   Serial.print(",");
   Serial.print(servoVal3);
   Serial.print(",");
   Serial.print(servoVal4);
   Serial.print(",");
   Serial.print(RotationV1);
   Serial.print("/");
   
   delay(10);
}

Did you think to open the serial monitor on the sending side and check what was actually being sent? I did and saw this:

,350/35/

Hardly the numbers you expect, eh?

Now if we change the sending code to send "decimal" numbers like this:

  Serial.print(".");
   Serial.print(servoVal1, DEC);
   Serial.print(",");
   Serial.print(servoVal2, DEC);
   Serial.print(",");
   Serial.print(servoVal3, DEC);
   Serial.print(",");
   Serial.print(servoVal4, DEC);
   Serial.print(",");
   Serial.print(RotationV1, DEC);
   Serial.print("/");

Then we get better results:

.255,0,0,255,340/.255,0,0,255,344/.255,0,0,255,368/

[quote author=Nick Gammon link=topic=89212.msg682144#msg682144 date=1328654431] Did you think to open the serial monitor on the sending side and check what was actually being sent? I did and saw this:

,350/35/

Hardly the numbers you expect, eh?

Now if we change the sending code to send "decimal" numbers like this:

  Serial.print(".");
   Serial.print(servoVal1, DEC);
   Serial.print(",");
   Serial.print(servoVal2, DEC);
   Serial.print(",");
   Serial.print(servoVal3, DEC);
   Serial.print(",");
   Serial.print(servoVal4, DEC);
   Serial.print(",");
   Serial.print(RotationV1, DEC);
   Serial.print("/");

Then we get better results:

.255,0,0,255,340/.255,0,0,255,344/.255,0,0,255,368/

[/quote] Ah perfect! Now another problem... So i have 5 of these: http://www.hobbyking.com/hobbyking/store/uh_viewItem.asp?idProduct=6221

I am using an arduino for all this also. Now should i just power these servos with the 5v and gnd from the arduino or something else? When i power it with the arduino it powers then restarts then repeats all that. I have a 7.2v 2200mah lipo battery that im using for all this. I am also powering the xbee too.

I certainly would not power them from the Arduino 5V line. That goes through a voltage regulator that is not designed to handle that amount of current. I assume (hope) you are using some kind of motor board to actually drive the motors. That should be independently powered, not from the Arduino's 5V line.

I made a custom shield that i have the digital lines from the arduino tied to then the power from the lipo battery. I have common grounds connected also. Should this work?

Is this different to what you said earlier?

should i just power these servos with the 5v and gnd from the arduino or something else?

Certainly you should have the grounds common. I agree with that. And from the battery I would run a wire to the Arduino's "power in" socket (so it gets voltage regulated). And also direct from the battery to the motor shield.

Sounds OK, subject to seeing a schematic.

[quote author=Nick Gammon link=topic=89212.msg682286#msg682286 date=1328664447] Is this different to what you said earlier?

should i just power these servos with the 5v and gnd from the arduino or something else?

Certainly you should have the grounds common. I agree with that. And from the battery I would run a wire to the Arduino's "power in" socket (so it gets voltage regulated). And also direct from the battery to the motor shield.

Sounds OK, subject to seeing a schematic. [/quote] I believe it should be something like this?