Example B: Changing the Address of your SDI-12 Sensor

Communication with an SDI-12 sensor depends on its 1-character alphanumeric address (1-9, A-Z, a-z). A sensor can also be programmed with an address of 0, but that address cannot always be used to get measurements from the sensor. This sketch enables you to find and change the address of your sensor.

First, physically connect your SDI-12 sensor to your device. Some helpful hits for connecting it can be found here: https://envirodiy.org/topic/logging-mayfly-with-decagon-sdi-12-sensor/#post-2129.

Once your sensor is physically connected to your board, download this library and open this sketch.

Scroll to line 54 of the sketch (int8_t dataPin = 7;). Change the 7 to the pin number that your sensor is attached to.

Set the pin to provide power to your sensor in line 55 (int8_t powerPin = 22;). If your sensor is continuously powered, set the power pin to -1.

Upload the sketch to your board. After the upload finishes, open up the serial port monitor at a baud rate of 115200 on line 53.

In the serial monitor you will see it begin scanning through all possible SDI-12 addresses. Once it has found an occupied address, it will stop and ask you to enter a new address. Send your desired address to the serial port. On the screen you should see "Readdressing Sensor." followed by "Success. Rescanning for verification." The scan will begin again, stopping at your new address. If you are now happy with the address you've selected, smile and close the serial port monitor.

If you are using a Meter Group Hydros 21 CTD sensor, change the channel to 1 in the serial monitor where prompted.

PlatformIO Configuration

1; PlatformIO Project Configuration File
2
3[platformio]
4description = SDI-12 Library Example B: Changing the SDI-12 Address of a Sensor
5src_dir = .piolibdeps/Arduino-SDI-12_ID1486/examples/b_address_change
6
7[env:mayfly]
8monitor_speed = 115200
9board = mayfly
10platform = atmelavr
11framework = arduino
12lib_ldf_mode = deep+
13lib_ignore = RTCZero
14lib_deps =
15 SDI-12

The Complete Example

1/**
2 * @example{lineno} b_address_change.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 B: Changing the Address of your SDI-12 Sensor
9 *
10 * This is a simple demonstration of the SDI-12 library for arduino.
11 * It discovers the address of the attached sensor and allows you to change it.
12 */
13
14#include <SDI12.h>
15
16uint32_t serialBaud = 57600; /*!< The baud rate for the output serial port */
17int8_t dataPin = 7; /*!< The pin of the SDI-12 data bus */
18int8_t powerPin = 22; /*!< The sensor power pin (or -1 if not switching power) */
19uint32_t wake_delay = 0; /*!< Extra time needed for the sensor to wake (0-100ms) */
20
21/** Define the SDI-12 bus */
22SDI12 mySDI12(dataPin);
23
24String myCommand = ""; // empty to start
25char oldAddress = '!'; // invalid address as placeholder
26
27/**
28 * @brief gets identification information from a sensor, and prints it to the serial
29 * port
30 *
31 * @param i a character between '0'-'9', 'a'-'z', or 'A'-'Z'.
32 */
33void printInfo(char i) {
34 String command = "";
35 command += (char)i;
36 command += "I!";
37 mySDI12.sendCommand(command, wake_delay);
38 delay(100);
39
40 String sdiResponse = mySDI12.readStringUntil('\n');
41 sdiResponse.trim();
42 // allccccccccmmmmmmvvvxxx...xx<CR><LF>
43 Serial.print(sdiResponse.substring(0, 1)); // address
44 Serial.print(", ");
45 Serial.print(sdiResponse.substring(1, 3).toFloat() / 10); // SDI-12 version number
46 Serial.print(", ");
47 Serial.print(sdiResponse.substring(3, 11)); // vendor id
48 Serial.print(", ");
49 Serial.print(sdiResponse.substring(11, 17)); // sensor model
50 Serial.print(", ");
51 Serial.print(sdiResponse.substring(17, 20)); // sensor version
52 Serial.print(", ");
53 Serial.print(sdiResponse.substring(20)); // sensor id
54 Serial.print(", ");
55}
56
57// this checks for activity at a particular address
58// expects a char, '0'-'9', 'a'-'z', or 'A'-'Z'
59boolean checkActive(byte i) { // this checks for activity at a particular address
60 Serial.print("Checking address ");
61 Serial.print((char)i);
62 Serial.print("...");
63 myCommand = "";
64 myCommand += (char)i; // sends basic 'acknowledge' command [address][!]
65 myCommand += "!";
66
67 for (int j = 0; j < 3; j++) { // goes through three rapid contact attempts
68 mySDI12.sendCommand(myCommand, wake_delay);
69 delay(100);
70 if (mySDI12.available()) { // If we here anything, assume we have an active sensor
71 Serial.println("Occupied");
72 mySDI12.clearBuffer();
73 return true;
74 } else {
75 Serial.println("Vacant"); // otherwise it is vacant.
76 mySDI12.clearBuffer();
77 }
78 }
79 return false;
80}
81
82void setup() {
83 Serial.begin(serialBaud);
84 while (!Serial)
85 ;
86
87 Serial.println("Opening SDI-12 bus...");
88 mySDI12.begin();
89 delay(500); // allow things to settle
90
91 Serial.println("Timeout value: ");
92 Serial.println(mySDI12.TIMEOUT);
93
94 // Power the sensors;
95 if (powerPin >= 0) {
96 Serial.println("Powering up sensors, wait 30s...");
97 pinMode(powerPin, OUTPUT);
98 digitalWrite(powerPin, HIGH);
99 delay(30000L);
100 }
101}
102
103void loop() {
104 boolean found = false; // have we identified the sensor yet?
105
106 for (byte i = '0'; i <= '9'; i++) { // scan address space 0-9
107 if (found) break;
108 if (checkActive(i)) {
109 found = true;
110 oldAddress = i;
111 printInfo(i);
112 }
113 }
114
115 for (byte i = 'a'; i <= 'z'; i++) { // scan address space a-z
116 if (found) break;
117 if (checkActive(i)) {
118 found = true;
119 oldAddress = i;
120 printInfo(i);
121 }
122 }
123
124 for (byte i = 'A'; i <= 'Z'; i++) { // scan address space A-Z
125 if (found) break;
126 if (checkActive(i)) {
127 found = true;
128 oldAddress = i;
129 printInfo(i);
130 }
131 }
132
133 if (!found) {
134 Serial.println(
135 "No sensor detected. Check physical connections."); // couldn't find a sensor.
136 // check connections..
137 while (1) // die
138 ;
139 } else {
140 Serial.print("Sensor active at address "); // found a sensor!
141 Serial.print(oldAddress);
142 Serial.println(".");
143
144 Serial.println("Enter new address."); // prompt for a new address
145 while (!Serial.available())
146 ;
147 char newAdd = Serial.read();
148
149 // wait for valid response
150 while (((newAdd < '0') || (newAdd > '9')) && ((newAdd < 'a') || (newAdd > 'z')) &&
151 ((newAdd < 'A') || (newAdd > 'Z'))) {
152 if (!(newAdd == '\n') || (newAdd == '\r') || (newAdd == ' ')) {
153 Serial.println(
154 "Not a valid address. Please enter '0'-'9', 'a'-'A', or 'z'-'Z'.");
155 }
156 while (!Serial.available())
157 ;
158 newAdd = Serial.read();
159 }
160
161 /* the syntax of the change address command is:
162 [currentAddress]A[newAddress]! */
163
164 Serial.println("Readdressing sensor.");
165 myCommand = "";
166 myCommand += (char)oldAddress;
167 myCommand += "A";
168 myCommand += (char)newAdd;
169 myCommand += "!";
170 mySDI12.sendCommand(myCommand);
171
172 /* wait for the response then throw it away by
173 clearing the buffer with clearBuffer() */
174 delay(300);
175 mySDI12.clearBuffer();
176
177 Serial.println("Success. Rescanning for verification.");
178 }
179}