diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index ecc9aac..5ebf98b 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -111,7 +111,7 @@ "C:\\Users\\derdoktor667\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\1.0.6\\tools\\sdk\\include\\fb_gfx", "C:\\Users\\derdoktor667\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\1.0.6\\cores\\esp32", "C:\\Users\\derdoktor667\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\1.0.6\\variants\\esp32", - "C:\\Users\\derdoktor667\\Documents\\Arduino\\libraries\\DShotRMT\\src", + "C:\\Users\\derdoktor667\\Documents\\Arduino\\libraries\\src", "c:\\users\\derdoktor667\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\1.22.0-97-gc752ad5-5.2.0\\xtensa-esp32-elf\\include\\c++\\5.2.0", "c:\\users\\derdoktor667\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\1.22.0-97-gc752ad5-5.2.0\\xtensa-esp32-elf\\include\\c++\\5.2.0\\xtensa-esp32-elf", "c:\\users\\derdoktor667\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\1.22.0-97-gc752ad5-5.2.0\\xtensa-esp32-elf\\include\\c++\\5.2.0\\backward", diff --git a/README.md b/README.md index 0d8e450..ae1bb5e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,32 @@ -# README +## DShot ESP32 Library utilizing RMT -This library can control a BlHeli_S by using encoded DShot commands. -More to come +### The DShot Protocol +The DSHOT protocol consists of transmitting 16-bit packets to the ESCs: 11-bit throttle value, 1-bit to request telemetry and a 4-bit checksum. There are three major protocol speeds: DSHOT150, DSHOT300 and DSHOT600. ---- +#### DShot -Timing: + DSHOT | Bitrate | TH1 | TH0 | Bit Time µs | Frame Time µs +--------:|---------:|-------:|-------:|------------:|-------------: +**150** | 150kbit/s| 5.00 | 2.50 | 6.67 | 106.72 +**300** | 300kbit/s| 2.50 | 1.25 | 3.33 | 53.28 +**600** | 600kbit/s| 1.25 | 0.625 | 1.67 | 26.72 +**1200** |1200kbit/s| 0.625 | 0.313 | 0.83 | 13.28 + +#### Calculating the CRC +The checksum is calculated over the throttle value and the telemetry bit, so the “first” 12 bits our value in the following example: + + crc = (value ^ (value >> 4) ^ (value >> 8)) & 0x0F; + +### Bidirectional DSHOT +Biderictional DSHOT is also known as inverted DSHOT, because the signal level is inverted, so 1 is low and a 0 is high. This is done in order to let the ESC know, that we are operating in bidirectional mode and that it should be sending back eRPM telemetry packages. + +#### Calculating the Bidirectional CRC +The calculation of the checksum is basically the same, just before the last step the values are inverted: + + crc = (~(value ^ (value >> 4) ^ (value >> 8))) & 0x0F; + +---- + +*References:* +- [DSHOT - the missing Handbook](https://brushlesswhoop.com/dshot-and-bidirectional-dshot/) + +- [DSHOT in the Dark](https://dmrlawson.co.uk/index.php/2017/12/04/dshot-in-the-dark/) diff --git a/examples/dshot300/dshot300.ino b/examples/dshot300/dshot300.ino index 4c9bdef..18e7331 100644 --- a/examples/dshot300/dshot300.ino +++ b/examples/dshot300/dshot300.ino @@ -1,7 +1,7 @@ // ...some very simple DShot example generating a DShot300 signal. #include -#include "DShotRMT.h" +#include // ...clearly name usb port #ifdef SERIAL diff --git a/keywords.txt b/keywords.txt index 9911c86..4f46df6 100644 --- a/keywords.txt +++ b/keywords.txt @@ -5,7 +5,7 @@ ####################################### # Datatypes (KEYWORD1) ####################################### -DShot_Lib KEYWORD1 +DShotRMT KEYWORD1 dshot_mode_t KEYWORD1 telemetric_request_t KEYWORD1 dshot_packet_t KEYWORD1 diff --git a/src/DShotRMT.cpp b/src/DShotRMT.cpp index a2c13d8..2eb0dab 100644 --- a/src/DShotRMT.cpp +++ b/src/DShotRMT.cpp @@ -6,9 +6,6 @@ #include "DShotRMT.h" -DShotRMT* DShotFirst = nullptr; -DShotRMT* DShotNext = nullptr; - DShotRMT::DShotRMT(gpio_num_t gpio, rmt_channel_t rmtChannel) { dshot_config.gpio_num = gpio; dshot_config.pin_num = uint8_t(gpio); @@ -45,27 +42,27 @@ bool DShotRMT::begin(dshot_mode_t dshot_mode, bool is_bidirectional) { switch (dshot_config.mode) { case DSHOT150: - dshot_config.ticks_per_bit = 64; // ...Bit Period Time 6.67 �s - dshot_config.ticks_zero_high = 24; // ...zero time 2.50 �s - dshot_config.ticks_one_high = 48; // ...one time 5.00 �s + dshot_config.ticks_per_bit = 64; // ...Bit Period Time 6.67 us + dshot_config.ticks_zero_high = 24; // ...zero time 2.50 us + dshot_config.ticks_one_high = 48; // ...one time 5.00 us break; case DSHOT300: - dshot_config.ticks_per_bit = 32; // ...Bit Period Time 3.33 �s - dshot_config.ticks_zero_high = 12; // ...zero time 1.25 �s - dshot_config.ticks_one_high = 24; // ...one time 2.50 �s + dshot_config.ticks_per_bit = 32; // ...Bit Period Time 3.33 us + dshot_config.ticks_zero_high = 12; // ...zero time 1.25 us + dshot_config.ticks_one_high = 24; // ...one time 2.50 us break; case DSHOT600: - dshot_config.ticks_per_bit = 16; // ...Bit Period Time 1.67 �s - dshot_config.ticks_zero_high = 6; // ...zero time 0.625 �s - dshot_config.ticks_one_high = 12; // ...one time 1.25 �s + dshot_config.ticks_per_bit = 16; // ...Bit Period Time 1.67 us + dshot_config.ticks_zero_high = 6; // ...zero time 0.625 us + dshot_config.ticks_one_high = 12; // ...one time 1.25 us break; case DSHOT1200: - dshot_config.ticks_per_bit = 8; // ...Bit Period Time 0.83 �s - dshot_config.ticks_zero_high = 3; // ...zero time 0.313 �s - dshot_config.ticks_one_high = 6; // ...one time 0.625 �s + dshot_config.ticks_per_bit = 8; // ...Bit Period Time 0.83 us + dshot_config.ticks_zero_high = 3; // ...zero time 0.313 us + dshot_config.ticks_one_high = 6; // ...one time 0.625 us break; // ...because having a default is "good style" @@ -95,7 +92,7 @@ bool DShotRMT::begin(dshot_mode_t dshot_mode, bool is_bidirectional) { rmt_config(&rmt_dshot_config); // ...essential step, return the result - return rmt_driver_install(rmt_dshot_config.channel, 0, 0); + return rmt_driver_install(rmt_dshot_config.channel, 0, 0); } //´...the config part is done, now the calculating and sending part