Serial communication between two arduinos with byte messages and new line feed?

Hey guys,

currently i am trying to build a miniaturized laser driver using an arduino as main processor. In this project, I have a temperature driver which communicates via Serial. It requires a command for example to read out the temperature etc. The read out structure is something like [12345 ] while im assuming LF will be \n. The datasheet link of the temperature driver is shown below:
https://www.thorlabs.com/drawings/6915011c39013acd-548FE80F-B898-EE51-28A8C7BEA423C59E/MTD415T-DataSheet.pdf

Right now I am in home office and want to imitate the temperature driver with a second arduino, which i use to send byte data via serial to my main processor arduino, whereafter i want to print the value to a SSD1306 OLED.

Im a very low level arduino user but i was able to write a code which can handle the later used temperature driver data structure, but i am not sure how to implement the into my byte-like serial message. The size of the temperature driver data forced me (correct me if im wrong) to implement a low/high-byte split and recombination. With this, i dont know how to include the linefeed command into the sender and receiver code.

My idea behind the system is that i can write a code on my main arduino sending commands to the temperature driver which then sends the information to the main arduino via serial. This data should then be shown on the OLED simultaniously (e.g. 6 different variables i get from the driver).

The code of the sender arduino looks like this:

String test = "[12345 Test Test]"; //Here the Test Test will be changed to \n in the real case
String test1;
int val2;


void writeIntAsBinary(int value){
    Serial.write(lowByte(value));
    Serial.write(highByte(value));
    
}

void setup() {
  // Begin the Serial at 9600 Baud
  Serial.begin(9600);
}

void loop() {
  test1 = test.substring(1, (test.length()-1)); 
  val2 = test1.toInt(); 
  writeIntAsBinary(val2);
  delay(1000);
}

The code of the receiver arduino like this:

#include <Adafruit_SSD1306.h>
int incomingByte = 0;
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  // Begin the Serial at 9600 Baud
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
}

void loop() {

  if (Serial.available() > 0) {
    byte b1 = Serial.read();
    byte b2 = Serial.read();

    int val = b1 * 256 + b2;
    Serial.println(val); //Print data on Serial Monitor
    display.clearDisplay();
    display.setCursor(0,0);
    display.print("Input: ");
    display.setCursor(0,28);
    display.print(val);
    display.display();
    delay(1000);
  }
}

I look forward to any ideas regarding this topic

Don't use Sting (capital S).

A line feed is the character '\n', so e.g. String test = "[12345 Test Test]\n"
2)
If you want to send binary data, why go the difficult way of characters arrays / Strings first.
3)
When using binary data, don't add '\n', it will confuse the receiver as it can be a valid value as part of the integer.

What would be the working alternative for using String? The temperature driver sends Strings so i thought it would be good to test it like that.

  1. I know but I dont know how to implement that with my binary byte-like structure of the serial message.

  2. Thats basically the problem I have. What would be the alternative if I need to separate e.g. 6 incoming messages of the TD, which i want to seperately show on the display as single variables.

In principle I know what my program should do, but coming to arduino code for me it is quite difficult from a syntax point of view.

It sends text, not Strings. Character arrays are the better alternative.

If your temperature driver sends text and you want to simulate that, then I would expect your simulator to send text. I guess that I'm missing something.

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

The technique in the 3rd example will be the most reliable. It is what I use for Arduino to Arduino and Arduino to PC communication.

You can send data in a compatible format with code like this (or the equivalent in any other programming language)

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

...R

Hey Robin2, the example 4 on your link was quite helpful thanks a lot! Right now im just struggling with manipulating my incoming serial data.

Since my sensor sends data as [123\n] i need to get rid of the first and last part of my serial.read data. I was looking for a solution but im quite confused with all the char, char*, String and c+string type of data.

I thought I can simply implement a C+ code to get rid of first and last character but it seems to be not as trivial as i thought, maybe anyone has an elegant solution to that? Or is it more convenient to open a new thread in such a case.

This is my example code, as stated before I want to get from [123\n] to 123\n, which my code can interpret:

// Example 4 - Receive a number as text and convert it to an int


const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

int dataNumber = 0;             // new for this version

void setup() {
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
    
}

void loop() {
    recvWithEndMarker();
    showNewNumber();
}

void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
    
   
    if (Serial.available() > 0) {
        rc = Serial.read();
        

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

void showNewNumber() {
    if (newData == true) {
        dataNumber = 0;             // new for this version
        dataNumber = atoi(receivedChars);   // new for this version
        Serial.print("This just in ... ");
        Serial.println(receivedChars);
        Serial.print("Data as Number ... ");    // new for this version
        Serial.println(dataNumber);     // new for this version
        newData = false;
    }
}

I thought I can simply implement a C+ code to get rid of first and last character but it seems to be not as trivial as i thought, maybe anyone has an elegant solution to that?

Why do you need to get rid of the first character? If you KNOW that the first piece of usable data is in position 1, just start using data from that position.

Getting rid of the last character is trivial. Just put a NULL in that position. Or decrement the count, if the array is not NULL terminated.

Because I want to print the sent Serial message to a OLED without the brackets i get from my sensor. My problem right now is mainly my shitty syntax knowledge of chars, arrays etc. Ill have a look into those then maybe.

stullinger89:
Since my sensor sends data as [123\n] i need to get rid of the first and last part of my serial.read data.

The code you have posted should store "[123" into receivedChars

If you use the 3rd example in my Tutorial (with start and end markers) and use '[' as the start marker and '\n' as the end marker it will just put "123" into receivedChars

And if you have control of the sending program why not get it to send "[123]" and use ']' as the end-marker (along with '[' as the start marker).

...R