When I use println using Serial data, it gives me unexpected output

hi, Jimit here, I want to send flight data through telemetry via Serial connection, but when I receive on telemetry my pc, I got weird data, that data I show is not in a proper format. I don't know how to deal with it.please help me

#include <Wire.h>
#include <Arduino.h>
#include <IMUs/IMU.h>

uint32_t LOOP_TIMER, now, then;

IMU imu = IMU();

float x;
float y;
float z;

void setup()
{
  imu.begin();
  imu.setConfig();

  Serial4.begin(57600);
  delay(10);

  LOOP_TIMER = micros();
}

void loop()
{
  // put your main code here, to run repeatedly:

  now = millis();

  if (now - then >= 10)
  {
    imu.getBMI088AccData();
    // Data in [rad/s]
    Serial4.print(imu.mAccBmi088Data(0), 6);
    Serial4.print(",");
    Serial4.print(imu.mAccBmi088Data(1), 6);
    Serial4.print(",");
    Serial4.println(imu.mAccBmi088Data(2), 6);
    Serial4.flush();
    then = now;
  }
}
0,-0.033700,91,-0.035897,0.994139
0.038095,-0.032234,0.998535
0.038095,-0.035165,1.005128
0.036630,-0.038095,0.998535
0.038828,-0.033700,1.000733
0.037363,-0.035897,0.997070
0.036630,-0.032234,0.994872
0.041026,-0.036630,0.998535
0.037363,-0.034432,1.000000
0.037363,-0.033700,0.996337
0.035897,-0.034432,0.95,-0.031502,1.000733
0.036630,-0.040293,0.993407
0.038828,-0.036630,0.998535
0.039560,-0.042491,535
0.036630,-0.037363,0.998535
0.041758,-0.031502,0.998535
0.035165,-0.031502,0.998535
0.039560,-0.030769,1.001465
0.037363,-0.034432,0.999267
0.035897,-0.028571,0.997070
0.041758,-0.032234,0.997802
0.038828,-0.032960.038828,-0.038095,0.996337
0.038828,-0.037363,1.002930
0.043223,-0.037363,0.999267
0.037363,-0.033700,0.997070
0.040293,-0.037363,0.998535
0.037363,-0.032967,0.997802
0.043223,-0.033700,0.997070
0.033700,-0.030037,0.999267
0.040293,-0.032967,0.995604
0.036630,-0.036630,0.9992658,-0.036630,1.000000
0.038828,-0.038828,0.996337
0.039560,-0.035897,0.999267
0.036630,-0.034432535
0.038095,-0.033700,1.000000
0.042491,-0.032234,0.999267
0.034432,-0.027839,1.000733
0.038828,-0.037363,0.997070
0.041026,-0.032967,0.998535
0.040293,-0.037363,0.999267
0.038828,-0.036630,0.994139
0.035897,-0.0337093,-0.034432,1.000733

For "proper format" I must imagine you just need a 6 decimals float number, right?
To let us understand you should specify what IMU model and what library (a direct link is the best way) you're using. I'm sorry, I can't find anything useful to know, for instance, the exact definition of "mAccBmi088Data()" data type.

while you not read the data, where is it goes?

no, this not help. so where is the data go while you don't want to receive it?

57600/10*0.010 ~ 57.6 characters/message

Could you increase the baud rate or increase the delay between reports and see if you are I/O bound?

dear sir, the proper format means I should get data like this "0.038095,-0.032234,0.998535" but you can see sometimes I get this type of data "0.036630,-0.036630,0.9992658,-0.036630,1.000000"

you can clearly view in my code how I can not get the expected results sometimes, so I can't properly read my data on my pc, I built my own IMU library BMI270 and BMI088 sensor, I used design patterns and wrap into the library, the problem is not that, mAccBmi088Data() is void function which updates imu.mAccBmi088Data this vector, and sadly I can not change baud rate because My telemetry does not support any other bauds If I decrease execution time my results are useless,

show output of this program:

#include <Wire.h>
#include <Arduino.h>
#include <IMUs/IMU.h>

uint32_t LOOP_TIMER,  then;

IMU imu = IMU();

float x;
float y;
float z;

void setup(){
  imu.begin();
  imu.setConfig();
  Serial4.begin(57600);
  delay(10);
  LOOP_TIMER = micros();
}

void loop(){
  if (millis() - then >= 10)  {
    imu.getBMI088AccData();
   
    Serial4.print(imu.mAccBmi088Data(0), 6); // Data in [rad/s]
    Serial4.print(":");
    Serial4.print(imu.mAccBmi088Data(1), 6);
    Serial4.print(";");
    Serial4.print(imu.mAccBmi088Data(2), 6);
    Serial4.println("!");
    then += 10;
  }
}

I was suggesting slower rate to test if the problem is IO and goes away if you use less bandwidth. It doesn't look like a println problem, or a serial problem--it looks like you are dropping data due to buffer overrun somewhere.

Perhaps try less precision:

    Serial4.print(imu.mAccBmi088Data(0), 3);
    Serial4.print(",");
    Serial4.print(imu.mAccBmi088Data(1), 3);
    Serial4.print(",");
    Serial4.println(imu.mAccBmi088Data(2), 3);

Serial wise, what hardware are you using? Is that software serial on an Uno?

Code?
Schematic?

If run a 10Hz program it runs perfectly! so no solution for high-rate data transfer? I use Teensy 4.1 controller for my drone where I Use Serial4! above I give My full of code! are you want to check IMU code? so I can not run my code at faster rate?

Teensy4? I think the code is probably fast enough, it's just the baud rate seems to be limiting your bandwidth.

Maybe look into increasing the buffer sizes:

https://www.pjrc.com/teensy/td_uart.html

Did you try the 3-decimal place printing?

I think the problem is not the Serial side, I try everything, including Increasing buffer size, but my program only runs expected at a 10Hz rate, I try the 3-decimal place printing, and it work but in that case, I lose presign.

bro, your program output is like this. I think the problem is not in the loop,

0.0530.052747,-0.035897,0.997802
0.051282,-0.034432,0.997802
0.049817,-0.035165,1.00
0.050549,-0.034432,0.999267
0.052747,-0.035165,0.999267
0.052747,-0.035897,0.997802
0.052747,-0.037363,0.996337
0.049084,-0.034432,1.000733
0.047619,-0.038828,0.998535
0.050549,-0.038828,0.999267
0.049817,-0.033700,10.050549,-0.030037,0.998535
0.049084,-0.034432,0.997802
0.052747,-0.033700,0.998535
0.050549,-0.036630,0.999267
0.049084,-0.040293,1.000733
0.047619,-0.034432,0.998535
0.047619,-0.038095,1.000733
0.048352,-0.040293,0.999267
0.053480,-0.033700,0.997802
0.046154,-0.034432,0.998535
0.051282,-0.038095,1.000000
0.050.035165,0.998535
0.052747,-0.033700,0.998535
0.053480,-0.0395
0.051282,-0.037363,0.996337
0.054945,-0.039560,0.997070
0.049084,-0.032967,1.000733
0.053480,-0.037363,0.999267
0.045421,-0.032234,0.996337
0.051282,-0.038828,0.997070
0.052015,-0.031502,0.997802
0.051282,-0.033700,00.050549,-0.033700,1.000000
0.049084,-0.037363,0.995604
0.051282,-0.033700,0.997070
0.049084,-0.039560,1.001465
0.051282,-0.036630,0.998535
0.052747,-0.035165,0.995604
0.048352,-0.038828,0.999267
0.052747,-0.035165,0.996337
0.047619,-0.030769,0.998535
0.053480,-0.035897,0.996337
0.048352,-0.031502,0.999267
0.0490.052747,-0.033700,0.998535
0.052747,-0.038095,0.999267
0.049084,-0.035897,1.03
0.050549,-0.041026,1.000733
0.052015,-0.032967,0.998535
0.053480,-0.036630,0.995604
0.046886,-0.033700,0.999267
0.052747,-0.037363,0.998535
0.049817,-0.033700,1.000733
0.050549,-0.034432,0.996337
0.049084,-0.036630,0.052015,-0.040293,0.995604
0.052015,-0.038095,0.996337
0.052747,-0.035897,0.999267
0.052015,-0.035897,0.999267
0.049084,-0.036630,0.997070
0.049817,-0.032967,0.998535
0.050549,-0.035897,0.998535
0.051282,-0.031502,1.000733
0.048352,-0.032967,0.996337
0.045421,-0.035897,0.997802
0.049817,-0.036630,0.996337
0.046.035897,1.000733
0.053480,-0.036630

It could be that the receiver or the telemetry channel can't handle the data rate.

As-is, it's a tradeoff between precision or reliability. One way forward is to encode your data: ASCII strings are wasteful. Three full Uno floats would encode into a short base64 string like "2w9JQNsPSUDbD0lA"


#include "base64.hpp" // https://github.com/Densaugeo/base64_arduino
// from https://github.com/Densaugeo/base64_arduino/blob/master/arduino-test/arduino-test.ino

typedef uint8_t u8;

u8 input_buffer[128];
u8 input_length;
u8 output_buffer[128];
u8 output_length;
u8 hex_buffer[384];
u8 hex_length;


float x[3] = {PI,PI,PI}; // test array

// Convert an unsigned integer to a hex value
u8 hex(u8 u) {
  if(u < 10) return '0' + u;
  if(u < 16) return 'a' - 10 + u;
  return 0xff;
}

void setup() {
  input_length = 0;

  encode_base64((unsigned char *)x,sizeof(x),output_buffer);

  Serial.begin(115200);
  Serial.println((char*) output_buffer);
  Serial.println("Base64 encoding example");
}

void loop() {
  u8 next = Serial.read();
  
  if(next == 0xff) { 
    delay(1);
  }
  else if(next == '\n') {
    if(input_length > 2 && input_buffer[0] == 'e' && input_buffer[1] == ' ') {
      encode_base64(input_buffer + 2, input_length - 2, output_buffer);
      Serial.println((char *) output_buffer);
      input_length = 0;
    } else if (input_length > 2 && input_buffer[0] == 'd' && input_buffer[1] == ' ') {
      output_length = decode_base64(input_buffer + 2, input_length - 2, output_buffer);
      for(u8 i = 0; i < output_length; ++i) {
        hex_buffer[3*i    ] = hex(output_buffer[i] / 16);
        hex_buffer[3*i + 1] = hex(output_buffer[i] % 16);
        hex_buffer[3*i + 2] = ' ';
      }
      hex_buffer[3*output_length] = 0;
      Serial.println((char *) hex_buffer);
      input_length = 0;
    } else {
      Serial.println("To encode: e STRING");
      Serial.println("To decode: d BASE64");
      input_length = 0;
    }
  }
  else {
    input_buffer[input_length++] = next;
  }
}

I have a project that transmits 6-minute water level data to a satellite with encoded 300 baud bursts through https://dcs1.noaa.gov/

1 Like

no, it is not mine.

bother I understand how to incode, but how to decode this string into double? can you help me to decode it?

by the way, you are a master blaster! I love u bro

Hi dev bro, I run telemetry in my laptop using USB port, actually I use both usb port, then using python I send one telemetry to other at 100hz, I get expected output without any problem, but only problem in Arduino, any solution?

When you use USB-only links, it just pretends to have a baud rate, with the data delivered behind the scenes in USB packets.

With the base64, I was just showing one way of delivering the data with less bytes. The decoding scheme is in the arduino code, but if you picked it up on the other end, it would depend on how the other ends handles data. You'd make a structure to hold the three floats, receive the data bytes, and translate them into the proper bytes in your end-point's structure. It can be a pain to get it all correct.

I'd try the 3-decimal place data first because it already works, and I'm not sure the accuracy really matches the micro-g precision as reported. Did you do any statistics on your data accuracy A micro-g is on the order of a micro-radian, or 0.000057° angle. Three decimal places is a milli-radian or 0.057°. Both are far below what could be conveniently measured.

I want to send data in less byte does it lose presign?

The string "0.049817," was probably stored in a float 32bit/4byte float on the teensy before it was converted to an 8-byte string with 'Serial4.print(imu.mAccBmi088Data(0), 6);' and then transmitted to your other endpoint which is already setup to parse the lines of comma-delimited ASCII bytes back into a set of floats on that system.

You can easily send data in less bytes in ASCII form if you sacrifice a couple decimal places of precision. You can keep the same precision if you encode to less bytes, or if you send the raw bytes directly, but you'd need to adjust your other system to decode the encoded or raw bytes back into useful information.

What system/software do you have that is reading the data that would be sent?

ETA: In python, you can decode a base64string to a set of bytes with, 'base64.decodebytes()' and then unpack the bytes as floats with 'struct.unpack()'

brother! I successfully get data, but the problem is somewhere else, I get a leggy Serial, and when I open Serial my Serial is not smooth, it's laggy! I don't know why? maybe I make my own connector for my project suitable? I sent you a photo wait,