1

I'm trying to build a GUI that sends the data from processing to arduino via serial. With the help of a couple of guys on here, I have come up with a basic framework that sends a variable ID, variable value and termination character (\n). So far so good!

However, the [arduino reference][1] advises to only use char for storing characters. How would I send a byte or int over serial, while still being able to use a termination character to ensure everything is working as expected?

edit: Using the arduino code from Edgar's answer below and the following processing code, I get the "could not parse value" error.

import processing.serial.*;

SerialConnection serialConnection;

boolean data_processed = false;
char[] var_array = new char[31];
char var_id;
char var_val;
char space = ' ';
char termchar = '\n';

void setup() {
  serialConnection = new SerialConnection(this, 9600);
}

void draw() {
  serialConnection.startSerialCommunication();

  if (serialConnection.isReady) {
    var_id = 'a';
    var_val = 127;
    serialConnection.serialPort.write(var_id);
    serialConnection.serialPort.write(space);
    serialConnection.serialPort.write(var_val);
    serialConnection.serialPort.write(termchar);

    delay(50);
    while (serialConnection.serialPort.available() > 0) {
      for (int i = 0; i < 30; i++) {
        char inchar = serialConnection.serialPort.readChar();
        var_array[i] = inchar;
        print(var_array[i]);
      }
    }
  }
}
1

1 Answer 1

2

If you want to send numeric values to your Arduino, the simplest option is to send them formatted as ASCII text. Thus you end up simply sending characters.

Let's assume for example a simple text-based protocol of the form

foo 42
bar 5678
baz -12

Each message is made of a variable name followed by its numeric value. The name and the value a separated by a space. Each message is terminated by a line feed ('\n').

In order to parse a message, you first have to split it at the space character. The strsep() function comes handy for this. Then, you have to parse the second part of the message (the value) as an integer. I would use strtol() for this job. Putting all together:

void process(char *message) {
    char *name = strsep(&message, " ");  // split at the space
    if (!message) {
        Serial.println("Error: no value given");
        return;
    }
    char *endp;  // end of the numeric value
    long value = strtol(message, &endp, 0);
    if (endp == message) {
        Serial.println("Error: could not parse value");
        return;
    }
    /* Successfully parsed. */
    Serial.print(name);
    Serial.print(" received value ");
    Serial.println(value);
}

Note there are some sanity checks in order to make sure the message does match the expected format. Obviously, you have to replace the last three lines by something more meaningful to your application.

Example sketch using this:

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

void loop() {
    static char buffer[40];
    static size_t buffer_pos = 0;
    while (Serial.available()) {
        char c = Serial.read();
        if (c == '\n') {  // end of message
            buffer[buffer_pos] = '\0';  // terminate the string
            process(buffer);
            buffer_pos = 0;  // reset for next message
        } else if (buffer_pos < sizeof buffer - 1) {
            buffer[buffer_pos++] = c;  // buffer the character
        }
    }
}
8
  • Thank you for the answer, Edgar! Sorry for the delay in responding, wanted to go through everything. I really appreciate the code example. Also, didn't even know these functions existed. If I understand what's happening correctly, you're passing by address the buffer array to the process function, which dereferences it, and is then fed into the str functions? What confuses me is, it looks like the process function takes a single char as argument, but it actually processes the whole buffer array. Is that normal C behavior when using pointers to arrays, or is specific to the str.. functions? Dec 17, 2021 at 11:33
  • Also these functions have double pointers. That's crazy. Dec 17, 2021 at 11:33
  • Finally, I love how elegant this code is, lots to learn here! Dec 17, 2021 at 11:42
  • 1
    @ZhelyazkoGrudov: Re “If I understand what's happening correctly, you're passing by address the buffer array”: Exactly. Whenever you pass an array to a function in C or C++, it “decays” to a pointer to its first element. This “decay to pointer” behavior is generic: it affects all arrays whenever you do mostly anything with them. The str*() functions all expect a pointer to the first element of a NUL-terminated array of char. What is specific about them is that they interpret the first null char they find as the end of the string. Dec 17, 2021 at 12:34
  • 1
    @ZhelyazkoGrudov: Your Processing code is sending an escape character (ASCII code 127) instead of "127". The Arduino expects an ASCII string: try sending '1', then '2', then '7'. I don't know Processing, but it is more than likely that it has a method similar to Arduino's print() that would format a number in ASCII for you. You may then write something like serialConnection.serialPort.print(127);. I don't know the exact name of the method. If you have to ask, look for some forum relevant to Processing (not here). Dec 17, 2021 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.