serial problems

Hello all,

I am trying to get my arduino to listen to its serial USB connection and save the information in two variables.

For instance, the serial RX would see these two bytes:
120
200

I would like to have one variable (lets say x) set the the first incoming byte, and another variable (lets say y) set to the second.

Im at a loss for how to have the arduino do this. I thought of indexing an array of the incoming information, but I think I was headed down the wrong path.

Thoughts? Thank you!

How are you reading in the characters? If you are using a string then you will need to convert the string to an integer using the atoi() function.

I am reading using a simple Serial.read()

for example:

x = Serial.read();

I understand that when I send "120" to the Rx pin, the arduino will not read that as the integer 120... however, that seems simple enough to figure out.

My main question is how do I set the arduino to continually listen to the serial line and set the first byte to one variable and the second byte received to another variable.

Thanks again.

I'm trying not to write the code for you. How about using a variable of type "boolean" which is initialized to false. When the variable is false then read the serial input into one variable otherwise read it into the second. Flip the boolean variable so it takes the "other" path next time.

This solution works but it is not general purpose. For a more general purpose solution, google on "Finite State Machines".

You could call Serial.read twice, and assign the returned values to different variables.
Or have I missed soemthing?

Mike,

Sorry if it seems like im asking you to give me some code as I am definitely not one to do that. I'm just having trouble with some overall concepts here.

I like your boolean idea. However, it wont work if my serial connection is interupted between the two bytes. The two variables would then be flipped, essentially steering my robot in reverse.

Maybe a better explanation of what my code will eventually do will make it easier for someone to point me in the right direction.

I'm using the arduino as an interface between many sensors, a motor controller (which is connected via software serial), and its own USB connection that will be hooked up to an onboard laptop that will be processing video feed and sending steering directions to the arduino.

Here is how I have the arduino talking to the motor controller:

void put(unsigned int m1, unsigned int m2){
//we use the put command to set the speed of the motors
Serial.print(0x80,BYTE); //start byte
Serial.print(0x07,BYTE); //device id
Serial.print(0x55,BYTE); //command number
Serial.print(m1,BYTE); //m1 speed
Serial.print(m2,BYTE); //m2 speed
}

The motor controller is listening and interpreting all these different bytes seperately... and more or less I would like to do the same with the arduino.

Is there some way to index the incoming bytes; so as to say I could, for example, set m1=input[4]?

However, it wont work if my serial connection is interupted between the two bytes

It looks like you're saying you can't rely on the integrity of the link, i.e. you can't be sure that what you've received is valid.

If that's the case, you should consider sending your data in packets, with a simple checksum. As you receive each packet, you re-calculate the checksum on the incoming data, and if it doesn't match the one transmitted, you reject the whole packet and request a retransmission.

Groove is right.

You need some kind of communication protocol between the host PC and Arduino. You could build on an existing one such as Modbus but in your case it is probably easier to make one up. You already have an example of what it might look like with the motor controller interface. However I would add responses and checksums.

A simple format might be:
[command code] [length of msg] [parameter values] [checksum]

A response might be:
[command code] [length of msg] [response code] [checksum]

where:
command code might be 0-254
response codes might be ok, checksum error, command error etc
checksum could be a 8 checksum or a 8/16-bit CRC

With this format you could decide to send the m1/m2 values either as two independent commands or in a single command. Whatever makes sense in your application.

You can clearly use the same protocol to send image data back to the PC. I'm don't know how you are doing it right now.

You also need to decide who is the master i.e. which end is passively waiting for work to do and sending acks when it is completed. Is it the host PC sending motor data and requesting back image data. Or is it the Arduino sending image data and requesting motor speed information.

Extensions to this protocol are only limited by your imagination.

To answer your question, you can declare an array of characters and Serial.read() serial data into the array. The Serial.available() function is useful to know how much to read in and the length field in each message tells you how much you need to read. You may decide that the length of a message for a given command code is fixed and that means you only need to read the command code byte to know how much more data to wait for. After reading in all of the bytes in the message, you need to verify the checksum, send a response back to the host PC. Then you can grab the individual parameter values. An integer parameter needs to be assembled from 2 bytes in the message - make sure you know the ordering of bytes in the message.

Thanks for all your help guys.

So what I think im going to do is have the computer wait for a start command (int or string) from the arduino. They will then both send/recieve data one integer at a time, and then waiting a specified delay (like 10 ms or less) before recieiving/sending the next piece of data. The arduino will save each After, the arduino will check to make sure that it recieved all the data it was supposed to, and it is within the bounds of what it expected.

For example:

//for arduino//

Serial.print('begin');
m1=Serial.read();
delay(10);
m2=Serial.read();
delay(10);
//and so on and so forth//

Sounds easy enough. Thanks again guys.

Alright guys... I have some code now. I've been testing it to various levels of success. Hopefully there is something glaringly obvious to those who are more coding proficient.

Here is my Arduino Code:

//include the software serial library
#include <SoftwareSerial.h>

//define the software serial tx and rx pins
#define rxPin 9
#define txPin 8

// set up the 'fake' serial port
SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);

/**

  • the following is WORKING code that sets the forward speed of both motors.
    **/

void put(unsigned int m1, unsigned int m2){
//we use the put command to set the speed of the motors
mySerial.print(0x80,BYTE); //start byte
mySerial.print(0x07,BYTE); //device id
mySerial.print(0x55,BYTE); //command number
mySerial.print(m1,BYTE); //m1 speed
mySerial.print(m2,BYTE); //m2 speed
}

int serialInArray[3]; // Where we'll put what we receive
int serialCount = 0; // A count of how many bytes we receive
int m1=0;
int m2=0; // Starting position of the ball
boolean firstContact = false; // Whether we've heard from the microcontroller

void setup() {
Serial.begin(9600);

//setup for mySerial port
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
mySerial.begin(19200); // this must be 19200 because that is the standard for the TreX motor controller

}

void loop(){

// read a byte from the serial port:
int inByte = Serial.read();
// if this is the first byte received, and it's an A,
// clear the serial buffer and note that you've
// had first contact from the microcontroller.
// Otherwise, add the incoming byte to the array:
if (firstContact == false) {
if (inByte == 'A') {
Serial.flush(); // clear the serial port buffer
firstContact = true; // you've had first contact from the microcontroller
Serial.write('A'); // ask for more
}
}
else {
// Add the latest byte from the serial port to array:
serialInArray[serialCount] = inByte;
serialCount++;

// If we have 3 bytes:
if (serialCount > 1 ) {
m1 = serialInArray[0];
m2 = serialInArray[1];

// print the values (for debugging purposes only):
Serial.println(m1 + "\t" + m2);

// Send a capital A to request new sensor readings:
Serial.write('A');
// Reset serialCount:
serialCount = 0;
}
}

put(m1,m2);

}

Note that if when I just use put(200,200) i get a response from my motor controller. This tells me that there is no problem with my software serial connection, and it has to be with the connection between the Arduino and processing.

Here is the code I use for processing:

import processing.serial.*;

Serial myPort; // The serial port

int firstSensor = 0; // first analog sensor
int secondSensor = 0; // second analog sensor
int thirdSensor = 0; // digital sensor
int inByte = 0; // incoming serial byte

void setup() {
size(256, 256); // Stage size
noStroke(); // No border on the next thing drawn

// Print a list of the serial ports, for debugging purposes:
println(Serial.list());

// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
establishContact(); // send a byte to establish contact until Arduino responds
}

void draw() {
{
// if we get a valid byte, read analog ins:
if (myPort.available() > 0) {
// get incoming byte:
inByte = myPort.read();
// send sensor values:
myPort.write(100);
myPort.write(100);
}
}
}

void establishContact() {
while (myPort.available() <= 0) {
myPort.write('A'); // send a capital A
delay(300);
}
}

Thoughts?

I assume it's the user on the processing side that instigates sending messages so your protocol does not need to request the data from arduino.

If your data consists of value that are less then 255 I suggest your message consists of a single byte header and the two binary bytes containing the data.

The Processing side could have something like this:

void sendMessage(byte value1, byte value2){
// send the given values as a three byte message to the serial port
myPort.write(255); // this is the header
myPort.write(value1);
myPort.write(value2);
}

The arduino code would have something like this:

byte value1;
byte value2;

void loop() {
if ( Serial.available() >= 3) // wait for header plus two bytes
{
if( Serial.read() == 255) // check for the header
{
value1 = Serial.read();
value2 = Serial.read();
// do something here with the values
}
}
}