Skip to content

Instantly share code, notes, and snippets.

@GOROman
Created June 5, 2023 11:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GOROman/6401fbdafcd6048edb9c32b190d708b9 to your computer and use it in GitHub Desktop.
Save GOROman/6401fbdafcd6048edb9c32b190d708b9 to your computer and use it in GitHub Desktop.
ExpressLRS - ELRS TX Simple Code for ESP32
#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);
}
@GOROman
Copy link
Author

GOROman commented Jun 5, 2023

受信の最小限のコードはこちら。

https://gist.github.com/GOROman/e194f501fbbfce589767966ce4241c6d

@GOROman
Copy link
Author

GOROman commented Jun 5, 2023

@GOROman
Copy link
Author

GOROman commented Jun 5, 2023

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