Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ardupilot
GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_Baro/AP_Baro_BMP581.cpp
9532 views
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
#include "AP_Baro_BMP581.h"
16
17
#if AP_BARO_BMP581_ENABLED
18
19
#include <AP_Math/AP_Math.h>
20
21
extern const AP_HAL::HAL &hal;
22
23
#define BMP581_ID 0x50
24
25
#define BMP581_REG_CHIP_ID 0x01
26
#define BMP581_REG_REV_ID 0x02
27
#define BMP581_REG_CHIP_STATUS 0x11
28
#define BMP581_REG_DRIVE_CONFIG 0x13
29
#define BMP581_REG_INT_CONFIG 0x14
30
#define BMP581_REG_INT_SOURCE 0x15
31
#define BMP581_REG_FIFO_CONFIG 0x16
32
#define BMP581_REG_FIFO_COUNT 0x17
33
#define BMP581_REG_FIFO_SEL 0x18
34
#define BMP581_REG_TEMP_DATA_XLSB 0x1D
35
#define BMP581_REG_TEMP_DATA_LSB 0x1E
36
#define BMP581_REG_TEMP_DATA_MSB 0x1F
37
#define BMP581_REG_PRESS_DATA_XLSB 0x20
38
#define BMP581_REG_PRESS_DATA_LSB 0x21
39
#define BMP581_REG_PRESS_DATA_MSB 0x22
40
#define BMP581_REG_INT_STATUS 0x27
41
#define BMP581_REG_STATUS 0x28
42
#define BMP581_REG_FIFO_DATA 0x29
43
#define BMP581_REG_NVM_ADDR 0x2B
44
#define BMP581_REG_NVM_DATA_LSB 0x2C
45
#define BMP581_REG_NVM_DATA_MSB 0x2D
46
#define BMP581_REG_DSP_CONFIG 0x30
47
#define BMP581_REG_DSP_IIR 0x31
48
#define BMP581_REG_OOR_THR_P_LSB 0x32
49
#define BMP581_REG_OOR_THR_P_MSB 0x33
50
#define BMP581_REG_OOR_RANGE 0x34
51
#define BMP581_REG_OOR_CONFIG 0x35
52
#define BMP581_REG_OSR_CONFIG 0x36
53
#define BMP581_REG_ODR_CONFIG 0x37
54
#define BMP581_REG_OSR_EFF 0x38
55
#define BMP581_REG_CMD 0x7E
56
57
AP_Baro_BMP581::AP_Baro_BMP581(AP_Baro &baro, AP_HAL::Device &dev)
58
: AP_Baro_Backend(baro)
59
, _dev(&dev)
60
{
61
}
62
63
AP_Baro_Backend *AP_Baro_BMP581::probe(AP_Baro &baro, AP_HAL::Device &dev)
64
{
65
AP_Baro_BMP581 *sensor = NEW_NOTHROW AP_Baro_BMP581(baro, dev);
66
if (!sensor || !sensor->init()) {
67
delete sensor;
68
return nullptr;
69
}
70
return sensor;
71
}
72
73
bool AP_Baro_BMP581::init()
74
{
75
if (!_dev) {
76
return false;
77
}
78
79
WITH_SEMAPHORE(_dev->get_semaphore());
80
81
_dev->set_speed(AP_HAL::Device::SPEED_HIGH);
82
83
uint8_t whoami;
84
85
// setup to allow reads on SPI
86
if (_dev->bus_type() == AP_HAL::Device::BUS_TYPE_SPI) {
87
_dev->set_read_flag(0x80);
88
89
if (!_dev->read_registers(BMP581_REG_CHIP_ID, &whoami, 1)) {
90
return false;
91
}
92
}
93
94
if (!_dev->read_registers(BMP581_REG_CHIP_ID, &whoami, 1)) {
95
return false;
96
}
97
98
switch (whoami) {
99
case BMP581_ID:
100
_dev->set_device_type(DEVTYPE_BARO_BMP581);
101
break;
102
default:
103
return false;
104
}
105
106
uint8_t status;
107
if (!_dev->read_registers(BMP581_REG_STATUS, &status, 1)) {
108
return false;
109
}
110
111
if ((status & 0b10) == 0 || (status & 0b100)) {
112
return false;
113
}
114
115
uint8_t int_status;
116
if (!_dev->read_registers(BMP581_REG_INT_STATUS, &int_status, 1)) {
117
return false;
118
}
119
120
if ((int_status & 0x10) == 0) {
121
return false;
122
}
123
124
_dev->setup_checked_registers(4);
125
126
// Standby mode
127
_dev->write_register(BMP581_REG_ODR_CONFIG, 0, true);
128
129
// Press EN | osr_p 64X | osr_t 4X
130
_dev->write_register(BMP581_REG_OSR_CONFIG, 0b01110010, true);
131
132
// ORD 50Hz | Normal Mode
133
_dev->write_register(BMP581_REG_ODR_CONFIG, 0b0111101, true);
134
135
instance = _frontend.register_sensor();
136
137
set_bus_id(instance, _dev->get_bus_id());
138
139
// request 50Hz update
140
_dev->register_periodic_callback(20 * AP_USEC_PER_MSEC, FUNCTOR_BIND_MEMBER(&AP_Baro_BMP581::timer, void));
141
142
return true;
143
}
144
145
// acumulate a new sensor reading
146
void AP_Baro_BMP581::timer(void)
147
{
148
uint8_t buf[6];
149
150
if (!_dev->read_registers(BMP581_REG_TEMP_DATA_XLSB, buf, sizeof(buf))) {
151
return;
152
}
153
154
WITH_SEMAPHORE(_sem);
155
156
if (buf[0] != 0x7f || buf[1] != 0x7f || buf[2] != 0x7f) {
157
// we have temperature data
158
temperature = (float)((int32_t)(((uint32_t)buf[2] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[0] << 8)) >> 8) * (1.0f / 65536.0f);
159
}
160
161
if (buf[3] != 0x7f || buf[4] != 0x7f || buf[5] != 0x7f) {
162
// we have pressure data
163
pressure_sum += (float)(((uint32_t)buf[5] << 16) | ((uint32_t)buf[4] << 8) | (uint32_t)buf[3]) * (1.0f / 64.0f);
164
pressure_count++;
165
}
166
167
_dev->check_next_register();
168
}
169
170
// transfer data to the frontend
171
void AP_Baro_BMP581::update(void)
172
{
173
WITH_SEMAPHORE(_sem);
174
175
if (pressure_count == 0) {
176
return;
177
}
178
179
_copy_to_frontend(instance,
180
pressure_sum/pressure_count,
181
temperature);
182
183
pressure_sum = 0;
184
pressure_count = 0;
185
}
186
187
#endif // AP_BARO_BMP581_ENABLED
188
189