tarask
6 days ago 532005c6573d95199ce0ffbc33df4c7a0a4c3ef9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#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);
    }
}