Prevent data loss over bluetooth

Hi,

as I am new to transfer protocols and can't seem to find the answer on the web (probably because I'm looking in the wrong places), I'd like to ask my question here.

I want to build a control which interfaces the Arduino with a phone App. To connect the devices I would like to use bluetooth. What I am not sure of is what happens when data is sent via the wireless connection and for whatever reason the connection is lost. As I understand, the UART serial port of the Arduino should check if the transmission finished correctly. Can I catch the error if it didn't? Is there already a "right" way to do this and maybe trigger a reconnect and try to send again for x seconds and if not throw an exception? Or is there a hardware buffer in the bluetooth chips, which will store the information to be sent and do the above and when it fails this is the error we get in the software?

I hope I am not to confuse about this but I am just starting to learn on connections and connection protocols. Related links or pointers to good books are also appreciated!

Btw. the transmission of the data should be save enough to trust the Arduino with a 1800 W heater.

Best,
Nico

kerl:
Btw. the transmission of the data should be save enough to trust the Arduino with a 1800 W heater.

What are the consequences of the 1800W heater being on or off (permanently?) when it should not be ?

kerl:
As I understand, the UART serial port of the Arduino should check if the transmission finished correctly.

No it does not.

The UART may think the data has left the UART but there could be a hardware fault and the UART would not know.

Neither does the UART know if the data has been received, without error, which is why there are send and acknowledge type protocols.

It would ruin the roast (coffee). Having it not respond while heating can set the machine on fire but one should always keep an eye on the roaster anyway. Realistically (when used with caution), it would ruin the current batch and be really annoing.

It would just be good to know what happens when the connection is lost and to have a good counter measure or change the code accordingly e.g. send heating information up front and check if the transmission was successful before turning the heater on.

It would also be nice to reconnect automatically while running the pid loop for the heating element. That way, if I run in the kitchen to get something and the connection is lost, the information sent during this period of time can be resent on reconnect and I am up to date with what is going on.

I should be fine with the error handling but am not sure how much really is necessary. Help will be appreciated! :slight_smile:

@srnet: Thanks! So I would need to send a check value and when it is recveived send a predefined answer back? Which protocols can be used for that and could you suggest something along the size and capabilities of the Arduino?

My guess is that if you are using a phone app it will only be occasionally communicating with the Arduino.

If I was building a system with continuous communication I would get the Tx to send data regularly (perhaps once per second) and if the Rx did not receive a message it would know that communication has failed and could take appropriate action - such as turn off the heater.

If you are not working with a continuous system I suggest that the Rx should be programmed to turn off the heater after a safe amount of time unless it receives another instruction.

All of this is in addition to the use of a check-value to ensure that a valid message is received.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

The technique in the 3rd example will be the most reliable.

You can send data in a compatible format with code like this

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

These techniques can be implemented in any programming language.

...R

@Robin2 Thanks for the info! The examples are great! So I will use markers for start and end and also a timeout safety feature. I am thinking of some sort of global variables which are always sent and updated. With a proper update order it should also work. One could then add multiple devices as slaves, such as a monitor connected to an raspberry pi running only a small script receiving and plotting the graph. But sending an 1500x2 array every second, containing uint8 and uint16 is probably not feasible? This would update the complete graph, so other devices could connect and also show the current progress from start, but:

115200 baud rate = 14400 bytes/s
3 byte/element * 1500 elements = 4500 byte
4500 byte /14400 byte/s = 0,31 s

Only sent from the Arduino, which in turn receives just user updates for the current temperature. My problem is, if the connection is lost often, I would also need to send the whole array again in order to get the complete graph back on the mobile device. I am not so keen on checking the last status and only updating the missing part, if this could be avoided.

How probable is it to disconnect/not work properly? When I am in the same room, is it 100 % accurate or is there a known error rate which also needs to be calculated in?

kerl:
115200 baud rate = 14400 bytes/s

Dividing by 10 is better - i.e. about 11,000 bytes per second - because a byte requires 10 bits to be sent when you take account of the start and stop bits.

Let's swap these parts around ...

How probable is it to disconnect/not work properly? When I am in the same room, is it 100 % accurate or is there a known error rate which also needs to be calculated in?

If your phone (or RPi) is in the same room as the Arduino that is sending Bluetooth data then I suspect that disconnections would be rare.

My problem is, if the connection is lost often, I would also need to send the whole array again in order to get the complete graph back on the mobile device. I am not so keen on checking the last status and only updating the missing part, if this could be avoided.

If the graph is important then either {A} don't use a mobile device if it is not reliable or {B} include arrangements for identifying and dealing with problems.

A common way to deal with problems is to have a dialogue between the two devices (phone and Arduino, for example). But such a dialogue tends to be specific to the pair it is designed for and would probably preclude the freedom to connect another Bluetooth device to the Arduino on a different occasion. (I am guessing that that is what you have in mind when you mention slaves).

Another option that you might consider is using an ESP8266 (with or without the Arduino) as a WiFi web server. Then the phone could connect to it through its browser (or a dedicated program if you know how to write one) and other WiFi enabled devices could also connect to it. A web server provides a lot more flexibility than the one-to-one capability of Bluetooth.

Or maybe you could build the webserver on the RPi and let the ESP8266 and the phone connect to it as clients. I think that would be my preference as the RPi can more easily store and regurgitate large quantities of data. And it can be programmed with Python.

...R

Thanks Robin2, you helped me alot!

As I understand it, you're trying to have an Arduino control a coffee roaster based on commands it receives by Bluetooth. So far so good. Do you use it as a glorified on/off button? Or do you give the Arduino a program to follow?

If the first: you'll be around to see whether the command is received.

In the second case: send the complete program, and have the Arduino only start up when the "end of program" code has been received. Thereby I assume a program sequence to be something like <10 mins at temp 1><30 mins at temp 2><slowly cool down to temp 3><program finished, total was 42 bytes>. Just make sure you have a unique code to designate the end of the program, and no problem.
If bytes get lost, you know this: the total bytes for the program doesn't match the received bytes.
If the communication is lost halfway, you know this: the end market isn't received.
Bluetooth for sure has error correction built in; errors on the Serial communication between Arduino and Bluetooth module will be extremely rare but if you want to be really sure, send a check sum with the message.

It would be case two. I would send the whole program, but with a temperature for each second. The user should also be able to change the temperature during roast and monitor changes. Adding a check sum for the first large transmission is a good idea!

Later on I would query on reconnect what the last known time is for the App and resend everything else up to current roast time. A small delay in this case should be ok since it only occurs once for half a second in the worst case.

This is one of the basic networking ideas that is not often required in Arduino projects. Basically your receiver needs to acknowledge that it received the data ok. This is usually shortened to "ACK". You can even have a negative ACK, called NAK for short.

So A sends something to B. If A gets a NAK then it must send again. Easy. What if B sent an ACK but it was lost? How does A know to send it again?

To ensure the integrity of the file you can have checksums of various complexity. If the file is small then you can just send two copies and the receiver checks both copies match.

You can also use some kind of cryptographic signature so that the receiver can check that the sender is authorized to send that instruction.