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.
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
4description = SDI-12 Library Example D: Getting Data from All Attached Sensors
5src_dir = .piolibdeps/Arduino-SDI-12_ID1486/examples/d_simple_logger
The Complete Example
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>
8 * @brief Example D: Check all Addresses for Active Sensors and Log Data
10 * This is a simple demonstration of the SDI-12 library for Arduino.
12 * It discovers the address of all sensors active on a single bus and takes continuous
13 * measurements from them.
18uint32_t serialBaud = 115200; /*!< The baud rate for the output serial port */
19int8_t dataPin = 7; /*!< The pin of the SDI-12 data bus */
20int8_t powerPin = 22; /*!< The sensor power pin (or -1 if not switching power) */
21int8_t firstAddress = 0; /* The first address in the address space to check (0='0') */
22int8_t lastAddress = 62; /* The last address in the address space to check (62='z') */
24/** Define the SDI-12 bus */
25SDI12 mySDI12(dataPin);
27// keeps track of active addresses
32uint8_t numSensors = 0;
35 * @brief converts allowable address characters ('0'-'9', 'a'-'z', 'A'-'Z') to a
36 * decimal number between 0 and 61 (inclusive) to cover the 62 possible
39byte charToDec(char i) {
40 if ((i >= '0') && (i <= '9')) return i - '0';
41 if ((i >= 'a') && (i <= 'z')) return i - 'a' + 10;
42 if ((i >= 'A') && (i <= 'Z'))
49 * @brief maps a decimal number between 0 and 61 (inclusive) to allowable
50 * address characters '0'-'9', 'a'-'z', 'A'-'Z',
52 * THIS METHOD IS UNUSED IN THIS EXAMPLE, BUT IT MAY BE HELPFUL.
54char decToChar(byte i) {
55 if (i < 10) return i + '0';
56 if ((i >= 10) && (i < 36)) return i + 'a' - 10;
57 if ((i >= 36) && (i <= 62))
64 * @brief gets identification information from a sensor, and prints it to the serial
67 * @param i a character between '0'-'9', 'a'-'z', or 'A'-'Z'.
69void printInfo(char i) {
73 mySDI12.sendCommand(command);
76 String sdiResponse = mySDI12.readStringUntil('\n');
78 // allccccccccmmmmmmvvvxxx...xx<CR><LF>
79 Serial.print(sdiResponse.substring(0, 1)); // address
81 Serial.print(sdiResponse.substring(1, 3).toFloat() / 10); // SDI-12 version number
83 Serial.print(sdiResponse.substring(3, 11)); // vendor id
85 Serial.print(sdiResponse.substring(11, 17)); // sensor model
87 Serial.print(sdiResponse.substring(17, 20)); // sensor version
89 Serial.print(sdiResponse.substring(20)); // sensor id
93bool getContinuousResults(char i, int resultsExpected) {
94 uint8_t resultsReceived = 0;
95 uint8_t cmd_number = 0;
96 while (resultsReceived < resultsExpected && cmd_number <= 9) {
98 // in this example we will only take the 'DO' measurement
102 command += cmd_number;
103 command += "!"; // SDI-12 command to get data [address][D][dataOption][!]
104 mySDI12.sendCommand(command);
106 uint32_t start = millis();
107 while (mySDI12.available() < 3 && (millis() - start) < 1500) {}
108 mySDI12.read(); // ignore the repeated SDI12 address
109 char c = mySDI12.peek(); // check if there's a '+' and toss if so
110 if (c == '+') { mySDI12.read(); }
112 while (mySDI12.available()) {
113 char c = mySDI12.peek();
114 if (c == '-' || (c >= '0' && c <= '9') || c == '.') {
115 float result = mySDI12.parseFloat(SKIP_NONE);
116 Serial.print(String(result, 10));
117 if (result != -9999) { resultsReceived++; }
118 } else if (c == '+') {
124 delay(10); // 1 character ~ 7.5ms
126 if (resultsReceived < resultsExpected) { Serial.print(", "); }
129 mySDI12.clearBuffer();
131 return resultsReceived == resultsExpected;
134// this checks for activity at a particular address
135// expects a char, '0'-'9', 'a'-'z', or 'A'-'Z'
136boolean checkActive(char i) {
137 String myCommand = "";
139 myCommand += (char)i; // sends basic 'acknowledge' command [address][!]
142 for (int j = 0; j < 3; j++) { // goes through three rapid contact attempts
143 mySDI12.sendCommand(myCommand);
145 if (mySDI12.available()) { // If we here anything, assume we have an active sensor
146 mySDI12.clearBuffer();
150 mySDI12.clearBuffer();
155 Serial.begin(serialBaud);
159 Serial.println("Opening SDI-12 bus...");
161 delay(500); // allow things to settle
163 Serial.println("Timeout value: ");
164 Serial.println(mySDI12.TIMEOUT);
166 // Power the sensors;
168 Serial.println("Powering up sensors, wait...");
169 pinMode(powerPin, OUTPUT);
170 digitalWrite(powerPin, HIGH);
174 // Quickly Scan the Address Space
175 Serial.println("Scanning all addresses, please wait...");
176 Serial.println("Sensor Address, Protocol Version, Sensor Vendor, Sensor Model, "
177 "Sensor Version, Sensor ID");
179 for (byte i = firstAddress; i < lastAddress; i++) {
180 char addr = decToChar(i);
181 if (checkActive(addr)) {
188 Serial.print("Total number of sensors found: ");
189 Serial.println(numSensors);
191 if (numSensors == 0) {
193 "No sensors found, please check connections and restart the Arduino.");
194 while (true) { delay(10); } // do nothing forever
199 "Time Elapsed (s), Sensor Address, Est Measurement Time (s), Number Measurements, "
200 "Real Measurement Time (ms), Measurement 1, Measurement 2, ... etc.");
202 "-------------------------------------------------------------------------------");
206 // measure one at a time
207 for (byte i = firstAddress; i < lastAddress; i++) {
208 char addr = decToChar(i);
210 // Serial.print(millis() / 1000);
211 Serial.print(millis());
213 getContinuousResults(addr, 4);
218 delay(5000L); // wait ten seconds between measurement attempts.