#include "NV7Rangefinder.h" #include "modules/my_task_creator/TaskCreator.h" #ifdef NV7RANGEFINDER_DISABLE_LOGS #define log_i(...) #define log_w(...) #define log_e(...) #endif NV7Rangefinder::NV7Rangefinder() {} void NV7Rangefinder::singleMeasure(Stream& port) { const uint8_t cmd[] = {0xAE, 0xA7, 0x04, 0x00, 0x05, 0x09, 0xBC, 0xBE}; port.write(cmd, sizeof(cmd)); log_i("NV7Rangefinder: Single measure command sent"); } void NV7Rangefinder::startContinuousMeasure(Stream& port) { const uint8_t cmd[] = {0xAE, 0xA7, 0x04, 0x00, 0x0E, 0x12, 0xBC, 0xBE}; port.write(cmd, sizeof(cmd)); log_i("NV7Rangefinder: Continuous measure command sent"); } void NV7Rangefinder::stopContinuousMeasure(Stream& port) { const uint8_t cmd[] = {0xAE, 0xA7, 0x04, 0x00, 0x0F, 0x13, 0xBC, 0xBE}; port.write(cmd, sizeof(cmd)); log_i("NV7Rangefinder: Stop continuous measure command sent"); } NV7Rangefinder::Measurement NV7Rangefinder::getLastMeasurement() { return lastMeasurement; } void NV7Rangefinder::TaskNV7Rangefinder(void* pvParameters) { TaskCreator* mCreator = (TaskCreator*)pvParameters; NV7Rangefinder* self = &(mCreator->mNV7); MavlinkTransmitter* transmitter = &(mCreator->mTransmitter); constexpr size_t PACKET_LEN = 27; uint8_t buffer[PACKET_LEN]; size_t idx = 0; Stream* serial = nullptr; #ifdef NV7RANGEFINDER_USE_SERIAL0 Serial.begin(9600, SERIAL_8N1, 16, 17); serial = &Serial; log_i("NV7Rangefinder: Using Serial0 @ %lu", 9600); #else SoftwareSerial softSerial; softSerial.begin(9600, SWSERIAL_8N1, 16, 17); serial = &softSerial; log_i("NV7Rangefinder: Using SoftwareSerial @ %lu", 9600); #endif log_i("NV7Rangefinder: Read task started"); self->startContinuousMeasure(*serial); vTaskDelay(10 / portTICK_PERIOD_MS); while (true) { while (serial->available()) { uint8_t b = serial->read(); if (idx == 0 && b != 0xAE) continue; if (idx == 1 && b != 0xA7) { idx = 0; continue; } if (idx < PACKET_LEN) { buffer[idx++] = b; } else { log_w("Buffer overflow, reset idx"); transmitter->SendDistanceSensor(0.0f, false, (float)RANGEFINDER_NV7_MAX_DISTANCE); idx = 0; continue; } if (idx == PACKET_LEN) { if (buffer[25] != 0xBC || buffer[26] != 0xBE) { // log_w("Invalid footer bytes"); transmitter->SendDistanceSensor(0.0f, false,(float)RANGEFINDER_NV7_MAX_DISTANCE); idx = 0; continue; } uint8_t checksum = 0; for (int i = 2; i <= 23; i++) checksum += buffer[i]; if (checksum != buffer[24]) { log_w("Checksum failed: got %02X, expected %02X", buffer[24], checksum); transmitter->SendDistanceSensor(0.0f, false,(float)RANGEFINDER_NV7_MAX_DISTANCE); idx = 0; continue; } const uint8_t* d = &buffer[5]; self->lastMeasurement = { .elevation = (int16_t)(d[0] << 8 | d[1]), .distance = (d[2] << 8 | d[3]) / 10.0f, .sineHeight = (int16_t)(d[4] << 8 | d[5]), .horizDistance = (int16_t)(d[6] << 8 | d[7]), .twoPointHeight = (int16_t)(d[8] << 8 | d[9]), .azimuth = (int16_t)(d[10] << 8 | d[11]), .horizAngle = (int16_t)(d[12] << 8 | d[13]), .span = (int16_t)(d[14] << 8 | d[15]), .speed = (int16_t)(d[16] << 8 | d[17]), .unit = d[18], .secondElevation = (int16_t)(d[19] << 8 | d[20]), .isValid = true }; log_i("Parsed: dist=%.1f (unit=%d)", self->lastMeasurement.distance, self->lastMeasurement.unit); transmitter->SendDistanceSensor(self->lastMeasurement.distance, true, (float)RANGEFINDER_NV7_MAX_DISTANCE); idx = 0; } } vTaskDelay(10 / portTICK_PERIOD_MS); } }