Hello all,
I am writing a program which essentially collects data from external sensors/boards and then sends it out to a laptop with an XBee dongle. Currently I have a GPS module, an IMU, a digital temperature sensor, an XBee, an RS232 serial shifter, and an OpenLog (all hooked up to an Arduino MEGA 2560). I collect data from the GPS, IMU, temperature sensor, and the serial shifter and send it all out over the XBee (and to the OpenLog). The issue I am having is the device sending data to the serial shifter sends a constant stream of data, no pauses. The device does not allow any sort of hardware flow control or handshaking of any sort. The device sends 25-byte packets of data one after the other at 9600bps. My first approach to parse the packet was to collect sample data, say 50-bytes, then search for the three start delimiters (0x10, 0x10, 0x10) in the 25-byte packet and then just send the 25-byte packet out. The issue I am having is I get some serious buffer overflow. I have tweaked the delay after I flush the Serial 3 buffer and I have found that a delay of 42ms produces the least amount of errors in my data, however, I am still receiving tons of errors due to the invalid data caused by the overflow.
How can I prevent the overflow and maintain data reliability? The data that is sent out from the Arduino to the laptop is important and the highest possible accuracy is crucial.
Thank you for your help!!!
#include <Wire.h>
float farenheit;
int temp;
int val;
float convertedtemp;
int i;
int j;
byte firstbyte;
byte secondbyte;
byte buffer[50];
void setup()
{
Wire.begin();
Serial.begin(9600); // Computer serial port (to be used for OpenLog later)
Serial1.begin(115200); // GPS Serial Port
Serial2.begin(57600); // IMU serial port
Serial3.begin(9600); // XBee/Serial Shifter serial port
}
void loop()
{
/**************************************************************
The following code is for the GPS module. The baud rate is set
to 115,200bps in the firmware and it polls at 2Hz. It will
only print the GPRMC statement.
***************************************************************/
while (Serial1.available() > 0) // Check if data exists in Serial 1 read buffer, if it does...
{
temp = Serial1.read(); // Read and store byte into temp variable
if (temp != 10) // If received character is NOT a new line character...
{
Serial3.print(temp, BYTE); // Print the byte to the XBee
Serial.print(temp, BYTE); // Print the byte to the OpenLog
}
else // If received character IS a new line character...
{
Serial3.println(); //Insert a new line
Serial.println(); // Insert a new line
Serial1.flush(); // Just in case
break; // Break out of the while loop
}
}
/**************************************************************
The following code is for the IMU. The baud rate is set to
57,600bps in the firmware and it will print the following:
$ANG,Roll,Pitch,Yaw
***************************************************************/
while (Serial2.available() > 0) // Check if data exists in Serial 2 read buffer, if it does...
{
temp = Serial2.read(); // Read and store byte into temp variable
if (temp != 10) // If received character is NOT a new line character...
{
Serial3.print(temp, BYTE); // Print the byte to the XBee
Serial.print(temp, BYTE); // Print the byte to the OpenLog
}
else // If received character IS a new line character...
{
Serial3.println(); //Insert a new line
Serial.println(); // Insert a new line
Serial2.flush(); // Just in case
break; // Break out of the while loop
}
}
Serial2.write(1); // Sends handshake to IMU to let it know that we are ready for data
// delay(20);
/***************************************************************
The following code is for the serial shifter which receives data
from the battery management system. It will print data serially
in the following format at 9600bps: $BMS,Data,Data,Data....
***************************************************************/
if (Serial3.available() > 0) // If there is data in the Serial 3 read buffer...
{
i = 0; // Reset counter
Serial3.flush(); // Flush the Serial3 read buffer so it can fill with new data
delay(42); // Delay to give time for Serial3 read buffer to fill
while(i <= 50){ // Fill buffer with 50 elements
buffer[i] = Serial3.read(); // Read byte from serial buffer and store in our buffer
i++; // Increment counter
}
for(j = 0; j <= 50; j++) // A for loop which will traverse our buffer
{
if(buffer[j] == 0x10) break; // Once first start delimiter is reached, break from for statement
temp = j; // Store position of start delimiter in variable
}
if((buffer[j+1] == 0x10) && (buffer[j+2] == 0x10)) // If the next two start delimiters are present in the buffer...
{
Serial3.print("$BMS"); // Print our start delimiter to the XBee
Serial.print("$BMS"); // Print our start delimiter to the OpenLog
for(j; j<=(temp + 25); j++) // A for statement that will only print the 25 bytes from the packet
{
if(j != (temp + 25)){ // While we aren't on the last element in the packet...
Serial3.print(","); // Print comma delimiter to XBee
Serial.print(","); // Print comma delimiter to OpenLog
Serial3.print((int)buffer[j]); // Print current buffer element to XBee
Serial.print((int)buffer[j]); // Print current buffer element to OpenLog
}
else { Serial3.println(); Serial.println(); } // Send a new line at the end of a packet
}
}
}
/***************************************************************
The following code is for the TMP-102 digital temperature sensor
and two potentiometers (acceleration and develeration).
It will print the following: $MOTOR,Temp,Accel,Decel
***************************************************************/
Wire.beginTransmission(72); // Start transmission with TMP-102 sensor
Wire.send(0x00); // Send two zero bytes to poll sensor for data
Wire.endTransmission(); // End send transmission with TMP-102 sensor
Wire.requestFrom(72, 2); // Request two bytes from sensor
Wire.endTransmission(); // End request trasmission with TMP-102 sensor
firstbyte = Wire.receive(); // Receive first byte and store
secondbyte = Wire.receive(); // Receive second byte and store
val = ((firstbyte) << 4); // Shift first byte to the left
val |= (secondbyte >> 4); // Shift second byte to to the right and OR with val
farenheit = ((1.8 * (val * 0.0625)) + 32) - 5; // Convert to farenheit and subtract since reads over by 5 degrees
int accel = analogRead(A0); // Read acceleration potentiometer, convert to percentage, and store in accel variable
if (accel > 1000) accel = 1000; // If the accel value is greater than 1000, truncate it to 1000
int decel = analogRead(A1); // Read decerleation potentiometer, convert to percentage, and store in decel variable
if (decel > 1000) decel = 1000; // If the decel value is greater than 1000, truncate it to 1000
Serial3.print("$MOTOR,"); // Print beginning of MOTOR line to the XBee
Serial3.print(farenheit); // Print temperature to XBee
Serial3.print(","); // Insert comma delimiter
Serial3.print(accel / 10); // Print accel in percentage
Serial3.print(","); // Insert comma delimiter
Serial3.println(decel / 10); // Print decel in percentage and insert a new line
Serial.print("$MOTOR,"); // Print beginning of MOTOR line to the OpenLog
Serial.print(farenheit); // Print temperature to OpenLog
Serial.print(","); // Insert comma delimiter
Serial.print(accel / 10); // Print accel in percentage
Serial.print(","); // Insert comma delimiter
Serial.println(decel / 10); // Print decel in percentage and insert a new line
}