How to receive multiple variables from the serial port and then convert them into a float?

Hello!

I am trying to receive three separate numbers from the serial port and then convert all of them into their own respective float variables so they can be mathematically manipulated separately.

This is what I have so far:


char input, lower, upper;

//void setup() code

void loop() 
{
  
if ( Serial.available())     //Checks the availability of Serial port 
{

input = Serial.read();      // Read the data and stores it in variable
lower = Serial.read();
upper = Serial.read();
 
}

float input;
float lower;
float upper;

//Rest of the code follows
}

However, I fear that I just write over the variable each time, so that input, lower and upper are all just the last entered variable.

Some direction and help would be much appreciated!

Thank you!

Serial.read gives You one byte! 0 - 255 as integer....
Check Arduino/reference about Serial.
Search for Serial.parseFloat!
Put a separation character between the floats when sendinh them.

1 Like

You can place the 3 received bytes in a union then take out the float.

union received      // union to convert bytes to floats.
{
  float f;
  byte first;
  byte second;
  byte third;
}x;

your specification is rather vauge
where are the three variables comming from ? what is the format?
are they binary bytes, two byte integers, four byte integers, four byte floats, etc or some text format such as JSON

1 Like

You only know that there's at least one character available, yet you go right ahead and read three of them

Time for a rethink.

1 Like

The three variable would come from a user input entered into the serial port, and I am honestly unsure the format!

This is my first time using the serial port for user inputs, so even though I have researched about this method, I still don't have a great grasp on all the fine details. (Before this I was using a physical keypad wired to the Arduino for user inputs!)

I actually didn't know that! Could you please elaborate on what you're saying and perhaps point me in a direction to go rethink?

The way you have used Serial.available, all you can tell is that there are zero characters available OR at least one character available.
If there's only one character available (most likely scenario, after zero available) then it makes no sense to read three characters.

think you need to specify what the program is to do, i.e. what is the input data, what processing, what output etc, etc etc
you cannot start to code until you have some idea what is program is to do

possibly start by looking at some tutorials?
get some idea what the various microcontroller development boards can do?

A good place to start would be to study the Serial Input Basics tutorial on this forum.

1 Like

Your problem is that at the moment you don't understand clearly how computers store and transmit data. The digit '1' is not sent as a number. It is sent as numeric value that represents a character which is a one.

You read characters one at a time then you need to work out what numbers those characters represent.

Look up ASCII

Serial.parseFloat() will parse characters read from Serial into a float.

Exactly! I use for an application ready for sharp work. Serial monitor sends a float to the controller some times. I thought the OP wanted to transfer floats.

1 Like

Assume that your Arduino UNO is expecting to receive 125.75, 61.73, and 243.69 from a remote sender/ Serial Monitor as ASCII codes over Serial Port; after reception, the data items would be saved in these variables: float y1, float y2, and float y3.

1. Upload the following sketch in UNO.

char myData[30] = {0};

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

void loop()
{
  byte n = Serial.available();
  if (n != 0)
  {
    byte m = Serial.readBytesUntil('\n', myData, 30);
    myData[m] = '\0'; //null-byte
 
    float y1 = atof(strtok(myData, ","));
    Serial.print("float y1 = "); Serial.println(y1, 2);

    float y2 = atof(strtok(NULL, ","));
    Serial.print("float y2 = "); Serial.println(y2, 2);

    float y3 = atof(strtok(NULL, ","));
    Serial.print("float y3 = "); Serial.println(y1, 2);
  }
}

2. Open Serial Monitor at Bd = 115200 with Newline option in the Line ending box.
3. Enter the following string in the InputBox of Serial Monitor and then click on the Send Button.

125.75, 61.73, 243.69 

4. Check that the OutputBox of Serial Monitor shows:

float y1 = 125.75
float y2 =  61.73
float y3 = 243.69

so far there has been no mention of the microcontroller to be used
it may be something with a little more power than a UNO
e.g. an ESP32 using sscanf()

// parse serial data input 125.75, 61.73,243.69

char myData[30] = { 0 };

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

void loop() {
  byte n = Serial.available();
  if (n != 0) {
    byte m = Serial.readBytesUntil('\n', myData, 30);
    myData[m] = '\0';  //null-byte
    float y1, y2, y3;
    if (sscanf(myData, "%f,%f,%f", &y1, &y2, &y3) == 3) {
      Serial.println("parsed three floats ok");
      Serial.print("float y1 = ");
      Serial.println(y1, 2);
      Serial.print("float y2 = ");
      Serial.println(y2, 2);
      Serial.print("float y3 = ");
      Serial.println(y3, 2);
    } else Serial.println("error in input!");
  }
}

serial monitor when given "125.75, 61.73,243.69" displays

parsed three floats ok
float y1 = 125.75
float y2 = 61.73
float y3 = 243.69
1 Like

Is the sketch of post #15 executable in Arduino UNO/MEGA/NANO?

The sketch works well in ESP32 (ESP32 Dev Module).

due to restrictions with conversion %f I would not expect an UNO to be able to use sscanf to parse floats
ints would be OK, e.g.

// parse serial data input 125,67,-45

char myData[30] = { 0 };

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

void loop() {
  byte n = Serial.available();
  if (n != 0) {
    byte m = Serial.readBytesUntil('\n', myData, 30);
    myData[m] = '\0';  //null-byte
    int y1, y2, y3;
    if (sscanf(myData, "%d,%d,%d", &y1, &y2, &y3) == 3) {
      Serial.println("parsed three ints ok");
      Serial.print("int y1 = ");
      Serial.println(y1);
      Serial.print("int y2 = ");
      Serial.println(y2);
      Serial.print("int y3 = ");
      Serial.println(y3);
    } else Serial.println("error in input!");
  }
}

when given "125,67,-45" UNO serial monitor displays

parsed three ints ok
int y1 = 125
int y2 = 67
int y3 = -45

Yes! The sketch does not work in standard Arduino for float numbers.

As UNO is the most common platform, then is there any other function other than strtok() to extract individual float numbers from an ASCII coded message?

you could set the sscanf delimiter as ',' and convert "125.75, 61.73,243.69" to three strings then use atof(), e.g.

// parse serial data input 125.75, 61.73,243.69

char myData[30] = { 0 }, s1[10], s2[10], s3[10];

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

void loop() {
  byte n = Serial.available();
  if (n != 0) {
    byte m = Serial.readBytesUntil('\n', myData, 30);
    myData[m] = '\0';  //null-byte
    float y1, y2, y3;
    if (sscanf(myData, "%[^','],%[^','],%s", s1, s2, s3) == 3) {
      y1 = atof(s1);
      y2 = atof(s2);
      y3 = atof(s3);
      Serial.println("parsed three strings ok");
      Serial.print("float y1 = ");
      Serial.println(y1, 2);
      Serial.print("float y2 = ");
      Serial.println(y2, 2);
      Serial.print("float y3 = ");
      Serial.println(y3, 2);
    } else Serial.println("error in input!");
  }
}

when given "125.75, 61.73,243.69" the UNO serial monitor displays

parsed three strings ok
float y1 = 125.75
float y2 = 61.73
float y3 = 243.69

starts to get convolved - probably on an UNO strtok() is easier to understand

Edit: the advantage of

 if (sscanf(myData, "%f,%f,%f", &y1, &y2, &y3) == 3) {

in post 15 is it checks for valid %f conversions, i.e. three in the above statement
but it does not work on low power micros such as UNO, Mega, etc
if there is invalid text atof() just returns 0

1 Like

If my input data items are "space separated", then should I have "spaces" to separate the format specifiers? For example"

char myData[] = "123 45";
int y1, y2;
sscanf(myData, "%d %d %d", &y1, &y2);