CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_Airspeed/AP_Airspeed_ASP5033.cpp
Views: 1798
1
/*
2
This program is free software: you can redistribute it and/or modify
3
it under the terms of the GNU General Public License as published by
4
the Free Software Foundation, either version 3 of the License, or
5
(at your option) any later version.
6
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
11
12
You should have received a copy of the GNU General Public License
13
along with this program. If not, see <http://www.gnu.org/licenses/>.
14
*/
15
16
/*
17
backend driver for airspeed sensor from www.qio-tek.com
18
I2C ASP5033 sensor
19
*/
20
21
#include "AP_Airspeed_ASP5033.h"
22
23
#if AP_AIRSPEED_ASP5033_ENABLED
24
25
#include <AP_HAL/I2CDevice.h>
26
27
extern const AP_HAL::HAL &hal;
28
29
#define ASP5033_I2C_ADDR_1 0x6C
30
#define ASP5033_I2C_ADDR_2 0x6D
31
#define REG_CMD 0x30
32
#define REG_PRESS_DATA 0x06
33
#define REG_TEMP_DATA 0x09
34
#define REG_PART_ID 0x01
35
#define REG_PART_ID_SET 0xa4
36
#define REG_SENSOR_READY 0x08
37
#define REG_WHOAMI_DEFAULT_ID 0X00
38
#define REG_WHOAMI_RECHECK_ID 0X66
39
#define CMD_MEASURE 0x0A
40
41
42
bool AP_Airspeed_ASP5033::init()
43
{
44
// probe the sensor, supporting multiple possible I2C addresses
45
const uint8_t addresses[] = { ASP5033_I2C_ADDR_1, ASP5033_I2C_ADDR_2 };
46
for (uint8_t address : addresses) {
47
dev = hal.i2c_mgr->get_device(get_bus(), address);
48
if (!dev) {
49
continue;
50
}
51
52
WITH_SEMAPHORE(dev->get_semaphore());
53
dev->set_speed(AP_HAL::Device::SPEED_HIGH);
54
dev->set_retries(2);
55
56
if (!confirm_sensor_id()) {
57
continue;
58
}
59
60
dev->set_device_type(uint8_t(DevType::ASP5033));
61
set_bus_id(dev->get_bus_id());
62
63
dev->register_periodic_callback(1000000UL/80U,
64
FUNCTOR_BIND_MEMBER(&AP_Airspeed_ASP5033::timer, void));
65
return true;
66
}
67
68
// not found
69
return false;
70
}
71
72
/*
73
this sensor has an unusual whoami scheme. The part_id is changeable
74
via another register. We check the sensor by looking for the
75
expected behaviour
76
*/
77
bool AP_Airspeed_ASP5033::confirm_sensor_id(void)
78
{
79
uint8_t part_id;
80
if (!dev->read_registers(REG_PART_ID_SET, &part_id, 1) ||
81
( (part_id != REG_WHOAMI_DEFAULT_ID) && (part_id != REG_WHOAMI_RECHECK_ID) ) ) {
82
return false;
83
}
84
if (!dev->write_register(REG_PART_ID_SET, REG_WHOAMI_RECHECK_ID)) {
85
return false;
86
}
87
if (!dev->read_registers(REG_PART_ID, &part_id, 1) ||
88
part_id != REG_WHOAMI_RECHECK_ID) {
89
return false;
90
}
91
return true;
92
}
93
94
95
// read the data from the sensor
96
void AP_Airspeed_ASP5033::timer()
97
{
98
// request a new measurement cycle begin
99
dev->write_register(REG_CMD, CMD_MEASURE);
100
101
uint8_t status;
102
if (!dev->read_registers(REG_CMD, &status, 1) ||
103
(status & REG_SENSOR_READY) == 0) {
104
// no data ready
105
return;
106
}
107
108
// read pressure and temperature as one block
109
uint8_t data[5];
110
if (!dev->read_registers(REG_PRESS_DATA, data, sizeof(data))) {
111
return;
112
}
113
114
// ADC pressure is signed 24 bit
115
int32_t press = (data[0]<<24) | (data[1]<<16) | (data[2]<<8);
116
117
// convert back to 24 bit
118
press >>= 8;
119
120
// k is a shift based on the pressure range of the device. See
121
// table in the datasheet
122
constexpr uint8_t k = 7;
123
constexpr float press_scale = 1.0 / (1U<<k);
124
125
// temperature is 16 bit signed in units of 1/256 C
126
const int16_t temp = (data[3]<<8) | data[4];
127
constexpr float temp_scale = 1.0 / 256;
128
129
WITH_SEMAPHORE(sem);
130
press_sum += press * press_scale;
131
temp_sum += temp * temp_scale;
132
press_count++;
133
temp_count++;
134
135
last_sample_ms = AP_HAL::millis();
136
}
137
138
139
// return the current differential_pressure in Pascal
140
bool AP_Airspeed_ASP5033::get_differential_pressure(float &pressure)
141
{
142
WITH_SEMAPHORE(sem);
143
144
if (AP_HAL::millis() - last_sample_ms > 100) {
145
return false;
146
}
147
148
if (press_count == 0) {
149
pressure = last_pressure;
150
return true;
151
}
152
153
last_pressure = pressure = press_sum / press_count;
154
155
press_count = 0;
156
press_sum = 0;
157
158
return true;
159
}
160
161
// return the current temperature in degrees C, if available
162
bool AP_Airspeed_ASP5033::get_temperature(float &temperature)
163
{
164
WITH_SEMAPHORE(sem);
165
166
if (AP_HAL::millis() - last_sample_ms > 100) {
167
return false;
168
}
169
if (temp_count == 0) {
170
temperature = last_temperature;
171
return true;
172
}
173
174
last_temperature = temperature = temp_sum / temp_count;
175
temp_count = 0;
176
temp_sum = 0;
177
178
return true;
179
}
180
181
#endif
182
183