Data becoming corrupted[solved]

Once again :frowning:

I'm sending a bunch of values over serial, that look like this:

.420,390,419,318,319,420,293090

Where the fullstop indicates the beginning of new data, the first 6 values are battery voltages, and the last is the time returned by a function using micros() to read speed. It is sent every 350ms at 250Kbaud.

This code is handling it:

String serial_data[6];
float cell_voltages[6];
int varcounter = 0;
boolean newdata = false;
float diameter = 250.00;
float circumference;
float groundspeed;
int setgndspd = 0;
int dispmode = 0;
int buttonanlg;
int bigcharpos;
boolean button1 = false;
boolean button2 = false;
boolean button3 = false;
boolean button4 = false;
#include <LiquidCrystal.h>


// the 8 arrays that form each segment of the custom numbers
byte LT[8] =
{
  B00111,
  B01111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
};
byte UB[8] =
{
  B11111,
  B11111,
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};
byte RT[8] =
{
  B11100,
  B11110,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
};
byte LL[8] =
{
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B01111,
  B00111
};
byte LB[8] =
{
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111,
  B11111
};
byte LR[8] =
{
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11110,
  B11100
};
byte UMB[8] =
{
  B11111,
  B11111,
  B11111,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111
};
byte LMB[8] =
{
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111,
  B11111
};


 
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(9, 8, 7, 4, 2, 5);
 
void setup() {
  pinMode(3, OUTPUT);
  digitalWrite(3, HIGH);
  lcd.begin(16, 2);
  Serial.begin(250000);
  circumference = diameter * 3.14;
   lcd.createChar(0,LT);
  lcd.createChar(1,UB);
  lcd.createChar(2,RT);
  lcd.createChar(3,LL);
  lcd.createChar(4,LB);
  lcd.createChar(5,LR);
  lcd.createChar(6,UMB);
  lcd.createChar(7,LMB);
}
 
void loop() {
// Check serial & get data
if (Serial.available() > 0){
  delay(6);
  while (Serial.available() > 0) {
    newdata = true;
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      varcounter++;
    }  //breaks out of capture loop to print readstring
    if (c != ',' && c != '.'){
    serial_data[varcounter] += c;
    }
    if (c == '.'){
       for (int i = 0; i<7; i++)
       serial_data[i] = "";
       varcounter = 0;
       newdata = true;
    }
  }
}
  
// Rest of loop  
  
if (newdata == true){
  lcd.setCursor(0,0);
  if (dispmode == 0){  // Main screen
     boolean gotdecimal = false;
    lcd.clear();
    calcspeed();
    char buffer[2];
    bigcharpos = 0;
    dtostrf(groundspeed, 2, 0, buffer);
    int len = strlen(buffer);
    for(int i=0; i<len; i++)
    {
      char ltr = buffer[i];
     switch(ltr)
    {
     case '0':
       custom0();
       break;
     case '1':
       custom1();
       break;
     case '2':
       custom2();
       break;
     case '3':
       custom3();
       break;
     case '4':
       custom4();
       break;
     case '5':
       custom5();
       break;
     case '6':
       custom6();
       break;
     case '7':
       custom7();
       break;
     case '8':
       custom8();
       break;
     case '9':
       custom9();
       break;
  }
   bigcharpos = bigcharpos + 4;
 }
 convertvoltages();
 float totalvoltage;
 for (int i=0; i<6; i++){
   totalvoltage = totalvoltage + cell_voltages[i];
 }
 lcd.setCursor(8,0);
 lcd.print("| ");
 lcd.print(totalvoltage);
 lcd.print("v");
}
  
  if (dispmode == 1){  // Cell voltage display
  lcd.clear();
  convertvoltages();
  for (int i=0; i < 6; i++){
   if (i == 3){
     lcd.setCursor(0,1);
   }
   lcd.print(cell_voltages[i]);
   lcd.print(" ");
   }
  }
  
  newdata = false;
}
 
 // Button reading
 buttonanlg = analogRead(A0);
 if (buttonanlg < 5){
   button1 = true;
   dispmode = 0;
 }
 if (buttonanlg < 600 && buttonanlg > 500){
   button2 = true;
   dispmode = 1;
 }
  if (buttonanlg < 700 && buttonanlg > 600){
   dispmode = 2;
 }
  if (buttonanlg < 800 && buttonanlg > 700){
   button4 = true;
 }
   if (buttonanlg > 1000){
     button1 = true;
     button2 = true;
     button3 = true;
     button4 = true;
   }

}

// FUNCTIONS

void calcspeed()
{
    float RPS;
    float RPM;
    unsigned long rpms;
    rpms = serial_data[6].toInt();
    RPS = 1000000.0/rpms;
    RPM = RPS * 60;
    groundspeed = (RPM * circumference)/16666.6;
    lcd.setCursor(8,1);
    lcd.print("        ");
    lcd.setCursor(8,1);
    lcd.print(groundspeed);
}

void convertvoltages()
{
  for (int i=0; i<6; i++){
  cell_voltages[i] = serial_data[i].toInt();
  cell_voltages[i] = cell_voltages[i] / 100;
  }
}
void custom0()
{ // uses segments to build the number 0
  lcd.setCursor(bigcharpos, 0); // set cursor to column 0, line 0 (first row)
  lcd.write((byte)0);  // call each segment to create
  lcd.write((byte)1);  // top half of the number
  lcd.write((byte)2);
  lcd.setCursor(bigcharpos, 1); // set cursor to colum 0, line 1 (second row)
  lcd.write((byte)3);  // call each segment to create
  lcd.write((byte)4);  // bottom half of the number
  lcd.write((byte)5);
}

void custom1()
{
  lcd.setCursor(bigcharpos+1,0);
  lcd.write((byte)2);
  lcd.setCursor(bigcharpos+1,1);
  lcd.write((byte)5);
}

void custom2()
{
  lcd.setCursor(bigcharpos,0);
  lcd.write((byte)6);
  lcd.write((byte)6);
  lcd.write((byte)2);
  lcd.setCursor(bigcharpos, 1);
  lcd.write((byte)3);
  lcd.write((byte)7);
  lcd.write((byte)7);
}

void custom3()
{
  lcd.setCursor(bigcharpos,0);
  lcd.write((byte)6);
  lcd.write((byte)6);
  lcd.write((byte)2);
  lcd.setCursor(bigcharpos, 1);
  lcd.write((byte)7);
  lcd.write((byte)7);
  lcd.write((byte)5);
}

void custom4()
{
  lcd.setCursor(bigcharpos,0);
  lcd.write((byte)3);
  lcd.write((byte)4);
  lcd.write((byte)2);
  lcd.setCursor(bigcharpos+2, 1);
  lcd.write((byte)5);
}

void custom5()
{
  lcd.setCursor(bigcharpos,0);
  lcd.write((byte)0);
  lcd.write((byte)6);
  lcd.write((byte)6);
  lcd.setCursor(bigcharpos, 1);
  lcd.write((byte)7);
  lcd.write((byte)7);
  lcd.write((byte)5);
}

void custom6()
{
  lcd.setCursor(bigcharpos,0);
  lcd.write((byte)0);
  lcd.write((byte)6);
  lcd.write((byte)6);
  lcd.setCursor(bigcharpos, 1);
  lcd.write((byte)3);
  lcd.write((byte)7);
  lcd.write((byte)5);
}

void custom7()
{
  lcd.setCursor(bigcharpos,0);
  lcd.write((byte)1);
  lcd.write((byte)1);
  lcd.write((byte)2);
  lcd.setCursor(bigcharpos+1, 1);
  lcd.write((byte)0);
}

void custom8()
{
  lcd.setCursor(bigcharpos,0);
  lcd.write((byte)0);
  lcd.write((byte)6);
  lcd.write((byte)2);
  lcd.setCursor(bigcharpos, 1);
  lcd.write((byte)3);
  lcd.write((byte)7);
  lcd.write((byte)5);
}

void custom9()
{
  lcd.setCursor(bigcharpos,0);
  lcd.write((byte)0);
  lcd.write((byte)6);
  lcd.write((byte)2);
  lcd.setCursor(bigcharpos+2, 1);
  lcd.write((byte)5);
}

However, I seem to have an issue where sometimes the data ends up getting corrupted, which in turn seems to "freeze" everything. This started happening since I added the function to calculate the speed, which involves floating point math. I have a feeling maybe something is going wrong in the math, and subsequently confusing the uC?

Dan

Well I'm much more inclined to suspect the use of the String class - there certainly have been (and may
still be) memory leaks with this causing a sketch to fall over from lack of RAM after a while - I'd check
that out.

BTW its easy to read in int data on the fly, each time you see a digit:

  cell_voltages[varcounter] = cell_voltages[varcounter] * 10 + ch - '0' ;

Hmm, thanks for that.

I think I may have a suspect here though - I'm actually sending the data from the other uC with seperate Serial.print commands, so I thought, maybe it's getting the ., first value, then going into the loop before the rest of the data arrives. It was also probably limiting how fast I could send data to it.

I've changed the code on the uC sending the data to send it all as one big string, and it seems to be working a lot better, no errors as yet :slight_smile:

It is sent every 350ms at 250Kbaud.

if (Serial.available() > 0){
  delay(6);

At 25000 bytes a second, your 64 byte input buffer will overflow in 2.5ms.
How many characters are you receiving?

you can add a handshake around the data,

  • a simple ACK that one can send
  • make proper records with a field begin and terminator (Like the <> in XML)
  • you can add CRC in the data to check the validity of the data received.
    char buffer[2];

I think this should be 3 no 2 for the digits and 1 for the null terminator.

Mark

Cheers, got it sorted :smiley: