/* * An Arduino library for the Hi-Link LD2410 24Ghz FMCW radar sensor. * * This sensor is a Frequency Modulated Continuous Wave radar, which makes it good for presence detection and its sensitivity at different ranges to both static and moving targets can be configured. * * The code in this library is based off the manufacturer datasheet and reading of this initial piece of work for ESPHome https://github.com/rain931215/ESPHome-LD2410. * * https://github.com/ncmreynolds/ld2410 * * Released under LGPL-2.1 see https://github.com/ncmreynolds/ld2410/LICENSE for full license * Modified by Robert Zmrzli */ #ifndef ld2410_cpp #define ld2410_cpp #include "ld2410.h" ld2410::ld2410() //Constructor function { } ld2410::~ld2410() //Destructor function { } bool ld2410::begin(Stream &radarStream, bool waitForRadar) { radar_uart_ = &radarStream; //Set the stream used for the LD2410 if(debug_uart_ != nullptr) { debug_uart_->println(F("ld2410 started")); } if(waitForRadar) { if(debug_uart_ != nullptr) { debug_uart_->print(F("\nLD2410 firmware: ")); } if(requestFirmwareVersion()) { if(debug_uart_ != nullptr) { debug_uart_->print(F(" v")); debug_uart_->print(firmware_major_version); debug_uart_->print('.'); debug_uart_->print(firmware_minor_version); debug_uart_->print('.'); debug_uart_->print(firmware_bugfix_version); debug_uart_->print(F("\nEnabling engineering mode: ")); } } if(requestStartEngineeringMode()) { if(debug_uart_ != nullptr) { debug_uart_->print(F(" E OK")); } return true; } else { if(debug_uart_ != nullptr) { debug_uart_->print(F(" E no response")); } } } else { if(debug_uart_ != nullptr) { debug_uart_->print(F("\nLD2410 library configured")); } return true; } return false; } void ld2410::debug(Stream &terminalStream) { debug_uart_ = &terminalStream; //Set the stream used for the terminal #if defined(ESP8266) if(&terminalStream == &Serial) { debug_uart_->write(17); //Send an XON to stop the hung terminal after reset on ESP8266 } #endif } bool ld2410::isConnected() { if(millis() - radar_uart_last_packet_ < radar_uart_timeout) //Use the last reading { return true; } if(read_frame_()) //Try and read a frame if the current reading is too old { return true; } return false; } bool ld2410::read() { return read_frame_(); } bool ld2410::presenceDetected() { return target_type_ != 0; } bool ld2410::stationaryTargetDetected() { if((target_type_ & 0x02) && stationary_target_distance_ > 0 && stationary_target_energy_ > 0) { return true; } return false; } uint16_t ld2410::stationaryTargetDistance() { //if(stationary_target_energy_ > 0) { return stationary_target_distance_; } //return 0; } uint8_t ld2410::stationaryTargetEnergy() { //if(stationary_target_distance_ > 0) { return stationary_target_energy_; } //return 0; } bool ld2410::movingTargetDetected() { if((target_type_ & 0x01) && moving_target_distance_ > 0 && moving_target_energy_ > 0) { return true; } return false; } uint16_t ld2410::movingTargetDistance() { //if(moving_target_energy_ > 0) { return moving_target_distance_; } //return 0; } uint8_t ld2410::movingTargetEnergy() { //if(moving_target_distance_ > 0) { return moving_target_energy_; } //return 0; } bool ld2410::read_frame_() { uint8_t byte_read_ = 0; if(radar_uart_ -> available()) { byte_read_ = radar_uart_ -> read(); #ifdef LD2410_DEBUG_RAW if(debug_uart_ != nullptr) { if(byte_read_ < 0x10) { debug_uart_->print('0'); } debug_uart_->print(byte_read_, HEX); debug_uart_->print(' '); } #endif if(frame_started_ == false) { radar_data_frame_position_ = 0; //if(byte_read_ == 0xF4 && getting_response == 0) if(byte_read_ == 0xF4) { #ifdef LD2410_DEBUG_DATA if(debug_uart_ != nullptr) { debug_uart_->print(F("\n< : F4 ")); } #endif radar_data_frame_[radar_data_frame_position_++] = byte_read_; frame_started_ = true; ack_frame_ = false; } else if(byte_read_ == 0xFD) { // #ifdef LD2410_DEBUG_COMMANDS // if(debug_uart_ != nullptr) // { // debug_uart_->print(F("\n< : FD ")); // } // #endif radar_data_frame_[radar_data_frame_position_++] = byte_read_; frame_started_ = true; ack_frame_ = true; } } else { if(radar_data_frame_position_ < LD2410_MAX_FRAME_LENGTH) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr && ack_frame_ == true) { if(radar_data_frame_position_ < 0x10) { debug_uart_->print('0'); } debug_uart_->print(radar_data_frame_position_, HEX); debug_uart_->print(' '); } #endif radar_data_frame_[radar_data_frame_position_++] = byte_read_; //print_frame_(); if(radar_data_frame_position_ > 7) //Can check for start and end { if( radar_data_frame_[0] == 0xF4 && //Data frame end state radar_data_frame_[1] == 0xF3 && radar_data_frame_[2] == 0xF2 && radar_data_frame_[3] == 0xF1 && radar_data_frame_[radar_data_frame_position_ - 4] == 0xF8 && radar_data_frame_[radar_data_frame_position_ - 3] == 0xF7 && radar_data_frame_[radar_data_frame_position_ - 2] == 0xF6 && radar_data_frame_[radar_data_frame_position_ - 1] == 0xF5 ) { //debug_uart_->print(F("\ndata frame found!")); if(parse_data_frame_()) { #ifdef LD2410_DEBUG_DATA if(debug_uart_ != nullptr) { debug_uart_->print(F("parsed data OK")); } #endif frame_started_ = false; radar_data_frame_position_ = 0; return true; } else { #ifdef LD2410_DEBUG_DATA if(debug_uart_ != nullptr) { debug_uart_->print(F("failed to parse data")); } #endif frame_started_ = false; radar_data_frame_position_ = 0; } } else if(radar_data_frame_[0] == 0xFD && //Command frame end state radar_data_frame_[1] == 0xFC && radar_data_frame_[2] == 0xFB && radar_data_frame_[3] == 0xFA && radar_data_frame_[radar_data_frame_position_ - 4] == 0x04 && radar_data_frame_[radar_data_frame_position_ - 3] == 0x03 && radar_data_frame_[radar_data_frame_position_ - 2] == 0x02 && radar_data_frame_[radar_data_frame_position_ - 1] == 0x01 ) { if(parse_command_frame_()) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("parsed command OK")); } #endif frame_started_ = false; radar_data_frame_position_ = 0; getting_response = 0; return true; } else { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("failed to parse command")); } #endif frame_started_ = false; radar_data_frame_position_ = 0; getting_response = 0; } } } } else { #if defined(LD2410_DEBUG_DATA) || defined(LD2410_DEBUG_COMMANDS) if(debug_uart_ != nullptr) { debug_uart_->print(F("\nLD2410 frame overran")); } #endif frame_started_ = false; radar_data_frame_position_ = 0; } } } return false; } void ld2410::print_frame_() { if(debug_uart_ != nullptr) { if(ack_frame_ == true) { debug_uart_->print(F("\n < Cmnd : ")); } else { debug_uart_->print(F("\n < Data: ")); } uint8_t frame_length = radar_data_frame_position_; for(uint8_t i = 0; i < frame_length; i ++) { if(radar_data_frame_[i] < 0x10) { debug_uart_->print('0'); } debug_uart_->print(radar_data_frame_[i],HEX); debug_uart_->print(' '); } // debug_uart_->println(""); } } void ld2410::resetGates() { for(uint8_t i = 0; i < 10 ; i ++) { motion_energy[i] = 0; stationary_energy[i] = 0; } for(uint8_t i = 10; i < 14 ; i ++) { motion_energy[i] = 0; } } bool ld2410::parse_data_frame_() { uint16_t intra_frame_data_length_ = radar_data_frame_[4] + (radar_data_frame_[5] << 8); if(radar_data_frame_position_ == intra_frame_data_length_ + 10) { #ifdef LD2410_DEBUG_DATA if(debug_uart_ != nullptr && ack_frame_ == false) { debug_uart_->print(F("\n @1 : ")); print_frame_(); } else if(debug_uart_ != nullptr){ debug_uart_->print(F("\n @2 : ")); } #endif #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr && ack_frame_ == true) { print_frame_(); } #endif if(radar_data_frame_[6] == 0x01 && radar_data_frame_[7] == 0xAA) //Engineering mode data { //engineering report target_type_ = radar_data_frame_[8]; #ifdef LD2410_DEBUG_PARSE if(debug_uart_ != nullptr) { //debug_uart_->print(F("\nEngineering data - ")); if(target_type_ == 0x00) { //debug_uart_->print(F("no target")); } else if(target_type_ == 0x01) { debug_uart_->println(F("moving target:")); } else if(target_type_ == 0x02) { //debug_uart_->print(F("stationary target:")); } else if(target_type_ == 0x03) { //debug_uart_->println(F("moving & stationary targets:")); } } #endif motion_energy[0] = motion_energy[0] + 1; #ifdef LD2410_DEBUG_PARSE if(debug_uart_ != nullptr){ debug_uart_->print("ME: "); debug_uart_->print( motion_energy[0]); } #endif motion_energy[1+target_type_] = motion_energy[1+target_type_] + 1; for(uint8_t gate = 1; gate <= 9; gate++) { motion_energy[gate+4] = motion_energy[gate+4] + radar_data_frame_[18+gate]; } stationary_energy[0] = stationary_energy[0] + 1; for(uint8_t gate = 1; gate <= 9; gate++) { stationary_energy[gate] = stationary_energy[gate] + radar_data_frame_[27+gate]; } radar_uart_last_packet_ = millis(); return true; } else if(intra_frame_data_length_ == 13 && radar_data_frame_[6] == 0x02 && radar_data_frame_[7] == 0xAA && radar_data_frame_[17] == 0x55 && radar_data_frame_[18] == 0x00) //Normal target data { //normal report target_type_ = radar_data_frame_[8]; //moving_target_distance_ = radar_data_frame_[9] + (radar_data_frame_[10] << 8); stationary_target_distance_ = radar_data_frame_[9] + (radar_data_frame_[10] << 8); stationary_target_energy_ = radar_data_frame_[14]; moving_target_energy_ = radar_data_frame_[11]; //stationary_target_distance_ = radar_data_frame_[12] + (radar_data_frame_[13] << 8); moving_target_distance_ = radar_data_frame_[15] + (radar_data_frame_[16] << 8); #ifdef LD2410_DEBUG_PARSE if(debug_uart_ != nullptr) { //debug_uart_->print(F("\nNormal data - ")); if(target_type_ == 0x00) { debug_uart_->println(F("\nno target")); } else if(target_type_ == 0x01) { debug_uart_->println(F("\nmoving target:")); } else if(target_type_ == 0x02) { //debug_uart_->print(F("stationary target:")); } else if(target_type_ == 0x03) { //debug_uart_->println(F("\nmoving & stationary targets:")); } if(radar_data_frame_[8] & 0x01) { //debug_uart_->print(F(" moving at ")); //debug_uart_->print(moving_target_distance_); //debug_uart_->print(F("cm power ")); //debug_uart_->print(moving_target_energy_); } if(radar_data_frame_[8] & 0x02) { //debug_uart_->print(F(" stationary at ")); //debug_uart_->print(stationary_target_distance_); //debug_uart_->print(F("cm power ")); //debug_uart_->print(stationary_target_energy_); } } #endif radar_uart_last_packet_ = millis(); return true; } else { #ifdef LD2410_DEBUG_DATA if(debug_uart_ != nullptr) { debug_uart_->print(F("\nUnknown frame type")); } #endif //print_frame_(); } } else { #ifdef LD2410_DEBUG_DATA if(debug_uart_ != nullptr) { debug_uart_->print(F("\nFrame length unexpected: ")); debug_uart_->print(radar_data_frame_position_); debug_uart_->print(F(" not ")); debug_uart_->print(intra_frame_data_length_ + 10); } #endif } return false; } bool ld2410::parse_command_frame_() { uint16_t intra_frame_data_length_ = radar_data_frame_[4] + (radar_data_frame_[5] << 8); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { //print_frame_(); debug_uart_->print(F("\nACK frame payload: ")); debug_uart_->print(intra_frame_data_length_); debug_uart_->print(F(" bytes")); debug_uart_->print(F("\nparsed command ")); } #endif //print_frame_(); latest_ack_ = radar_data_frame_[6]; latest_command_success_ = (radar_data_frame_[8] == 0x00 && radar_data_frame_[9] == 0x00); if(intra_frame_data_length_ == 8 && latest_ack_ == 0xFF) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nACK for entering configuration mode: ")); } #endif if(latest_command_success_) { radar_uart_last_packet_ = millis(); if(debug_uart_ != nullptr) { debug_uart_->print(F(" OK")); } return true; } else { if(debug_uart_ != nullptr) { debug_uart_->print(F(" failed")); } return false; } } else if(intra_frame_data_length_ == 4 && latest_ack_ == 0xFE) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nACK for leaving configuration mode: ")); } #endif if(latest_command_success_) { radar_uart_last_packet_ = millis(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("OK")); } #endif return true; } else { if(debug_uart_ != nullptr) { debug_uart_->print(F("failed")); } return false; } } else if(intra_frame_data_length_ == 4 && latest_ack_ == 0x60) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nACK for setting max values: ")); } #endif if(latest_command_success_) { radar_uart_last_packet_ = millis(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("OK")); } #endif return true; } else { if(debug_uart_ != nullptr) { debug_uart_->print(F("failed")); } return false; } } else if(intra_frame_data_length_ == 28 && latest_ack_ == 0x61) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nACK for current configuration: ")); } #endif if(latest_command_success_) { radar_uart_last_packet_ = millis(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("OK")); } #endif max_gate = radar_data_frame_[11]; max_moving_gate = radar_data_frame_[12]; max_stationary_gate = radar_data_frame_[13]; motion_sensitivity[0] = radar_data_frame_[14]; motion_sensitivity[1] = radar_data_frame_[15]; motion_sensitivity[2] = radar_data_frame_[16]; motion_sensitivity[3] = radar_data_frame_[17]; motion_sensitivity[4] = radar_data_frame_[18]; motion_sensitivity[5] = radar_data_frame_[19]; motion_sensitivity[6] = radar_data_frame_[20]; motion_sensitivity[7] = radar_data_frame_[21]; motion_sensitivity[8] = radar_data_frame_[22]; stationary_sensitivity[0] = radar_data_frame_[23]; stationary_sensitivity[1] = radar_data_frame_[24]; stationary_sensitivity[2] = radar_data_frame_[25]; stationary_sensitivity[3] = radar_data_frame_[26]; stationary_sensitivity[4] = radar_data_frame_[27]; stationary_sensitivity[5] = radar_data_frame_[28]; stationary_sensitivity[6] = radar_data_frame_[29]; stationary_sensitivity[7] = radar_data_frame_[30]; stationary_sensitivity[8] = radar_data_frame_[31]; sensor_idle_time = radar_data_frame_[32]; sensor_idle_time += (radar_data_frame_[33] << 8); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nMax gate distance: ")); debug_uart_->print(max_gate); debug_uart_->print(F("\nMax motion detecting gate distance: ")); debug_uart_->print(max_moving_gate); debug_uart_->print(F("\nMax stationary detecting gate distance: ")); debug_uart_->print(max_stationary_gate); debug_uart_->print(F("\nSensitivity per gate")); for(uint8_t i = 0; i < 9; i++) { debug_uart_->print(F("\nGate ")); debug_uart_->print(i); debug_uart_->print(F(" (")); debug_uart_->print(i * 0.75); debug_uart_->print('-'); debug_uart_->print((i+1) * 0.75); debug_uart_->print(F(" metres) Motion: ")); debug_uart_->print(motion_sensitivity[i]); debug_uart_->print(F(" Stationary: ")); debug_uart_->print(stationary_sensitivity[i]); } debug_uart_->print(F("\nSensor idle timeout: ")); debug_uart_->print(sensor_idle_time); debug_uart_->print('s'); } #endif return true; } else { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("failed")); } #endif return false; } } else if(intra_frame_data_length_ == 4 && latest_ack_ == 0x64) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nACK for setting sensitivity values: ")); } #endif if(latest_command_success_) { radar_uart_last_packet_ = millis(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("OK")); } #endif return true; } else { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("failed")); } #endif return false; } } else if(intra_frame_data_length_ == 12 && latest_ack_ == 0xA0) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nACK for firmware version: ")); } #endif if(latest_command_success_) { firmware_major_version = radar_data_frame_[13]; firmware_minor_version = radar_data_frame_[12]; firmware_bugfix_version = radar_data_frame_[14]; firmware_bugfix_version += radar_data_frame_[15]<<8; firmware_bugfix_version += radar_data_frame_[16]<<16; firmware_bugfix_version += radar_data_frame_[17]<<24; radar_uart_last_packet_ = millis(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("OK")); } #endif return true; } else { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("failed")); } #endif return false; } } else if(intra_frame_data_length_ == 4 && latest_ack_ == 0xA2) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nACK for factory reset: ")); } #endif if(latest_command_success_) { radar_uart_last_packet_ = millis(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("OK")); } #endif return true; } else { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("failed")); } #endif return false; } } else if(intra_frame_data_length_ == 4 && latest_ack_ == 0xA3) { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nACK for restart: ")); } #endif if(latest_command_success_) { radar_uart_last_packet_ = millis(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("OK")); } #endif return true; } else { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("failed")); } #endif return false; } } else if(intra_frame_data_length_ == 4 && latest_ack_ == 0x62) { return true; } else { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\nUnknown ACK")); } #endif } return false; } void ld2410::SendToRadar(uint8_t to_send) { radar_uart_->write((byte)to_send); // #ifdef LD2410_DEBUG_COMMANDS // if(debug_uart_ != nullptr) // { // if(to_send < 0x10) // { // debug_uart_->print('0'); // } // debug_uart_->print(to_send, HEX); // debug_uart_->print(' '); // } // #endif } void ld2410::send_command_preamble_() { #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) debug_uart_->print("Sending: "); #endif //Command preamble radar_uart_->write((byte)0xFD); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(" FD"); } #endif radar_uart_->write((byte)0xFC); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(" FC"); } #endif radar_uart_->write((byte)0xFB); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(" FB"); } #endif radar_uart_->write((byte)0xFA); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(" FA"); } #endif } void ld2410::send_command_postamble_() { //Command end radar_uart_->write((byte)0x04); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(" 04"); } #endif radar_uart_->write((byte)0x03); if(debug_uart_ != nullptr) { debug_uart_->print(" 03"); } radar_uart_->write((byte)0x02); if(debug_uart_ != nullptr) { debug_uart_->print(" 02"); } radar_uart_->write((byte)0x01); if(debug_uart_ != nullptr) { debug_uart_->print(" 01"); } } bool ld2410::enter_configuration_mode_() { //Serial.print(F("\nenter_configuration_mode_")); send_command_preamble_(); //Request firmware radar_uart_->write((byte) 0x04); //Command is four bytes long if(debug_uart_ != nullptr) { debug_uart_->print(" 04"); } radar_uart_->write((byte) 0x00); if(debug_uart_ != nullptr) { debug_uart_->print(" 00"); } radar_uart_->write((byte) 0xFF); //Request enter command mode if(debug_uart_ != nullptr) { debug_uart_->print(" FF"); } radar_uart_->write((byte) 0x00); if(debug_uart_ != nullptr) { debug_uart_->print(" 00"); } radar_uart_->write((byte) 0x01); if(debug_uart_ != nullptr) { debug_uart_->print(" 01"); } radar_uart_->write((byte) 0x00); if(debug_uart_ != nullptr) { debug_uart_->print(" 00"); } send_command_postamble_(); frame_started_ = false; radar_data_frame_position_ = 0; radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { if(read_frame_()) { //debug_uart_->print(F("\nFrame read!")); if(latest_ack_ == 0xFF && latest_command_success_) { //Serial.println(" OK"); return true; } } } //Serial.println(" NOK"); return false; } bool ld2410::leave_configuration_mode_() { //Serial.print(F("\nleave_configuration_mode_")); send_command_preamble_(); //Request firmware radar_uart_->write((byte) 0x02); //Command is four bytes long radar_uart_->write((byte) 0x00); radar_uart_->write((byte) 0xFE); //Request leave command mode radar_uart_->write((byte) 0x00); send_command_postamble_(); radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { if(read_frame_()) { if(latest_ack_ == 0xFE && latest_command_success_) { //Serial.println(" OK"); return true; } } } //Serial.println(" NOK"); return false; } bool ld2410::requestStartEngineeringMode() { if(enter_configuration_mode_()) { delay(50); send_command_preamble_(); //Request firmware radar_uart_->write((byte) 0x02); //Command is four bytes long if(debug_uart_ != nullptr) { debug_uart_->print(" 02"); } radar_uart_->write((byte) 0x00); if(debug_uart_ != nullptr) { debug_uart_->print(" 00"); } radar_uart_->write((byte) 0x62); //Request enter command mode if(debug_uart_ != nullptr) { debug_uart_->print(" 62"); } radar_uart_->write((byte) 0x00); if(debug_uart_ != nullptr) { debug_uart_->print(" 00"); } send_command_postamble_(); radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { if(read_frame_()) { if(latest_ack_ == 0x62 && latest_command_success_) { delay(50); leave_configuration_mode_(); return true; } } } } else { delay(50); leave_configuration_mode_(); return false; } delay(50); leave_configuration_mode_(); return false; } bool ld2410::requestEndEngineeringMode() { send_command_preamble_(); //Request firmware radar_uart_->write((byte) 0x02); //Command is four bytes long radar_uart_->write((byte) 0x00); radar_uart_->write((byte) 0x63); //Request leave command mode radar_uart_->write((byte) 0x00); send_command_postamble_(); radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { if(read_frame_()) { if(latest_ack_ == 0x63 && latest_command_success_) { return true; } } } return false; } void ld2410::Marker(uint8_t state) { radar_uart_->write((byte)0xAA); radar_uart_->write((byte)state); radar_uart_->write((byte)0x55); } bool ld2410::requestCurrentConfiguration() { if(enter_configuration_mode_()) { delay(50); send_command_preamble_(); //Request firmware SendToRadar(0x02); //Command is two bytes long SendToRadar(0x00); SendToRadar(0x61); //Request current configuration SendToRadar(0x00); send_command_postamble_(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\n> Out : FDFCFBFA 02 00 61 00 04030201")); } #endif radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { if(read_frame_()) { if(latest_ack_ == 0x61 && latest_command_success_) { delay(50); leave_configuration_mode_(); return true; } } } } delay(50); leave_configuration_mode_(); return false; } bool ld2410::requestFirmwareVersion() { if(enter_configuration_mode_()) { delay(50); send_command_preamble_(); //Request firmware SendToRadar(0x02); //Command is two bytes long SendToRadar(0x00); SendToRadar(0xA0); //Request firmware version SendToRadar(0x00); send_command_postamble_(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\n> Out : FDFCFBFA 02 00 A0 00 04030201")); } #endif radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { read_frame_(); if(latest_ack_ == 0xA0 && latest_command_success_) { delay(50); leave_configuration_mode_(); return true; } } } delay(50); leave_configuration_mode_(); return false; } bool ld2410::requestRestart() { if(enter_configuration_mode_()) { delay(50); send_command_preamble_(); //Request firmware SendToRadar(0x02); //Command is two bytes long SendToRadar(0x00); SendToRadar(0xA3); //Request restart SendToRadar(0x00); send_command_postamble_(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\n> Out : FDFCFBFA 02 00 A3 00 04030201")); } #endif radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { if(read_frame_()) { if(latest_ack_ == 0xA3 && latest_command_success_) { delay(50); leave_configuration_mode_(); return true; } } } } delay(50); leave_configuration_mode_(); return false; } bool ld2410::requestFactoryReset() { if(enter_configuration_mode_()) { delay(50); send_command_preamble_(); //Request firmware SendToRadar(0x02); //Command is two bytes long SendToRadar(0x00); SendToRadar(0xA2); //Request factory reset SendToRadar(0x00); send_command_postamble_(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\n> Out : FDFCFBFA 02 00 A2 00 04030201")); } #endif radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { if(read_frame_()) { if(latest_ack_ == 0xA2 && latest_command_success_) { delay(50); leave_configuration_mode_(); return true; } } } } delay(50); leave_configuration_mode_(); return false; } bool ld2410::setMaxValues(uint16_t moving, uint16_t stationary, uint16_t inactivityTimer) { if(enter_configuration_mode_()) { delay(50); send_command_preamble_(); SendToRadar(0x14); //Command is 20 bytes long SendToRadar(0x00); SendToRadar(0x60); //Request set max values SendToRadar(0x00); SendToRadar(0x00); //Moving gate command SendToRadar(0x00); SendToRadar(char(moving & 0x00FF)); //Moving gate value SendToRadar(char((moving & 0xFF00)>>8)); SendToRadar(0x00); //Spacer SendToRadar(0x00); SendToRadar(0x01); //Stationary gate command SendToRadar(0x00); SendToRadar(char(stationary & 0x00FF)); //Stationary gate value SendToRadar(char((stationary & 0xFF00)>>8)); SendToRadar(0x00); //Spacer SendToRadar(0x00); SendToRadar(0x02); //Inactivity timer command SendToRadar(0x00); SendToRadar(char(inactivityTimer & 0x00FF)); //Inactivity timer SendToRadar(char((inactivityTimer & 0xFF00)>>8)); SendToRadar(0x00); //Spacer SendToRadar(0x00); send_command_postamble_(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\n> Out : A lot!!!")); } #endif radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { if(read_frame_()) { if(latest_ack_ == 0x60 && latest_command_success_) { delay(50); leave_configuration_mode_(); return true; } } } } delay(50); leave_configuration_mode_(); return false; } bool ld2410::setGateSensitivityThreshold(uint8_t gate, uint8_t moving, uint8_t stationary) { if(enter_configuration_mode_()) { delay(50); send_command_preamble_(); SendToRadar(0x14); //Command is 20 bytes long SendToRadar(0x00); SendToRadar(0x64); //Request set sensitivity values SendToRadar(0x00); SendToRadar(0x00); //Gate command SendToRadar(0x00); SendToRadar(char(gate)); //Gate value SendToRadar(0x00); SendToRadar(0x00); //Spacer SendToRadar(0x00); SendToRadar(0x01); //Motion sensitivity command SendToRadar(0x00); SendToRadar(char(moving)); //Motion sensitivity value SendToRadar(0x00); SendToRadar(0x00); //Spacer SendToRadar(0x00); SendToRadar(0x02); //Stationary sensitivity command SendToRadar(0x00); SendToRadar(char(stationary)); //Stationary sensitivity value SendToRadar(0x00); SendToRadar(0x00); //Spacer SendToRadar(0x00); send_command_postamble_(); #ifdef LD2410_DEBUG_COMMANDS if(debug_uart_ != nullptr) { debug_uart_->print(F("\n> Out : Also a lot!!!")); } #endif radar_uart_last_command_ = millis(); while(millis() - radar_uart_last_command_ < radar_uart_command_timeout_) { if(read_frame_()) { if(latest_ack_ == 0x64 && latest_command_success_) { delay(50); leave_configuration_mode_(); return true; } } } } delay(50); leave_configuration_mode_(); return false; } #endif