This advanced example uses the polling API for acknowledgement, identification, a CRC-requesting normal measurement, and complete data retrieval. It also makes one intentionally undersized data request to show that the recorder reports RESULT_DATA_BUFFER_TOO_SMALL without transmitting or discarding the retained measurement context.
The caller-owned data array remains in scope for the entire asynchronous data operation, and SDI12Recorder::update() is called on every pass through loop().
PlatformIO Configuration
1; PlatformIO Project Configuration File
4description = SDI-12 Library Example N: Non-Blocking Measurement
5src_dir = .piolibdeps/Arduino-SDI-12_ID1486/examples/n_non_blocking_measurement
The Complete Example
2 * @example{lineno} n_non_blocking_measurement.ino
3 * @copyright Stroud Water Research Center
4 * @license This example is published under the BSD-3 license.
5 * @author Codex, at instruction of Sara Geleskie Damiano <sdamiano@stroudcenter.org>
7 * @brief Example N: Advanced non-blocking measurement workflow.
9 * This example acknowledges and identifies one sensor, requests a CRC measurement,
10 * demonstrates recovery from an undersized data buffer, and retrieves every value.
11 * No recorder operation blocks the loop; update() advances the active transaction.
14#include <SDI12Config.h>
15#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && !defined(SDI12_INTERNAL_PCINT)
16#include <EnableInterrupt.h>
19#include <SDI12Recorder.h>
22#define SDI12_DATA_PIN 7
24#ifndef SDI12_POWER_PIN
25#define SDI12_POWER_PIN 22
27#ifndef SDI12_TERMINAL_BAUD
28#define SDI12_TERMINAL_BAUD 115200
31const int8_t dataPin = SDI12_DATA_PIN;
32const int8_t powerPin = SDI12_POWER_PIN;
33const uint32_t serialBaud = SDI12_TERMINAL_BAUD;
34const char sensorAddress = '0';
35const bool useCRC = true;
37SDI12 mySDI12(dataPin);
38SDI12Recorder mySDI12Recorder(mySDI12);
42enum WorkflowStage : uint8_t {
43 START_ACKNOWLEDGEMENT,
56WorkflowStage stage = START_ACKNOWLEDGEMENT;
57WorkflowStage restartStage = START_MEASUREMENT;
58uint32_t measurementEnd = 0U;
60void printFailure(const __FlashStringHelper* operation,
61 WorkflowStage stageAfterWait = START_MEASUREMENT) {
62 Serial.print(operation);
63 Serial.print(F(" failed: "));
64 mySDI12Recorder.printRecorderResult(Serial);
66 measurementEnd = millis();
67 restartStage = stageAfterWait;
68 stage = WAIT_NEXT_MEASUREMENT;
72 Serial.begin(serialBaud);
73 while (!Serial && millis() < 10000UL);
76 pinMode(powerPin, OUTPUT);
77 digitalWrite(powerPin, HIGH);
83 Serial.println(F("Starting the non-blocking recorder workflow."));
87 mySDI12Recorder.update();
90 case START_ACKNOWLEDGEMENT:
91 mySDI12Recorder.startRequestAcknowledgement(sensorAddress);
92 stage = WAIT_ACKNOWLEDGEMENT;
95 case WAIT_ACKNOWLEDGEMENT:
96 if (mySDI12Recorder.isBusy()) { break; }
97 if (mySDI12Recorder.result() != SDI12Recorder::RESULT_SUCCESS) {
98 printFailure(F("Acknowledgement"), START_ACKNOWLEDGEMENT);
101 Serial.println(F("Sensor acknowledged."));
102 stage = START_IDENTIFICATION;
105 case START_IDENTIFICATION:
106 mySDI12Recorder.startIdentify(sensorAddress);
107 stage = WAIT_IDENTIFICATION;
110 case WAIT_IDENTIFICATION:
111 if (mySDI12Recorder.isBusy()) { break; }
112 if (mySDI12Recorder.result() != SDI12Recorder::RESULT_SUCCESS) {
113 printFailure(F("Identification"), START_IDENTIFICATION);
116 mySDI12Recorder.printSensorInfo(mySDI12Recorder.identification(), Serial);
117 restartStage = START_MEASUREMENT;
118 stage = START_MEASUREMENT;
121 case START_MEASUREMENT:
122 mySDI12Recorder.startMeasurement(sensorAddress, 0U, useCRC);
123 stage = WAIT_MEASUREMENT;
126 case WAIT_MEASUREMENT:
127 if (mySDI12Recorder.isBusy()) { break; }
128 if (mySDI12Recorder.result() != SDI12Recorder::RESULT_SUCCESS) {
129 printFailure(F("Measurement"));
132 Serial.print(F("Sensor advertised "));
133 Serial.print(mySDI12Recorder.expectedValueCount());
134 Serial.println(F(" values."));
135 stage = mySDI12Recorder.expectedValueCount() == 0U ? START_DATA
136 : START_CAPACITY_CHECK;
139 case START_CAPACITY_CHECK:
140 // This local error does not transmit and leaves the measurement context intact.
141 mySDI12Recorder.requestData(sensorAddress, values,
142 mySDI12Recorder.expectedValueCount() - 1U);
143 stage = WAIT_CAPACITY_CHECK;
146 case WAIT_CAPACITY_CHECK:
147 if (mySDI12Recorder.isBusy()) { break; }
148 if (mySDI12Recorder.result() == SDI12Recorder::RESULT_DATA_BUFFER_TOO_SMALL) {
149 Serial.println(F("The intentional capacity error was reported correctly."));
151 printFailure(F("Capacity check"));
158 mySDI12Recorder.requestData(sensorAddress, values, 9U);
163 if (mySDI12Recorder.isBusy()) { break; }
164 if (mySDI12Recorder.result() != SDI12Recorder::RESULT_SUCCESS) {
165 printFailure(F("Data retrieval"));
168 for (size_t i = 0U; i < mySDI12Recorder.dataValueCount(); ++i) {
169 Serial.print(F("Value "));
170 Serial.print(i + 1U);
171 Serial.print(F(": "));
172 Serial.println(values[i], 7);
174 measurementEnd = millis();
175 stage = WAIT_NEXT_MEASUREMENT;
178 case WAIT_NEXT_MEASUREMENT:
179 if (millis() - measurementEnd >= 10000UL) { stage = restartStage; }