Brussels, BE
Offline
Newbie
Karma: 0
Posts: 38
|
 |
« on: January 26, 2013, 03:38:49 pm » |
Hello all, I'm trying to send the values taken from the analog inputs read by one Arduino to another Arduino via Xbee. I have a working code for only one value, but I am unable to send several ones. I tried by sending an array; here is my non-working code (shortened to two inputs for simplicity) : //Define Pins int DirectionPot = A5; int ThrottlePot = A3; int Coords[2];
void setup() { Serial.begin(9600); }
void loop() { delay(100); int dir = map(analogRead(DirectionPot), 0, 1024, 90, 140); int thr = analogRead(ThrottlePot); Coords[0] == dir; Coords[1] == thr; Serial.write(Coords); }
The error message reads : invalid conversion from 'int*' to 'uint8_t', with Serial.write(Coords); highlighted. Could you explain me the reason of this error, and how to acheive what I'm trying to do ? In advance, thank you.
|
|
|
|
|
Logged
|
|
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #2 on: January 27, 2013, 08:35:40 am » |
Coords[0] == dir; Coords[1] == thr; = and == are not interchangeable. Serial.write() expects to write bytes, as binary data, not ints. It expects, too, to write ONE byte. If it is to write more than one, when the 1st argument is an array, the number of bytes to write must be supplied as the second argument.
|
|
|
|
|
Logged
|
|
|
|
|
Brussels, BE
Offline
Newbie
Karma: 0
Posts: 38
|
 |
« Reply #3 on: January 27, 2013, 01:52:50 pm » |
Serial.write() expects to write bytes, as binary data, not ints. It expects, too, to write ONE byte. If it is to write more than one, when the 1st argument is an array, the number of bytes to write must be supplied as the second argument.
Thank you. I have rescaled the analog inputs so that they fit in a byte, and asked Serial.write to send 2 bytes. I got no error message on this one: int DirectionPot = A5; int ThrottlePot = A3; byte Coords[2];
void setup() { Serial.begin(9600); }
void loop() { delay(100); byte dir = map(analogRead(DirectionPot), 0, 1024, 90, 140); byte thr = map(analogRead(ThrottlePot),0,1024,0,255); Coords[0] = dir; Coords[1] = thr; Serial.write(Coords,2); }
Is this the "standard way" to send an arbitrary number of values via serial ? And how do I have the second Arduino to discriminate between these two bytes ? I am very interested in your code with just one value being transmitted.
I got the working code for a single byte on this topic : http://arduino.cc/forum/index.php/topic,123820.0.html, reply #6. I was basically trying to emulate Blum's tutorial about how to control a servo wirelessly. Hope this helps !
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #4 on: January 27, 2013, 01:59:24 pm » |
Is this the "standard way" to send an arbitrary number of values via serial ? No. The "standard" way is to use highByte() and lowByte() to extract the MSB and LSB, and send all 4 bytes. And how do I have the second Arduino to discriminate between these two bytes ? Well, now, there's the rub. You can't. Serial data is not guaranteed to be delivered. That is why using serial to send binary data is such a challenge. Sending ASCII data is far simpler to parse and error-check. Is there a need to send a value like 1024 as 2 bytes instead of 4? Or 1 byte, instead of three?
|
|
|
|
|
Logged
|
|
|
|
|
Brussels, BE
Offline
Newbie
Karma: 0
Posts: 38
|
 |
« Reply #5 on: January 27, 2013, 02:12:42 pm » |
Is there a need to send a value like 1024 as 2 bytes instead of 4? Or 1 byte, instead of three?
Nope, actually I proceeded that way because I thought sending two separate values would be recieved as such on the other end. A quick search led me to Serial.print(), is that correct ? Now, to send my Coord[n] vector, I just have to send it "as is", and have the second Arduino to extract the different entries once received ?
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #6 on: January 27, 2013, 02:22:46 pm » |
A quick search led me to Serial.print(), is that correct ? Now, to send my Coord[n] vector, I just have to send it "as is", and have the second Arduino to extract the different entries once received ? Yes, and mo. Using Serial.print() is a better idea. But, you can't Serial.print() an array of anything except characters. You can use a loop to Serial.print() one element at a a time. But, suppose that dir was 541 and thr was 82. If you use this code: Serial.print(dir); Serial.print(thr); the two values would be sent as a collection of characters: "54182". Now, how are you going to take them apart? Are the numbers that were sent 541 and 83? Or, were they 54 and 182? Sending delimiters between the value removes the ambiguity. Serial.print(dir); Serial.print(","); Serial.print(thr); But, now, loop() runs twice, and you send "541,82541,82". Now, you have a different, but similar problem. I'll leave it to you to figure out how to deal with this conundrum. A hint, though. Don't use the same delimiter to mark the end of the packet.
|
|
|
|
|
Logged
|
|
|
|
|
Brussels, BE
Offline
Newbie
Karma: 0
Posts: 38
|
 |
« Reply #7 on: January 27, 2013, 05:21:47 pm » |
It works ! Thank you. Controlling end://Define Pins int DirectionPot = A5; int ThrottlePot = A3;
void setup() { Serial.begin(9600); }
void loop() { delay(100); int dir = map(analogRead(DirectionPot), 0, 1024, 90, 140); int thr = map(analogRead(ThrottlePot), 0, 1024, 0, 255); Serial.print("i"); Serial.print(dir); Serial.print("i"); Serial.print(thr); Serial.print("e"); }
Receiving end:#include <Servo.h>
//Define Pins int servoPin = 9; int pwma = 3;
//Create Servo Object Servo directionServo;
void setup() { Serial.begin(9600); directionServo.attach(servoPin); pinMode(pwma,OUTPUT); delay(100); }
void loop() { while( Serial.available() == 0); { while(Serial.findUntil("i", "e")) { byte pos = Serial.parseInt(); directionServo.write(pos); byte spd = Serial.parseInt(); analogWrite(pwma, spd); } } }
Suggestions for improvement welcome.
|
|
|
|
« Last Edit: January 27, 2013, 05:24:11 pm by N_Tesla »
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #8 on: January 27, 2013, 05:47:55 pm » |
Suggestions for improvement welcome. This part: It works ! says that they really aren't needed. But... Serial.print("i"); Serial.print(dir); Serial.print("i"); Serial.print(thr); Serial.print("e"); I prefer < as the start of packet marker, comma as the field separator, and > as the end of packet marker. To me, "<540, 167>" is easier to read than "i540i167e". To the receiving computer, it makes no difference (unless the start of packet marker is important (as it is in my code), but to humans, it does. By the way, congratulations on persevering to achieve your goal.
|
|
|
|
« Last Edit: January 27, 2013, 05:49:30 pm by PaulS »
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 51
Posts: 6572
Arduino rocks
|
 |
« Reply #9 on: January 27, 2013, 06:07:41 pm » |
A way I capture a string to operate various servos. //zoomkat 11-22-12 simple delimited ',' string parse //from serial port input (via serial monitor) //and print result out serial port //multi servos added
String readString; #include <Servo.h> Servo myservoa, myservob, myservoc, myservod; // create servo object to control a servo
void setup() { Serial.begin(9600);
//myservoa.writeMicroseconds(1500); //set initial servo position if desired
myservoa.attach(6); //the pin for the servoa control myservob.attach(7); //the pin for the servob control myservoc.attach(8); //the pin for the servoc control myservod.attach(9); //the pin for the servod control Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded }
void loop() {
//expect single strings like 700a, or 1500c, or 2000d, //or like 30c, or 90a, or 180d, //or 30c,180b,70a,120d,
if (Serial.available()) { char c = Serial.read(); //gets one byte from serial buffer if (c == ',') { if (readString.length() >1) { Serial.println(readString); //prints string to serial port out
int n = readString.toInt(); //convert readString into a number
// auto select appropriate value, copied from someone elses code. if(n >= 500) { Serial.print("writing Microseconds: "); Serial.println(n); if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n); if(readString.indexOf('b') >0) myservob.writeMicroseconds(n); if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n); if(readString.indexOf('d') >0) myservod.writeMicroseconds(n); } else { Serial.print("writing Angle: "); Serial.println(n); if(readString.indexOf('a') >0) myservoa.write(n); if(readString.indexOf('b') >0) myservob.write(n); if(readString.indexOf('c') >0) myservoc.write(n); if(readString.indexOf('d') >0) myservod.write(n); } readString=""; //clears variable for new input } } else { readString += c; //makes the string readString } } }
|
|
|
|
|
Logged
|
|
|
|
|
|