This is very similar to example D - finding all attached sensors and logging data from them. Unlike example D, however, which waits for each sensor to complete a measurement, this asks all sensors to take measurements concurrently and then waits until each is finished to query for results. This can be much faster than waiting for each sensor when you have multiple sensor attached.
PlatformIO Configuration
1; PlatformIO Project Configuration File
4description = SDI-12 Library Example K: Using Concurrent Measurements
5src_dir = .piolibdeps/Arduino-SDI-12_ID1486/examples/k_concurrent_logger
The Complete Example
2 * @example{lineno} k_concurrent_logger.ino
3 * @copyright Stroud Water Research Center
4 * @license This example is published under the BSD-3 license.
5 * @author Sara Geleskie Damiano <sdamiano@stroudcenter.org>
7 * @brief Example K: Concurrent Measurements
9 * This is very similar to example B - finding all attached sensors and logging data
10 * from them. Unlike example B, however, which waits for each sensor to complete a
11 * measurement, this asks all sensors to take measurements concurrently and then waits
12 * until each is finished to query for results. This can be much faster than waiting for
13 * each sensor when you have multiple sensor attached.
18/* connection information */
19uint32_t serialBaud = 115200; /*!< The baud rate for the output serial port */
20int8_t dataPin = 7; /*!< The pin of the SDI-12 data bus */
21int8_t powerPin = 22; /*!< The sensor power pin (or -1 if not switching power) */
22int8_t firstAddress = 0; /* The first address in the address space to check (0='0') */
23int8_t lastAddress = 62; /* The last address in the address space to check (62='z') */
25/** Define the SDI-12 bus */
26SDI12 mySDI12(dataPin);
28// keeps track of active addresses
31// keeps track of the wait time for each active addresses
32uint8_t meas_time_ms[64];
34// keeps track of the time each sensor was started
35uint32_t millisStarted[64];
37// keeps track of the time each sensor will be ready
38uint32_t millisReady[64];
40// keeps track of the number of results expected
41uint8_t expectedResults[64];
43// keeps track of the number of results returned
44uint8_t returnedResults[64];
46uint8_t numSensors = 0;
49 * @brief converts allowable address characters ('0'-'9', 'a'-'z', 'A'-'Z') to a
50 * decimal number between 0 and 61 (inclusive) to cover the 62 possible
53byte charToDec(char i) {
54 if ((i >= '0') && (i <= '9')) return i - '0';
55 if ((i >= 'a') && (i <= 'z')) return i - 'a' + 10;
56 if ((i >= 'A') && (i <= 'Z'))
63 * @brief maps a decimal number between 0 and 61 (inclusive) to allowable
64 * address characters '0'-'9', 'a'-'z', 'A'-'Z',
66 * THIS METHOD IS UNUSED IN THIS EXAMPLE, BUT IT MAY BE HELPFUL.
68char decToChar(byte i) {
69 if (i < 10) return i + '0';
70 if ((i >= 10) && (i < 36)) return i + 'a' - 10;
71 if ((i >= 36) && (i <= 62))
77bool getResults(char address, int resultsExpected) {
78 uint8_t resultsReceived = 0;
79 uint8_t cmd_number = 0;
80 while (resultsReceived < resultsExpected && cmd_number <= 9) {
85 command += cmd_number;
86 command += "!"; // SDI-12 command to get data [address][D][dataOption][!]
87 mySDI12.sendCommand(command);
89 uint32_t start = millis();
90 while (mySDI12.available() < 3 && (millis() - start) < 1500) {}
91 mySDI12.read(); // ignore the repeated SDI12 address
92 char c = mySDI12.peek(); // check if there's a '+' and toss if so
93 if (c == '+') { mySDI12.read(); }
95 while (mySDI12.available()) {
96 char c = mySDI12.peek();
97 if (c == '-' || (c >= '0' && c <= '9') || c == '.') {
98 float result = mySDI12.parseFloat(SKIP_NONE);
99 Serial.print(String(result, 10));
100 if (result != -9999) { resultsReceived++; }
101 } else if (c == '+') {
107 delay(10); // 1 character ~ 7.5ms
109 if (resultsReceived < resultsExpected) { Serial.print(", "); }
112 mySDI12.clearBuffer();
113 returnedResults[charToDec(address)] = resultsReceived;
114 return resultsReceived == resultsExpected;
117int startConcurrentMeasurement(char i, String meas_type = "") {
118 mySDI12.clearBuffer();
122 command += meas_type;
123 command += "!"; // SDI-12 concurrent measurement command format [address]['C'][!]
124 mySDI12.sendCommand(command);
127 // wait for acknowlegement with format [address][ttt (3 char, seconds)][number of
128 // measurments available, 0-9]
129 String sdiResponse = mySDI12.readStringUntil('\n');
132 // find out how long we have to wait (in seconds).
133 uint8_t wait = sdiResponse.substring(1, 4).toInt();
135 // Set up the number of results to expect
136 int numResults = sdiResponse.substring(4).toInt();
138 uint8_t sensorNum = charToDec(i); // e.g. convert '0' to 0, 'a' to 10, 'Z' to 61.
139 meas_time_ms[sensorNum] = wait;
140 millisStarted[sensorNum] = millis();
142 millisReady[sensorNum] = millis();
144 millisReady[sensorNum] = millis() + wait * 1000;
146 expectedResults[sensorNum] = numResults;
151// this checks for activity at a particular address
152// expects a char, '0'-'9', 'a'-'z', or 'A'-'Z'
153boolean checkActive(char i) {
154 String myCommand = "";
156 myCommand += (char)i; // sends basic 'acknowledge' command [address][!]
159 for (int j = 0; j < 3; j++) { // goes through three rapid contact attempts
160 mySDI12.sendCommand(myCommand);
162 if (mySDI12.available()) { // If we here anything, assume we have an active sensor
163 mySDI12.clearBuffer();
167 mySDI12.clearBuffer();
172 * @brief gets identification information from a sensor, and prints it to the serial
175 * @param i a character between '0'-'9', 'a'-'z', or 'A'-'Z'.
176 * @param printCommands true to print the raw output and input from the command
178void printInfo(char i) {
182 mySDI12.sendCommand(command);
185 String sdiResponse = mySDI12.readStringUntil('\n');
187 // allccccccccmmmmmmvvvxxx...xx<CR><LF>
188 Serial.print("Address: ");
189 Serial.print(sdiResponse.substring(0, 1)); // address
190 Serial.print(", SDI-12 Version: ");
191 Serial.print(sdiResponse.substring(1, 3).toFloat() / 10); // SDI-12 version number
192 Serial.print(", Vendor ID: ");
193 Serial.print(sdiResponse.substring(3, 11)); // vendor id
194 Serial.print(", Sensor Model: ");
195 Serial.print(sdiResponse.substring(11, 17)); // sensor model
196 Serial.print(", Sensor Version: ");
197 Serial.print(sdiResponse.substring(17, 20)); // sensor version
198 Serial.print(", Sensor ID: ");
199 Serial.print(sdiResponse.substring(20)); // sensor id
204 Serial.begin(serialBaud);
208 Serial.println("Opening SDI-12 bus...");
210 delay(500); // allow things to settle
212 Serial.println("Timeout value: ");
213 Serial.println(mySDI12.TIMEOUT);
215 // Power the sensors;
217 Serial.println("Powering up sensors, wait...");
218 pinMode(powerPin, OUTPUT);
219 digitalWrite(powerPin, HIGH);
223 // Quickly Scan the Address Space
224 Serial.println("Scanning all addresses, please wait...");
225 Serial.println("Protocol Version, Sensor Address, Sensor Vendor, Sensor Model, "
226 "Sensor Version, Sensor ID");
228 for (int8_t i = firstAddress; i <= lastAddress; i++) {
229 char addr = decToChar(i);
230 if (checkActive(addr)) {
237 Serial.print("Total number of sensors found: ");
238 Serial.println(numSensors);
240 if (numSensors == 0) {
242 "No sensors found, please check connections and restart the Arduino.");
243 while (true) { delay(10); } // do nothing forever
247 Serial.println("Time Elapsed (s), Measurement 1, Measurement 2, ... etc.");
249 "-------------------------------------------------------------------------------");
253 // start all sensors measuring concurrently
254 for (int8_t i = firstAddress; i <= lastAddress; i++) {
255 char addr = decToChar(i);
256 if (isActive[i]) { startConcurrentMeasurement(addr); }
260 uint8_t numReadingsRecorded = 0;
262 for (int8_t i = firstAddress; i <= lastAddress; i++) {
263 char addr = decToChar(i);
264 if (isActive[i] && millis() > millisReady[i] && expectedResults[i] > 0 &&
265 (returnedResults[i] < expectedResults[i])) {
266 Serial.print(millis() / 1000);
270 getResults(addr, expectedResults[i]);
271 numReadingsRecorded++;
275 } while (numReadingsRecorded < numSensors);
277 delay(10000); // wait ten seconds between measurement attempts.