Created
June 5, 2023 11:15
-
-
Save GOROman/6401fbdafcd6048edb9c32b190d708b9 to your computer and use it in GitHub Desktop.
ExpressLRS - ELRS TX Simple Code for ESP32
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <M5Stack.h> | |
#define PACKED __attribute__((packed)) | |
#define SERIAL_BAUDRATE 420000 // ELRS モジュールの通信速度 | |
#define GPIO_PIN_RCSIGNAL_TX 21 // ELRS TX モジュールとの接続ピン(半二重) | |
#define GPIO_PIN_RCSIGNAL_RX 21 // ELRS TX モジュールとの接続ピン(半二重) | |
// CRC8 計算 | |
#define CRSF_CRC_POLY 0xd5 | |
static byte getCRC8(byte *buf, size_t size) | |
{ | |
byte crc8 = 0x00; | |
for (int i = 0; i < size; i++) | |
{ | |
crc8 ^= buf[i]; | |
for (int j = 0; j < 8; j++) | |
{ | |
if (crc8 & 0x80) | |
{ | |
crc8 <<= 1; | |
crc8 ^= CRSF_CRC_POLY; | |
} | |
else | |
{ | |
crc8 <<= 1; | |
} | |
} | |
} | |
return crc8; | |
} | |
void ICACHE_RAM_ATTR duplex_set_TX() | |
{ | |
portDISABLE_INTERRUPTS(); | |
gpio_set_pull_mode((gpio_num_t)GPIO_PIN_RCSIGNAL_TX, GPIO_FLOATING); | |
gpio_set_pull_mode((gpio_num_t)GPIO_PIN_RCSIGNAL_RX, GPIO_FLOATING); | |
gpio_set_level((gpio_num_t)GPIO_PIN_RCSIGNAL_TX, 1); | |
gpio_set_direction((gpio_num_t)GPIO_PIN_RCSIGNAL_TX, GPIO_MODE_OUTPUT); | |
constexpr uint8_t MATRIX_DETACH_IN_HIGH = 0x38; // routes 1 to matrix slot | |
gpio_matrix_in(MATRIX_DETACH_IN_HIGH, U1RXD_IN_IDX, false); // Disconnect RX from all pads | |
gpio_matrix_out((gpio_num_t)GPIO_PIN_RCSIGNAL_TX, U1TXD_OUT_IDX, false, false); | |
portENABLE_INTERRUPTS(); | |
} | |
/** | |
* Define the shape of a standard header | |
*/ | |
typedef struct crsf_header_s | |
{ | |
uint8_t device_addr; // from crsf_addr_e | |
uint8_t frame_size; // counts size after this byte, so it must be the payload size + 2 (type and crc) | |
uint8_t type; // from crsf_frame_type_e | |
} PACKED crsf_header_t; | |
/** | |
* Crossfire packed channel structure, each channel is 11 bits | |
*/ | |
typedef struct crsf_channels_s | |
{ | |
unsigned ch0 : 11; | |
unsigned ch1 : 11; | |
unsigned ch2 : 11; | |
unsigned ch3 : 11; | |
unsigned ch4 : 11; | |
unsigned ch5 : 11; | |
unsigned ch6 : 11; | |
unsigned ch7 : 11; | |
unsigned ch8 : 11; | |
unsigned ch9 : 11; | |
unsigned ch10 : 11; | |
unsigned ch11 : 11; | |
unsigned ch12 : 11; | |
unsigned ch13 : 11; | |
unsigned ch14 : 11; | |
unsigned ch15 : 11; | |
} PACKED crsf_channels_t; | |
typedef struct { | |
crsf_header_t header; | |
crsf_channels_t ch; // payload | |
byte crc = 0xff; | |
} PACKED RC_CHANNEL; | |
#define CRSF_ADDRESS_FLIGHT_CONTROLLER 0xC8 | |
#define CRSF_ADDRESS_CRSF_TRANSMITTER 0xEE | |
#define CRSF_FRAMETYPE_RC_CHANNELS_PACKED 0x16 | |
static RC_CHANNEL rc; | |
void setup() | |
{ | |
M5.begin(); | |
Serial1.begin(SERIAL_BAUDRATE, SERIAL_8N1, -1, GPIO_PIN_RCSIGNAL_TX, false, 500); | |
delay(200); | |
} | |
void loop() | |
{ | |
// CRSFパケット ヘッダ | |
rc.header.device_addr = CRSF_ADDRESS_CRSF_TRANSMITTER; | |
rc.header.frame_size = sizeof(RC_CHANNEL)-2; | |
rc.header.type = CRSF_FRAMETYPE_RC_CHANNELS_PACKED; | |
// プロポのチャンネル情報を書き換える | |
rc.ch.ch0 += 1; | |
rc.ch.ch1 += 2; | |
rc.ch.ch2 += 3; | |
rc.ch.ch3 += 4; | |
// CRC計算 | |
rc.crc = getCRC8(&rc.header.type, rc.header.frame_size-1); | |
// 半二重 送信モードへ | |
duplex_set_TX(); | |
// 送信 | |
Serial1.write((byte *)&rc, sizeof(RC_CHANNEL)); | |
delay(1); | |
} |
PING Packet
byte ping[] = {0xEE, 0x04, 0x28, 0x00, 0xEA, 0x54};
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
受信の最小限のコードはこちら。
https://gist.github.com/GOROman/e194f501fbbfce589767966ce4241c6d