Go Down

Topic: Sending several integers through serial (Read 534 times) previous topic - next topic

Mad physicist

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) :
Code: [Select]

//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.

caliph

Hi.

I am having a similar issue.Have a look at this post, especially the parsing part:
http://arduino.cc/forum/index.php?topic=88647.0

Maybe this helps..

I am very interested in your code with just one value being transmitted. Could you post it here or maybe in my question thread:
http://arduino.cc/forum/index.php/topic,145137.0.html
Thanks!

PaulS

Code: [Select]
  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.

Mad physicist

Quote

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:
Code: [Select]

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 ?

Quote

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 !

PaulS

Quote
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.

Quote
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?

Mad physicist


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 ?

PaulS

Quote
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:
Code: [Select]
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.
Code: [Select]
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.

Mad physicist

#7
Jan 27, 2013, 11:21 pm Last Edit: Jan 27, 2013, 11:24 pm by N_Tesla Reason: 1
It works ! Thank you.

Controlling end:
Code: [Select]

//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:
Code: [Select]

#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.

PaulS

#8
Jan 27, 2013, 11:47 pm Last Edit: Jan 27, 2013, 11:49 pm by PaulS Reason: 1
Quote
Suggestions for improvement welcome.

This part:
Quote
It works !

says that they really aren't needed. But...

Code: [Select]
 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.

zoomkat

A way I capture a string to operate various servos.

Code: [Select]

//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
    }
  }
}

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   8)

Go Up