c_check_all_addresses.ino example

Example C: Check all Addresses for Active Sensors and Print Status.

Example C: Check all Addresses for Active Sensors and Print Status

This is a simple demonstration of the SDI-12 library for Arduino.

It discovers the address of all sensors active and attached to the board. THIS CAN BE REALLY SLOW TO RUN!!!

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

1/**
2 * @example{lineno} c_check_all_addresses.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 C: Check all Addresses for Active Sensors and Print Status
9 *
10 * This is a simple demonstration of the SDI-12 library for Arduino.
11 *
12 * It discovers the address of all sensors active and attached to the board.
13 * THIS CAN BE *REALLY* SLOW TO RUN!!!
14 *
15 * Each sensor should have a unique address already - if not, multiple sensors may
16 * respond simultaneously to the same request and the output will not be readable
17 * by the Arduino.
18 *
19 * To address a sensor, please see Example B: b_address_change.ino
20 */
21
22#include <SDI12.h>
23
24#ifndef SDI12_DATA_PIN
25#define SDI12_DATA_PIN 7
26#endif
27#ifndef SDI12_POWER_PIN
28#define SDI12_POWER_PIN 22
29#endif
30
31uint32_t serialBaud = 115200; /*!< The baud rate for the output serial port */
32int8_t powerPin = SDI12_POWER_PIN; /*!< The sensor power pin (or -1) */
33uint32_t wake_delay = 0; /*!< Extra time needed for the sensor to wake (0-100ms) */
34int8_t firstPin = 3; /*! change to lowest pin number to search on your board */
35int8_t lastPin = 7; /*! change to highest pin number to search on your board */
36int8_t firstAddress = 0; /* The first address in the address space to check (0='0') */
37int8_t lastAddress = 61; /* The last address in the address space to check (61='z') */
38
39/**
40 * @brief converts allowable address characters ('0'-'9', 'a'-'z', 'A'-'Z') to a
41 * decimal number between 0 and 61 (inclusive) to cover the 62 possible
42 * addresses.
43 */
44byte charToDec(char i) {
45 if ((i >= '0') && (i <= '9')) return i - '0';
46 if ((i >= 'a') && (i <= 'z')) return i - 'a' + 10;
47 if ((i >= 'A') && (i <= 'Z'))
48 return i - 'A' + 36;
49 else
50 return i;
51}
52
53/**
54 * @brief maps a decimal number between 0 and 61 (inclusive) to allowable
55 * address characters '0'-'9', 'a'-'z', 'A'-'Z',
56 *
57 * THIS METHOD IS UNUSED IN THIS EXAMPLE, BUT IT MAY BE HELPFUL.
58 */
59char decToChar(byte i) {
60 if (i < 10) return i + '0';
61 if ((i >= 10) && (i < 36)) return i + 'a' - 10;
62 if ((i >= 36) && (i <= 62))
63 return i + 'A' - 36;
64 else
65 return i;
66}
67
68/**
69 * @brief gets identification information from a sensor, and prints it to the serial
70 * port expects
71 *
72 * @param sdi the SDI-12 instance
73 * @param i a character between '0'-'9', 'a'-'z', or 'A'-'Z'
74 */
75void printInfo(SDI12& sdi, char i) {
76 String command = "";
77 command += (char)i;
78 command += "I!";
79 sdi.clearBuffer();
80 sdi.sendCommand(command, wake_delay);
81 delay(30);
82
83 String sdiResponse = sdi.readStringUntil('\n');
84 sdiResponse.trim();
85 // allccccccccmmmmmmvvvxxx...xx<CR><LF>
86 Serial.print(sdiResponse.substring(0, 1)); // address
87 Serial.print(", ");
88 Serial.print(sdiResponse.substring(1, 3).toFloat() / 10); // SDI-12 version number
89 Serial.print(", ");
90 Serial.print(sdiResponse.substring(3, 11)); // vendor id
91 Serial.print(", ");
92 Serial.print(sdiResponse.substring(11, 17)); // sensor model
93 Serial.print(", ");
94 Serial.print(sdiResponse.substring(17, 20)); // sensor version
95 Serial.print(", ");
96 Serial.println(sdiResponse.substring(20)); // sensor id
97}
98
99// this checks for activity at a particular address
100// expects a char, '0'-'9', 'a'-'z', or 'A'-'Z'
101bool checkActive(SDI12& sdi, char i) {
102 String myCommand = "";
103 myCommand = "";
104 myCommand += (char)i; // sends basic 'acknowledge' command [address][!]
105 myCommand += "!";
106
107 for (int j = 0; j < 3; j++) { // goes through three rapid contact attempts
108 sdi.clearBuffer();
109 sdi.sendCommand(myCommand, wake_delay);
110 Serial.print(">>>");
111 Serial.println(myCommand);
112 uint32_t start_millis = millis();
113 while (!sdi.available() && millis() - start_millis < 250);
114 if (sdi.available()) { // If we hear anything, assume we have an active sensor
115 Serial.print("<<<");
116 while (sdi.available()) { Serial.write(sdi.read()); }
117 Serial.println();
118 return true;
119 }
120 }
121 sdi.clearBuffer();
122 return false;
123}
124
125void scanAddressSpace(SDI12& sdi) {
126 // Quickly scan the address space
127 for (int8_t i = firstAddress; i <= lastAddress; i++) {
128 char addr = decToChar(i);
129 Serial.print("i=");
130 Serial.print(i);
131 Serial.print(" addr=");
132 Serial.println(addr);
133 if (checkActive(sdi, addr)) { printInfo(sdi, addr); };
134 }
135}
136
137void setup() {
138 Serial.begin(serialBaud);
139 while (!Serial && millis() < 10000L);
140
141 Serial.println("//\n// Start Search for SDI-12 Devices \n// -----------------------");
142
143 // Power the sensors;
144 if (powerPin >= 0) {
145 Serial.println("Powering up sensors, wait...");
146 pinMode(powerPin, OUTPUT);
147 digitalWrite(powerPin, HIGH);
148 delay(5000L);
149 }
150
151 for (int8_t pin = firstPin; pin <= lastPin; pin++) {
152 Serial.print("Checking pin ");
153 Serial.print(pin);
154 Serial.println("...");
155 if (pin != powerPin) {
156 pinMode(pin, INPUT);
157 SDI12 mySDI12(pin);
158 mySDI12.begin();
159 scanAddressSpace(mySDI12);
160 mySDI12.end();
161 }
162 }
163
164 Serial.println("\n//\n// End Search for SDI-12 Devices \n// ---------------------");
165
166 // Cut power
167 digitalWrite(powerPin, LOW);
168}
169
170void loop() {}