Example D: Check all Addresses for Active Sensors and Log Data

This is a simple demonstration of the SDI-12 library for Arduino.

It discovers the address of all sensors active on a single bus and takes measurements from them.

The sketch uses the beginner-facing blocking SDI12Recorder::measure() workflow. That one call requests a normal measurement and retrieves the complete advertised result across D0 through the necessary final data block. Set the sketch's useCRC value to request the MC command family and validate response CRCs.

Every SDI-12 device is different in the time it takes to take a measurement, and the amount of data it returns. This sketch will not serve every sensor type, but it will likely be helpful in getting you started.

Each sensor should have a unique address already - if not, multiple sensors may respond simultaneously to the same request and the output will not be readable by the Arduino.

To address a sensor, please see Example B: b_address_change.ino

PlatformIO Configuration

1; PlatformIO Project Configuration File
2
3[platformio]
4description = SDI-12 Library Example D: Getting Data from All Attached Sensors
5src_dir = .piolibdeps/Arduino-SDI-12_ID1486/examples/d_simple_logger
6
7[env:mayfly]
8monitor_speed = 115200
9board = mayfly
10platform = atmelavr
11framework = arduino
12lib_ldf_mode = deep+
13lib_ignore = RTCZero
14lib_deps =
15 SDI-12

The Complete Example

1/**
2 * @example{lineno} d_simple_logger.ino
3 * @copyright Stroud Water Research Center
4 * @license This example is published under the BSD-3 license.
5 * @author Kevin M.Smith <SDI12@ethosengineering.org>
6 * @date August 2013
7 *
8 * @brief Example D: Check all Addresses for Active Sensors and Log Data
9 *
10 * This is a simple demonstration of the SDI-12 library for Arduino.
11 *
12 * It discovers the address of all sensors active on a single bus and takes measurements
13 * from them.
14 *
15 * Every SDI-12 device is different in the time it takes to take a
16 * measurement, and the amount of data it returns. This sketch will not serve every
17 * sensor type, but it will likely be helpful in getting you started.
18 *
19 * Each sensor should have a unique address already - if not, multiple sensors may
20 * respond simultaneously to the same request and the output will not be readable by the
21 * Arduino.
22 *
23 * To address a sensor, please see Example B: b_address_change.ino
24 */
25
26#include <SDI12Config.h>
27#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && !defined(SDI12_INTERNAL_PCINT)
28#include <EnableInterrupt.h>
29#endif
30
31#include <SDI12Recorder.h>
32
33#ifndef SDI12_DATA_PIN
34#define SDI12_DATA_PIN 7
35#endif
36#ifndef SDI12_POWER_PIN
37#define SDI12_POWER_PIN 22
38#endif
39#ifndef SDI12_TERMINAL_BAUD
40#define SDI12_TERMINAL_BAUD 115200
41#endif
42
43/* connection information */
44uint32_t serialBaud = SDI12_TERMINAL_BAUD; /*!< The baud rate for the serial port */
45int8_t dataPin = SDI12_DATA_PIN; /*!< The pin of the SDI-12 data bus */
46int8_t powerPin = SDI12_POWER_PIN; /*!< The sensor power pin (or -1) */
47bool useCRC = false; /*!< Whether to use CRC checking */
48int8_t firstAddress = 0; /* The first address in the address space to check (0='0') */
49int8_t lastAddress = 61; /* The last address in the address space to check (61='z') */
50
51/** Define the SDI-12 bus */
52SDI12 mySDI12(dataPin);
53SDI12Recorder mySDI12Recorder(mySDI12);
54
55// keeps track of active addresses
56bool isActive[64];
57
58uint8_t numSensors = 0;
59
60bool printInfo(char address) {
61 SDI12Recorder::Identification sensorInfo;
62 if (mySDI12Recorder.identify(address, sensorInfo)) {
63 mySDI12Recorder.printSensorInfo(sensorInfo, Serial);
64 return true;
65 } else {
66 Serial.print(F("Identification failed for address "));
67 Serial.print(address);
68 Serial.print(F(": "));
69 mySDI12Recorder.printRecorderResult(Serial);
70 Serial.println();
71 }
72 return false;
73}
74
75bool takeMeasurement(char i, uint8_t measurementNumber = 0U) {
76 float values[9];
77 size_t valueCount = mySDI12Recorder.measure(i, values, 9U, measurementNumber, useCRC);
78 if (mySDI12Recorder.result() != SDI12Recorder::RESULT_SUCCESS) {
79 mySDI12Recorder.printRecorderResult(Serial);
80 return false;
81 }
82
83 for (size_t valueNumber = 0U; valueNumber < valueCount; ++valueNumber) {
84 Serial.print(String(values[valueNumber], 7));
85 Serial.print(F(", "));
86 }
87 return true;
88}
89
90void setup() {
91 Serial.begin(serialBaud);
92 while (!Serial && millis() < 10000L);
93 char tbuf[3] = {'\0'};
94
95 Serial.print(F("Opening SDI-12 bus on pin "));
96 Serial.print(dataPin);
97 Serial.print(F(" ("));
98 Serial.print(itoa(dataPin, tbuf, 10));
99 Serial.print(')');
100 Serial.println(F("..."));
101 mySDI12.begin();
102 delay(500); // allow things to settle
103
104 Serial.println(F("Timeout value: "));
105 Serial.println(mySDI12.TIMEOUT);
106
107 // Power the sensors;
108 if (powerPin >= 0) {
109 Serial.print(F("Powering up sensors with pin "));
110 Serial.print(String(powerPin));
111 Serial.println(F(", wait 10s..."));
112 pinMode(powerPin, OUTPUT);
113 digitalWrite(powerPin, HIGH);
114 delay(10000L);
115 } else {
116 Serial.println(F("Wait 5s..."));
117 delay(5000L);
118 }
119
120 // Quickly scan the address space
121 Serial.println(F("\n\nScanning all addresses, please wait..."));
122
123 for (int8_t i = firstAddress; i <= lastAddress; i++) {
124 char addr = SDI12Address::fromIndex(i);
125 if (mySDI12Recorder.requestAcknowledgement(addr)) {
126 numSensors++;
127 isActive[i] = 1;
128 printInfo(addr);
129 }
130 }
131 Serial.print(F("Total number of sensors found: "));
132 Serial.println(numSensors);
133
134 if (numSensors == 0) {
135 Serial.println(
136 "No sensors found, please check connections and restart the Arduino.");
137 while (true); // do nothing forever
138 }
139
140 Serial.println();
141 Serial.println(F("Time Elapsed (ms), Sensor Address, Measurement Number, Result 1, "
142 "Result 2, ... etc."));
143 Serial.println(F(
144 "------------------------------------------------------------------------------"));
145}
146
147void loop() {
148 for (uint8_t measurementNumber = 0U; measurementNumber < 1U; ++measurementNumber) {
149 // measure one at a time
150 for (int8_t i = firstAddress; i <= lastAddress; i++) {
151 char addr = SDI12Address::fromIndex(i);
152 if (isActive[i]) {
153 Serial.print(millis());
154 Serial.print(F(", "));
155 Serial.print(addr);
156 Serial.print(F(", "));
157 Serial.print(measurementNumber);
158 Serial.print(F(", "));
159 takeMeasurement(addr, measurementNumber);
160 Serial.println();
161 }
162 }
163 }
164
165 delay(10000L); // wait ten seconds between measurement attempts.
166}