Home › Forums › Other Data Loggers › SDI-12 Library
- This topic has 14 replies, 7 voices, and was last updated 2024-05-01 at 2:21 AM by merondibia.
-
AuthorPosts
-
-
2020-02-22 at 2:08 PM #13844Hi:
I am using this library SDI12. I’m trying to read SRS sensor from De
Hi:I am using this library SDI12. I’m trying to read SRS sensor from Decagon. The code used is the provided in the example codes call “d_simple_logger.ino”. The code works well and I can read all the sensors. However, the time to read all the sensors is too high. Due to the code takes 3-4 seconds for reading each sensors. I have 8 sensors attached. In this sense, the time required to read all sensors is around 25 seconds. Could someone tell me how to solve this problem?
-
2020-02-22 at 7:03 PM #13845That example goes through the list of available address to see if a sensor is attached that has a corresponding address, so it definitely takes awhile to go through the whole list. You could rewriteThat example goes through the list of available address to see if a sensor is attached that has a corresponding address, so it definitely takes awhile to go through the whole list. You could rewrite it to only go through the addresses of your sensors and not the entire list. But your sensors have a 600ms sample time (as stated in the datasheet), so you’ll need to add a little delay after that and then you’ll have the poll time, so I’d allow 1 second for each sensor, and with 8 sensors it’ll take 8 seconds total. Is that acceptable?
-
2020-02-22 at 7:10 PM #13846
Could you tell me the lines I need to rewrite to read only my adress. I have 8 sensors with adress from 0 to 7.
-
2020-02-23 at 9:12 AM #13847That demo sketch is just a sample of how to talk to your sensors, there’s lots of stuff in there that you could trim out if you’re actually trying to collect data at a certain rate. WhatThat demo sketch is just a sample of how to talk to your sensors, there’s lots of stuff in there that you could trim out if you’re actually trying to collect data at a certain rate. What type of board are you using? Are you planning to store the data on a memory card or just print to the computer’s serial monitor? There’s a 10-second delay on the very last line of the sketch that isn’t needed if you’re trying to cut down on time between samples. Do you want to take one discrete reading from each sensor each time, or are you interested in taking several readings from each sensor an averaging them to limit the “noise” or variation between readings of each sensor? Are you sensors going to be powered continuously or do you want to turn them off between readings? Do you need a timestamp to go along with each data record?
-
2020-02-23 at 9:18 AM #13848I achieve to reduce the time to 8 seconds (see the code attached). I am storing the data in a Micro SD Card. The sensors will be powered continuously. I am using an Arduino UNO board. I am interestingI achieve to reduce the time to 8 seconds (see the code attached). I am storing the data in a Micro SD Card. The sensors will be powered continuously. I am using an Arduino UNO board. I am interesting in take on discrete reading from each sensor. In the code I also include a Melexis infrared thermometers.
Regards, Enrique
Attachments:
-
2020-02-28 at 11:44 AM #13868Is your goal to read all of your sensors and write to your SD card as fast as you possibly can? You could get faster readings by using concurrent sampling on the Decagons like this: https://githubIs your goal to read all of your sensors and write to your SD card as fast as you possibly can? You could get faster readings by using concurrent sampling on the Decagons like this: https://github.com/EnviroDIY/Arduino-SDI-12/blob/master/examples/k_concurrent_logger/k_concurrent_logger.ino
-
2020-02-28 at 11:51 AM #13869Re-Wrote for you. I didn’t even test if it compiles, but this should get you going with concurrent measurements:1/*The Sensor Orientation Index. This numRe-Wrote for you. I didn’t even test if it compiles, but this should get you going with concurrent measurements:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170/*The Sensor Orientation Index. This number is two when the sensor is upward facing, one when the sensor is downward facing, and zerowhen orientation is undetermined.*/#include <SDI12.h>#include <SD.h>#include <Wire.h>#include <DS3232RTC.h>#include <Adafruit_MLX90614.h>#define DATA_PIN 3SDI12 mySDI12(DATA_PIN);const int chipSelect = 10;unsigned long time;File logFile;Adafruit_MLX90614 sensor_52 = Adafruit_MLX90614(0x52);Adafruit_MLX90614 sensor_53 = Adafruit_MLX90614(0x53);Adafruit_MLX90614 sensor_03 = Adafruit_MLX90614(0x03);Adafruit_MLX90614 sensor_07 = Adafruit_MLX90614(0x07);// keeps track of the wait time for each active addressesuint8_t waitTime[8] = {0,};// keeps track of the time each sensor was starteduint32_t millisStarted[8] = {0,};// keeps track of the time each sensor will be readyuint32_t millisReady[8] = {0,};// How many sensors to readuint8_t numSensors = 8;void startConcurrentMeasurement(char i){String command = "";command += i;command += "C!"; // SDI-12 concurrent measurement command format [address]['C'][!]mySDI12.sendCommand(command);delay(30);// wait for acknowlegement with format [address][ttt (3 char, seconds)][number of measurments available, 0-9]String sdiResponse = "";delay(30);while (mySDI12.available()) // build response string{char c = mySDI12.read();if ((c != '\n') && (c != '\r')){sdiResponse += c;delay(5);}}mySDI12.clearBuffer();// find out how long we have to wait (in seconds).uint8_t wait = 0;wait = sdiResponse.substring(1, 4).toInt();uint8_t sensorNum = charToDec(i); // e.g. convert '0' to 0, 'a' to 10, 'Z' to 61.waitTime[sensorNum] = wait;millisStarted[sensorNum] = millis();millisReady[sensorNum] = millis() + wait * 1000;}void logSDI12Results(char i){String command = "";// in this example we will only take the 'DO' measurementcommand = "";command += i;command += "D0!"; // SDI-12 command to get data [address][D][dataOption][!]mySDI12.sendCommand(command);// wait for acknowlegementuint32_t startMillis = millis();while (!(mySDI12.available() > 7) && (millis() - startMillis < 5000L)){}mySDI12.read(); // throw away the repeated addresslogfile.print(mySDI12.readStringUntil('+')); // read and log red bandlogFile.print(";");logfile.print(mySDI12.readStringUntil('+')); // read and log nir bandlogFile.print(";");logfile.print(mySDI12.readStringUntil('\n')); // read and log orientationlogFile.print(";");printBufferToScreen();mySDI12.clearBuffer();}void setup(){Serial.begin(115200);sensor_52.begin();sensor_53.begin();sensor_03.begin();sensor_07.begin();Wire.begin();if (!SD.begin(chipSelect)){return;}while (!Serial);mySDI12.begin();delay(500);for (byte i = '0'; i <= '9'; i++)if (checkActive(i)){numSensors++;setTaken(i);}logFile = SD.open("hwheat.txt", FILE_WRITE);if (logFile){logFile.println("fecha;hora;r_red;r_nir;r_orientation;r_red;r_nir;r_orientation;r_red;r_nir;r_orientation;r_532;r_570;orientation;r_532;r_570;orientation;r_532;r_570;orientation;i_532;i_570;orientation;r_red;r_nir;r_orientation;Temp1;Temp2;Temp3;Temp4");logFile.close();}}void lectura_sensores(){logFile.print(sensor_52.readObjectTempC());logFile.print(";");logFile.print(sensor_53.readObjectTempC());logFile.print(";");logFile.print(sensor_03.readObjectTempC());logFile.print(";");logFile.println(sensor_07.readObjectTempC());}void loop(){time_t p;p = RTC.get();logFile = SD.open("hwheat.txt", FILE_WRITE);if (logFile){logFile.print(String(day(p)) + "/" + String(month(p)) + "/" + String(year(p)) + ";" + String(hour(p)) + ":" + String(minute(p)) + ":" + String(second(p)));// Start a concurrent measurement on all of the SDI-12 sensorsfor (char i = '0'; i < '8'; i++){startConcurrentMeasurement(i);}// get all readingsuint8_t numReadingsRecorded = 0;while (numReadingsRecorded < numSensors){for (char i = '0'; i < '8'; i++){if (millis() > millisReady[charToDec(i)]){logSDI12Results(i);numReadingsRecorded++;}}}logFile.print(";");lectura_sensores();logFile.close();}}
-
2020-02-29 at 7:11 AM #13872
Hi Sara:
Thank you for your quickly answer. However, when I tried to compile the code several errors were shown (see images attached).
Regards, Enrique
Attachments:
-
2020-03-05 at 10:40 AM #13903
Delete lines 112-117 of the code I posted.
-
2020-03-19 at 4:17 AM #13963
Hi again Sara:
I deleted the lines that you say in previous comment. However, the problem do not have solution.
Thanks in advance
-
2020-03-20 at 10:33 AM #13967My intent was to help you by giving you an example of something you could modify to your needs, not to give you a final working program.
This version will compile. I don’t know if it will act
My intent was to help you by giving you an example of something you could modify to your needs, not to give you a final working program.This version will compile. I don’t know if it will actually work for your sensors or log data as expected. You will need to test that.
C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169#include <SDI12.h>#include <SD.h>#include <Wire.h>#include <DS3232RTC.h>#include <Adafruit_MLX90614.h>#define DATA_PIN 3SDI12 mySDI12(DATA_PIN);const int chipSelect = 10;unsigned long time;File logFile;Adafruit_MLX90614 sensor_52 = Adafruit_MLX90614(0x52);Adafruit_MLX90614 sensor_53 = Adafruit_MLX90614(0x53);Adafruit_MLX90614 sensor_03 = Adafruit_MLX90614(0x03);Adafruit_MLX90614 sensor_07 = Adafruit_MLX90614(0x07);// keeps track of the wait time for each active addressesuint8_t waitTime[8] = {0,};// keeps track of the time each sensor was starteduint32_t millisStarted[8] = {0,};// keeps track of the time each sensor will be readyuint32_t millisReady[8] = {0,};// How many sensors to readuint8_t numSensors = 8;// converts allowable address characters '0'-'9', 'a'-'z', 'A'-'Z',// to a decimal number between 0 and 61 (inclusive) to cover the 62 possible addressesbyte charToDec(char i){if((i >= '0') && (i <= '9')) return i - '0';if((i >= 'a') && (i <= 'z')) return i - 'a' + 10;if((i >= 'A') && (i <= 'Z')) return i - 'A' + 37;else return i;}void startConcurrentMeasurement(char i){String command = "";command += i;command += "C!"; // SDI-12 concurrent measurement command format [address]['C'][!]mySDI12.sendCommand(command);delay(30);// wait for acknowlegement with format [address][ttt (3 char, seconds)][number of measurments available, 0-9]String sdiResponse = "";delay(30);while (mySDI12.available()) // build response string{char c = mySDI12.read();if ((c != '\n') && (c != '\r')){sdiResponse += c;delay(5);}}mySDI12.clearBuffer();// find out how long we have to wait (in seconds).uint8_t wait = 0;wait = sdiResponse.substring(1, 4).toInt();uint8_t sensorNum = charToDec(i); // e.g. convert '0' to 0, 'a' to 10, 'Z' to 61.waitTime[sensorNum] = wait;millisStarted[sensorNum] = millis();millisReady[sensorNum] = millis() + wait * 1000;}void logSDI12Results(char i){String command = "";// in this example we will only take the 'DO' measurementcommand = "";command += i;command += "D0!"; // SDI-12 command to get data [address][D][dataOption][!]mySDI12.sendCommand(command);// wait for acknowlegementuint32_t startMillis = millis();while (!(mySDI12.available() > 7) && (millis() - startMillis < 5000L)){}mySDI12.read(); // throw away the repeated addresslogFile.print(mySDI12.readStringUntil('+')); // read and log red bandlogFile.print(";");logFile.print(mySDI12.readStringUntil('+')); // read and log nir bandlogFile.print(";");logFile.print(mySDI12.readStringUntil('\n')); // read and log orientationlogFile.print(";");mySDI12.clearBuffer();}void setup(){Serial.begin(115200);sensor_52.begin();sensor_53.begin();sensor_03.begin();sensor_07.begin();Wire.begin();if (!SD.begin(chipSelect)){return;}while (!Serial);mySDI12.begin();delay(500);logFile = SD.open("hwheat.txt", FILE_WRITE);if (logFile){logFile.println("fecha;hora;r_red;r_nir;r_orientation;r_red;r_nir;r_orientation;r_red;r_nir;r_orientation;r_532;r_570;orientation;r_532;r_570;orientation;r_532;r_570;orientation;i_532;i_570;orientation;r_red;r_nir;r_orientation;Temp1;Temp2;Temp3;Temp4");logFile.close();}}void lectura_sensores(){logFile.print(sensor_52.readObjectTempC());logFile.print(";");logFile.print(sensor_53.readObjectTempC());logFile.print(";");logFile.print(sensor_03.readObjectTempC());logFile.print(";");logFile.println(sensor_07.readObjectTempC());}void loop(){time_t p;p = RTC.get();logFile = SD.open("hwheat.txt", FILE_WRITE);if (logFile){logFile.print(String(day(p)) + "/" + String(month(p)) + "/" + String(year(p)) + ";" + String(hour(p)) + ":" + String(minute(p)) + ":" + String(second(p)));// Start a concurrent measurement on all of the SDI-12 sensorsfor (char i = '0'; i < '8'; i++){startConcurrentMeasurement(i);}// get all readingsuint8_t numReadingsRecorded = 0;while (numReadingsRecorded < numSensors){for (char i = '0'; i < '8'; i++){if (millis() > millisReady[charToDec(i)]){logSDI12Results(i);numReadingsRecorded++;}}}logFile.print(";");lectura_sensores();logFile.close();}} -
2022-12-21 at 9:50 AM #17506Has anyone looked to see if the SDI-12 library could be ported to the new RP2040 chip. Maybe that already works in its existing state, but I haven’t see it mentioned anywhere. This is the new ICHas anyone looked to see if the SDI-12 library could be ported to the new RP2040 chip. Maybe that already works in its existing state, but I haven’t see it mentioned anywhere. This is the new IC that runs the RPi Pico and can be used via the Arduino language.
-
2022-12-27 at 8:00 PM #17508@vogelrnws I had been looking at porting it to another processor and been using it and digging into the code. I’ve looked at some of the RP2040, but I’m cautious about its ability to go in@vogelrnws I had been looking at porting it to another processor and been using it and digging into the code. I’ve looked at some of the RP2040, but I’m cautious about its ability to go into low power – but haven’t looked at it in depth.
The SDI-12 lib uses a software based UART – running at 1200Baud, so 1200Baud is pretty slow and it does handle it. It needs to have a timer generated to be able to look for the changes in the data stream.
Unfortunately, IMHO, I’ve found it to be quite fragile. Also the software timing has made debugging fragile. In 2021 I had also found it worked with some Insitu LT500 sensors and not others. I tried to put a “test station” together, against a traceable SDI-12 test setup using https://www.vegetronix.com/Products/SDI-12 and it failed on the basic physical test.
So I’m thinking about how to 1) +5V buffer possibly this solution https://github.com/EnviroDIY/Arduino-SDI-12/issues/87
2) hardware timing. Possibly emulate the UART with with either DMA or Timer/Capture.
So maybe the hardware interface could be done with a simple 4 wire Seeed plugin with an off-board buffer and boost to +12V, and software modified.
So just IMHO a heads up on some of the possible issues to consider.
-
2024-04-23 at 4:07 PM #18445Could you please look at porting the code to the new Arduino R4 UNOs? They use a different chip (Renesas RA4M1 (Arm® Cortex®-M4)), and I cannot get SDI-12 code to compile for those board definitioCould you please look at porting the code to the new Arduino R4 UNOs? They use a different chip (Renesas RA4M1 (Arm® Cortex®-M4)), and I cannot get SDI-12 code to compile for those board definitions.
Reading the preceding posts, I saw you use a software UART for the communication. The R4 UNO has 2 hardware UARTS, but another plus is that the built-in softwareSerial library supports customizable parity, stop and data bits. We were able to configure a couple of new ultrasonic water flow sensors with UART output available from Mouser and Digikey for around $30 to $60 each. This promises to be a huge improvement for our remote instruments that always required cleaning the Hall effect flow sensors due to debris clogging them. Neither has Arduino support yet, but we were able to reverse engineer some of the python code of one of the evaluation kits and get them to work with Arduino R3 and R4 UNOs. I would be happy to share our research and product links.
-
2024-05-01 at 2:21 AM #18451I am trying to update a data logger, which was using Arduino Mega+SD reader, and use Arduino GiGA R1 in order to monitor it remotely, but SDI-12 library is not working on the new Arduino GIGA board, II am trying to update a data logger, which was using Arduino Mega+SD reader, and use Arduino GiGA R1 in order to monitor it remotely, but SDI-12 library is not working on the new Arduino GIGA board, Is it possible to use your fix to update the library for this set up?
-
-
-
AuthorPosts
- You must be logged in to reply to this topic.