Example E: Check all Addresses for Active Sensors and Start Continuous Measurements

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 continuous measurements from them.

Each call to SDI12Recorder::requestContinuousData() requests one independent R0 through R9 response. The example can instead request RC0 through RC9 and validate the returned CRC by setting useCRC to true.

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} e_continuous_measurement.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 E: Check all Addresses for Active Sensors and Request Continuous 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 periodically
13 * requests their current continuous data without initiating a measurement.
14 */
15
16#include <SDI12Config.h>
17#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && !defined(SDI12_INTERNAL_PCINT)
18#include <EnableInterrupt.h>
19#endif
20
21#include <SDI12Recorder.h>
22
23#ifndef SDI12_DATA_PIN
24#define SDI12_DATA_PIN 7
25#endif
26#ifndef SDI12_POWER_PIN
27#define SDI12_POWER_PIN 22
28#endif
29#ifndef SDI12_TERMINAL_BAUD
30#define SDI12_TERMINAL_BAUD 115200
31#endif
32
33/* connection information */
34uint32_t serialBaud = SDI12_TERMINAL_BAUD; /*!< The baud rate for the serial port */
35int8_t dataPin = SDI12_DATA_PIN; /*!< The pin of the SDI-12 data bus */
36int8_t powerPin = SDI12_POWER_PIN; /*!< The sensor power pin (or -1) */
37bool useCRC = false; /*!< Whether to use CRC checking */
38int8_t firstAddress = 0; /* The first address in the address space to check (0='0') */
39int8_t lastAddress = 61; /* The last address in the address space to check (61='z') */
40
41/** Define the SDI-12 bus */
42SDI12 mySDI12(dataPin);
43SDI12Recorder mySDI12Recorder(mySDI12);
44
45// keeps track of active addresses
46bool isActive[64];
47
48uint8_t numSensors = 0;
49
50// A continuous response can contain at most 75 value characters. At the minimum
51// two characters per value (a sign and one digit), no more than 37 values can fit.
52float continuousResults[37];
53
54bool printInfo(char address) {
55 SDI12Recorder::Identification sensorInfo;
56 if (mySDI12Recorder.identify(address, sensorInfo)) {
57 mySDI12Recorder.printSensorInfo(sensorInfo, Serial);
58 return true;
59 } else {
60 Serial.print(F("Identification failed for address "));
61 Serial.print(address);
62 Serial.print(F(": "));
63 mySDI12Recorder.printRecorderResult(Serial);
64 Serial.println();
65 }
66 return false;
67}
68
69bool getContinuousResults(char address, uint8_t dataOption = 0U) {
70 const size_t resultsReceived = mySDI12Recorder.requestContinuousData(
71 address, continuousResults,
72 sizeof(continuousResults) / sizeof(continuousResults[0]), dataOption, useCRC);
73 if (mySDI12Recorder.result() != SDI12Recorder::RESULT_SUCCESS) {
74 mySDI12Recorder.printRecorderResult(Serial);
75 return false;
76 }
77
78 if (resultsReceived == 0U) {
79 Serial.print(F("No continuous results available"));
80 return true;
81 }
82
83 for (size_t i = 0U; i < resultsReceived; ++i) {
84 if (i > 0U) { Serial.print(F(", ")); }
85 Serial.print(continuousResults[i], 7);
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(
142 "Time Elapsed (ms), Sensor Address, Measurement 1, Measurement 2, ... etc.");
143 Serial.println(
144 "-------------------------------------------------------------------------------");
145}
146
147void loop() {
148 // measure one at a time
149 for (int8_t i = firstAddress; i <= lastAddress; i++) {
150 char addr = SDI12Address::fromIndex(i);
151 if (isActive[i]) {
152 Serial.print(millis());
153 Serial.print(F(", "));
154 Serial.print(addr);
155 Serial.print(F(", "));
156 getContinuousResults(addr);
157 Serial.println();
158 }
159 }
160
161 delay(10000L); // wait ten seconds between measurement attempts.
162}