-
Notifications
You must be signed in to change notification settings - Fork 0
/
ads1015.cpp
177 lines (146 loc) · 3.73 KB
/
ads1015.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
#include "ads1015.hpp"
ADS1015::ADS1015(i2c_inst_t *i2c_type) {
i2c = i2c_type;
}
// TODO: replace writes and reads with timeouts
bool ADS1015::write_register(const uint8_t reg, const uint16_t val) {
uint8_t buf[3];
buf[0] = reg;
buf[1] = (val >> 8) & 0xFF;
buf[2] = val & 0xFF;
if (i2c_write_blocking(i2c, ADS1015_ADDR, buf, 3, true) < 1) {
return false;
}
return true;
}
bool ADS1015::read_register(const uint8_t reg, uint8_t *val) {
// Write the register address first
if (i2c_write_blocking(i2c, ADS1015_ADDR, ®, 1, true) < 1) {
return false;
}
// Read the register value
if (i2c_read_blocking(i2c, ADS1015_ADDR, val, 2, false) != 2) {
return false;
}
return true;
}
bool ADS1015::begin(ads_data_rate_t dr) {
data_rate = dr;
uint16_t sps;
// Calculate conversion delay in microseconds
switch (data_rate) {
case DR_128SPS:
sps = 128;
break;
case DR_250SPS:
sps = 250;
break;
case DR_490SPS:
sps = 490;
break;
case DR_920SPS:
sps = 920;
break;
case DR_1600SPS:
sps = 1600;
break;
case DR_2400SPS:
sps = 2400;
break;
case DR_3300SPS:
sps = 3300;
break;
default: // Based on default dr = DR_3300SPS
sps = 3300;
break;
}
delay = (1000000 + sps - 1) / sps;
if (!configure_adc(MUX_SINGLE_0)) {
return false;
}
return true;
}
bool ADS1015::configure_adc(ads_mux_t mux) {
config = ADS1015_REG_CONFIG_CQUE_NONE |
ADS1015_REG_CONFIG_CLAT_NONLAT |
ADS1015_REG_CONFIG_CPOL_ACTVLOW |
ADS1015_REG_CONFIG_CMODE_TRAD |
data_rate |
ADS1015_REG_CONFIG_MODE_SINGLE |
gain | mux |
ADS1015_REG_CONFIG_OS_SINGLE;
#ifdef DEBUG
printf("Config: %x\n", config);
#endif
// Write config register to the ADC
if (!write_register(ADS1015_REG_POINTER_CONFIG, config)) {
return false;
}
// Confirm bits in config register match bits in config value
uint8_t val[2];
if (!read_register(ADS1015_REG_POINTER_CONFIG, val)) {
return false;
}
uint16_t result = (val[0] << 8) | val[1];
if ((result & ~ADS1015_REG_CONFIG_OS_SINGLE) != (config & ~ADS1015_REG_CONFIG_OS_SINGLE)) {
return false;
}
return true;
}
uint16_t ADS1015::read_single_ended(uint8_t channel) {
if (channel > 3) {
return 0;
}
ads_mux_t mux;
// Get mux config corresponding to given channel
switch (channel) {
case 0:
mux = MUX_SINGLE_0;
break;
case 1:
mux = MUX_SINGLE_1;
break;
case 2:
mux = MUX_SINGLE_2;
break;
case 3:
mux = MUX_SINGLE_3;
break;
}
// Update config
if (!configure_adc(mux)) {
return 0;
}
// Wait for the conversion to complete
sleep_us(delay);
// Read the conversion results
uint8_t val[2];
uint16_t result;
if (read_register(ADS1015_REG_POINTER_CONVERT, val)) {
result = (val[0] << 8) | val[1];
result >>= 4;
#ifdef DEBUG
printf("ADC Value: %u\n", result);
#endif
} else {
result = 0xFFF;
#ifdef VERBOSE
printf("Failed to read register!\n");
#endif
}
return result;
}
bool ADS1015::read_data(const uint8_t *channels, size_t channels_size, uint16_t *data) {
if (!data) {
return false;
}
// Read data for each channel in channels
for (size_t i = 0; i < channels_size; i++) {
uint16_t result = read_single_ended(channels[i]);
if (result == 0xFFF) {
return false;
}
data[i] = result;
}
return true;
}