So im using two xbees. i need this code to work for a few hours so it needs to be solid. Let me know if you have any questions. Here is what i have:
Send:
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()
{
while((char)Serial.read() !='.');
byte val = Serial.read();
analogWrite(pwm_a, val);
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);
delay(10);
}
Receive:
#include <Servo.h>
Servo myservo1; // create servo object to control a servo
Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;
Servo myservo6;
Servo myservo7;
int potpin = A0;
int val;
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
Serial.print(".");
}
void loop()
{
while((char)Serial.read() !='.');
byte vals[5];
vals[0] = Serial.read();
Serial.read();
vals[1] = Serial.read();
Serial.read();
vals[2] = Serial.read();
Serial.read();
vals[3] = Serial.read();
Serial.read();
vals[4] = Serial.read();
myservo1.write(vals[0]);
myservo2.write(vals[1]);
myservo3.write(vals[2]);
myservo4.write(vals[2]);
myservo5.write(vals[3]);
myservo7.write(vals[4]);
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
byte val = map(val, 0, 950, 0, 255); // scale it to use it with the servo (value between 0 and 180) // sets the servo position according to the scaled value
if (val>250){val=250;}
Serial.print(".");
Serial.print(val);
}
Let me know if you have any questions.
What question are
you asking?
In both sketches, you are doing Serial.reads, without checking that there is anything to read.
Let me know if you have any questions.
What question are you asking?
In both sketches, you are doing Serial.reads, without checking that there is anything to read.
So do I just use if serial available? If so where would I put it?
Before the reads?
http://gammon.com.au/serial
Let me know if you have any questions.
Does it compile?
Does it do what you intend?
Does it do it reliably for as long as you need?
Let me know if you have any questions.
Does it compile?
Does it do what you intend?
Does it do it reliably for as long as you need?
it does compile. Other than that nothing works.
So im using two xbees.
About which you have told us what? Nothing. Nothing about the type. Nothing about how they are attached to the Arduino. Nothing about how they are configured. Nothing about whether you know that they are communicating.
So im using two xbees.
About which you have told us what? Nothing. Nothing about the type. Nothing about how they are attached to the Arduino. Nothing about how they are configured. Nothing about whether you know that they are communicating.
Well that shouldnt matter to much should it? they are just standard xbees attached with a shield. I have config them with a custom channel so only they can talk to eachother.
Before the reads?
http://gammon.com.au/serial
Something like this?
void loop()
{
if (Serial.available ())
while((char)Serial.read() !='.');
byte vals[5];
vals[0] = Serial.read();
Well that shouldnt matter to much should it?
I guess that it doesn't matter that they are compatible. Doesn't matter that they might be attached to shields that are configured to use something other than the Serial port. Doesn't matter that they might not be configured correctly.
You have two Arduinos that are failing to properly exchange data. Ignoring the mechanism that is used to exchange the data hardly seems like a good idea.
Well that shouldnt matter to much should it?
I guess that it doesn't matter that they are compatible. Doesn't matter that they might be attached to shields that are configured to use something other than the Serial port. Doesn't matter that they might not be configured correctly.
You have two Arduinos that are failing to properly exchange data. Ignoring the mechanism that is used to exchange the data hardly seems like a good idea.
I have tested those radios before and they can talk to each other and communicate. The shields are xbee shields and those have worked before also. Its not a problem with the radios or anything physical i have had all of it working before. Its just code issues.
Something like this?
No. Did my site have code like that there? Look,you have this:
while((char)Serial.read() !='.');
byte vals[5];
vals[0] = Serial.read();
Serial.read();
vals[1] = Serial.read();
Serial.read();
vals[2] = Serial.read();
Serial.read();
vals[3] = Serial.read();
Serial.read();
vals[4] = Serial.read();
If there is no data Serial.date will return -1, so the "while" part will work OK. It will sit there until a dot arrives. Then, very quickly, you grab 5 more bytes, which since your processor is much faster than a serial port, will almost certainly be -1. So you have filled vals array with -1 (turned into 0xFF since vals is not an int).
Look at the code on the link I posted. First you just read and fill an array with data (using Serial.available() for every byte). Then when some delimiter comes, you go back and process it.
I've added some more examples to the link above.
In particular, this shows how fast you are reading at 9600 baud compared to how fast the data arrives:
(http://www.gammon.com.au/images/Serial_data_read_rateb.png)
See that line at the bottom? That is all 5 reads executing (in my test code). Even at a much faster baud rate, it can't even read a second byte:
(http://www.gammon.com.au/images/Serial_data_read_rate.png)
Something like this?
No. Did my site have code like that there? Look,you have this:
while((char)Serial.read() !='.');
byte vals[5];
vals[0] = Serial.read();
Serial.read();
vals[1] = Serial.read();
Serial.read();
vals[2] = Serial.read();
Serial.read();
vals[3] = Serial.read();
Serial.read();
vals[4] = Serial.read();
If there is no data Serial.date will return -1, so the "while" part will work OK. It will sit there until a dot arrives. Then, very quickly, you grab 5 more bytes, which since your processor is much faster than a serial port, will almost certainly be -1. So you have filled vals array with -1 (turned into 0xFF since vals is not an int).
Look at the code on the link I posted. First you just read and fill an array with data (using Serial.available() for every byte). Then when some delimiter comes, you go back and process it.
Are you talking about something like this?
void loop()
{
while((char)Serial.read() !='.');
if (Serial.available() >0)
{
byte vals[5];
vals[0] = Serial.read();
Serial.read();
vals[1] = Serial.read();
Serial.read();
vals[2] = Serial.read();
Serial.read();
vals[3] = Serial.read();
Serial.read();
vals[4] = Serial.read();
}
myservo1.write(vals[0]);
myservo2.write(vals[1]);
myservo3.write(vals[2]);
myservo4.write(vals[2]);
myservo5.write(vals[3]);
myservo7.write(vals[4]);
Are you talking about something like this?
Why do you keep ignoring what Nick Gammon tells you? You code looks nothing like what he is suggesting.
Are you talking about something like this?
Why do you keep ignoring what Nick Gammon tells you? You code looks nothing like what he is suggesting.
I'm trying to understand what he's saying and learn. I need to start somewhere
I'm trying to understand what he's saying and learn.
He's telling you that you can't check to see that there is at least one character available to read, and then assume that that means you can read as many as you want. What's so hard to understand about that?
What do you suggest about doing it a different way? I need this to work for a few hours or so. I had code that worked before but after a few minutes it got all weird.
but after a few minutes it got all weird.
Because you are not checking that there IS something to read before EVERY read.
but after a few minutes it got all weird.
Because you are not checking that there IS something to read before EVERY read.
So something like this?
if (Serial.available())
vals[0] = Serial.read();
if (Serial.available())
Serial.read();
if (Serial.available())
vals[1] = Serial.read();
You are not thinking about this, you are trying stuff at random.
Look at that code and work through in your mind what will happen when it runs, bearing in mind that the code runs much faster than the serial port can receive data. Think about it in terms of a real-world analogy if it helps.
Somebody is sending you postcards. You can check the letterbox as often as you like. Sometimes there will be a postcard there, sometimes there won't. Now, how are you going to make sure you receive the complete set of cards and keep them all in order?
Nick Gammon has told you what you're doing wrong and how to do it right. Either take his advice and do it like he showed you, or stop and THINK about what you need to do to read a sequence of bytes from a serial port.
You are not thinking about this, you are trying stuff at random.
Look at that code and work through in your mind what will happen when it runs, bearing in mind that the code runs much faster than the serial port can receive data. Think about it in terms of a real-world analogy if it helps.
Somebody is sending you postcards. You can check the letterbox as often as you like. Sometimes there will be a postcard there, sometimes there won't. Now, how are you going to make sure you receive the complete set of cards and keep them all in order?
Nick Gammon has told you what you're doing wrong and how to do it right. Either take his advice and do it like he showed you, or stop and THINK about what you need to do to read a sequence of bytes from a serial port.
Great! thank you this helped! i think im understanding it now. Would something like this work?
Send:
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("/");
Receive:
while((char)Serial.read() !='.');
if (Serial.available() >8)
{
vals[0] = Serial.read();
Serial.read();
vals[1] = Serial.read();
Serial.read();
vals[2] = Serial.read();
Serial.read();
vals[3] = Serial.read();
Serial.read();
vals[4] = Serial.read();
}
while((char)Serial.read() !='/')
{
myservo1.write(vals[0]);
myservo2.write(vals[1]);
myservo3.write(vals[2]);
myservo4.write(vals[2]);
myservo5.write(vals[3]);
myservo7.write(vals[4]);
}
Hmmm ....
From your first post:
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);
So most numbers are in the range 0 to 255, right?
So let's work through an example. You send:
.123,100,92,42,99/
Now once you get the first dot you read like this:
if (Serial.available() >8)
{
vals[0] = Serial.read(); // <-- this will be 1
Serial.read(); // skip the 2
vals[1] = Serial.read(); // <-- this will be 3
Serial.read(); // skip the comma
vals[2] = Serial.read(); // <-- this will be 1
Serial.read(); // skip the 0
vals[3] = Serial.read(); // <-- this will be 0
Serial.read(); // skip the comma
vals[4] = Serial.read(); // <-- this will be 9
}
So you get the values: 1, 3, 1, 0, 9.
Is that really what you want?
(edit)
Plus the values are ASCII values (so '1' is really 49, '3' is 52, '0' is 48 and '9' is 57).
So you will set your 5 servos to: 49, 52, 49, 48 and 57.
Hmmm ....
From your first post:
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);
So most numbers are in the range 0 to 255, right?
So let's work through an example. You send:
.123,100,92,42,99/
Now once you get the first dot you read like this:
if (Serial.available() >8)
{
vals[0] = Serial.read(); // <-- this will be 1
Serial.read(); // skip the 2
vals[1] = Serial.read(); // <-- this will be 3
Serial.read(); // skip the comma
vals[2] = Serial.read(); // <-- this will be 1
Serial.read(); // skip the 0
vals[3] = Serial.read(); // <-- this will be 0
Serial.read(); // skip the comma
vals[4] = Serial.read(); // <-- this will be 9
}
So you get the values: 1, 3, 1, 0, 9.
Is that really what you want?
(edit)
Plus the values are ASCII values (so '1' is really 49, '3' is 52, '0' is 48 and '9' is 57).
So you will set your 5 servos to: 49, 52, 49, 48 and 57.
Hmmm alright. I understand this better now. But with that said hows the best way to read the values?
Capture the whole lot into a buffer. You could look for a terminating "/" character, since that is what you are sending.
There's an example of doing that here: http://gammon.com.au/serial
Then you could use strtok to break the resulting string apart at the commas, and use atoi to convert the ASCII strings into numbers you can send to the servos.
Capture the whole lot into a buffer. You could look for a terminating "/" character, since that is what you are sending.
There's an example of doing that here: http://gammon.com.au/serial
Then you could use strtok to break the resulting string apart at the commas, and use atoi to convert the ASCII strings into numbers you can send to the servos.
Ahh didn't scroll all the way to the bottom :)
Capture the whole lot into a buffer. You could look for a terminating "/" character, since that is what you are sending.
There's an example of doing that here: http://gammon.com.au/serial
Then you could use strtok to break the resulting string apart at the commas, and use atoi to convert the ASCII strings into numbers you can send to the servos.
So i have this now:
void loop()
{
while((char)Serial.read() !='.');
if (Serial.available() >8)
{
vals[0] = Serial.read();
flash ();
Serial.read();
flash ();
vals[1] = Serial.read();
flash ();
Serial.read();
flash ();
vals[2] = Serial.read();
flash ();
Serial.read();
flash ();
vals[3] = Serial.read();
flash ();
Serial.read();
flash ();
vals[4] = Serial.read();
flash ();
}
while((char)Serial.read() !='/')
{
myservo1.write(vals[0]);
myservo2.write(vals[1]);
myservo3.write(vals[2]);
myservo4.write(vals[2]);
myservo5.write(vals[3]);
myservo7.write(vals[4]);
}
Whats the easiest way to use atoi and strok with this?
Why are you still calling Serial.read(), and throwing away the character read?
Why are you still calling Serial.read(), and throwing away the character read?
oh so i dont need the Serial.read(), i used it to get rid of the comma. How am i throwing away the character read?
How am i throwing away the character read?
You call Serial.read() to get the next value in the buffer. If you don't store the value, what do you think happens to it?
How am i throwing away the character read?
You call Serial.read() to get the next value in the buffer. If you don't store the value, what do you think happens to it?
Doesnt this store it?
vals[4] = Serial.read();
So im waiting until i have all 5 values then im moving the servos with them right?
Doesnt this store it?
Yes.
This, on the other hand, throws it away:
Serial.read();
Doesnt this store it?
Yes.
This, on the other hand, throws it away:
Serial.read();
So i get rid of those. Separate it at the commas and convert them?
So i get rid of those. Separate it at the commas and convert them?
Yes.
Why are you still calling Serial.read(), and throwing away the character read?
He's getting rid of what he hopes, without any justification whatsoever, is a comma.
Capture the whole lot into a buffer.
So i have this now:
...
vals[0] = Serial.read();
flash ();
Serial.read();
flash ();
vals[1] = Serial.read();
flash ();
Serial.read();
flash ();
vals[2] = Serial.read();
flash ();
Serial.read();
flash ();
vals[3] = Serial.read();
flash ();
Serial.read();
flash ();
vals[4] = Serial.read();
flash ();
...
I don't think you are paying the slightest bit of attention to what I am saying. You look at the page, grab a bit of code, stick it in, and hope for the best. What is the "flash ()" for?
What you are doing there is
not putting the incoming text into a buffer, as I have recommended about three or four times now.
Why are you still calling Serial.read(), and throwing away the character read?
He's getting rid of what he hopes, without any justification whatsoever, is a comma.
So i do want to keep the Serial.read() to get rid of the comma?
Capture the whole lot into a buffer.
So i have this now:
...
vals[0] = Serial.read();
flash ();
Serial.read();
flash ();
vals[1] = Serial.read();
flash ();
Serial.read();
flash ();
vals[2] = Serial.read();
flash ();
Serial.read();
flash ();
vals[3] = Serial.read();
flash ();
Serial.read();
flash ();
vals[4] = Serial.read();
flash ();
...
I don't think you are paying the slightest bit of attention to what I am saying. You look at the page, grab a bit of code, stick it in, and hope for the best. What is the "flash ()" for?
What you are doing there is not putting the incoming text into a buffer, as I have recommended about three or four times now.
I guess im just unsure how to but the incoming text into a buffer. Im new at coding and come here for help. I thank you so much for putting effort in trying to teach and help! I just need to understand a bit more. How would i put the incoming text into a buffer?
Thank you again!
The link I gave you about 2 or 3 pages back now, more than once, shows how to put text into a buffer. You are choosing to ignore the methods shown there, which I put there to teach people how to do this, and sticking with your code, which we have said won't work. The top part of that page. Where it says "Buffering input".
The link I gave you about 2 or 3 pages back now, more than once, shows how to put text into a buffer. You are choosing to ignore the methods shown there, which I put there to teach people how to do this, and sticking with your code, which we have said won't work. The top part of that page. Where it says "Buffering input".
So help me understand this
Do i go something like this?
const unsigned int MAX_INPUT = 50;
void setup ()
{
Serial.begin(9600);
} // end of setup
// here to process incoming serial data after a terminator received
void process_data (char * data)
{
// for now just display it
Serial.println (data);
} // end of process_data
void loop()
{
static char input_line [MAX_INPUT];
static unsigned int input_pos = 0;
if (Serial.available () > 0) **change this to something like: if (Serial.available () > 8) because there are 9 characters **
{
char inByte = Serial.read (); **times this by 9? **
switch (inByte)
{
case '\n': // end of text
input_line [input_pos] = 0; // terminating null byte
// terminator reached! process input_line here ... **Have the char inByte's control the servos here? **
process_data (input_line);
// reset buffer for next time
input_pos = 0;
break;
case '\r': // discard carriage return
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
Do i need to add more to anything else to this? Also would it be good to add that flash(); function to read the better for this too?
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.
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.
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.
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.
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.h>
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
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.
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.
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.
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.
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?
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?
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?
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?
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?
On the receiving end, what do the serial prints show?
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?
Can you post your current sending code please?
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/<some gibberish>
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/
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/<some gibberish>
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/
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 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.
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.
I believe it should be something like this?
(http://i.imgur.com/M2DOt.jpg)
So i fallowed this diagram and it works fine :) one thing with the code is that it is really jumpy and random. The fingers do move when i move mine but there is a weird delay and the servos are pretty much always moving no matter if i flex my hand or not. We are really close!!!
Try increasing the baud rate to 115200 on both sides.
Try increasing the baud rate to 115200 on both sides.
hmmm now nothing is happening. It is still receiving though. Do i need to reconfigure the xbees for 115200?
I'd forgotten about them. If you can, yes, if you are talking through them. I found with my robot car that a slow communication rate can make the response to controls a bit sluggish.
For example:
.123,100,92,42,99/
That's 18 bytes. At 9600 baud (960 characters per second) that would take 18.7 mS to send. Maybe the problem is something else.
I'd forgotten about them. If you can, yes, if you are talking through them. I found with my robot car that a slow communication rate can make the response to controls a bit sluggish.
For example:
.123,100,92,42,99/
That's 18 bytes. At 9600 baud (960 characters per second) that would take 18.7 mS to send. Maybe the problem is something else.
Could it be the delay? should i change that?
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("/");
delay(10);
You and your delays! Yes get rid of it unless you want a 10 mS sluggishness.
Also comment-out the debugging prints in the receiving end.
Also comment-out the debugging prints in the receiving end.
That did it! perfect!! im going to see if the client wants the feedback system and ill do the code and post it on here
Thank you so much! I will credit you as much as i can! thank you :)