forked from ArduPilot/ardupilot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAP_ADC_ADS1115.cpp
230 lines (188 loc) · 7.3 KB
/
AP_ADC_ADS1115.cpp
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#include <AP_HAL/AP_HAL.h>
#include <AP_HAL/utility/sparse-endian.h>
#include "AP_ADC_ADS1115.h"
#define ADS1115_ADDRESS_ADDR_GND 0x48 // address pin low (GND)
#define ADS1115_ADDRESS_ADDR_VDD 0x49 // address pin high (VCC)
#define ADS1115_ADDRESS_ADDR_SDA 0x4A // address pin tied to SDA pin
#define ADS1115_ADDRESS_ADDR_SCL 0x4B // address pin tied to SCL pin
#define ADS1115_I2C_ADDR ADS1115_ADDRESS_ADDR_GND
#define ADS1115_I2C_BUS 1
#define ADS1115_RA_CONVERSION 0x00
#define ADS1115_RA_CONFIG 0x01
#define ADS1115_RA_LO_THRESH 0x02
#define ADS1115_RA_HI_THRESH 0x03
#define ADS1115_OS_SHIFT 15
#define ADS1115_OS_INACTIVE 0x00 << ADS1115_OS_SHIFT
#define ADS1115_OS_ACTIVE 0x01 << ADS1115_OS_SHIFT
#define ADS1115_MUX_SHIFT 12
#define ADS1115_MUX_P0_N1 0x00 << ADS1115_MUX_SHIFT /* default */
#define ADS1115_MUX_P0_N3 0x01 << ADS1115_MUX_SHIFT
#define ADS1115_MUX_P1_N3 0x02 << ADS1115_MUX_SHIFT
#define ADS1115_MUX_P2_N3 0x03 << ADS1115_MUX_SHIFT
#define ADS1115_MUX_P0_NG 0x04 << ADS1115_MUX_SHIFT
#define ADS1115_MUX_P1_NG 0x05 << ADS1115_MUX_SHIFT
#define ADS1115_MUX_P2_NG 0x06 << ADS1115_MUX_SHIFT
#define ADS1115_MUX_P3_NG 0x07 << ADS1115_MUX_SHIFT
#define ADS1115_PGA_SHIFT 9
#define ADS1115_PGA_6P144 0x00 << ADS1115_PGA_SHIFT
#define ADS1115_PGA_4P096 0x01 << ADS1115_PGA_SHIFT
#define ADS1115_PGA_2P048 0x02 << ADS1115_PGA_SHIFT // default
#define ADS1115_PGA_1P024 0x03 << ADS1115_PGA_SHIFT
#define ADS1115_PGA_0P512 0x04 << ADS1115_PGA_SHIFT
#define ADS1115_PGA_0P256 0x05 << ADS1115_PGA_SHIFT
#define ADS1115_PGA_0P256B 0x06 << ADS1115_PGA_SHIFT
#define ADS1115_PGA_0P256C 0x07 << ADS1115_PGA_SHIFT
#define ADS1115_MV_6P144 0.187500f
#define ADS1115_MV_4P096 0.125000f
#define ADS1115_MV_2P048 0.062500f // default
#define ADS1115_MV_1P024 0.031250f
#define ADS1115_MV_0P512 0.015625f
#define ADS1115_MV_0P256 0.007813f
#define ADS1115_MV_0P256B 0.007813f
#define ADS1115_MV_0P256C 0.007813f
#define ADS1115_MODE_SHIFT 8
#define ADS1115_MODE_CONTINUOUS 0x00 << ADS1115_MODE_SHIFT
#define ADS1115_MODE_SINGLESHOT 0x01 << ADS1115_MODE_SHIFT // default
#define ADS1115_RATE_SHIFT 5
#define ADS1115_RATE_8 0x00 << ADS1115_RATE_SHIFT
#define ADS1115_RATE_16 0x01 << ADS1115_RATE_SHIFT
#define ADS1115_RATE_32 0x02 << ADS1115_RATE_SHIFT
#define ADS1115_RATE_64 0x03 << ADS1115_RATE_SHIFT
#define ADS1115_RATE_128 0x04 << ADS1115_RATE_SHIFT // default
#define ADS1115_RATE_250 0x05 << ADS1115_RATE_SHIFT
#define ADS1115_RATE_475 0x06 << ADS1115_RATE_SHIFT
#define ADS1115_RATE_860 0x07 << ADS1115_RATE_SHIFT
#define ADS1115_COMP_MODE_SHIFT 4
#define ADS1115_COMP_MODE_HYSTERESIS 0x00 << ADS1115_COMP_MODE_SHIFT // default
#define ADS1115_COMP_MODE_WINDOW 0x01 << ADS1115_COMP_MODE_SHIFT
#define ADS1115_COMP_POL_SHIFT 3
#define ADS1115_COMP_POL_ACTIVE_LOW 0x00 << ADS1115_COMP_POL_SHIFT // default
#define ADS1115_COMP_POL_ACTIVE_HIGH 0x01 << ADS1115_COMP_POL_SHIFT
#define ADS1115_COMP_LAT_SHIFT 2
#define ADS1115_COMP_LAT_NON_LATCHING 0x00 << ADS1115_COMP_LAT_SHIFT // default
#define ADS1115_COMP_LAT_LATCHING 0x01 << ADS1115_COMP_LAT_SHIFT
#define ADS1115_COMP_QUE_SHIFT 0
#define ADS1115_COMP_QUE_ASSERT1 0x00 << ADS1115_COMP_SHIFT
#define ADS1115_COMP_QUE_ASSERT2 0x01 << ADS1115_COMP_SHIFT
#define ADS1115_COMP_QUE_ASSERT4 0x02 << ADS1115_COMP_SHIFT
#define ADS1115_COMP_QUE_DISABLE 0x03 // default
#define ADS1115_DEBUG 0
#if ADS1115_DEBUG
#include <cstdio>
#define debug(fmt, args ...) do {hal.console->printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); } while(0)
#define error(fmt, args ...) do {fprintf(stderr,"%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); } while(0)
#else
#define debug(fmt, args ...)
#define error(fmt, args ...)
#endif
extern const AP_HAL::HAL &hal;
#define ADS1115_CHANNELS_COUNT 6
const uint8_t AP_ADC_ADS1115::_channels_number = ADS1115_CHANNELS_COUNT;
/* Only two differential channels used */
static const uint16_t mux_table[ADS1115_CHANNELS_COUNT] = {
ADS1115_MUX_P1_N3,
ADS1115_MUX_P2_N3,
ADS1115_MUX_P0_NG,
ADS1115_MUX_P1_NG,
ADS1115_MUX_P2_NG,
ADS1115_MUX_P3_NG
};
AP_ADC_ADS1115::AP_ADC_ADS1115()
: _dev{}
, _gain(ADS1115_PGA_4P096)
, _channel_to_read(0)
{
_samples = NEW_NOTHROW adc_report_s[_channels_number];
}
AP_ADC_ADS1115::~AP_ADC_ADS1115()
{
delete[] _samples;
}
bool AP_ADC_ADS1115::init()
{
_dev = hal.i2c_mgr->get_device(ADS1115_I2C_BUS, ADS1115_I2C_ADDR);
if (!_dev) {
return false;
}
_gain = ADS1115_PGA_4P096;
_dev->register_periodic_callback(100000, FUNCTOR_BIND_MEMBER(&AP_ADC_ADS1115::_update, void));
return true;
}
bool AP_ADC_ADS1115::_start_conversion(uint8_t channel)
{
struct PACKED {
uint8_t reg;
be16_t val;
} config;
config.reg = ADS1115_RA_CONFIG;
config.val = htobe16(ADS1115_OS_ACTIVE | _gain | mux_table[channel] |
ADS1115_MODE_SINGLESHOT | ADS1115_COMP_QUE_DISABLE |
ADS1115_RATE_250);
return _dev->transfer((uint8_t *)&config, sizeof(config), nullptr, 0);
}
size_t AP_ADC_ADS1115::read(adc_report_s *report, size_t length) const
{
for (size_t i = 0; i < length; i++) {
report[i].data = _samples[i].data;
report[i].id = _samples[i].id;
}
return length;
}
float AP_ADC_ADS1115::_convert_register_data_to_mv(int16_t word) const
{
float pga;
switch (_gain) {
case ADS1115_PGA_6P144:
pga = ADS1115_MV_6P144;
break;
case ADS1115_PGA_4P096:
pga = ADS1115_MV_4P096;
break;
case ADS1115_PGA_2P048:
pga = ADS1115_MV_2P048;
break;
case ADS1115_PGA_1P024:
pga = ADS1115_MV_1P024;
break;
case ADS1115_PGA_0P512:
pga = ADS1115_MV_0P512;
break;
case ADS1115_PGA_0P256:
pga = ADS1115_MV_0P256;
break;
case ADS1115_PGA_0P256B:
pga = ADS1115_MV_0P256B;
break;
case ADS1115_PGA_0P256C:
pga = ADS1115_MV_0P256C;
break;
default:
pga = 0.0f;
DEV_PRINTF("Wrong gain");
AP_HAL::panic("ADS1115: wrong gain selected");
break;
}
return (float) word * pga;
}
void AP_ADC_ADS1115::_update()
{
uint8_t config[2];
be16_t val;
if (!_dev->read_registers(ADS1115_RA_CONFIG, config, sizeof(config))) {
error("_dev->read_registers failed in ADS1115");
return;
}
/* check rdy bit */
if ((config[1] & 0x80) != 0x80 ) {
return;
}
if (!_dev->read_registers(ADS1115_RA_CONVERSION, (uint8_t *)&val, sizeof(val))) {
return;
}
float sample = _convert_register_data_to_mv(be16toh(val));
_samples[_channel_to_read].data = sample;
_samples[_channel_to_read].id = _channel_to_read;
/* select next channel */
_channel_to_read = (_channel_to_read + 1) % _channels_number;
_start_conversion(_channel_to_read);
}