#include "modules/my_altimeter/NRA15.h" #include "modules/my_task_creator/TaskCreator.h" // Protocol constants #define START_SEQUENCE 0xAA // same for L and H bit #define END_SEQUENCE 0x55 // same for L and H bit // Message IDs #define MSG_TARGET_INFO 0x070C // Initializing the static variables double NRA15::distance = 0.0; Stream* NRA15::serial = nullptr; #ifndef NRA15_USE_HARDWARE_SERIAL SoftwareSerial* NRA15::softSerial = nullptr; #endif // Destructor NRA15::~NRA15() { #ifndef NRA15_USE_HARDWARE_SERIAL if (softSerial) { delete softSerial; softSerial = nullptr; } #endif } void NRA15::NRA15RxTask(void *pvParameters) { log_i("NRA15 Task Started"); // Logging task start // Initialize Serial (Hardware or Software) #ifdef NRA15_USE_HARDWARE_SERIAL // Using HardwareSerial (Serial0) Serial.begin(115200, SERIAL_8N1, NRA15_RX_PIN, NRA15_TX_PIN); serial = &Serial; log_i("NRA15: Using HardwareSerial @ 115200 on GPIO%d/%d", NRA15_RX_PIN, NRA15_TX_PIN); #else // Using SoftwareSerial softSerial = new SoftwareSerial(NRA15_RX_PIN, NRA15_TX_PIN); softSerial->begin(115200); serial = softSerial; log_i("NRA15: Using SoftwareSerial @ 115200 on GPIO%d/%d", NRA15_RX_PIN, NRA15_TX_PIN); #endif // Getting TaskCreator object TaskCreator *mCreator = (TaskCreator *)pvParameters; NRA15 *obj = &(mCreator->mNRA15); // Getting NRA15 object from TaskCreator MavlinkTransmitter *transmitter = &(mCreator->mTransmitter); vTaskDelay(50); // Delay to allow initialization uint32_t lastMavlinkTime = xTaskGetTickCount(); uint32_t lastValidDataTime = xTaskGetTickCount(); // Local variables for packet assembly uint8_t buffer[14]; // Setting buffer size for UART communication uint8_t bufferIndex = 0; bool isValid = false; for (;;) { // Read data from Serial while (serial->available()) { uint8_t byte = serial->read(); if (bufferIndex < 2) { if (byte == START_SEQUENCE) { buffer[bufferIndex++] = byte; } else { bufferIndex = 0; // Reset } } else if (bufferIndex >= 2 && bufferIndex < 14) { buffer[bufferIndex++] = byte; // Complete packet received if (bufferIndex == 14) { // Validate end sequence if (buffer[12] == END_SEQUENCE && buffer[13] == END_SEQUENCE) { // Get Message ID uint16_t msgId = buffer[2] | (buffer[3] << 8); if (msgId == MSG_TARGET_INFO) { // Parse target information uint8_t rangeH = buffer[6]; uint8_t rangeL = buffer[7]; // Calculate distance in meters obj->distance = (rangeH * 256 + rangeL) * 0.01; isValid = true; lastValidDataTime = xTaskGetTickCount(); log_v("NRA15: %.2fm", obj->distance); } } else { log_v("NRA15: Invalid end sequence"); } bufferIndex = 0; // Reset for next packet } } } uint32_t currentTime = xTaskGetTickCount(); //Timeout check if ((currentTime - lastMavlinkTime) > pdMS_TO_TICKS(500)) { if (isValid) { isValid = false; log_w("NRA15: no target (timeout)"); } } // Send MAVLink distance sensor message every 100ms if ((currentTime - lastMavlinkTime) >= pdMS_TO_TICKS(100)) { transmitter->SendDistanceSensor( obj->distance, isValid, (float)RANGEFINDER_NRA15_MAX_DISTANCE ); lastMavlinkTime = currentTime; } vTaskDelay(pdMS_TO_TICKS(10)); // 10ms delay } }