0

I have two Arduino Megas with HC-05 on Serial1 connected to a Raspberry Pi 3b+ via bluetooth, using the HC-05 and the RPi's built-in bluetooth, and python's pySerialTransfer library to make the connections.

For reasons I am still trying to root cause, the bluetooth connection gets severed a few times an hour. Ideally, I'd get hours to perhaps a day between severed connections; is this a realistic goal?

Over a course of a few days, my testing has shown:

  1. Mega#1 median connection duration is 10 minutes & 88 minute max duration; 25 bytes sent by RPi->Arduino, and by Arduino->RPi every 0.2sec
  2. Mega#2 median connection duration is 38 minutes & 153 minute max duration; 4 bytes sent by RPi->Arduino, and by Arduino->RPi every 0.2sec

During this testing, they're completely stationary within about 12" of each other, so range should not be an issue.

My RPi code detects a lost connection by virtue of failure to receive a message within 5 seconds, and attempts to reestablish the connection, and that is successful about 80% of the time. I have a second-tier of lost-connection recovery - resetting the HC-05 via an Arduino-triggered MOSFET - if a message isn't received by the Arduino in ~20 seconds, that works in the remainder of the cases, so I'm ultimately able to systematically recover within a max of about 30 seconds. However, this lost connection for ~10-30 seconds every 10-60 minutes causes a poor user experience for my remote controls.

The Python errors given for about 95% of the failures are a lack of a receipt of a heartbeat message from the Arduino to the RPi python; about 5% give a unspecific [Errno 5] Input/output error error.

While I'm running down multiple theories via day-long stability tests (longer byte transmissions are more error prone? there's some bug in my Arduino code causing crashes, so remove all logic except the send/receive code to test?), I've read a few posts about how finicky & fragile bluetooth can be, and so I'm curious for some thoughts about the general goal / attempt to get a longer-term (hours to a day or more) connection.

Have folks been able to achieve this with the HC-05 on Arduino? Or is a dropped connection every 10-60 minutes just something one needs to deal with through robust code? Thank you.

1
  • 1
    Speaking only from my personal experience, I've found the Bluetooth implementation on RPi (the 3B+ in particular) to be virtually useless. I've spent hours troubleshooting, but it was never relaible, and in many cases would not connect at all. From reading other Q's on RPi SE I've formed the opinion that others have had similar experiences. Also, I think it's true that RPi 3B+ has only a single antenna for WiFi and BT - which of course makes things difficult if you need them both.
    – Seamus
    Jun 2 '20 at 8:47
0

Bluetooth communication works with fixed time intervals that both communication partners have to agree during the advertising and connection phases. Such an agreement could be: "While connected, lets' meet every second. If one does not show up during 3 meetings, let's leave the connection state".

From this you can see that timing is a very important factor in bluetooth communication. So both communication partners need a very accurate clock. No two clocks have exactly the same speed, one is always lagging the other.

It could be that one or multiple of the clocks of your HC-05's do have too much clock drift, so the connection will be lost. Maximum clock deviation allowed for a bluetooth clock is ±40 ppm (i.e. ±40 parts-per-million!) over the entire temperature range.

You could check this theory with multiple HC-05s. If individual modules lead to individual connection lengths, then this could be your problem.

2
  • Thanks, Stefan - I'll add that to the test list, and will report back (even if to share still unknown) in a few days after I've run each test for a day or so. Appreciate it.
    – David W
    Jun 1 '20 at 23:18
  • You can also measure the clocks directly at the crystal if you have access to a timer/counter measurement device and a low capacitance (<1pF) probe. Jun 2 '20 at 7:24
0

I ultimately found a solution, but for the benefit of others, wanted to share the tests that also did not prove fruitful. TL;DR: Reducing message rate from Arduino's to RPi solved the problem.

My hypotheses to test:

  1. Hypothesis: Faulty Arduino code written by myself. Test: Remove all logic except read / write.
  2. Hypothesis: Something to do with message size. Test: Add an extra arbitrary 80 bytes to the Mega#1 message.
  3. Hypothesis: Too many small messages for RPi to deal with. Test: Reduce message frequency.
  4. Hypothesis: Timing problem or other HC-05 fault as suggested by @stefan-wyss. Test: Swap modules with a 3rd one.
  5. Hypothesis: Faulty RPi python code written by myself. Test: Return to basic python test harness that does nothing except exchange bluetooth messages.

Hypotheses #1 & #2 led to no appreciable difference in failure rate or failure mode.

However, hypothesis #3 was the winner, with both Arduinos running for 12+ hours so far with no severed communications. (So I did not bother to test #4 & #5).

Specifically, in the original "problem code", there were 20 messages sent every second (and 40 read attempts; I have "overclocked" the receiving in relation to the sending make sure buffers don't fill up due to slight variations in RPi vs. Arduino clocks):

  • 5 sends of 25 bytes by Mega#1 to RPi per second
  • 5 sends of 25 bytes by RPi to Mega#1 per second
  • 5 sends of 4 bytes by Mega#2 to RPi per second
  • 5 sends of 4 bytes by RPi to Mega#2 per second

Some of those didn't really need that frequency to achieve my design goals; so I changed to:

  • 1 send of 25 bytes by Mega#1 to RPi every 2 seconds
  • 5 sends of 25 bytes by RPi to Mega#1 per second
  • 1 send of 4 bytes by Mega#2 to RPi every 2 seconds
  • 5 sends of 4 bytes by RPi to Mega#2 per second

So now, instead of the RPi receiving 10x/second, it receives 1x/second. (It's still attempting to read 10x per second on each of the two Arduinos to minimize latency, but most of those return no data received). The RPI still has to send 10x/second (5x to each of the two Arduinos).

This simple change fixed the problem. I have no insight as to why the RPi couldn't handle the faster rate of message receipt; some benchmarking on my Python code showed that processing of the received heartbeat messages was not a bottleneck. But the important part, at least for me & the project, is that the problem is solved.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.