26 |
27 |
28 | // device 1
29 | // Address: A1=0, A0=1
30 | // Command: SD=1, PD1=1, PD0=1
31 | ADS7828 device1(1, SINGLE_ENDED | REFERENCE_ON | ADC_ON, 0xFF);
32 |
33 | // device 2
34 | // Address: A1=1, A0=0
35 | // Command: SD=1, PD1=1, PD0=1
36 | // Scaling: min=0, max=1000
37 | ADS7828 device2(2, SINGLE_ENDED | REFERENCE_ON | ADC_ON, 0xFF, 0, 1000);
38 |
39 | void setup()
40 | {
41 | // enable serial monitor
42 | Serial.begin(19200);
43 |
44 | // enable I2C communication
45 | ADS7828::begin();
46 | }
47 |
48 |
49 | void loop()
50 | {
51 | uint8_t a, ch;
52 |
53 | // update all registered ADS7828 devices/unmasked channels
54 | ADS7828::updateAll();
55 |
56 | // iterate through device 1..2 channels 0..7
57 | for (a = 1; a <= 2; a++)
58 | {
59 | for (ch = 0; ch < 8; ch++)
60 | {
61 | serialPrint(ADS7828::device(a)->channel(ch));
62 | }
63 | }
64 | Serial.print("\n");
65 |
66 | // output moving average values to console
67 | Serial.print("\n- - - - - - - - - - - - - - - - - - - - \n");
68 |
69 | // delay
70 | delay(1000);
71 | }
72 |
73 |
74 | void serialPrint(ADS7828Channel* ch)
75 | {
76 | // device address (0..3)
77 | Serial.print("\nAD:");
78 | Serial.print(ch->device()->address(), DEC);
79 |
80 | // channel ID (0..7)
81 | Serial.print(", CH:");
82 | Serial.print(ch->id(), DEC);
83 |
84 | // moving average value (scaled)
85 | Serial.print(", v:");
86 | Serial.print(ch->value(), DEC);
87 |
88 | // minimum scale applied to moving average value
89 | Serial.print(", mn:");
90 | Serial.print(ch->minScale, DEC);
91 |
92 | // maximum scale applied to moving average value
93 | Serial.print(", mx:");
94 | Serial.print(ch->maxScale, DEC);
95 | }
96 |
--------------------------------------------------------------------------------
/extras/README.txt:
--------------------------------------------------------------------------------
1 | Documentation is available at:
2 | http://4-20ma.github.com/i2c_adc_ads7828
3 |
4 | Alternatively, you can download the HTML files at:
5 | [tarball] https://github.com/4-20ma/i2c_adc_ads7828/tarball/gh-pages
6 | [zipball] https://github.com/4-20ma/i2c_adc_ads7828/zipball/gh-pages
7 |
--------------------------------------------------------------------------------
/extras/i2c_adc_ads7828 reference-2.0.2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4-20ma/i2c_adc_ads7828/4bc11a0f7f70fed108e1258288e034e936c6e9ec/extras/i2c_adc_ads7828 reference-2.0.2.pdf
--------------------------------------------------------------------------------
/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map For i2c_adc_ads7828
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 |
9 | i2c_adc_ads7828 KEYWORD1
10 | ADS7828 KEYWORD1
11 | ADS7828Channel KEYWORD1
12 |
13 | #######################################
14 | # Methods and Functions (KEYWORD2)
15 | #######################################
16 |
17 | address KEYWORD2
18 | begin KEYWORD2
19 | channel KEYWORD2
20 | commandByte KEYWORD2
21 | device KEYWORD2
22 | id KEYWORD2
23 | index KEYWORD2
24 | newSample KEYWORD2
25 | reset KEYWORD2
26 | sample KEYWORD2
27 | start KEYWORD2
28 | total KEYWORD2
29 | update KEYWORD2
30 | updateAll KEYWORD2
31 | value KEYWORD2
32 |
33 | maxScale KEYWORD2
34 | minScale KEYWORD2
35 |
36 |
37 | #######################################
38 | # Instances (KEYWORD2)
39 | #######################################
40 |
41 | #######################################
42 | # Constants (LITERAL1)
43 | #######################################
44 |
45 | DIFFERENTIAL LITERAL1
46 | SINGLE_ENDED LITERAL1
47 | REFERENCE_OFF LITERAL1
48 | REFERENCE_ON LITERAL1
49 | ADC_OFF LITERAL1
50 | ADC_ON LITERAL1
51 |
52 | DEFAULT_CHANNEL_MASK LITERAL1
53 | DEFAULT_MIN_SCALE LITERAL1
54 | DEFAULT_MAX_SCALE LITERAL1
55 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=i2c_adc_ads7828
2 | version=2.0.2
3 | author=Doc Walker
4 | maintainer=Doc Walker <4-20ma@wvfans.net>
5 | sentence=Arduino library for the Texas Instruments ADS7828 12-bit, 8-channel I2C A/D converter.
6 | paragraph=The ADS7828 provides a 12-bit, 8-channel A/D converter accessible via the I2C interface serial clock (SCL) and serial data (SDA).
7 | category=Signal Input/Output
8 | url=https://github.com/4-20ma/i2c_adc_ads7828
9 | architectures=*
10 | includes=i2c_adc_ads7828.h
11 |
--------------------------------------------------------------------------------
/src/i2c_adc_ads7828.cpp:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | i2c_adc_ads7828.cpp - Arduino library for TI i2c_adc_ads7828 I2C A/D converter
4 |
5 | Library:: i2c_adc_ads7828
6 | Author:: Doc Walker <4-20ma@wvfans.net>
7 |
8 | Copyright:: 2009-2016 Doc Walker
9 |
10 | Licensed under the Apache License, Version 2.0 (the "License");
11 | you may not use this file except in compliance with the License.
12 | You may obtain a copy of the License at
13 |
14 | http://www.apache.org/licenses/LICENSE-2.0
15 |
16 | Unless required by applicable law or agreed to in writing, software
17 | distributed under the License is distributed on an "AS IS" BASIS,
18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 | See the License for the specific language governing permissions and
20 | limitations under the License.
21 |
22 | */
23 |
24 |
25 | // __________________________________________________________ PROJECT INCLUDES
26 | #include "i2c_adc_ads7828.h"
27 |
28 |
29 | // ___________________________________________________ PUBLIC MEMBER FUNCTIONS
30 | /// \remark Invoked by ADS7828 constructor;
31 | /// this function will not normally be called by end user.
32 | ADS7828Channel::ADS7828Channel(ADS7828* const device, uint8_t id,
33 | uint8_t options, uint16_t min, uint16_t max)
34 | {
35 | this->device_ = device;
36 | this->commandByte_ = (bitRead(options, 7) << 7) | (bitRead(id, 0) << 6) |
37 | (bitRead(id, 2) << 5) | (bitRead(id, 1) << 4);
38 | this->minScale = min;
39 | this->maxScale = max;
40 | reset();
41 | }
42 |
43 |
44 | /// Return command byte for channel object.
45 | /// \optional This function is for testing and troubleshooting.
46 | /// \return command byte (0x00..0xFC)
47 | /// \par Usage:
48 | /// \code
49 | /// ...
50 | /// ADS7828 adc(0);
51 | /// ADS7828Channel* temperature = adc.channel(0);
52 | /// uint8_t command = temperature->commandByte();
53 | /// ...
54 | /// \endcode
55 | uint8_t ADS7828Channel::commandByte()
56 | {
57 | return commandByte_ | device_->commandByte();
58 | }
59 |
60 |
61 | /// Return pointer to parent device object.
62 | /// \return pointer to parent ADS7828 object
63 | /// \par Usage:
64 | /// \code
65 | /// ...
66 | /// ADS7828 adc(0);
67 | /// ADS7828Channel* temperature = adc.channel(0);
68 | /// ADS7828* parentDevice = temperature->device();
69 | /// ...
70 | /// \endcode
71 | ADS7828* ADS7828Channel::device()
72 | {
73 | return device_;
74 | }
75 |
76 |
77 | /// Return ID number of channel object (+IN connection).
78 | /// Single-ended inputs use COM as -IN; Differential inputs are as follows:
79 | /// \arg 0 indicates CH0 as +IN, CH1 as -IN
80 | /// \arg 1 indicates CH1 as +IN, CH0 as -IN
81 | /// \arg 2 indicates CH2 as +IN, CH3 as -IN
82 | /// \arg ...
83 | /// \arg 7 indicates CH7 as +IN, CH6 as -IN
84 | ///
85 | /// \return id (0..7)
86 | /// \retval 0 command byte C2 C1 C0 = 000
87 | /// \retval 1 command byte C2 C1 C0 = 100
88 | /// \retval 2 command byte C2 C1 C0 = 001
89 | /// \retval 3 command byte C2 C1 C0 = 101
90 | /// \retval 4 command byte C2 C1 C0 = 010
91 | /// \retval 5 command byte C2 C1 C0 = 110
92 | /// \retval 6 command byte C2 C1 C0 = 011
93 | /// \retval 7 command byte C2 C1 C0 = 111
94 | /// \par Usage:
95 | /// \code
96 | /// ...
97 | /// ADS7828 adc(0);
98 | /// ADS7828Channel* temperature = adc.channel(0);
99 | /// uint8_t channelId = temperature->id();
100 | /// ...
101 | /// \endcode
102 | uint8_t ADS7828Channel::id()
103 | {
104 | return ((bitRead(commandByte_, 5) << 2) | (bitRead(commandByte_, 4) << 1) |
105 | (bitRead(commandByte_, 6)));
106 | }
107 |
108 |
109 | /// Return index position within moving average array.
110 | /// \optional This function is for testing and troubleshooting.
111 | /// \return index (0..2\ref MOVING_AVERAGE_BITS_ - 1)
112 | /// \par Usage:
113 | /// \code
114 | /// ...
115 | /// ADS7828 adc(0);
116 | /// ADS7828Channel* temperature = adc.channel(0);
117 | /// uint8_t channelIndex = temperature->index();
118 | /// ...
119 | /// \endcode
120 | uint8_t ADS7828Channel::index()
121 | {
122 | return index_;
123 | }
124 |
125 |
126 | /// Add (unscaled) sample value to moving average array, update totalizer.
127 | /// \param sample sample value (0x0000..0xFFFF)
128 | /// \remark Invoked by ADS7828::update() / ADS7828::updateAll() functions;
129 | /// this function will not normally be called by end user.
130 | void ADS7828Channel::newSample(uint16_t sample)
131 | {
132 | this->index_++;
133 | if (index_ >= (1 << MOVING_AVERAGE_BITS_)) this->index_ = 0;
134 | this->total_ -= samples_[index_];
135 | this->samples_[index_] = sample;
136 | this->total_ += samples_[index_];
137 | }
138 |
139 |
140 | /// Reset moving average array, index, totalizer to zero.
141 | /// \par Usage:
142 | /// \code
143 | /// ...
144 | /// ADS7828 adc(0);
145 | /// ADS7828Channel* temperature = adc.channel(0);
146 | /// temperature->reset();
147 | /// ...
148 | /// \endcode
149 | void ADS7828Channel::reset()
150 | {
151 | this->index_ = this->total_ = 0;
152 | for (uint8_t k = 0; k < (1 << MOVING_AVERAGE_BITS_); k++)
153 | {
154 | this->samples_[k] = 0;
155 | }
156 | }
157 |
158 |
159 | /// Return most-recent (unscaled) sample value from moving average array.
160 | /// \optional This function is for testing and troubleshooting.
161 | /// \return sample value (0x0000..0xFFFF)
162 | /// \par Usage:
163 | /// \code
164 | /// ...
165 | /// ADS7828 adc(0);
166 | /// ADS7828Channel* temperature = adc.channel(0);
167 | /// uint16_t sampleValue = temperature->sample();
168 | /// ...
169 | /// \endcode
170 | uint16_t ADS7828Channel::sample()
171 | {
172 | return samples_[index_];
173 | }
174 |
175 |
176 | /// Initiate A/D conversion for channel object.
177 | /// \optional This function is for testing and troubleshooting.
178 | /// \todo Determine whether this function is needed.
179 | /// \retval 0 success
180 | /// \retval 1 length too long for buffer
181 | /// \retval 2 address send, NACK received (device not on bus)
182 | /// \retval 3 data send, NACK received
183 | /// \retval 4 other twi error (lost bus arbitration, bus error, ...)
184 | /// \par Usage:
185 | /// \code
186 | /// ...
187 | /// ADS7828 adc(0);
188 | /// ADS7828Channel* temperature = adc.channel(0);
189 | /// uint8_t status = temperature->start();
190 | /// ...
191 | /// \endcode
192 | uint8_t ADS7828Channel::start()
193 | {
194 | return device_->start(id());
195 | }
196 |
197 |
198 | /// Return (unscaled) totalizer value for channel object.
199 | /// \optional This function is for testing and troubleshooting.
200 | /// \return totalizer value (0x0000..0xFFFF)
201 | /// \par Usage:
202 | /// \code
203 | /// ...
204 | /// ADS7828 adc(0);
205 | /// ADS7828Channel* temperature = adc.channel(0);
206 | /// uint16_t totalValue = temperature->total();
207 | /// ...
208 | /// \endcode
209 | uint16_t ADS7828Channel::total()
210 | {
211 | return total_;
212 | }
213 |
214 |
215 | /// Initiate A/D conversion, read data, update moving average for channel object.
216 | /// \optional This function is for testing and troubleshooting.
217 | /// \todo Determine whether this function is needed.
218 | /// \retval 0 success
219 | /// \retval 1 length too long for buffer
220 | /// \retval 2 address send, NACK received (device not on bus)
221 | /// \retval 3 data send, NACK received
222 | /// \retval 4 other twi error (lost bus arbitration, bus error, ...)
223 | /// \par Usage:
224 | /// \code
225 | /// ...
226 | /// ADS7828 adc(0);
227 | /// ADS7828Channel* temperature = adc.channel(0);
228 | /// uint8_t status = temperature->update();
229 | /// ...
230 | /// \endcode
231 | uint8_t ADS7828Channel::update()
232 | {
233 | device_->update(id());
234 | }
235 |
236 |
237 | /// Return moving average value for channel object.
238 | /// \required This is the most commonly-used channel function.
239 | /// \return scaled value (0x0000..0xFFFF)
240 | /// \par Usage:
241 | /// \code
242 | /// ...
243 | /// ADS7828 adc(0);
244 | /// ADS7828Channel* temperature = adc.channel(0);
245 | /// uint16_t ambient = temperature->value();
246 | /// ...
247 | /// \endcode
248 | uint16_t ADS7828Channel::value()
249 | {
250 | uint16_t r = (total_ >> MOVING_AVERAGE_BITS_);
251 | return map(r, DEFAULT_MIN_SCALE, DEFAULT_MAX_SCALE, minScale, maxScale);
252 | }
253 |
254 |
255 | // ____________________________________________ STATIC PUBLIC MEMBER FUNCTIONS
256 |
257 |
258 | // __________________________________________________ PRIVATE MEMBER FUNCTIONS
259 |
260 |
261 | // ___________________________________________ STATIC PRIVATE MEMBER FUNCTIONS
262 |
263 |
264 | // ___________________________________________________ PUBLIC MEMBER FUNCTIONS
265 | /// Constructor with the following defaults:
266 | ///
267 | /// \arg differential inputs (SD=0)
268 | /// \arg internal reference OFF between conversions (PD1=0)
269 | /// \arg A/D converter OFF between conversions (PD0=0)
270 | /// \arg min scale=0
271 | /// \arg max scale=4095
272 | ///
273 | /// \param address device address (0..3)
274 | /// \par Usage:
275 | /// \code
276 | /// ...
277 | /// // construct device with address 2
278 | /// ADS7828 adc(2);
279 | /// ...
280 | /// \endcode
281 | /// \sa ADS7828::address()
282 | ADS7828::ADS7828(uint8_t address)
283 | {
284 | init(address, (DIFFERENTIAL | REFERENCE_OFF | ADC_OFF),
285 | DEFAULT_CHANNEL_MASK, DEFAULT_MIN_SCALE, DEFAULT_MAX_SCALE);
286 | }
287 |
288 |
289 | /// \overload ADS7828::ADS7828(uint8_t address, uint8_t options)
290 | /// \param options command byte bits SD, PD1, PD0
291 | /// \par Usage:
292 | /// \code
293 | /// ...
294 | /// // device address 0, differential inputs, ref/ADC ON between conversions
295 | /// ADS7828 adc0(0, DIFFERENTIAL | REFERENCE_ON | ADC_ON);
296 | ///
297 | /// // device address 1, single-ended inputs, ref/ADC OFF between conversions
298 | /// ADS7828 adc1(1, SINGLE_ENDED | REFERENCE_OFF | ADC_OFF);
299 | ///
300 | /// // device address 2, single-ended inputs, ref/ADC ON between conversions
301 | /// ADS7828 adc2(2, SINGLE_ENDED | REFERENCE_ON | ADC_ON);
302 | /// ...
303 | /// \endcode
304 | /// \sa ADS7828Channel::commandByte()
305 | ADS7828::ADS7828(uint8_t address, uint8_t options)
306 | {
307 | init(address, options, DEFAULT_CHANNEL_MASK, DEFAULT_MIN_SCALE,
308 | DEFAULT_MAX_SCALE);
309 | }
310 |
311 |
312 | /// \overload ADS7828::ADS7828(uint8_t address, uint8_t options, uint8_t channelMask)
313 | /// \param channelMask bit positions containing a 1 represent channels that
314 | /// are to be read via update() / updateAll()
315 | /// \par Usage:
316 | /// \code
317 | /// ...
318 | /// // device address 0, update all channels via updateAll() (bits 7..0 are set)
319 | /// ADS7828 adc0(0, 0, 0xFF);
320 | ///
321 | /// // device address 1, update channels 0..3 via updateAll() (bits 3..0 are set)
322 | /// ADS7828 adc1(1, 0, 0b00001111);
323 | ///
324 | /// // device address 2, update channels 0, 1, 2, 7 via updateAll() (bits 7, 2, 1, 0 are set)
325 | /// ADS7828 adc2(2, 0, 0b10000111);
326 | /// ...
327 | /// \endcode
328 | /// \sa ADS7828::channelMask
329 | ADS7828::ADS7828(uint8_t address, uint8_t options, uint8_t channelMask)
330 | {
331 | init(address, options, channelMask, DEFAULT_MIN_SCALE, DEFAULT_MAX_SCALE);
332 | }
333 |
334 |
335 | /// \overload ADS7828::ADS7828(uint8_t address, uint8_t options, uint8_t channelMask, uint16_t min, uint16_t max)
336 | /// \param min minimum scaling value applied to value()
337 | /// \param max maximum scaling value applied to value()
338 | /// \par Usage:
339 | /// \code
340 | /// ...
341 | /// // device address 2, channel default minScale 0, maxScale 100
342 | /// ADS7828 adc(2, 0, DEFAULT_CHANNEL_MASK, 0, 100);
343 | /// ...
344 | /// \endcode
345 | /// \sa ADS7828Channel::minScale, ADS7828Channel::maxScale
346 | ADS7828::ADS7828(uint8_t address, uint8_t options, uint8_t channelMask,
347 | uint16_t min, uint16_t max)
348 | {
349 | init(address, options, channelMask, min, max);
350 | }
351 |
352 |
353 | /// Device address as defined by pins A1, A0
354 | /// \retval 0x00 A1=0, A0=0
355 | /// \retval 0x01 A1=0, A0=1
356 | /// \retval 0x02 A1=1, A0=0
357 | /// \retval 0x03 A1=1, A0=1
358 | /// \par Usage:
359 | /// \code
360 | /// ...
361 | /// ADS7828 adc(3);
362 | /// uint8_t deviceAddress = adc.address();
363 | /// ...
364 | /// \endcode
365 | uint8_t ADS7828::address()
366 | {
367 | return address_;
368 | }
369 |
370 |
371 | /// Return pointer to channel object.
372 | /// \param ch channel number (0..7)
373 | /// \return pointer to ADS7828Channel object
374 | /// \par Usage:
375 | /// \code
376 | /// ...
377 | /// ADS7828 adc(0);
378 | /// ADS7828Channel* temperature = adc.channel(0);
379 | /// ...
380 | /// \endcode
381 | ADS7828Channel* ADS7828::channel(uint8_t ch)
382 | {
383 | return &channels_[ch & 0x07];
384 | }
385 |
386 |
387 | /// Return command byte for device object (PD1 PD0 bits only).
388 | /// \optional This function is for testing and troubleshooting.
389 | /// \retval 0x00 Power Down Between A/D Converter Conversions
390 | /// \retval 0x04 Internal Reference OFF and A/D Converter ON
391 | /// \retval 0x08 Internal Reference ON and A/D Converter OFF
392 | /// \retval 0x0C Internal Reference ON and A/D Converter ON
393 | /// \par Usage:
394 | /// \code
395 | /// ...
396 | /// ADS7828 adc(0);
397 | /// uint8_t command = adc.commandByte();
398 | /// ...
399 | /// \endcode
400 | uint8_t ADS7828::commandByte()
401 | {
402 | return commandByte_;
403 | }
404 |
405 |
406 | /// Initiate communication with device.
407 | /// \optional This function is for testing and troubleshooting and
408 | /// can be used to determine whether a device is available (similar to
409 | /// the TCP/IP \c ping \c command).
410 | /// \retval 0 success
411 | /// \retval 1 length too long for buffer
412 | /// \retval 2 address send, NACK received (device not on bus)
413 | /// \retval 3 data send, NACK received
414 | /// \retval 4 other twi error (lost bus arbitration, bus error, ...)
415 | /// \par Usage:
416 | /// \code
417 | /// ...
418 | /// ADS7828 adc(3);
419 | /// // test whether device is available
420 | /// uint8_t status = adc.start();
421 | /// ...
422 | /// \endcode
423 | uint8_t ADS7828::start()
424 | {
425 | return start(0);
426 | }
427 |
428 |
429 | /// \overload ADS7828::start(uint8_t ch)
430 | /// \optional This function is for testing and troubleshooting.
431 | /// \param ch channel number (0..7)
432 | /// \retval 0 success
433 | /// \retval 1 length too long for buffer
434 | /// \retval 2 address send, NACK received (device not on bus)
435 | /// \retval 3 data send, NACK received
436 | /// \retval 4 other twi error (lost bus arbitration, bus error, ...)
437 | /// \par Usage:
438 | /// \code
439 | /// ...
440 | /// ADS7828 adc(0);
441 | /// // test whether device is available (channel 3 A/D conversion started)
442 | /// uint8_t status = adc.start(3);
443 | /// ...
444 | /// \endcode
445 | uint8_t ADS7828::start(uint8_t ch)
446 | {
447 | return start(address_, commandByte_ | channel(ch)->commandByte());
448 | }
449 |
450 |
451 | /// Update all unmasked channels on device.
452 | /// \required Call this or one of the update() / updateAll() functions
453 | /// from within \c loop() in order to read data from device(s).
454 | /// \return quantity of channels updated (0..8)
455 | /// \par Usage:
456 | /// \code
457 | /// ...
458 | /// ADS7828 adc(0);
459 | /// ...
460 | /// void loop()
461 | /// {
462 | /// ...
463 | /// // update device 0, all unmasked channels
464 | /// uint8_t quantity = adc.update();
465 | /// ...
466 | /// }
467 | /// ...
468 | /// \endcode
469 | uint8_t ADS7828::update()
470 | {
471 | return update(this);
472 | }
473 |
474 |
475 | /// \overload uint8_t ADS7828::update(uint8_t ch)
476 | /// \required Call this or one of the update() / updateAll() functions
477 | /// from within \c loop() in order to read data from device(s).
478 | /// \param ch channel number (0..7)
479 | /// \retval 0 success
480 | /// \retval 1 length too long for buffer
481 | /// \retval 2 address send, NACK received (device not on bus)
482 | /// \retval 3 data send, NACK received
483 | /// \retval 4 other twi error (lost bus arbitration, bus error, ...)
484 | /// \par Usage:
485 | /// \code
486 | /// ...
487 | /// ADS7828 adc(0);
488 | /// ...
489 | /// void loop()
490 | /// {
491 | /// ...
492 | /// // update device 0, channel 3
493 | /// uint8_t status = adc.update(3);
494 | /// ...
495 | /// }
496 | /// ...
497 | /// \endcode
498 | uint8_t ADS7828::update(uint8_t ch)
499 | {
500 | return update(this, ch);
501 | }
502 |
503 |
504 | // ____________________________________________ STATIC PUBLIC MEMBER FUNCTIONS
505 | /// Enable I2C communication.
506 | /// \required Call from within \c setup()\c to enable I2C communication.
507 | /// \par Usage:
508 | /// \code
509 | /// ...
510 | /// void setup()
511 | /// {
512 | /// // enable I2C communication
513 | /// ADS7828::begin();
514 | /// }
515 | /// ...
516 | /// \endcode
517 | void ADS7828::begin()
518 | {
519 | Wire.begin();
520 | }
521 |
522 |
523 | /// Return pointer to device object.
524 | /// \param address device address (0..3)
525 | /// \return pointer to ADS7828 object
526 | /// \par Usage:
527 | /// \code
528 | /// ...
529 | /// // device 2 pointer
530 | /// ADS7828* device2 = ADS7828::device(2);
531 | /// ...
532 | /// \endcode
533 | ADS7828* ADS7828::device(uint8_t address)
534 | {
535 | return devices_[address & 0x03];
536 | }
537 |
538 |
539 | /// Update all unmasked channels on all registered devices.
540 | /// \required Call this or one of the update() functions
541 | /// from within \c loop() in order to read data from device(s).
542 | /// This is the most commonly-used device update function.
543 | /// \return quantity of channels updated (0..32)
544 | /// \par Usage:
545 | /// \code
546 | /// ...
547 | /// void loop()
548 | /// {
549 | /// ...
550 | /// // update all registered ADS7828 devices/unmasked channels
551 | /// uint8_t quantity = ADS7828::updateAll();
552 | /// ...
553 | /// }
554 | /// ...
555 | /// \endcode
556 | uint8_t ADS7828::updateAll()
557 | {
558 | uint8_t a, ch, count = 0;
559 | for (a = 0; a < 4; a++)
560 | {
561 | if (0 != devices_[a]) count += update(devices_[a]);
562 | }
563 | return count;
564 | }
565 |
566 |
567 | // __________________________________________________ PRIVATE MEMBER FUNCTIONS
568 | /// Common code for constructors.
569 | /// \param address device address (0..3)
570 | /// \param options command byte bits SD, PD1, PD0
571 | /// \param channelMask bit positions containing a 1 represent channels that
572 | /// are to be read via update() / updateAll()
573 | /// \param min minimum scaling value applied to value()
574 | /// \param max maximum scaling value applied to value()
575 | void ADS7828::init(uint8_t address, uint8_t options,
576 | uint8_t channelMask, uint16_t min, uint16_t max)
577 | {
578 | this->address_ = address & 0x03; // A1 A0 bits
579 | this->commandByte_ = options & 0x0C; // PD1 PD0 bits
580 | this->channelMask = channelMask;
581 | for (uint8_t ch = 0; ch < 8; ch++)
582 | {
583 | channels_[ch] = ADS7828Channel(this, ch, options, min, max);
584 | }
585 | this->devices_[address_] = this;
586 | }
587 |
588 |
589 | /// Request and receive data from most-recent A/D conversion from device.
590 | /// \return 16-bit zero-padded word (12 data bits D11..D0)
591 | uint16_t ADS7828::read()
592 | {
593 | return read(address_);
594 | }
595 |
596 |
597 | // ___________________________________________ STATIC PRIVATE MEMBER FUNCTIONS
598 | /// Request and receive data from most-recent A/D conversion from device.
599 | /// \param address device address (0..3)
600 | /// \return 16-bit zero-padded word (12 data bits D11..D0)
601 | uint16_t ADS7828::read(uint8_t address)
602 | {
603 | Wire.requestFrom(BASE_ADDRESS_ | (address & 0x03), 2);
604 | return word(Wire.read(), Wire.read());
605 | }
606 |
607 |
608 | /// Initiate communication with device.
609 | /// \param address device address (0..3)
610 | /// \param command command byte (0x00..0xFC)
611 | /// \retval 0 success
612 | /// \retval 1 length too long for buffer
613 | /// \retval 2 address send, NACK received (device not on bus)
614 | /// \retval 3 data send, NACK received
615 | /// \retval 4 other twi error (lost bus arbitration, bus error, ...)
616 | uint8_t ADS7828::start(uint8_t address, uint8_t command)
617 | {
618 | Wire.beginTransmission(BASE_ADDRESS_ | (address & 0x03));
619 | Wire.write((uint8_t) command);
620 | return Wire.endTransmission();
621 | }
622 |
623 |
624 | /// Initiate communication with device.
625 | /// \param device pointer to device object
626 | /// \return quantity of channels updated (0..8)
627 | uint8_t ADS7828::update(ADS7828* device)
628 | {
629 | if (0 == device) device = devices_[0];
630 | uint8_t ch, count = 0;
631 | for (ch = 0; ch < 8; ch++)
632 | {
633 | if (bitRead(device->channelMask, ch))
634 | {
635 | if (0 == update(device, ch)) count++;
636 | }
637 | }
638 | return count;
639 | }
640 |
641 |
642 | /// Initiate communication with device.
643 | /// \param device pointer to device object
644 | /// \param ch channel number (0..7)
645 | /// \retval 0 success
646 | /// \retval 1 length too long for buffer
647 | /// \retval 2 address send, NACK received (device not on bus)
648 | /// \retval 3 data send, NACK received
649 | /// \retval 4 other twi error (lost bus arbitration, bus error, ...)
650 | uint8_t ADS7828::update(ADS7828* device, uint8_t ch)
651 | {
652 | if (0 == device) device = devices_[0];
653 | uint8_t status = device->start(ch);
654 | if (0 == status) device->channel(ch)->newSample(device->read());
655 | return status;
656 | }
657 |
658 |
659 | // _________________________________________________ STATIC PRIVATE ATTRIBTUES
660 | ADS7828* ADS7828::devices_[] = {};
661 |
--------------------------------------------------------------------------------
/src/i2c_adc_ads7828.h:
--------------------------------------------------------------------------------
1 | /// \file
2 | /// Arduino library for TI ADS7828 I2C A/D converter.
3 | /*
4 |
5 | i2c_adc_ads7828.h - Arduino library for TI ADS7828 I2C A/D converter
6 |
7 | Library:: i2c_adc_ads7828
8 | Author:: Doc Walker <4-20ma@wvfans.net>
9 |
10 | Copyright:: 2009-2016 Doc Walker
11 |
12 | Licensed under the Apache License, Version 2.0 (the "License");
13 | you may not use this file except in compliance with the License.
14 | You may obtain a copy of the License at
15 |
16 | http://www.apache.org/licenses/LICENSE-2.0
17 |
18 | Unless required by applicable law or agreed to in writing, software
19 | distributed under the License is distributed on an "AS IS" BASIS,
20 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | See the License for the specific language governing permissions and
22 | limitations under the License.
23 |
24 | */
25 |
26 |
27 | /// \mainpage Arduino library for TI ADS7828 I2C A/D converter.
28 | /// \version \verbinclude VERSION
29 | /// \date 27 Sep 2016
30 | /// \par Source Code Repository:
31 | /// https://github.com/4-20ma/i2c_adc_ads7828
32 | /// \par Programming Style Guidelines:
33 | /// http://geosoft.no/development/cppstyle.html
34 | ///
35 | /// \par Features
36 | /// The ADS7828 is a single-supply, low-power, 12-bit data acquisition
37 | /// device that features a serial I2C interface and an 8-channel
38 | /// multiplexer. The Analog-to-Digital (A/D) converter features a
39 | /// sample-and-hold amplifier and internal, asynchronous clock. The
40 | /// combination of an I2C serial, 2-wire interface and micropower
41 | /// consumption makes the ADS7828 ideal for applications requiring the A/D
42 | /// converter to be close to the input source in remote locations and for
43 | /// applications requiring isolation. The ADS7828 is available in a TSSOP-16
44 | /// package.
45 | /// \par Schematic
46 | /// \verbinclude SCHEMATIC
47 | /// \par Caveats
48 | /// Conforms to Arduino IDE 1.5 Library Specification v2.1 which requires
49 | /// Arduino IDE >= 1.5.
50 | /// \par Support
51 | /// Please [submit an issue](https://github.com/4-20ma/i2c_adc_ads7828/
52 | /// issues) for all questions, bug reports, and feature requests. Email
53 | /// requests will be politely redirected to the issue tracker so others may
54 | /// contribute to the discussion and requestors get a more timely response.
55 | /// \author Doc Walker ([4-20ma@wvfans.net](mailto:4-20ma@wvfans.net))
56 | /// \copyright 2009-2016 Doc Walker
57 | /// \par License
58 | ///
59 | /// Licensed under the Apache License, Version 2.0 (the "License");
60 | /// you may not use this file except in compliance with the License.
61 | /// You may obtain a copy of the License at
62 | ///
63 | /// http://www.apache.org/licenses/LICENSE-2.0
64 | ///
65 | /// Unless required by applicable law or agreed to in writing, software
66 | /// distributed under the License is distributed on an "AS IS" BASIS,
67 | /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68 | /// See the License for the specific language governing permissions and
69 | /// limitations under the License.
70 | ///
71 |
72 |
73 | #ifndef i2c_adc_ads7828_h
74 | #define i2c_adc_ads7828_h
75 |
76 | // _________________________________________________________ STANDARD INCLUDES
77 | // include types & constants of Wiring core API
78 | #include "Arduino.h"
79 |
80 |
81 | // __________________________________________________________ PROJECT INCLUDES
82 | // include twi/i2c library
83 | #include
84 |
85 |
86 | // ____________________________________________________________ UTILITY MACROS
87 |
88 |
89 | // _________________________________________________________________ CONSTANTS
90 | /// Configure channels to use differential inputs (Command byte SD=0).
91 | /// Use either \ref DIFFERENTIAL or \ref SINGLE_ENDED in ADS7828
92 | /// constructor; default is \ref DIFFERENTIAL.
93 | /// \par Usage:
94 | /// \code
95 | /// ...
96 | /// // address 0, differential inputs, ref/ADC OFF between conversions
97 | /// ADS7828 adc0(0, DIFFERENTIAL | REFERENCE_OFF | ADC_OFF);
98 | /// ...
99 | /// \endcode
100 | /// \relates ADS7828
101 | static const uint8_t DIFFERENTIAL = 0 << 7; // SD == 0
102 |
103 |
104 | /// Configure channels to use single-ended inputs (Command byte SD=1).
105 | /// Use either \ref DIFFERENTIAL or \ref SINGLE_ENDED in ADS7828
106 | /// constructor; default is \ref DIFFERENTIAL.
107 | /// \par Usage:
108 | /// \code
109 | /// ...
110 | /// // address 1, single-ended inputs, ref/ADC OFF between conversions
111 | /// ADS7828 adc1(1, SINGLE_ENDED | REFERENCE_OFF | ADC_OFF);
112 | /// ...
113 | /// \endcode
114 | /// \relates ADS7828
115 | static const uint8_t SINGLE_ENDED = 1 << 7; // SD == 1
116 |
117 |
118 | /// Configure channels to turn internal reference OFF between conversions (Command byte PD1=0).
119 | /// Use either \ref REFERENCE_OFF or \ref REFERENCE_ON in ADS7828
120 | /// constructor; default is \ref REFERENCE_OFF.
121 | /// \par Usage:
122 | /// \code
123 | /// ...
124 | /// // address 0, differential inputs, ref/ADC OFF between conversions
125 | /// ADS7828 adc0(0, DIFFERENTIAL | REFERENCE_OFF | ADC_OFF);
126 | /// ...
127 | /// \endcode
128 | /// \relates ADS7828
129 | static const uint8_t REFERENCE_OFF = 0 << 3; // PD1 == 0
130 |
131 |
132 | /// Configure channels to turn internal reference ON between conversions (Command byte PD1=1).
133 | /// Use either \ref REFERENCE_OFF or \ref REFERENCE_ON in ADS7828
134 | /// constructor; default is \ref REFERENCE_OFF.
135 | /// \par Usage:
136 | /// \code
137 | /// ...
138 | /// // address 2, differential inputs, ref ON/ADC OFF between conversions
139 | /// ADS7828 adc2(2, DIFFERENTIAL | REFERENCE_ON | ADC_OFF);
140 | /// ...
141 | /// \endcode
142 | /// \relates ADS7828
143 | static const uint8_t REFERENCE_ON = 1 << 3; // PD1 == 1
144 |
145 |
146 | /// Configure channels to turn A/D converter OFF between conversions (Command byte PD0=0).
147 | /// Use either \ref ADC_OFF or \ref ADC_ON in ADS7828
148 | /// constructor; default is \ref ADC_OFF.
149 | /// \par Usage:
150 | /// \code
151 | /// ...
152 | /// // address 0, differential inputs, ref/ADC OFF between conversions
153 | /// ADS7828 adc0(0, DIFFERENTIAL | REFERENCE_OFF | ADC_OFF);
154 | /// ...
155 | /// \endcode
156 | /// \relates ADS7828
157 | static const uint8_t ADC_OFF = 0 << 2; // PD0 == 0
158 |
159 |
160 | /// Configure channels to turn A/D converter ON between conversions (Command byte PD0=1).
161 | /// Use either \ref ADC_OFF or \ref ADC_ON in ADS7828
162 | /// constructor; default is \ref ADC_OFF.
163 | /// \par Usage:
164 | /// \code
165 | /// ...
166 | /// // address 3 , differential inputs, ref OFF/ADC ON between conversions
167 | /// ADS7828 adc3(3, DIFFERENTIAL | REFERENCE_OFF | ADC_ON);
168 | /// ...
169 | /// \endcode
170 | /// \relates ADS7828
171 | static const uint8_t ADC_ON = 1 << 2; // PD0 == 1
172 |
173 |
174 | /// Default channel mask used in ADS7828 constructor.
175 | /// \relates ADS7828
176 | static const uint8_t DEFAULT_CHANNEL_MASK = 0xFF;
177 |
178 |
179 | /// Default scaling minimum value used in ADS7828 constructor.
180 | /// \relates ADS7828
181 | static const uint16_t DEFAULT_MIN_SCALE = 0;
182 |
183 |
184 | /// Default scaling maximum value used in ADS7828 constructor.
185 | /// \relates ADS7828
186 | static const uint16_t DEFAULT_MAX_SCALE = 0xFFF;
187 |
188 |
189 | // _________________________________________________________ CLASS DEFINITIONS
190 | class ADS7828;
191 | class ADS7828Channel
192 | {
193 | public:
194 | // ............................................... public member functions
195 | ADS7828Channel() {};
196 | ADS7828Channel(ADS7828* const, uint8_t, uint8_t, uint16_t, uint16_t);
197 | uint8_t commandByte();
198 | ADS7828* device();
199 | uint8_t id();
200 | uint8_t index();
201 | void newSample(uint16_t);
202 | void reset();
203 | uint16_t sample();
204 | uint8_t start();
205 | uint16_t total();
206 | uint8_t update();
207 | uint16_t value();
208 |
209 | // ........................................ static public member functions
210 |
211 | // ..................................................... public attributes
212 | /// Maximum value of moving average (defaults to 0x0FFF).
213 | /// \par Usage:
214 | /// \code
215 | /// ...
216 | /// ADS7828 device(0);
217 | /// ADS7828Channel* temperature = device.channel(0);
218 | /// uint16_t old = temperature->maxScale; // get current value and/or
219 | /// temperature->maxScale = 100; // set new value
220 | /// ...
221 | /// \endcode
222 | uint16_t maxScale;
223 |
224 | /// Minimum value of moving average (defaults to 0x0000).
225 | /// \par Usage:
226 | /// \code
227 | /// ...
228 | /// ADS7828 device(0);
229 | /// ADS7828Channel* temperature = device.channel(0);
230 | /// uint16_t old = temperature->minScale; // get current value and/or
231 | /// temperature->minScale = 0; // set new value
232 | /// ...
233 | /// \endcode
234 | uint16_t minScale;
235 |
236 | // .............................................. static public attributes
237 |
238 | private:
239 | // .............................................. private member functions
240 |
241 | // ....................................... static private member functions
242 |
243 | // .................................................... private attributes
244 | /// Command byte for channel object (SD C2 C1 C0 bits only).
245 | uint8_t commandByte_;
246 |
247 | /// Pointer to parent device object.
248 | ADS7828* device_;
249 |
250 | /// Index position within moving average array.
251 | uint8_t index_;
252 |
253 | /// Array of (unscaled) sample values.
254 | /// \note Bit shift must match \ref MOVING_AVERAGE_BITS_.
255 | uint16_t samples_[1 << 4];
256 |
257 | /// (Unscaled) running total of moving average array elements.
258 | uint16_t total_;
259 |
260 | // ............................................. static private attributes
261 | /// Quantity of samples to be averaged =
262 | /// 2\ref MOVING_AVERAGE_BITS_.
263 | /// \note \ref MOVING_AVERAGE_BITS_ must match \ref samples_ bit shift.
264 | static const uint8_t MOVING_AVERAGE_BITS_ = 4;
265 | };
266 |
267 |
268 | class ADS7828
269 | {
270 | public:
271 | // ............................................... public member functions
272 | ADS7828(uint8_t);
273 | ADS7828(uint8_t, uint8_t);
274 | ADS7828(uint8_t, uint8_t, uint8_t);
275 | ADS7828(uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
276 | uint8_t address();
277 | ADS7828Channel* channel(uint8_t);
278 | uint8_t commandByte();
279 | uint8_t start();
280 | uint8_t start(uint8_t);
281 | uint8_t update(); // single device, all unmasked channel
282 | uint8_t update(uint8_t); // single device, single channel
283 |
284 | // ........................................ static public member functions
285 | static void begin();
286 | static ADS7828* device(uint8_t);
287 | static uint8_t updateAll(); // all devices, all unmasked channels
288 |
289 | // ..................................................... public attributes
290 | /// Each bit position containing a 1 represents a channel that is to be
291 | /// read via update() / updateAll().
292 | uint8_t channelMask; // mask of active channels
293 |
294 | // .............................................. static public attributes
295 |
296 | private:
297 | // .............................................. private member functions
298 | void init(uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
299 | uint16_t read();
300 |
301 | // ....................................... static private member functions
302 | static uint16_t read(uint8_t);
303 | static uint8_t start(uint8_t, uint8_t);
304 | static uint8_t update(ADS7828*); // single device, all unmasked channels
305 | static uint8_t update(ADS7828*, uint8_t); // single device, single channel
306 |
307 | // .................................................... private attributes
308 | /// Device address as defined by pins A1, A0
309 | uint8_t address_;
310 |
311 | /// Array of channel objects.
312 | ADS7828Channel channels_[8];
313 |
314 | /// Command byte for device object (PD1 PD0 bits only).
315 | uint8_t commandByte_;
316 |
317 | // ............................................. static private attributes
318 | /// Array of pointers to registered device objects.
319 | static ADS7828* devices_[4];
320 |
321 | /// Factory pre-set slave address.
322 | static const uint8_t BASE_ADDRESS_ = 0x48;
323 | };
324 | #endif
325 | /// \example examples/one_device/one_device.ino
326 | /// \example examples/two_devices/two_devices.ino
327 |
--------------------------------------------------------------------------------