How to identify a block send from arduino

Hey there,

this might not be a strict arduino question, but maybe someone can help me nevertheless.
I am sending acceleration data from my arduino through the serial port to a connected windows machine. On the windows machine i read the serial port to then try to do something with this data.
My problem now is: How can i make sure that i read the block exactly how it was send on the arduino? The problem is that i might read the port exactly in between two blocks and thus getting “wrong” data.

Here is my arduino code:

void loop() {
  unsigned long currentMillis = millis();
  
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    sendData();
  }
  
}

void sendData() {
      // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    Serial.write(lowByte(ax)); 
    Serial.write(highByte(ax));
    Serial.write(lowByte(ay)); 
    Serial.write(highByte(ay));
    Serial.write(lowByte(az)); 
    Serial.write(highByte(az));
    //Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
    //Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
    //Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
}

And this is how i try to read:

char incomingData[6] = "";			// don't forget to pre-allocate memory
	//printf("%s\n",incomingData);
	int dataLength = 6;
	int readResult = 0;

	while (SP->IsConnected())
	{
		readResult = SP->ReadData(incomingData, dataLength);
		if (readResult < 0) {
			continue;
		}
		printf("Bytes read: (-1 means no data available) %i\n", readResult);

		char low = incomingData[0];
		char high = incomingData[1];

		int ax = (high << 8 | low);

		printf("%i", ax);

		//Sleep(500);
	}

SP is just a SerialPort object which handles the communication with the serial port. ReadData just reads the amount specified at max, or the amount in the pipe at the moment
Now i thought about flagging the block with a “1” or something before and after the block gets send. But then how do i identify this block on the client side?

If something is unclear…Please let me know. Thank you in advance.

My problem now is: How can i make sure that i read the block exactly how it was send on the arduino? The problem is that i might read the port exactly in between two blocks and thus getting “wrong” data.

Puts a start of message and end of message marker on the data. Maybe < and >. Then change the receiving code appropriately to read data between the markers.

UKHeliBob:

My problem now is: How can i make sure that i read the block exactly how it was send on the arduino? The problem is that i might read the port exactly in between two blocks and thus getting “wrong” data.

Puts a start of message and end of message marker on the data. Maybe < and >. Then change the receiving code appropriately to read data between the markers.

I thought about something like this. Would i just read 1 byte at a time until a “<” appears and then save the next 6 bytes into my buffer? Or is there something faster / better? Because i would imagine that if i am unlucky that i could lose some data this way.

I thought about something like this. Would i just read 1 byte at a time until a “<” appears and then save the next 6 bytes into my buffer? Or is there something faster / better? Because i would imagine that if i am unlucky that i could lose some data this way.

That’s exactly what you need to do. The PC has much more memory, and therefore larger buffers, than the Arduino. The Arduino can read data sent this way, without loosing data.

I will try to implement the method suggested by you!
Thanks a lot!

So i tried to implement the method suggested above, but i still run into some problem.
First of all: What datatype to use? i am currently using a unsigned char array to save the acceleration values on the arduino:

    unsigned char writeBuffer[8];
    writeBuffer[0] = '<';
    writeBuffer[1] = lowByte(ax);
    writeBuffer[2] = highByte(ax);
    writeBuffer[3] = lowByte(ay);
    writeBuffer[4] = highByte(ay);
    writeBuffer[5] = lowByte(az);
    writeBuffer[6] = highByte(az);
    writeBuffer[7] = '>';
    
    Serial.write(writeBuffer, 8);

And on the client side i expect this to be a unsigned char aswell:

int Serial::ReadData(unsigned char *buffer, unsigned int nbChar)
{
	size_t buffIndex = 0;
	bool startFound = false;
	DWORD dwBytesRead = 0; // Not needed, but access violation without it. (Because of how we open the file)
	for (;;) {
		unsigned char c;
		if (!ReadFile(this->hSerial, &c, 1, &dwBytesRead, NULL)) {
			//something went wrong...
			return -1;
		}

		if (c == '<') {
			// Found the start marker
			startFound = true;
		}
		else if (c == '>') {
			// End found...do some sanity checks.
			if (buffIndex != nbChar) {
				// The number of bytes between start and end marker is wrong..
				
			}
			else {
				return 1;
			}
			buffIndex = 0;
			startFound = false;
		}
		else {
			if (startFound) { // start found and still bytes to fill
				if (buffIndex < nbChar) {
					buffer[buffIndex++] = c;
				}
				else {
					// we found too many bytes between the markers..abort
					buffIndex = 0;
					startFound = false;
				}
				
			}
		}
	}
}

While this is my main-loop.

unsigned char incomingData[6] = "";			// don't forget to pre-allocate memory
	//printf("%s\n",incomingData);
	int dataLength = 6;
	int readResult = 0;

	while (SP->IsConnected())
	{
		readResult = SP->ReadData(incomingData, dataLength);
		//printf("Bytes read: (-1 means no data available) %i\n", readResult);

		if (readResult < 0) {
			continue;
		}

		unsigned char low = incomingData[0];
		unsigned char high = incomingData[1];

		int ax = ((high << 8) | low);

		low = incomingData[2];
		high = incomingData[3];

		int ay = ((high << 8) | low);

		low = incomingData[4];
		high = incomingData[5];

		int az = ((high << 8) | low);

		printf("ax: %i, ay: %i, az: %i\n", ax, ay, az); 

		//Sleep(500);
	}

This seems to work somewhat…but i am not sure if the data i recieve is correct…on idle with no movements the values are:

ax: ~65000 ay: ~65000 az: ~16000

Which seems not right to me…If i use a normal char for the high and low value i end up with negative values.
Anyone has any ideas?

			if (buffIndex != nbChar) {
				// The number of bytes between start and end marker is wrong..
				
			}
			else {
				return 1;
			}

This doesn’t make sense. If the number of characters read was not what was expected, do nothing. If the number of characters read was what was expected, return 1.

You are sending 8 bytes and expecting to read 6. Something is wrong with your math.

		int ax = ((high << 8) | low);

What happens when you shift an 8 bit value 8 bits? high and low should be ints, so that they CAN be shifted 8 bits without loosing data.

PaulS:

			if (buffIndex != nbChar) {
			// The number of bytes between start and end marker is wrong..
			
		}
		else {
			return 1;
		}


This doesn't make sense. If the number of characters read was not what was expected, do nothing. If the number of characters read was what was expected, return 1.

You are sending 8 bytes and expecting to read 6. Something is wrong with your math.



  int ax = ((high << 8) | low);


What happens when you shift an 8 bit value 8 bits? high and low should be ints, so that they CAN be shifted 8 bits without loosing data.

Oh damn. You are right!
I am only reading 6 bytes because i already keep the “<” and “>” out of my 6 byte buffer.