Bad output from uint32_t followed by a "\t" in serial monitor

Hello, I am working on a project to send simulated sensor data from an Arduino into an application that I am building. I am sending actual data from one I2C accelerometer, then creating random numbers based on the expected sizes of other sensors data and sending that as well. In between each piece of data I am sending a '\t' character as a delimiter. Alll data values are sending as expected, except for the uint32_t values. When I run the serial monitor I see that when a uint32_t is sent, if the value takes less than 4bytes to be represented, the formatting of the out put is wrong. I am wondering if this is due to the serial monitor output, and the the expected bytes and '\t' are sent, but for textual output reasons it looks miss aligned.

Here is the code on my Arduino, the uint32_t's are at the bottom of the sketch:

//This is an example code from the following web site to rx sensor data every 1/2 second
//http://www.lucidarme.me/?p=5057
// With my own modifications to get an analoug for our sensor suite
//VDD --> Arduino 3.3v
//GND --> Arduino GND
//SDA --> Arduino SDA
//SCL --> Arduino SCL

#include <Wire.h>
#include <TimerOne.h>

#define    MPU9250_ADDRESS            0x68
#define    MAG_ADDRESS                0x0C

#define    GYRO_FULL_SCALE_250_DPS    0x00  
#define    GYRO_FULL_SCALE_500_DPS    0x08
#define    GYRO_FULL_SCALE_1000_DPS   0x10
#define    GYRO_FULL_SCALE_2000_DPS   0x18

#define    ACC_FULL_SCALE_2_G        0x00  
#define    ACC_FULL_SCALE_4_G        0x08
#define    ACC_FULL_SCALE_8_G        0x10
#define    ACC_FULL_SCALE_16_G       0x18



// This function read Nbytes bytes from I2C device at address Address. 
// Put read bytes starting at register Register in the Data array. 
void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
{
  // Set register address
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.endTransmission();
  
  // Read Nbytes
  Wire.requestFrom(Address, Nbytes); 
  uint8_t index=0;
  while (Wire.available())
    Data[index++]=Wire.read();
}


// Write a byte (Data) in device (Address) at register (Register)
void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
{
  // Set register address
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.write(Data);
  Wire.endTransmission();
}



// Initial time
long int ti;
volatile bool intFlag=false;

// Initializations
void setup()
{
  // Arduino initializations
  Wire.begin();
  Serial.begin(115200);
  
  // Set accelerometers low pass filter at 5Hz
  I2CwriteByte(MPU9250_ADDRESS,29,0x06);
  // Set gyroscope low pass filter at 5Hz
  I2CwriteByte(MPU9250_ADDRESS,26,0x06);
 
  
  // Configure gyroscope range
  I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_1000_DPS);
  // Configure accelerometers range
  I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_4_G);
  // Set by pass mode for the magnetometers
  I2CwriteByte(MPU9250_ADDRESS,0x37,0x02);
  
  // Request continuous magnetometer measurements in 16 bits
  I2CwriteByte(MAG_ADDRESS,0x0A,0x16);
  
   pinMode(13, OUTPUT);
  //Timer1.initialize(10000);         // initialize timer1, and set a 1/2 second period
  Timer1.initialize(500000);          //Now it is a 1/2 second interval, the previous value is 1/10
  Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt

  randomSeed(analogRead(0)); // randomize using noise from analog pin 5
  
  // Store initial time
  ti=millis();
}





// Counter
long int cpt=0;

//Added 2/18/2017 to get data when I want it
bool sendData = false;

void callback()
{ 
  intFlag=true;
  digitalWrite(13, digitalRead(13) ^ 1);
}

// Main loop, read and display data
void loop()
{

    sendData = true;

    while(sendData)
    {
      while (!intFlag);
      intFlag=false;

      //Send the letter 'a' to ondicate new message
      //int8_t startSymbol = 'a';
      Serial.print ('\t');
      //Serial.print ('a');
      Serial.print ('S');     //Start
      Serial.print ('N');     //New
      Serial.print ('P');     //Packet
      Serial.print ('\t');
  
      // Display time
      Serial.print (millis()-ti,DEC);
      Serial.print ("\t");

      // ____________________________________
      // :::  accelerometer and gyroscope ::: 

      // Read accelerometer and gyroscope
      uint8_t Buf[14];
      I2Cread(MPU9250_ADDRESS,0x3B,14,Buf);
  
      // Create 16 bits values from 8 bits data
  
      // Accelerometer
      int16_t ax=-(Buf[0]<<8 | Buf[1]);
      int16_t ay=-(Buf[2]<<8 | Buf[3]);
      int16_t az=Buf[4]<<8 | Buf[5];

      // Gyroscope
      int16_t gx=-(Buf[8]<<8 | Buf[9]);
      int16_t gy=-(Buf[10]<<8 | Buf[11]);
      int16_t gz=Buf[12]<<8 | Buf[13];
  
       // Display values
  
      // Accelerometer
      Serial.print (ax,DEC); 
      Serial.print ("\t");
      Serial.print (ay,DEC);
      Serial.print ("\t");
      Serial.print (az,DEC);  
      Serial.print ("\t");
  
      // Gyroscope
      Serial.print (gx,DEC); 
      Serial.print ("\t");
      Serial.print (gy,DEC);
      Serial.print ("\t");
      Serial.print (gz,DEC);  
      Serial.print ("\t");

  
      // _____________________
      // :::  Magnetometer ::: 
  
  
      // Read register Status 1 and wait for the DRDY: Data Ready
  
      uint8_t ST1;
      do
      {
        I2Cread(MAG_ADDRESS,0x02,1,&ST1);
      }
      while (!(ST1&0x01));

      // Read magnetometer data  
      uint8_t Mag[7];  
      I2Cread(MAG_ADDRESS,0x03,7,Mag);
  

      // Create 16 bits values from 8 bits data
  
      // Magnetometer
      int16_t mx=-(Mag[3]<<8 | Mag[2]);
      int16_t my=-(Mag[1]<<8 | Mag[0]);
      int16_t mz=-(Mag[5]<<8 | Mag[4]);
  
  
      // Magnetometer
      Serial.print (mx+200,DEC); 
      Serial.print ("\t");
      Serial.print (my-70,DEC);
      Serial.print ("\t");
      Serial.print (mz-700,DEC);  
      Serial.print ("\t");
  
  

//_________________________________
// Start H3LIS 200DL High G Accelerometer

       int8_t accxH = random(-128, 127);
       int8_t accyH = random(-128, 127);
       int8_t acczH = random(-128, 127);
       int8_t gyroXH = random(-128, 127);
       int8_t gyroYH = random(-128, 127);
       int8_t gyroZH = random(-128, 127);
       int8_t magXH = random(-128, 127);
       int8_t magYH = random(-128, 127);
       int8_t magZH = random(-128, 127);
       
       Serial.print (accxH,DEC);
       Serial.print ("\t");
       
       Serial.print (accyH,DEC);
       Serial.print ("\t");
       
       Serial.print (acczH,DEC);
       Serial.print ("\t");
      
       Serial.print (gyroXH,DEC);
       Serial.print ("\t");
       
       Serial.print (gyroYH,DEC);
       Serial.print ("\t");
       
       Serial.print (gyroZH,DEC);
       Serial.print ("\t");
       
       Serial.print (magXH,DEC);
       Serial.print ("\t");
       
       Serial.print (magYH,DEC);
       Serial.print ("\t");
       
       Serial.print (magZH,DEC);
       Serial.print ("\t");

//_________________________________
// Start MS5611 High Res Altimeter

        uint32_t altitude = random(0, 294967295);    //24bit number
        
        Serial.print(altitude, DEC);
        Serial.print("\t");

//_________________________________
// Start MAX-M8 GPS
       
       uint32_t lat = random(0,294967295);
       uint32_t lon = random(0,294967295);
       uint32_t altGPS = random(0,294967295);
       
       Serial.print(lat, DEC);
       Serial.print("\t");

       Serial.print(lon, DEC);
       Serial.print("\t");
       
       Serial.print(altGPS, DEC); 
       Serial.print("\t");
               
      // End of line
      Serial.println("\0");
        delay(100);

      Serial.flush();

    }


}

And here is a picture of the output with the misaligned text highlighted:

Thanks for any help!

Insert an extra tab if the number is too small.

Thanks, but I am more wondering if all 4 bytes of the 32 bit value are sent followed by a '\t'. This is because I need to parse it on the receiving side, so I need a static size for all values, so formatting of output inst a concern, as long as all bytes and \t are sent.

CavemanAGz:
Thanks, but I am more wondering if all 4 bytes of the 32 bit value are sent followed by a '\t'.
This is because I need to parse it on the receiving side, so I need a static size for all values.

That does not make sense to me, why should print ignore some of the data it is sent?

If you only want to display it aligned, insert the tab if the number is too small.
Alternatively you could print all numbers with leading/trailing blanks in fields with fixed size.

Your parser should be able to parse different numbers of digits per number.
If it uses tab as a field seperator you could ignore empty fields or use the alternative print methods.

Maybe you could post an example of what you'd like it to look like?

A couple of things come to mind: Either you can add white space (as suggested above), or you can pad the numbers with leading zeros.

Or, if it doesn't need to look pretty to a human, then fix whatever is parsing it to be happy with how it looks right now. If you don't have to waste time sending all kinds of extra padding, you probably shouldn't.

@jaholmes
I may have blown it asking my question, so sorry for the confusion. My main concern is that the uint32_t followed by '\t' is actually sending 4 bytes followed by a 1 byte '\t' character over the serial port. This is so on the receiving end I can calculate the offset to the next set of data to ensure I am getting all the values.

I hope this clears up what I am asking.

CavemanAGz:
This is so on the receiving end I can calculate the offset to the next set of data to ensure I am getting all the values.

This is not how to parse data generated by your program. It will not work.

While the tabbed output looks aligned to humans if displayed by a program (thats what tabs are for),
all your fields (the numbers) will have differnt sizes, because they are the decimal representation of binary values.

Whandall:
This is not how to parse data generated by your program. It will not work.

While the tabbed output looks aligned to humans if displayed by a program (thats what tabs are for),
all your fields (the numbers) will have different sizes, because they are the decimal representation of binary values.

Thanks for the reply. Since I am sending the uint32_t as DEC, the serial port will use the minimum number of bits required to represent the decimal value of the number. If this is the case can you point me in the right direction to figure out how to properly packetize my data to conform to a fixed size regardless of the decimal representation of the numbers being sent?

Thanks

Hex dump format would be easy to generate and parse.

On which platform will the parser run and in which language will it be written?

Whandall:
Hex dump format would be easy to generate and parse.

On which platform will the parser run and in which language will it be written?

The application receiving the data will be a windows machine, and I am using QT to develop the application. So it is C++ on the parsing end basically.

fscanf(), sscanf() and strtok() come to my mind.

Very flexible and all of them work well with variable length input.

Just use strtok or strchr to parse at the receiving side. Should work with your current code.

And your arduino code does not send 4 bytes for the number, it sends a text representation of that number which can be 1, 2, etc characters.

@sterretje

Thank you! this is working as expected, the terminal output was just throwing me off. Data is parsing in my application as expected.

Thanks to everyone else that helped to. This is the best help forum i have used, you all are great!