BLHeli icon indicating copy to clipboard operation
BLHeli copied to clipboard

auto telemetry protocol

Open pbecchi opened this issue 5 years ago • 11 comments

I am trying to read a autotelemetry with an arduino. I was expecting a record lenght of 10 bytes: 1 byte temperature, 2 bytes Voltage,2 bytes Amps, 2 bytes Amps hour , 2bytes eRPM, 1 byte CRC But the record seams to be 7 bytes!! How can I decode it?

pbecchi avatar Feb 13 '20 09:02 pbecchi

Hi. I recently implemented the telemetry request via dShot on the teensy (an arduino like microcontroller). I received back the documented 10 bytes. Something that was documented, and that I learned was essential, was to put a 1K resistor between the (arduino) RX in and 5V... this is a pull-up resistor that decreases the noise on the wire. You still connect the telemetry wire to the RX.
After I did this, my error rate went from 25% to 0%.

Also, I didn't see a way to know which 10 packets are your message. I ended up calculating the CRC against the prior 9 bytes, and when I got a match, that was the completed message.

No idea if that info will help you. Good Luck.

jimkazmer avatar Feb 17 '20 05:02 jimkazmer

I too am trying to use "auto-telemetry". Our situations may be different. I am trying to use auto-telemetry with dShot using bidirectional flight mode settings. What I recently learned is that an entirely new protocol was created to support this (and avoid issues that happened with some ESCs with the original Dshot protocol). The new protocol is called "inverted DShot" and is only used with bidirectional flight modes. It is a bidirectional (send and receive) protocol using the one command wire. Every "speed command" sent to the ESC gets an eRPM telemetry response (on the same wire).

Here is the issue thread that provides more details: https://github.com/bitdump/BLHeli/issues/434

I have not tried using the BLHeli_32 ESC configuration setting enabling "Auto Telemetry" every 32ms. That update rate is far too slow for what I am trying to do.

jimkazmer avatar Feb 17 '20 16:02 jimkazmer

I have found problem and solution. Auto telemetry is a continuous stream of 10 bytes messages sent every 36 ms. I was using an Arduino Uno or Mega that are not fast enougth to read and decode full messages , that why i was only getting 7 or 8 bytes! I am running now same code on an Esp32 and all 10 bytes are read and decoded. When the Crc match (90% of the time) the data is correct and can be processed.

pbecchi avatar Feb 17 '20 20:02 pbecchi

Did you add the 1K pull-up resistor?

jimkazmer avatar Feb 17 '20 20:02 jimkazmer

Yes, i did......no effect on Arduino Uno results! On Esp32 is not necessary CrC is correct 90% of the time...

pbecchi avatar Feb 17 '20 20:02 pbecchi

I too am using an 32-bit microcontroller, and my error rate went to 0% when I added the resistor.

jimkazmer avatar Feb 17 '20 20:02 jimkazmer

Any chance someone could point be in the direction of some examples on how I could read the telemetry output of BLHeli_32 (eg I have Wraith32 ESCs) using Serial RX input GPIO on a Raspberry Pi?

Im working on a project using 4x ESCs and Motors to make a RC truck from drone parts and telemetry (specifically eRPM) would allow me to make a proper active differential.

vonkoda avatar Apr 21 '20 06:04 vonkoda

@vonkoda: https://github.com/betaflight/betaflight/blob/master/src/main/sensors/esc_sensor.c

mikeller avatar Apr 21 '20 07:04 mikeller

Hi. I recently implemented the telemetry request via dShot on the teensy (an arduino like microcontroller). I received back the documented 10 bytes. Something that was documented, and that I learned was essential, was to put a 1K resistor between the (arduino) RX in and 5V... this is a pull-up resistor that decreases the noise on the wire. You still connect the telemetry wire to the RX. After I did this, my error rate went from 25% to 0%.

Also, I didn't see a way to know which 10 packets are your message. I ended up calculating the CRC against the prior 9 bytes, and when I got a match, that was the completed message.

No idea if that info will help you. Good Luck.

Hi @jimkazmer , may I ask which Teensy version and ESC did you use? I am currently working to read the telemetry output of BLHeli_32 ESC on Teensy 4.1.

Could you share with me any examples of code? Thank you.

brianleoshd avatar Nov 03 '21 03:11 brianleoshd

Hi. Just saw this; sorry for the delay. Using Teensy 4.0.

Code: //Initialize ESC Telemetry if (ACTIVATE_LEFT_RIGHT_TELEMETRY&1) { Serial4.begin(115200,SERIAL_8N1); Serial4.addMemoryForRead(TelemLeftCache, 128); } if (ACTIVATE_LEFT_RIGHT_TELEMETRY&2) { Serial5.begin(115200,SERIAL_8N1); Serial5.addMemoryForRead(TelemRightCache, 128); } ... // later in the code, you'll read in the messages // what I did below was from my testing routine... // message buffer management is not robust, but worked for testing int r_byteIndex=0; int l_byteIndex=0; uint32_t tmp_m; while(1) { while (Serial4.available() > 0) { TelemLeftBuffer[(l_byteIndex&31)]=Serial4.read(); l_byteIndex++; } if (l_byteIndex>=10) { if (TelemLeftBuffer[l_byteIndex-1] == telem_getCRC(&(TelemLeftBuffer[l_byteIndex-10]),9)) { tmp_m = micros(); //Serial3.printf("\nLEFT %d\n", tmp_m); //Serial3.printf("LEFT TELEM Values for CRC=%.2X\n", TelemLeftBuffer[l_byteIndex-1]); //Serial3.printf("LEFT Temp=%d Celsius\n", TelemLeftBuffer[l_byteIndex-10]); //printf("LEFT Voltage=%3.2f Volts\n", 1.0*(TelemLeftBuffer[l_byteIndex-9]<<8 | TelemLeftBuffer[l_byteIndex-8])/100); //Serial3.printf("LEFT Current=%3.2f Amps\n", 1.0*(TelemLeftBuffer[l_byteIndex-7]<<8 | TelemLeftBuffer[l_byteIndex-6])/100); //Serial3.printf("LEFT Consump=%d mAh\n", (TelemLeftBuffer[l_byteIndex-5]<<8 | TelemLeftBuffer[l_byteIndex-4])); //Serial3.printf("LEFT eRPM=%d\n", 100*(TelemLeftBuffer[l_byteIndex-3]<<8 | TelemLeftBuffer[l_byteIndex-2])); //Serial3.printf("LEFT RPM=%d\n", 100*(TelemLeftBuffer[l_byteIndex-3]<<8 | TelemLeftBuffer[l_byteIndex-2])/MOTOR_POLES_DIV_2); //Serial3.printf("LEFT CRC=%.2X\n",TelemLeftBuffer[l_byteIndex-1]); //Serial3.printf("LEFT New CRC=%.2X\n",telem_getCRC(&(TelemLeftBuffer[l_byteIndex-10]), 9)); Serial3.printf("l-temp %d\n", TelemLeftBuffer[l_byteIndex-10]); Serial3.printf("l-volt %3.2f\n", 1.0*(TelemLeftBuffer[l_byteIndex-9]<<8 | TelemLeftBuffer[l_byteIndex-8])/100); Serial3.printf("l-amps %3.2f\n", 1.0*(TelemLeftBuffer[l_byteIndex-7]<<8 | TelemLeftBuffer[l_byteIndex-6])/100); l_byteIndex=0; } } while (Serial5.available() > 0) { TelemRightBuffer[(r_byteIndex&31)]=Serial5.read(); r_byteIndex++; } if (r_byteIndex>=10) { if (TelemRightBuffer[r_byteIndex-1] == telem_getCRC(&(TelemRightBuffer[r_byteIndex-10]),9)) { tmp_m = micros(); //Serial3.printf("\nRIGHT %d\n", tmp_m); //Serial3.printf("RIGHT TELEM Values for CRC=%.2X\n", TelemRightBuffer[r_byteIndex-1]); //Serial3.printf("RIGHT Temp=%d Celsius\n", TelemRightBuffer[r_byteIndex-10]); //Serial3.printf("RIGHT Voltage=%3.2f Volts\n", 1.0*(TelemRightBuffer[r_byteIndex-9]<<8 | TelemRightBuffer[r_byteIndex-8])/100); //Serial3.printf("RIGHT Current=%3.2f Amps\n", 1.0*(TelemRightBuffer[r_byteIndex-7]<<8 | TelemRightBuffer[r_byteIndex-6])/100); //Serial3.printf("RIGHT Consump=%d mAh\n", (TelemRightBuffer[r_byteIndex-5]<<8 | TelemRightBuffer[r_byteIndex-4])); //Serial3.printf("RIGHT eRPM=%d\n", 100*(TelemRightBuffer[r_byteIndex-3]<<8 | TelemRightBuffer[r_byteIndex-2])); //Serial3.printf("RIGHT RPM=%d\n", 100*(TelemRightBuffer[r_byteIndex-3]<<8 | TelemRightBuffer[r_byteIndex-2])/MOTOR_POLES_DIV_2); //Serial3.printf("RIGHT CRC=%.2X\n",TelemRightBuffer[r_byteIndex-1]); //Serial3.printf("RIGHT New CRC=%.2X\n",telem_getCRC(&(TelemRightBuffer[r_byteIndex-10]), 9)); Serial3.printf("r-temp %d\n", TelemRightBuffer[r_byteIndex-10]); Serial3.printf("r-volt %3.2f\n", 1.0*(TelemRightBuffer[r_byteIndex-9]<<8 | TelemRightBuffer[r_byteIndex-8])/100); Serial3.printf("r-amps %3.2f\n", 1.0*(TelemRightBuffer[r_byteIndex-7]<<8 | TelemRightBuffer[r_byteIndex-6])/100); r_byteIndex=0; } }

}

uint8_t CRCTable[256]; uint8_t getCRCForByte(uint8_t val) { uint32_t j; for (j = 0; j < 8; j++) val = ( val & 0x80 ) ? 0x7 ^ ( val << 1 ) : ( val << 1 ); return val; } void telem_buildCRCTable() { uint32_t i; // fill an array with CRC values of all 256 possible bytes for (i = 0; i < 256; i++) CRCTable[i] = getCRCForByte(i); } uint8_t telem_getCRC(uint8_t message[], uint32_t lngth) { uint32_t i; uint32_t crc = 0; for (i = 0; i < lngth; i++) crc = CRCTable[crc ^ message[i]]; return crc; }

jimkazmer avatar Jan 05 '22 20:01 jimkazmer

I use the rpi pico to request telemetry over uart and it seems to be working well as documented in this repo. Is auto-telemetry the same as onewire KISS ESC telemetry? It should have a theoretical speed of around 1 ms.

Guppy16 avatar Jun 03 '23 22:06 Guppy16