2 * @example{lineno} TestCommands.ino
3 * @copyright Stroud Water Research Center
4 * @license This example is published under the BSD-3 license.
5 * @author Sara Damiano <sdamiano@stroudcenter.org>
11#define SDI12_DATA_PIN 7
13#ifndef SDI12_POWER_PIN
14#define SDI12_POWER_PIN 22
17// #define TEST_PRINT_ARRAY
19/* connection information */
21uint32_t serialBaud = 921600; /*!< The baud rate for the output serial port */
23uint32_t serialBaud = 115200; /*!< The baud rate for the output serial port */
25int8_t dataPin = SDI12_DATA_PIN; /*!< The pin of the SDI-12 data bus */
26int8_t powerPin = SDI12_POWER_PIN; /*!< The sensor power pin (or -1) */
27uint32_t wake_delay = 10; /*!< Extra time needed for the sensor to wake (0-100ms) */
28const int8_t firstAddress =
29 0; /* The first address in the address space to check (0='0') */
30const int8_t lastAddress =
31 61; /* The last address in the address space to check (61='z') */
32const int8_t commandsToTest =
33 1; /*!< The number of measurement commands to test, between 1 and 11. */
35/** Define the SDI-12 bus */
36SDI12 mySDI12(dataPin);
38/** Define some testing specs */
39const int8_t n_addresses = (lastAddress - firstAddress) + 1;
41/** Error codes, if returned */
42int8_t error_result_number = 7;
43float no_error_value = 0;
45/// variable that alternates output type back and forth between parsed and raw
48String commands[] = {"", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
50// keeps track of active addresses
51bool isActive[n_addresses];
53// keeps track of the wait time for each active addresses
54uint32_t meas_time_ms[n_addresses];
56// keeps track of the time each sensor was started
57uint32_t millisStarted[n_addresses];
59// keeps track of the time each sensor will be ready
60uint32_t millisReady[n_addresses];
62// keeps track of the number of results expected
63uint8_t expectedResults[n_addresses];
65// keeps track of the number of results returned
66uint8_t returnedResults[n_addresses];
68String prev_result[n_addresses];
69String this_result[n_addresses];
70uint8_t numSensors = 0;
72struct startMeasurementResult { // Structure declaration
73 String returnedAddress;
78struct getResultsResult { // Structure declaration
79 uint8_t resultsReceived;
80 uint8_t maxDataCommand;
88 * @brief converts allowable address characters ('0'-'9', 'a'-'z', 'A'-'Z') to a
89 * decimal number between 0 and 61 (inclusive) to cover the 62 possible
92byte charToDec(char i) {
93 if ((i >= '0') && (i <= '9')) return i - '0';
94 if ((i >= 'a') && (i <= 'z')) return i - 'a' + 10;
95 if ((i >= 'A') && (i <= 'Z'))
102 * @brief maps a decimal number between 0 and 61 (inclusive) to allowable
103 * address characters '0'-'9', 'a'-'z', 'A'-'Z',
105 * THIS METHOD IS UNUSED IN THIS EXAMPLE, BUT IT MAY BE HELPFUL.
107char decToChar(byte i) {
108 if (i < 10) return i + '0';
109 if ((i >= 10) && (i < 36)) return i + 'a' - 10;
110 if ((i >= 36) && (i <= 62))
117 * @brief gets identification information from a sensor, and prints it to the serial
120 * @param i a character between '0'-'9', 'a'-'z', or 'A'-'Z'.
121 * @param printIO true to print the raw output and input from the command
123bool printInfo(char address, bool printIO = true) {
125 command += (char)address;
127 mySDI12.sendCommand(command, wake_delay);
130 Serial.println(command);
134 String sdiResponse = mySDI12.readStringUntil('\n');
136 // allccccccccmmmmmmvvvxxx...xx<CR><LF>
139 Serial.println(sdiResponse);
142 Serial.print("Address: ");
143 Serial.print(sdiResponse.substring(0, 1)); // address
144 Serial.print(", SDI-12 Version: ");
145 Serial.print(sdiResponse.substring(1, 3).toFloat() / 10); // SDI-12 version number
146 Serial.print(", Vendor ID: ");
147 Serial.print(sdiResponse.substring(3, 11)); // vendor id
148 Serial.print(", Sensor Model: ");
149 Serial.print(sdiResponse.substring(11, 17)); // sensor model
150 Serial.print(", Sensor Version: ");
151 Serial.print(sdiResponse.substring(17, 20)); // sensor version
152 Serial.print(", Sensor ID: ");
153 Serial.print(sdiResponse.substring(20)); // sensor id
156 if (sdiResponse.length() < 3) { return false; };
160getResultsResult getResults(char address, int resultsExpected, bool verify_crc = false,
161 bool printIO = true) {
162 uint8_t resultsReceived = 0;
163 uint8_t cmd_number = 0;
164 uint8_t cmd_retries = 0;
166 // From SDI-12 Protocol v1.4, Section 4.4 SDI-12 Commands and Responses:
167 // The maximum number of characters that can be returned in the <values> part of the
168 // response to a D command is either 35 or 75. If the D command is issued to
169 // retrieve data in response to a concurrent measurement command, or in response to
170 // a high-volume ASCII measurement command, the maximum is 75. The maximum is also
171 // 75 in response to a continuous measurement command. Otherwise, the maximum is 35.
172 int max_sdi_response = 76;
173 // From SDI-12 Protocol v1.4, Table 11 The send data command (aD0!, aD1! . . . aD9!):
174 // - the maximum number of digits for a data value is 7, even without a decimal point
175 // - the minimum number of digits for a data value (excluding the decimal point) is 1
176 // - the maximum number of characters in a data value is 9 (the (polarity sign + 7
177 // digits + the decimal point))
178 // - SRGD Note: The polarity symbol (+ or -) acts as a delimeter between the numeric
180 int max_sdi_digits = 10;
182 String compiled_response = "";
186 // Create the return struct
187 getResultsResult return_result;
188 return_result.resultsReceived = 0;
189 return_result.maxDataCommand = 0;
190 return_result.addressMatch = true;
191 return_result.crcMatch = true;
192 return_result.errorCode = false;
193 return_result.success = true;
195 while (resultsReceived < resultsExpected && cmd_number <= 9 && cmd_retries < 5) {
196 bool gotResults = false;
197 uint8_t cmd_results = 0;
199 // Assemble the command based on how many commands we've already sent,
200 // starting with D0 and ending with D9
201 // SDI-12 command to get data [address][D][dataOption][!]
202 mySDI12.clearBuffer();
206 command += cmd_number;
208 mySDI12.sendCommand(command, wake_delay);
212 Serial.println(command);
214 char resp_buffer[max_sdi_response] = {'\0'};
216 // read bytes into the char array until we get to a new line (\r\n)
217 size_t bytes_read = mySDI12.readBytesUntil('\n', resp_buffer, max_sdi_response);
218 // Serial.print(bytes_read);
219 // Serial.println(" characters");
221 size_t data_bytes_read = bytes_read - 1; // subtract one for the /r before the /n
222 String sdiResponse = String(resp_buffer);
223 compiled_response += sdiResponse;
227 Serial.println(sdiResponse);
228 // Serial.println(sdiResponse.length());
229 // Serial.print("<<<");
230 // Serial.println(resp_buffer);
231 // Serial.println(strnlen(resp_buffer, max_sdi_response));
233 // read and clear anything else from the buffer
235 while (mySDI12.available()) {
236 Serial.write(mySDI12.read());
239 if (extra_chars > 0) {
240 Serial.print(extra_chars);
241 Serial.println(" additional characters received.");
243 mySDI12.clearBuffer();
245 // check the crc, break if it's incorrect
247 bool crcMatch = mySDI12.verifyCRC(sdiResponse);
248 // subtract the 3 characters of the CRC from the total number of data values
249 data_bytes_read = data_bytes_read - 3;
251 if (printIO) { Serial.println("CRC valid"); }
253 if (printIO) { Serial.println("CRC check failed!"); }
254 return_result.crcMatch = false;
256 // if we failed CRC in the response, add one to the retry
257 // attempts but do not bump up the command number or transfer any
258 // results because we want to retry the same data command to try get
261 // stop processing; no reason to read the numbers when we already know
267 // check the address, break if it's incorrect
268 // NOTE: If the address is wrong because the response is garbled, the CRC check
269 // above should fail. But we still verify the address in case we're not checking the
270 // CRC or we got a well formed response from the wrong sensor.
271 char returnedAddress = resp_buffer[0];
272 if (returnedAddress != address) {
274 Serial.println("Wrong address returned!");
275 Serial.print("Expected ");
276 Serial.print(String(address));
277 Serial.print(" Got ");
278 Serial.println(String(returnedAddress));
279 Serial.println(String(resp_buffer));
282 return_result.addressMatch = false;
283 // if we didn't get the correct address, add one to the retry
284 // attempts but do not bump up the command number or transfer any
285 // results because we want to retry the same data command to try get
288 // stop processing; no reason to read the numbers when we already know
293 bool bad_read = false;
294 char float_buffer[max_sdi_digits] = {'\0'};
295 bool got_decimal = false;
296 char* dec_pl = float_buffer; // just used for pretty printing
297 uint8_t fb_pos = 0; // start at start of buffer
298 // iterate through the char array and to check results
299 // NOTE: start at 1 since we already looked at the address!
300 for (size_t i = 1; i <= data_bytes_read; i++) {
301 // Get the character at position
302 char c = resp_buffer[i];
304 // Serial.print(" of ");
305 // Serial.print(data_bytes_read);
306 // Serial.print(" '");
308 // Serial.println("'");
309 // if we get a polarity sign (+ or -) that is not the first character after the
310 // address, or we've reached the end of the buffer, then we're at the end of the
311 // previous number and can parse the float buffer
312 if ((((c == '-' || c == '+') && i != 1) || i == data_bytes_read) &&
313 strnlen(float_buffer, max_sdi_digits) > 0) {
314 float result = atof(float_buffer);
316 Serial.print("Result ");
317 Serial.print(resultsReceived);
318 Serial.print(", Raw value: ");
319 Serial.print(float_buffer);
320 dec_pl = strchr(float_buffer, '.');
321 // NOTE: This bit below is just for pretty-printing
322 size_t len_post_dec = 0;
323 if (dec_pl != nullptr) { len_post_dec = strnlen(dec_pl, max_sdi_digits) - 1; }
324 Serial.print(", Len after decimal: ");
325 Serial.print(len_post_dec);
326 Serial.print(", Parsed value: ");
327 Serial.println(String(result, len_post_dec));
329 // add how many results we have
330 if (result != -9999) {
334 // check for a failure error code at the end
335 if (error_result_number >= 1) {
336 if (resultsReceived == error_result_number && result != no_error_value) {
338 return_result.errorCode = true;
340 Serial.print("Got a failure code of ");
341 Serial.println(String(result, strnlen(dec_pl, max_sdi_digits) - 1));
345 // empty the float buffer so it's ready for the next number
346 float_buffer[0] = '\0';
350 if (i == data_bytes_read) { continue; }
351 // if we're mid-number and there's a digit, a decimal, or a negative sign in the
352 // sdi12 response buffer, add it to the current float buffer
353 if (c == '-' || (c >= '0' && c <= '9') || (c == '.' && !got_decimal)) {
354 float_buffer[fb_pos] = c;
356 float_buffer[fb_pos] = '\0'; // null terminate the buffer
357 // Serial.print("Added to float buffer, currently: '");
358 // Serial.print(float_buffer);
359 // Serial.print("' (");
360 // Serial.print(strnlen(float_buffer, max_sdi_digits));
361 // Serial.println(")");
362 } else if (c == '+') {
363 // if we get a "+", it's a valid SDI-12 polarity indicator, but not something
364 // accepted by atof in parsing the float, so we just ignore it
365 // NOTE: A mis-read like this should also cause the CRC to be wrong, but still
366 // check here in case we're not using a CRC.
367 } else { //(c != '-' && c != '+' && (c < '0' || c > '9') && c != '.')
368 Serial.print("Invalid data response character: ");
373 // if we get a decimal, mark it so we can verify we don't get repeated decimals
374 if (c == '.') { got_decimal = true; }
377 // if (!gotResults) {
379 // Serial.println((" No results received, will not continue requests!"));
382 // } // don't do another loop if we got nothing
384 if (gotResults && !bad_read) {
385 resultsReceived = resultsReceived + cmd_results;
387 Serial.print(F(" Total Results Received: "));
388 Serial.print(resultsReceived);
389 Serial.print(F(", Remaining: "));
390 Serial.println(resultsExpected - resultsReceived);
394 // if we got a bad charater in the response, add one to the retry
395 // attempts but do not bump up the command number or transfer any
396 // results because we want to retry the same data command to try get
400 mySDI12.clearBuffer();
404 Serial.print("After ");
405 Serial.print(cmd_number);
406 Serial.print(" data commands got ");
407 Serial.print(resultsReceived);
408 Serial.print(" results of the expected ");
409 Serial.print(resultsExpected);
410 Serial.print(" expected. This is a ");
411 Serial.println(resultsReceived == resultsExpected ? "success." : "failure.");
414 success &= resultsReceived == resultsExpected;
415 this_result[charToDec(address) - firstAddress] = compiled_response;
416 return_result.resultsReceived = resultsReceived;
417 return_result.maxDataCommand = cmd_number;
418 return_result.success = success;
419 return return_result;
422bool getContinuousResults(char address, int resultsExpected, bool printIO = true) {
423 uint8_t resultsReceived = 0;
424 uint8_t cmd_number = 0;
425 while (resultsReceived < resultsExpected && cmd_number <= 9) {
429 command += cmd_number;
430 command += "!"; // SDI-12 command to get data [address][D][dataOption][!]
431 mySDI12.sendCommand(command, wake_delay);
434 Serial.println(command);
437 uint32_t start = millis();
438 while (mySDI12.available() < 3 && (millis() - start) < 1500) {};
441 Serial.write(mySDI12.read()); // ignore the repeated SDI12 address
444 while (mySDI12.available()) {
445 char c = mySDI12.peek();
446 if (c == '-' || c == '+' || (c >= '0' && c <= '9') || c == '.') {
447 float result = mySDI12.parseFloat();
448 Serial.print(String(result, 7));
449 if (result != -9999) { resultsReceived++; }
450 } else if (c >= 0 && c != '\r' && c != '\n') {
451 Serial.write(mySDI12.read());
455 delay(10); // 1 character ~ 7.5ms
458 Serial.print("Total Results Received: ");
459 Serial.print(resultsReceived);
460 Serial.print(", Remaining: ");
461 Serial.println(resultsExpected - resultsReceived);
463 if (!resultsReceived) { break; } // don't do another loop if we got nothing
466 mySDI12.clearBuffer();
468 return resultsReceived == resultsExpected;
471startMeasurementResult startMeasurement(char address, bool is_concurrent = false,
472 bool request_crc = false, String meas_type = "",
473 bool printIO = true) {
474 // Create the return struct
475 startMeasurementResult return_result;
476 return_result.returnedAddress = "";
477 return_result.meas_time_s = 0;
478 return_result.numberResults = 0;
481 command += address; // All commands start with the address
482 command += is_concurrent ? "C" : "M"; // C for concurrent, M for standard
483 command += request_crc ? "C" : ""; // add an additional C to request a CRC
484 command += meas_type; // Measurement type, "" or 0-9
485 command += "!"; // All commands end with "!"
486 mySDI12.sendCommand(command, wake_delay);
489 Serial.println(command);
493 // wait for acknowledgement with format [address][ttt (3 char, seconds)][number of
494 // measurements available, 0-9]
495 String sdiResponse = mySDI12.readStringUntil('\n');
499 Serial.println(sdiResponse);
501 mySDI12.clearBuffer();
503 // check the address, return if it's incorrect
504 String returnedAddress = sdiResponse.substring(0, 1);
505 char ret_addr_array[2] = {'\0'};
506 returnedAddress.toCharArray(ret_addr_array, sizeof(ret_addr_array));
507 return_result.returnedAddress = ret_addr_array[0];
508 if (returnedAddress != String(address)) {
510 Serial.println("Wrong address returned!");
511 Serial.print("Expected ");
512 Serial.print(String(address));
513 Serial.print(" Got ");
514 Serial.println(returnedAddress);
516 return return_result;
519 // find out how long we have to wait (in seconds).
520 uint8_t meas_time_s = sdiResponse.substring(1, 4).toInt();
521 return_result.meas_time_s = meas_time_s;
523 Serial.print("expected measurement time: ");
524 Serial.print(meas_time_s);
525 Serial.print(" s, ");
528 // Set up the number of results to expect
529 int numResults = sdiResponse.substring(4).toInt();
530 return_result.numberResults = numResults;
532 Serial.print("Number Results: ");
533 Serial.println(numResults);
536 return return_result;
539// This is a separate function in this example so the wait times can all be filled into
540// the appropriate arrays
541int startConcurrentMeasurement(char address, bool request_crc = false,
542 String meas_type = "", bool printIO = true) {
543 startMeasurementResult startResult = startMeasurement(address, true, request_crc,
546 uint8_t sensorNum = charToDec(address - firstAddress);
547 meas_time_ms[sensorNum] = (static_cast<uint32_t>(startResult.meas_time_s)) * 1000;
548 millisStarted[sensorNum] = millis();
549 if (startResult.meas_time_s == 0) {
550 millisReady[sensorNum] = millis();
552 // give an extra second
553 // millisReady[sensorNum] = millis() + meas_time_ms[sensorNum] + 1000;
554 // subtract a second to start polling early
555 millisReady[sensorNum] = millis() + meas_time_ms[sensorNum] - 1000;
557 expectedResults[sensorNum] = startResult.numberResults;
559 return startResult.numberResults;
562uint32_t takeMeasurement(char address, bool request_crc = false, String meas_type = "",
563 bool printIO = true) {
564 startMeasurementResult startResult = startMeasurement(address, false, request_crc,
566 if (startResult.numberResults == 0) { return -1; }
568 uint32_t timerStart = millis();
569 uint32_t measTime = -1;
570 // wait up to 1 second longer than the specified return time
571 while ((millis() - timerStart) <
572 (static_cast<uint32_t>(startResult.meas_time_s) + 1) * 1000) {
573 if (mySDI12.available()) {
575 } // sensor can interrupt us to let us know it is done early
577 measTime = millis() - timerStart;
578 String interrupt_response = mySDI12.readStringUntil('\n');
581 Serial.println(interrupt_response);
582 Serial.print("Completed after ");
583 Serial.print(measTime);
584 Serial.println(" ms");
587 // if we got results, return the measurement time, else -1
588 if (getResults(address, startResult.numberResults, request_crc, printIO).success) {
595// this checks for activity at a particular address
596// expects a char, '0'-'9', 'a'-'z', or 'A'-'Z'
597bool checkActive(char address, int8_t numPings = 3, bool printIO = true) {
598 mySDI12.clearBuffer();
600 command += (char)address; // sends basic 'acknowledge' command [address][!]
603 for (int j = 0; j < numPings; j++) { // goes through rapid contact attempts
606 Serial.println(command);
608 mySDI12.sendCommand(command, wake_delay);
611 // the sensor should just return its address followed by '\r\n'
612 if (mySDI12.available()) {
613 String sdiResponse_r = mySDI12.readStringUntil('\n');
614 String sdiResponse = sdiResponse_r;
615 sdiResponse_r.replace("\r", "←");
616 sdiResponse_r.replace("\n", "↓");
618 Serial.print("<<< '");
619 Serial.print(sdiResponse_r);
621 Serial.print(sdiResponse_r.length());
625 sdiResponse.replace("\r", "←");
626 sdiResponse.replace("\n", "↓");
628 Serial.print("<<< Trimmed: '");
629 Serial.print(sdiResponse);
631 Serial.print(sdiResponse.length());
634 mySDI12.clearBuffer();
636 // check the address, return false if it's incorrect
637 String returnedAddress = sdiResponse.substring(0, 1);
638 Serial.print("returnedAddress '");
639 Serial.print(returnedAddress);
641 Serial.print(returnedAddress.length());
643 if (returnedAddress == String(address)) {
645 Serial.print("Got response from '");
646 Serial.print(String(returnedAddress));
652 Serial.println("Wrong address returned!");
653 Serial.print("Expected '");
654 Serial.print(String(address));
655 Serial.print("' Got '");
656 Serial.print(returnedAddress);
658 // Serial.println(sdiResponse);
663 mySDI12.clearBuffer();
668 Serial.begin(serialBaud);
669 while (!Serial && millis() < 10000L);
670 char tbuf[3] = {'\0'};
672 Serial.print("Opening SDI-12 bus on pin ");
673 Serial.print(dataPin);
675 Serial.print(itoa(dataPin, tbuf, 10));
677 Serial.println("...");
679 delay(500); // allow things to settle
681 Serial.println("Timeout value: ");
682 Serial.println(mySDI12.TIMEOUT);
684 // Fill arrays with 0's
685 for (int8_t address_number = firstAddress; address_number <= lastAddress;
687 int8_t pos = address_number - firstAddress;
688 isActive[pos] = false;
689 meas_time_ms[pos] = 0;
690 millisStarted[pos] = 0;
691 millisReady[pos] = 0;
692 expectedResults[pos] = 0;
693 returnedResults[pos] = 0;
694 prev_result[pos] = "";
695 this_result[pos] = "";
698 // Power the sensors;
700 Serial.print("Powering up sensors with pin ");
701 Serial.print(String(powerPin));
702 Serial.println(", wait 10s...");
703 pinMode(powerPin, OUTPUT);
704 digitalWrite(powerPin, HIGH);
707 Serial.println("Wait 5s...");
711 // Quickly scan the address space
712 Serial.println("\n\nScanning all addresses, please wait...");
714 for (int8_t address_number = firstAddress; address_number <= lastAddress;
716 int8_t pos = address_number - firstAddress;
717 char address = decToChar(address_number);
719 Serial.print(address_number);
720 Serial.print(", address: ");
721 Serial.print(address);
722 Serial.print(", reversed: ");
723 Serial.println(charToDec(address));
724 if (checkActive(address, 5, true)) {
727 // Serial.println(", +");
728 printInfo(address, true);
730 // Serial.println(", -");
733 Serial.print("Total number of sensors found: ");
734 Serial.println(numSensors);
736 if (numSensors == 0) {
738 "No sensors found, please check connections and restart the Arduino.");
739 while (true) { delay(10); } // do nothing forever
743 Serial.println("-------------------------------------------------------------------"
745 Serial.println("Wait 10s...");
748 Serial.println("-------------------------------------------------------------------"
753 flip = !flip; // flip the switch between concurrent and not
754 Serial.print("Starting ");
755 Serial.print(flip ? "concurrent" : "individual");
758 uint32_t start = millis();
759 // Serial.print("Flip: ");
760 // Serial.println(flip);
762 // Fill arrays with 0's
763 for (int8_t address_number = firstAddress; address_number <= lastAddress;
765 int8_t pos = address_number - firstAddress;
766 meas_time_ms[pos] = 0;
767 millisStarted[pos] = 0;
768 millisReady[pos] = 0;
769 expectedResults[pos] = 0;
770 returnedResults[pos] = 0;
774 // measure one at a time
775 for (int8_t address_number = firstAddress; address_number <= lastAddress;
777 int8_t pos = address_number - firstAddress;
778 char address = decToChar(address_number);
780 for (uint8_t a = 0; a < commandsToTest; a++) {
781 takeMeasurement(address, true, commands[a], true);
784 // getContinuousResults(address, 3);
786 Serial.print("Address ");
787 Serial.print(address);
788 Serial.println(" is not active");
791 Serial.print("Total Time for Individual Measurements: ");
792 Serial.println(millis() - start);
794 for (uint8_t a = 0; a < commandsToTest; a++) {
795 uint32_t min_wait = 60000L;
796 uint32_t max_wait = 0;
797 uint32_t for_start = millis();
798 // start all sensors measuring concurrently
799 for (int8_t address_number = firstAddress; address_number <= lastAddress;
801 int8_t pos = address_number - firstAddress;
802 char address = decToChar(address_number);
804 startConcurrentMeasurement(address, true, commands[a], true);
805 if (meas_time_ms[pos] < min_wait) { min_wait = meas_time_ms[pos]; }
806 if (meas_time_ms[pos] > max_wait) { max_wait = meas_time_ms[pos]; }
808 Serial.print("Address ");
809 Serial.print(address);
810 Serial.println(" is not active");
814 min_wait = max(static_cast<uint32_t>(10), min_wait / 2);
815 max_wait = max(static_cast<uint32_t>(1000),
816 max_wait + static_cast<uint32_t>(2000));
817 Serial.print("minimum expected wait for all sensors: ");
818 Serial.println(min_wait);
819 Serial.print("maximum expected wait for all sensors: ");
820 Serial.println(max_wait);
822#if defined(TEST_PRINT_ARRAY)
823 Serial.print("address_number,\t");
824 Serial.print("address,\t");
825 Serial.print("position,\t");
826 Serial.print("isActive[i],\t");
827 Serial.print("millis,\t");
828 Serial.print("timeWaited,\t");
829 Serial.print("millisReady[i],\t");
830 Serial.print("expectedResults[i],\t");
831 Serial.print("returnedResults[i],\t");
832 Serial.print("millis() > millisReady[i],\t");
833 Serial.print("expectedResults[i] > 0,\t");
834 Serial.print("returnedResults[i] < expectedResults[i],\t");
835 Serial.print("numSensors,\t");
836 Serial.print("numReadingsRecorded,\t");
837 Serial.print("maxDataCommand,\t");
838 Serial.print("resultsReceived,\t");
839 Serial.print("errorCode,\t");
840 Serial.print("crcMatch,\t");
841 Serial.print("gotGoodResults,\t");
842 Serial.print("numReadingsRecorded");
846 uint8_t numReadingsRecorded = 0;
851 for (int8_t address_number = firstAddress; address_number <= lastAddress;
853 int8_t pos = address_number - firstAddress;
854 uint32_t timeWaited = 0;
855 if (millisStarted[pos] != 0) { timeWaited = millis() - millisStarted[pos]; }
856 if (this_result[pos] != "") { prev_result[pos] = this_result[pos]; }
858 char addr = decToChar(address_number);
860#if defined(TEST_PRINT_ARRAY)
861 Serial.print(address_number);
862 Serial.print(",\t\"");
863 Serial.print(decToChar(address_number));
864 Serial.print("\",\t");
866 Serial.print(",\t\"");
867 Serial.print(isActive[pos]);
869 Serial.print(millis());
871 Serial.print(timeWaited);
873 Serial.print(millisReady[pos]);
875 Serial.print(expectedResults[pos]);
877 Serial.print(returnedResults[pos]);
879 Serial.print(millis() > millisReady[pos]);
881 Serial.print(expectedResults[pos] > 0);
883 Serial.print(returnedResults[pos] < expectedResults[pos]);
885 Serial.print(numSensors);
887 Serial.print(numReadingsRecorded);
890 if (isActive[pos] && (millis() > millisReady[pos]) &&
891 (expectedResults[pos] > 0) &&
892 (returnedResults[pos] < expectedResults[pos])) {
893#ifndef TEST_PRINT_ARRAY
894 Serial.print("timeWaited: ");
895 Serial.println(timeWaited);
897 getResultsResult cResult = getResults(addr, expectedResults[pos], true);
898 returnedResults[pos] = cResult.resultsReceived;
899 bool gotGoodResults = cResult.success;
900 if (gotGoodResults) {
901 numReadingsRecorded++;
902#ifndef TEST_PRINT_ARRAY
903 Serial.print("Got results from ");
904 Serial.print(numReadingsRecorded);
905 Serial.print(" of ");
906 Serial.print(numSensors);
907 Serial.print(" sensors");
910#if defined(TEST_PRINT_ARRAY)
912 Serial.print(cResult.maxDataCommand);
914 Serial.print(cResult.resultsReceived);
916 Serial.print(cResult.errorCode);
918 Serial.print(cResult.crcMatch);
920 Serial.print(gotGoodResults);
925 } while (millis() - for_start < max_wait && numReadingsRecorded < numSensors);
927 Serial.print("Total Time for Concurrent Measurements: ");
928 Serial.println(millis() - start);
931 Serial.println("-------------------------------------------------------------------"