DIY RFCOMM refresh rate problem


We have been using RaceChrono with an external GPS running at 10hz (Qsartz BT-Q818XT) on my son's go kart as an alternative to an AIM MyChron mainly because when we got into the sport the MyChrons weren't available due to the global supply issues. The RaceChrono app is great and has worked really well for us so I haven't felt the need to spend the money on the AIM unit.

We are now getting a little more serious and the need for RPM and lamda has seen me dust off some rusty old programming and electronic skills to build a DIY device using an ESP32 to see if we can still avoid the cost of the AIM and stick with RC. After being inspired by and checking out some projects on here I decided to keep things simple and go with a hall effect sensor on the crank for RPM sensing and send the data to RaceChrono via RC2 messages using Bluetooth RFCOMM. My initial test unit build went well and the device sends out RC2 messages at 10hz but RC doesn't seem to process all of the messages.

I can watch all of the test data being received on the phone (Galaxy S9) when I connect a terminal app to the ESP32. It appears to be coming in at 10Hz and looks like this:

When working Racechrono appears to be only processing every 4th message and reports a rate of 2.5Hz at best. It always shows it is connected with a data rate of 3.2 kbits/s but it often pauses and sometimes struggles to even get started showing data. I have tried sending at different rates (even 1hz and 5Hz struggles), tried different phones and I have also tried using the counter and not using it which doesn't seem to make a difference. I was hoping someone could help me figure out where the problem is or point me towards a process that will help me diagnose what is going on as I'm currently out of ideas.

Here is my code: (I had to learn some c++ and am new to it so go easy on me. Suggestions welcome)


#define LED 4
#define HALL_PIN 0

//Setup some variables for timing revolutions
volatile unsigned long rev_diff = 0;
volatile unsigned long prev_rev_time = 0;
volatile unsigned long rev_time = 0;

void Revolution() { //interrupt routine for a rev detection
rev_time = micros();

BluetoothSerial SerialBT;

uint32_t TimeToSend = 0;
unsigned int RC2count = 0;
uint16_t RPM = 0;
uint8_t checksum = 0;

void setup() {
pinMode(LED, OUTPUT);

SerialBT.begin("KartRPM1"); //Get Bluetooth running

attachInterrupt(HALL_PIN, Revolution, FALLING); //Setup interrupt for when a revolution occurs

void loop() {

rev_diff = rev_time - prev_rev_time;
if (rev_diff > 3000) { //ignore readings that suggest >20,000 RPM or no new rev
RPM = 60e6 / rev_diff; //60e6 micoseconds = 1 minute
prev_rev_time = rev_time;

if (micros() - rev_time > (ulong)3e6) { //no rev for 3 seconds so let's assume the engine stopped
RPM = 0;

if (millis() > TimeToSend) { //time to send data via BT to Race Chrono

TimeToSend+=100; //Set the time To Send the next lot of data. 100 millis = 10Hz

// $RC2,[time],[count],[xacc],[yacc],[zacc],[rpm/d1],[d2],[a1],[a2],[a3],[a4],[a5],[a6],[a7],[a8]*checksum
char buffer[255];
sprintf(buffer, "RC2,%s,%d,%s,%s,%s,%d,%s,%d,%d,%s,%s,%s,%s,%s,%s",
"", //time
RC2count, //count
"", //xacc
"", //yacc
"", //zacc
RPM, //RPM/d1
"", //d2
RC2count, //a1
millis(), //a2
"", //a3
"", //a4
"", //a5
"", //a6
"", //a7
""); //a8

int length = strlen(buffer);
for (int i = 0; i < length; i++){ // calc the check sum
checksum = checksum ^ (uint8_t)buffer[i];

SerialBT.printf("$%s*%02X\r\n", buffer, checksum); // send the RC2 Message

if (RC2count == 65535){
RC2count = 0;




  • I figured out the problem. I wasn't setting the checksum to 0 before calculating it.
    Should be:
    int length = strlen(buffer);
    uint8_t checksum = 0;
    for (int i = 0; i < length; i++){ // calc the check sum
    checksum = checksum ^ (uint8_t)buffer[i];

    It's working great now even at 20Hz
  • For anyone following along and wanting to use the code above it turns out that PIN 0 is not the best choice for the hall effect sensor. If it happens to be pulled low by the crank magnet when you power up the board it will enter flash mode rather than starting the program. Use PIN 4 instead.
Sign In or Register to comment.