Fix LD2410 using HardwareSerial on ESP8266

This commit is contained in:
Theo Arends 2022-12-01 16:18:38 +01:00
parent baed1e06a8
commit 816fd78fbb
3 changed files with 69 additions and 15 deletions

View File

@ -54,7 +54,8 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal
serial_buffer_size = buffer_size;
m_rx_pin = receive_pin;
m_tx_pin = transmit_pin;
m_in_pos = m_out_pos = 0;
m_in_pos = 0;
m_out_pos = 0;
#ifdef ESP8266
if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) {
return;
@ -293,7 +294,8 @@ void TasmotaSerial::flush(void) {
while (TSerial->available()) { TSerial->read(); }
#endif // ESP32
} else {
m_in_pos = m_out_pos = 0;
m_in_pos = 0;
m_out_pos = 0;
}
}
@ -428,13 +430,14 @@ size_t TasmotaSerial::write(uint8_t b) {
}
void IRAM_ATTR TasmotaSerial::rxRead(void) {
uint32_t m_out_pos_fixed = m_out_pos;
if (!m_nwmode) {
int32_t loop_read = m_very_high_speed ? serial_buffer_size : 1;
// Advance the starting point for the samples but compensate for the
// initial delay which occurs before the interrupt is delivered
uint32_t wait = m_bit_start_time;
uint32_t start = ESP.getCycleCount();
while (loop_read-- > 0) { // try to receveive all consecutive bytes in a raw
while (loop_read-- > 0) { // try to receveive all consecutive bytes in a row
uint32_t rec = 0;
for (uint32_t i = 0; i < 8; i++) {
TM_SERIAL_WAIT_RCV;
@ -442,14 +445,14 @@ void IRAM_ATTR TasmotaSerial::rxRead(void) {
if (digitalRead(m_rx_pin)) rec |= 0x80;
}
// Store the received value in the buffer unless we have an overflow
uint32_t next = (m_in_pos+1) % serial_buffer_size;
if (next != (int)m_out_pos) {
uint32_t next = (m_in_pos + 1) % serial_buffer_size;
if (next != m_out_pos_fixed) {
m_buffer[m_in_pos] = rec;
m_in_pos = next;
} else {
// Buffer overrun - exit and fix Hardware Watchdog in case of high speed flooding
// Buffer overrun - exit
m_overflow = true;
break;
loop_read = 0;
}
TM_SERIAL_WAIT_RCV_LOOP; // wait for stop bit
@ -511,7 +514,7 @@ void IRAM_ATTR TasmotaSerial::rxRead(void) {
}
//stobyte(0,ssp->ss_byte>>1);
uint32_t next = (m_in_pos + 1) % serial_buffer_size;
if (next != (uint32_t)m_out_pos) {
if (next != m_out_pos_fixed) {
m_buffer[m_in_pos] = ss_byte >> 1;
m_in_pos = next;
}
@ -525,7 +528,7 @@ void IRAM_ATTR TasmotaSerial::rxRead(void) {
// bit zero was 0,
//stobyte(0,ssp->ss_byte>>1);
uint32_t next = (m_in_pos + 1) % serial_buffer_size;
if (next != (uint32_t)m_out_pos) {
if (next != m_out_pos_fixed) {
m_buffer[m_in_pos] = ss_byte >> 1;
m_in_pos = next;
}

View File

@ -70,11 +70,12 @@ class TasmotaSerial : public Stream {
private:
bool isValidGPIOpin(int pin);
size_t txWrite(uint8_t byte);
void _fast_write(uint8_t b); // IRAM minimized version
#ifdef ESP32
bool freeUart(void);
void Esp32Begin(void);
#endif
size_t txWrite(uint8_t byte);
// Member variables
int m_rx_pin;
@ -97,9 +98,6 @@ class TasmotaSerial : public Stream {
bool m_high_speed = false;
bool m_very_high_speed = false; // above 100000 bauds
uint8_t *m_buffer = nullptr;
void _fast_write(uint8_t b); // IRAM minimized version
#ifdef ESP32
uint32_t m_speed;
uint32_t m_config;

View File

@ -67,6 +67,7 @@ struct {
uint8_t step;
uint8_t retry;
uint8_t settings;
uint8_t byte_counter;
bool valid_response;
} LD2410;
@ -93,13 +94,13 @@ void Ld1410HandleTargetData(void) {
LD2410.static_distance = LD2410.buffer[13] << 8 | LD2410.buffer[12];
LD2410.static_energy = LD2410.buffer[14];
LD2410.detect_distance = LD2410.buffer[16] << 8 | LD2410.buffer[15];
/*
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Type %d, State %d, Moving %d/%d%%, Static %d/%d%%, Detect %d"),
LD2410.buffer[6], LD2410.buffer[8],
LD2410.moving_distance, LD2410.moving_energy,
LD2410.static_distance, LD2410.static_energy,
LD2410.detect_distance);
*/
if (0x01 == LD2410.buffer[6]) { // Engineering mode data
// Adds 22 extra bytes of data
@ -153,6 +154,8 @@ bool Ld2410Match(const uint8_t *header, uint32_t offset) {
}
void Ld2410Input(void) {
/*
// Works with TasmotaSerial as SoftwareSerial but fails with HardwareSerial
uint32_t size = LD2410Serial->read(LD2410.buffer, LD2410_BUFFER_SIZE);
if (size) {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Rcvd %*_H"), size, LD2410.buffer);
@ -175,6 +178,56 @@ void Ld2410Input(void) {
}
}
}
*/
// Works with TasmotaSerial and HardwareSerial
while (LD2410Serial->available()) {
yield(); // Fix watchdogs
LD2410.buffer[LD2410.byte_counter++] = LD2410Serial->read();
if (LD2410.byte_counter < 4) { continue; } // Need first four header bytes
uint32_t header_start = LD2410.byte_counter -4; // Fix interrupted header transmits
bool target_header = (Ld2410Match(LD2410_target_header, header_start)); // F4F3F2F1
bool config_header = (Ld2410Match(LD2410_config_header, header_start)); // FDFCFBFA
if ((target_header || config_header) && (header_start != 0)) {
memmove(LD2410.buffer, LD2410.buffer + header_start, 4); // Sync buffer with header
LD2410.byte_counter = 4;
}
if (LD2410.byte_counter < 6) { continue; } // Need packet size bytes
target_header = (Ld2410Match(LD2410_target_header, 0)); // F4F3F2F1
config_header = (Ld2410Match(LD2410_config_header, 0)); // FDFCFBFA
if (target_header || config_header) {
uint32_t len = LD2410.buffer[4] +10; // Total packet size
if (len > LD2410_BUFFER_SIZE) {
LD2410.byte_counter = 0; // Invalid data
break; // Exit loop to satisfy yields
}
if (LD2410.byte_counter < len) { continue; } // Need complete packet
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Rcvd %*_H"), len, LD2410.buffer);
if (target_header) { // F4F3F2F1
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Rcvd %*_H"), len, LD2410.buffer);
if (Ld2410Match(LD2410_target_footer, len -4)) { // F8F7F6F5
Ld1410HandleTargetData();
}
}
else if (config_header) { // FDFCFBFA
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Rcvd %*_H"), len, LD2410.buffer);
if (Ld2410Match(LD2410_config_footer, len -4)) { // 04030201
Ld1410HandleConfigData();
}
}
}
LD2410.byte_counter = 0; // Finished or bad received footer
break; // Exit loop to satisfy yields
}
// If here then LD2410.byte_counter could still be partial correct for next loop
}
void Ld2410SendCommand(uint32_t command, uint8_t *val = nullptr, uint32_t val_len = 0);