Merge pull request #10558 from iNavFlight/MrD_Correct-comments-on-OSD-symbols
[inav.git] / src / main / drivers / rangefinder / rangefinder_us42.c
blobeabb571d92750f71f7184a2179aae92d225202f4
1 /*
2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdbool.h>
19 #include <stdint.h>
21 #include "platform.h"
23 #if defined(USE_RANGEFINDER) && defined(USE_RANGEFINDER_US42)
25 #include "build/build_config.h"
27 #include "drivers/time.h"
28 #include "drivers/bus_i2c.h"
30 #include "drivers/rangefinder/rangefinder.h"
31 #include "drivers/rangefinder/rangefinder_us42.h"
33 #include "build/debug.h"
35 // GY-US42(v2) Ultrasonic Range Sensor
36 #define US42_MAX_RANGE_CM 400 // vcc=3.3v -> 500cm; vcc=5v -> 700cm; Ardupilot recommends a maximum of 400cm
37 #define US42_DETECTION_CONE_DECIDEGREES 250
38 #define US42_DETECTION_CONE_EXTENDED_DECIDEGREES 300
39 #define US42_MIN_PROBE_INTERVAL 50
41 #define US42_I2C_ADDRESS 0x70
42 #define US42_I2C_REGISTRY_BASE 0x00
43 #define US42_I2C_REGISTRY_PROBE 0x51
44 #define US42_I2C_REGISTRY_STATUS_OK 0x00
45 #define US42_I2C_REGISTRY_DISTANCE_HIGH 0x00
46 #define US42_I2C_REGISTRY_DISTANCE_LOW 0x01
48 volatile int32_t us42MeasurementCm = RANGEFINDER_OUT_OF_RANGE;
49 static int16_t minimumReadingIntervalMs = US42_MIN_PROBE_INTERVAL;
50 static uint32_t timeOfLastMeasurementMs;
51 uint8_t nullProbeCommandValue[0];
52 static bool isUs42Responding = false;
54 static void us42Init(rangefinderDev_t *rangefinder)
56 busWriteBuf(rangefinder->busDev, US42_I2C_REGISTRY_PROBE, nullProbeCommandValue, 0);
59 void us42Update(rangefinderDev_t *rangefinder)
61 uint8_t data[2];
62 isUs42Responding = busReadBuf(rangefinder->busDev, US42_I2C_REGISTRY_PROBE, data, 2);
64 if (isUs42Responding) {
65 us42MeasurementCm = (int32_t)data[0] << 8 | (int32_t)data[1];
67 if (us42MeasurementCm > US42_MAX_RANGE_CM) {
68 us42MeasurementCm = RANGEFINDER_OUT_OF_RANGE;
71 } else {
72 us42MeasurementCm = RANGEFINDER_HARDWARE_FAILURE;
75 const timeMs_t timeNowMs = millis();
76 if (timeNowMs > timeOfLastMeasurementMs + minimumReadingIntervalMs) {
77 // measurement repeat interval should be greater than minimumReadingIntervalMs
78 // to avoid interference between connective measurements.
79 timeOfLastMeasurementMs = timeNowMs;
80 busWriteBuf(rangefinder->busDev, US42_I2C_REGISTRY_PROBE, nullProbeCommandValue, 0);
84 /**
85 * Get the distance that was measured by the last pulse, in centimeters.
87 int32_t us42GetDistance(rangefinderDev_t *rangefinder)
89 UNUSED(rangefinder);
90 return us42MeasurementCm;
93 static bool deviceDetect(busDevice_t * busDev)
95 for (int retry = 0; retry < 5; retry++) {
96 uint8_t inquiryResult;
98 delay(150);
100 bool ack = busRead(busDev, US42_I2C_REGISTRY_BASE, &inquiryResult);
101 if (ack && inquiryResult == US42_I2C_REGISTRY_STATUS_OK) {
102 return true;
106 return false;
109 bool us42Detect(rangefinderDev_t *rangefinder)
111 rangefinder->busDev = busDeviceInit(BUSTYPE_I2C, DEVHW_US42, 0, OWNER_RANGEFINDER);
112 if (rangefinder->busDev == NULL) {
113 return false;
116 if (!deviceDetect(rangefinder->busDev)) {
117 busDeviceDeInit(rangefinder->busDev);
118 return false;
121 rangefinder->delayMs = RANGEFINDER_US42_TASK_PERIOD_MS;
122 rangefinder->maxRangeCm = US42_MAX_RANGE_CM;
123 rangefinder->detectionConeDeciDegrees = US42_DETECTION_CONE_DECIDEGREES;
124 rangefinder->detectionConeExtendedDeciDegrees = US42_DETECTION_CONE_EXTENDED_DECIDEGREES;
126 rangefinder->init = &us42Init;
127 rangefinder->update = &us42Update;
128 rangefinder->read = &us42GetDistance;
130 return true;
132 #endif