I have a project with a Sanguino (644P chip) in which I need to read a stream of serial binary data at 19,200 and do some processing on it, then log the results and do a few other things. The trouble is, it seems to take more processing power than I have available just to read the data in and assemble the packet. I am using a hardware port on the Sanguino with the hardware serial library.
My code is lengthy, but basically it reads a byte, checks to make sure it is > -1, then stors it in the proper spot in a data structure. The headers are all 4 bytes, including a byte that says how many bytes are int he payload, usually between 1 and 7. It then flags what kind of byte is expected next, and repeats. Once I have the packet and payload I do the checksum.
Once there is one error, there is a rash of them. So, after an error I flush() the Serial port, which throws away all the buffered data but lets me re-sync and receive more packets until the next error.
I have hacked HardwareSerial.cpp and increased the 128 byte buffer to 256, but all tht did was slightly postpone the enevitable.
So I'm at a loss. I think i am loosing bytes, but I'm not sure. Is an Arduino/Sanguino up to this task or am I asking too much from it?
You do not show us your code and you do not tell us anything about the sending device.....
How does the sending device send data ? in bursts ? continously ? at randdom intervals ?
at 19.200 baud and with each byte using 10 bits including the start and stop bits you could potentially be dealing with 1920 incoming bytes a second, depending on the sending side......
Well I'm not trying to hide the code, its just that its a little on the long side, but I'll paste it below. The data is a continious stream of nonstop binary data.
Thanks very much.
loop()
{
unsigned char readByte = 0;
short raw = 0;
raw = Serial1.read();
if(raw >= 0) // If we didn't read a byte, its because none was available
{
// We did read a byte
readByte = (unsigned char) raw;
// This function returns true if we have both a valid header
// and a valid payload.
bool result = processInByte(readByte);
if(result)
{
// At this point it appears we have a valid packet header and packet payload. We can
// now go ahead and process the data inside the packets.
processPacket();
// If we're logging the NXB data, do it now
if(logNxb)
{
logNxbPacket();
}
// Save data to the log
if(logCsv)
{
if(logNow)
{
logNow = false;
dataRec.logCsvRecord();
}
}
}
}
// *
// *
// Check for button inpuit here
// *
// *
}
// Return true only when both header and payload packets are valid
bool processInByte(unsigned char readByte)
{
errorLed.off();
// The first byte of a new packet is 0x81, but we make sure
// When reading real data we may start our of sync, so we will need to sync up
// Also, an 0x81 byte may come along as part of the payload or header
// data, so we use the inProcessFlag to determine if we're assembling
// a packet or waiting for one to start.
if(readByte == 0x81 && !inProcessFlag) // Is this a "start of packet" byte?
{
// Flag that we are inside a packet
inProcessFlag = true;
payloadPos = 0;
gHeader.setStartOfPacket(readByte);
byteType = 'A'; // set for next read
return false;
}
switch(byteType)
{
case 'A':
gHeader.setPacketId(readByte);
byteType = 'B';
return false;
case 'B':
gHeader.setNumDataBytes(readByte);
byteType = 'C';
return false;
case 'C':
gHeader.setChecksum(readByte);
byteType = 'D';
if(!gHeader.isValid())
{
// some error occured reading the packet header. We may be out of sync or
// the data may be corrupted on read. Either way, we can not process this
// packet.
errorLed.on();
badPacketCounter++;
if(wrtSerial)
{
Serial << "Bad Header" << endl;
Serial << "Good Packets: " << goodPacketCounter << " Bad Packets: " << badPacketCounter << endl;
}
if(debugLog)
{
debugLogFile << "Bad Header" << endl;
debugLogFile << "Good Packets: " << goodPacketCounter << " Bad Packets: " << badPacketCounter << endl;
debugLogFile.sync();
}
// At this point, we just kill incoming bytes until the next SOP and start again
inProcessFlag = false;
return false;
}
else
{
// We have a valid header.
return false; // Still need valid payload to return true
}
case 'D':
// If we don't have a valid header, we just consume bytes
// until the next SOP byte comes along.
if(!gHeader.isValid())
{
return false;
}
// Start payload data
gPayload[payloadPos] = readByte;
payloadPos++;
if(payloadPos == gHeader.getNumDataBytes())
{
byteType = 'E';
}
return false; // go for the next byte
case 'E':
// Serial << "E: process Status Byte: " << _HEX(readByte) << endl;
// This is the last byte of the packet
inProcessFlag = false;
byteType = 'Z';
gHeader.setPayloadStatus(readByte);
// Test the statusByte to make sure the checksum is valid
unsigned char statusTemp = 0;
for(unsigned char s = 0; s < gHeader.getNumDataBytes(); s++)
{
statusTemp ^= gPayload[s];
}
if(statusTemp != gHeader.getPayloadStatus())
{
// Bad payload. We can't use this packet.
badPacketCounter++;
if(wrtSerial)
{
Serial << "Good Packets: " << goodPacketCounter << " Bad packets: " << badPacketCounter << endl;
Serial << "Valid Header: Packet ID " << "DEC: " << _DEC(gHeader.getPacketId()) << " Num DB: " << gHeader.getNumDataBytes() << endl;
Serial << "BAD PAYLOAD CHECKSUM! Received Status Byte: " << _HEX(gHeader.getPayloadStatus()) << " Calculated Status Byte: " << _HEX(statusTemp) << endl;
Serial << endl;
}
if(debugLog)
{
debugLogFile << "Good Packets: " << goodPacketCounter << " Bad packets: " << badPacketCounter << endl;
debugLogFile << "Valid Header: Packet ID " << "DEC: " << _DEC(gHeader.getPacketId()) << " Num DB: " << gHeader.getNumDataBytes() << endl;
debugLogFile << "BAD PAYLOAD CHECKSUM! Received Status Byte: " << _HEX(gHeader.getPayloadStatus()) << " Calculated Status Byte: " << _HEX(statusTemp) << endl;
debugLogFile << endl;
debugLogFile.sync();
}
// Give a visual indication of the error
errorLed.on();
// JWA
// After we receive a packet which fails its own checksum test, we get into a
// condition where many of the following payload packets report file. This is
// probably an issue with the code here, but I have not found it yet. Clearing
// the incoming data buffer resolves this issue, although probably at the price
// of a packet.
//
// This needs to be fixed, as this is just a nasty hack workaround.
Serial1.flush();
return false;
}
else
{
// Valid payload!
//return gHeader.validateChecksum();
goodPacketCounter++;
return true;
}
} // end switch
}