RaceChrono DIY Bluetooth BLE protocol

edited July 2020 in DIY builds

I've been tinkering with the example given on https://github.com/aollin/racechrono-ble-diy-device
with RaceChrono PRO v6.4.1 for Android, and had some feedback/questions.

1) In my testing, RaceChrono always requests a "50 ms" notify interval.
If I correctly understand what it means, this results in a 20 Hz refresh rate.
In my limited testing, it seems that Bluetooth BLE on Bluefruit nRF52832 can easily support 40 Hz refresh rate for a significant number of channels if I just ignore the "notify interval" and notify() on "fake" updates repeatedly without waiting.
I wonder if the refresh rate should be a parameter in the UI?
What is the reason RaceChrono limits CAN updates to 20 Hz?
That arguably removes one of the advantages of listening to CAN over OBD-II.

What's the worst thing that can happen if my DIY device ignores the notify interval on the request and uses a "10 ms" notify interval instead? :smiley:

2) Is one BLE characteristic 0x01 sufficient for data communication?
I'm not super familiar with Bluetooth BLE yet, or with how multiple updates are delivered when using notify().
What happens if the car sends 5 different "allowed" CAN messages 1 ms apart over and over?
With a 50 ms notify interval, we will notify() the characteristic 5 times with a 1 ms interval, and then do nothing for 45 ms.
Does it make the communication for the last CAN PID more reliable because its data is "exposed" for longer?
Or is there something that allows RaceChrono to see past value updates even if a new one came in shortly afterwards?

I wonder if it would be useful to have say 10 characteristics and update them in a round robin way, or something like that.

3) Strange requests in the "Vehicle profile" mode.
I've been looking at what commands RaceChrono sends via characteristic 0x02.
a) When I start a session, I get "DENY ALL", and then "ADD PID" for the set of enabled PIDs.
This makes sense. It's cool to see that RaceChrono is smart enough to only request the same PID once if it's shared by multiple channels.

b) When I enable "Test connection" in "Vehicle profile", I get "ALLOW ALL" — this makes sense, although not clear why you couldn't just reuse the same smart logic from the session mode.

c) When I open "Channel editor", I get TWO "ALLOW ALL" requests.
This is strange. I wonder if the intention was to send "DENY ALL" and one "ADD PID" afterwards, that would be a lot more efficient.

d) When I change the PID in "Channel editor", I get a "ALLOW ALL" request.
Again, if I change the PID, I'd expect to get "DENY ALL" followed by "ADD PID".
Interestingly, I get "ALLOW ALL" even if I hit the checkmark without changing the PID at all.


  • 1) You can ignore it no problem. Just something I ended up using with my KTM bike. You can create your own rate limiter or just disable it if you don't need one.

    2) You'll need to implement both 1 and 2, as RaceChrono expects to have them.

    3) DENY ALL and ADD PID means it wants to receive only the ones that are added. ALLOW ALL means it wants to see all PIDs, it does not know which ones to expect. Two ALLOW ALL is a bug, but it means same as one :)
  • 2) Yeah, I understand that currently RaceChrono requires 1 for data and 2 for filter requests.
    My questions are really
    a) how does it work if I notify() multiple different PIDs in a short succession?
    b) is there any contention or risk of timeouts?
    c) if there are, should RaceChrono change the protocol to use multiple characteristics?

    3) I understand what the requests mean, but my question is whether RaceChrono should be sending different requests. When I'm in the "Channel editor" looking at PID=123, there's really not much value in "ALLOW ALL" over "DENY, then ADD PID 123".
  • 2a) Yes, just shoot away

    2b) No idea

    2c) The hardware I used works better with only one characteristic in notify mode. I get the idea but it just did not work on this hardware.

    3) Well it's not perfect, like I said, there's probably bugs.
  • Re: (3) — can this be fixed in RC v7?
  • edited August 2020
    3) Sorry, no. The v7.0 is too far in to testing. Also it's not too severe of a bug, as the device should just blindly follow the commands from RC. When there's ALLOW ALL first, and DENY ALL right after, obviously the ALLOW ALL does nothing. I will look at it when I build the next generation DIY-device.
  • Understood wrt timing. Hope to see it fixed in 7.1 or something. Let me know what is the effective communication channel to report issues like that. This forum thread? Issue on GitHub? Something else?

    Just to clarify, I'm not getting ALLOWALL-then-DENYALL, I'm getting ALLOWALL-ALLOWALL when I would have expected to get DENYALL-ALLOWONE.
  • Hi @timurrrr just a couple of question on your code:
    - is ID filtering really needed?
    - is there a limit to the number of filters that one can specify?
    - I see there is only 1 channel (braking) updated at 50 messages/second while the rest are updated only 25 times/sec. Is this limitation due to stability issues?

  • @jeby Bluetooth is too slow to get you all the messages in the CAN-Bus. Need to filter to improve the update rate.
  • Thank you @aol ! I see now that MCP2515 allows for 2 acceptance masks and a total of 2+4 filters (page 5 of this datasheet https://ww1.microchip.com/downloads/en/DeviceDoc/MCP2515-Stand-Alone-CAN-Controller-with-SPI-20001801J.pdf)

    I see also that BLE is slow but not *that* slow, I'll try to push the rate of some ID and see what happens :smiley:
  • @jeby my MCP2515 project just filters the packets at the Arduino level. Filtering at MCP2515 level would primarily help the throughput between Arduino and MCP2515. Not sure if that's necessary.
  • @jeby This might be a useful starting point:
    You can tweak this file to send whatever data you want to send, and have full control over the bandwidth, PIDs, etc.

    I used something like that to stress-test the BLE connection, but didn't check it in.
    Unfortunately, BLE is indeed slow — the filtering and dropping of every other data packet that I implemented in my FT86 project was tuned to match the performance I observed in testing.

    It might be possible to slightly improve the transmission rate by changing the format in which RaceChrono receives data. For example, we could put data from multiple PIDs in the same payload. Unfortunately, that can complicate the protocol too much, and I don't think the benefits outweigh the complexity and understandability of the code.
  • @timurrrr Larger MTU size and many packets per payload would improve the throughput dramatically. Unfortunately changing the MTU size is a bit painful and works differently on Android vs. iOS. Also it works (or doesn't) differently on different OS versions.
Sign In or Register to comment.