Serial Frame

How do I go about creating a serial frame in the Arduino language? I want to communicate between two Arduinos, using the RX and TX pins.

Example:

Analog in 0-5 on the transmitting Arduino needs to be read by the receiving Arduino. These need to by synced up some how, don't they? The the best way would be to make frames for this, correct?

What are frames? You mean some kind of message protocol?
As in send 4 bytes over (since analog read is 10 bits), first 2 bytes the opposite of the second 2, the reciever ANDs them together, if result is 0 it sends them back to show a good message was received? Use the upper bits to make sure 00 00 doesn't go out.

A frame is simply a series of bytes in a format that has been agreed on by both ends of the comms link. What Crossroads suggests is as good an example as any for a very simple application and even has some error checking and acknowledging which most protocols at this level don't.

Or you could simply do something like this

Serial.print ('<');
Serial.print (pinNum, HEX);
Serial.print (pinVal, HEX);
Serial.print ('>');

which would send say "<11234>" and the receiver splits the 1 and the 1234 to get the pin number and the value. The < syncs the receiver and tells it to start reading characters and the > tells it to stop and parse the data. If the data is fixed length you don't need the >.

A more sophisticated version may be like this

Which has addressing, a frame sequence counter, data length, command and a CRC.

Really it's up to you to decide now you want to do it. Do a search for "communicating between two Arduinos" or some such, this comes up about twice a day.


Rob

If the data is fixed length you don't need the >.

Still, it's a good idea to send it. You can use the arrival of the > at the right time to know that the correct number of bytes was received.

Graynomad:
A frame is simply a series of bytes in a format that has been agreed on by both ends of the comms link. What Crossroads suggests is as good an example as any for a very simple application and even has some error checking and acknowledging which most protocols at this level don't.

Or you could simply do something like this

Serial.print ('<');

Serial.print (pinNum, HEX);
Serial.print (pinVal, HEX);
Serial.print ('>');




which would send say "<11234>" and the receiver splits the 1 and the 1234 to get the pin number and the value. The < syncs the receiver and tells it to start reading characters and the > tells it to stop and parse the data. If the data is fixed length you don't need the >.

A more sophisticated version may be like this

![](http://busnet.robgray.com/software/graphics/frame.png)

Which has addressing, a frame sequence counter, data length, command and a CRC.

Really it's up to you to decide now you want to do it. Do a search for "communicating between two Arduinos" or some such, this comes up about twice a day.

______
Rob

That is exactly what I am looking for. I want something that has addressing, and data. Do you know how I would code both ends?

If you're referring to the frame in the graphic I have code to create and transmit that but it's still very much in an alpha state and I haven't even started writing the receive code.

I can cut some parts from the code and post it but it will be specific to my applicaiton and may not make much sense outside that.

As you need addressing I take it you're doing some form of multi-drop network. What is the application?


Rob

Below is some simple code that uses an end of data packet marker.

//zoomkat 9-9-10 simple delimited ',' string parce 
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter

String readString;

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

void loop() {

        //expect a string like wer,qwe rty,123 456,hyre kjhg,
        //or like hello world,who are you?,bye!,
        while (Serial.available()) {
        delay(1);  //small delay to allow input buffer to fill
    	char c = Serial.read();  //gets one byte from serial buffer
        if (c == ',') {break;}  //breaks out of capture loop to print readstring
        readString += c; //makes the string readString
        }
      
      if (readString.length() >0) {
      Serial.println(readString); //prints string to serial port out
      
      //do stuff here
      
      readString=""; //clears variable for new input
      }
   }

The application is a large led board. I have one arduino that converts Ethernet to whatever, currently UART. The other arduino I have is designated for driving TLC5940's. I have the ethernet code working great. I just need a way to send data from arduino to arduino. I want an address and a value.

I just need a way to send data from arduino to arduino. I want an address and a value.

For the communication, you could appropriately connect the arduino serial ports together. As to address and value, you could send a128, where the "a" is an address and the "128" is the value.

What would be the command for receiving a Serial.write for the value, and Serial.print for the address? Serial.read only seems to work with Serial.write.

Serial.read only seems to work with Serial.write.

No. Serial.read() will read (one character at a time) stuff sent by Serial.print() and Serial.println().

Could you give an example of the code? The only way I see it can be done is with if statements. Would I put in a Serial.read in the if statement to get the address, and then another to get the value?

The only way I see it can be done is with if statements. Would I put in a Serial.read in the if statement to get the address, and then another to get the value?

An if statement has a conditional section and a body, that may consist of a single statement or multiple statements. The Serial.read() MIGHT be part of the body of an if statement, but I can't imagine what the conditional part would be.

The value is being sent as an array of characters. They will need to be read and stored in a char array, NULL terminated of course, and that array passed to atoi() to convert it back to an int.

How do you know when the end of the value has been received?

The values will be 0-255. I don't know what i'm going to use for addressing yet.

If you have binary data that makes it harder to differentiate between data and delimiters. In my pretty picture above the value 0x40 is a sync character, of course that's a valid data character as well so if you start reading chars half way through a frame you could get all screwed up, I use some low-level timing to detect an idle line but that's all way too much for your app I would think.

So you might find it easier to stick with ASCII representations of the data and use atoi() on the receiving end to reconstruct the data.

There must be 1000s of examples in this forum by now, this problem is raised every few days. Have a search for something like "communication between two arduinos"


Rob

in the Example,
Code:
Serial.print ('<');
Serial.print (pinNum, HEX);
Serial.print (pinVal, HEX);
Serial.print ('>');

How do I read that and interpret it on the receiving end?

How do I read that and interpret it on the receiving end?

Did you try the code I posted? You probably don't need delimiters on both ends of the data to just communicate between two arduinos. As to working code with two delimiters, people will tell you you need it, but they've never posted working code that I remember.

If you use Serial.print(pinNum, BYTE); instead, your life will be better =) (the following code assumes this).

note: code untested

sending code:

  uint8_t pinNum = 0;
  uint16_t pinVal = analogRead(pinNum);
  Serial.print('<');
  Serial.print(pinNum, BYTE);
  Serial.print(pinVal >> 8, BYTE);
  Serial.print(pinVal & 0xff, BYTE);
  Serial.print('>');

receiving code

char buf[8];
uint8_t bufPtr = 0;

void flush() {
  bufPtr = 0;
  for (uint8_t i = 0; i < 8; i++) {
    buf[i] = ' ';
  }
}

void process() {
  // if the string is the right length
  if (strlen(buf) == 3) {
    // the first byte is the pin number
    uint8_t pinNum = buf[0];
    // the next two bytes make up the pin value
    uint16_t pinVal = (buf[1] << 8) | buf[2];
    // do something
  }
  // reset the buffer
  flush();
}

void loop() {
  while (Serial.available()) {
    // read the byte in
    char c = Serial.read();
    // if it is the start character, reset the buffer
    if (c == '<') {
      flush();
    // if it is the end character, or the buffer isn't long enough
    } else if (c =='>' || bufPtr >= 8 - 1) {
      // terminate the string
      buf[bufPtr] = '\0';
      // process the buffer
      process();
    // otherwise
    } else {
      // append to the buffer
      buf[bufPtr] = c;
      bufPtr++;
    }
  }
}

This works with delimiters on both ends - it also doesn't use the String class, so no dynamic memory pains =).

This works with delimiters on both ends - it also doesn't use the String class, so no dynamic memory pains =).

It doesn't compile. :roll_eyes:

Aeturnalus:
If you use Serial.print(pinNum, BYTE); instead, your life will be better =) (the following code assumes this).

note: code untested

sending code:

  uint8_t pinNum = 0;

uint16_t pinVal = analogRead(pinNum);
  Serial.print('<');
  Serial.print(pinNum, BYTE);
  Serial.print(pinVal >> 8, BYTE);
  Serial.print(pinVal & 0xff, BYTE);
  Serial.print('>');




receiving code


char buf[8];
uint8_t bufPtr = 0;

void flush() {
  bufPtr = 0;
  for (uint8_t i = 0; i < 8; i++) {
    buf[i] = ' ';
  }
}

void process() {
  // if the string is the right length
  if (strlen(buf) == 3) {
    // the first byte is the pin number
    uint8_t pinNum = buf[0];
    // the next two bytes make up the pin value
    uint16_t pinVal = (buf[1] << 8) | buf[2];
    // do something
  }
  // reset the buffer
  flush();
}

void loop() {
  while (Serial.available()) {
    // read the byte in
    char c = Serial.read();
    // if it is the start character, reset the buffer
    if (c == '<') {
      flush();
    // if it is the end character, or the buffer isn't long enough
    } else if (c =='>' || bufPtr >= 8 - 1) {
      // terminate the string
      buf[bufPtr] = '\0';
      // process the buffer
      process();
    // otherwise
    } else {
      // append to the buffer
      buf[bufPtr] = c;
      bufPtr++;
    }
  }
}




This works with delimiters on both ends - it also doesn't use the String class, so no dynamic memory pains =).

How would the receiving end work with multiple input pins? From what I see, you only are sending the value of a single pin.