-
-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Meter Teros 11 soil moisture sensor, not tested
First attempt to address #276
- Loading branch information
1 parent
d85be2d
commit eebc93b
Showing
2 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* | ||
*MeterTeros11.cpp - MODIFIED FOR new TEROS 11 sensor !!! | ||
*This file is part of the EnviroDIY modular sensors library for Arduino | ||
* | ||
*Written by Anthony Aufdenkampe <[email protected]>, based on | ||
*Initial library developement done by Sara Damiano ([email protected]). | ||
* | ||
*This file is for the Meter Teros 11 Advanced Soil Moisture probe | ||
*It is dependent on the EnviroDIY SDI-12 library and the SDI12Sensors super class. | ||
* | ||
*Documentation for the SDI-12 Protocol commands and responses | ||
*for the Meter Teros 11 can be found at: | ||
* http://publications.metergroup.com/Integrator%20Guide/18224%20TEROS%2011-12%20Integrator%20Guide.pdf | ||
* | ||
* For Ea and VWC: | ||
* Resolution is 0.001 m3/m3 (0.1% VWC) from 0 – 70% VWC | ||
* Accuracy for Generic calibration equation: ± 0.03 m3/m3 (± 3% VWC) typ | ||
* Accuracy for Medium Specific Calibration: ± 0.01 to 0.02 m3/m3 (± 1-2% VWC) | ||
* Range is 0 – 1 m3/m3 (0 – 100% VWC) | ||
* | ||
* For Temperature: | ||
* Resolution is 0.1°C | ||
* Accuracy is ± 0.5°C, from - 40°C to 0°C | ||
* Accuracy is ± 0.3°C, from 0°C to + 60°C | ||
* | ||
* Warm-up time in SDI-12 mode: 245ms typical, assume stability at warm-up | ||
* Measurement duration: 25 ms to 50 ms | ||
* | ||
* Supply Voltage (VCC to GND), 4.0 to 15.0 VDC | ||
* Digital Input Voltage (logic high), 2.8 to 3.9 V (3.6 typical) | ||
* Digital Output Voltage (logic high), 3.6 typical | ||
*/ | ||
|
||
#include "MeterTeros11.h" | ||
|
||
bool MeterTeros11::addSingleMeasurementResult(void) | ||
{ | ||
bool success = false; | ||
|
||
// Set up the float variables for receiving data | ||
float raw = -9999; | ||
float ea = -9999; | ||
float temp = -9999; | ||
float VWC = -9999; | ||
|
||
// Check a measurement was *successfully* started (status bit 6 set) | ||
// Only go on to get a result if it was | ||
if (bitRead(_sensorStatus, 6)) | ||
{ | ||
// MS_DBG(F(" Activating SDI-12 instance for"), getSensorNameAndLocation()); | ||
// Check if this the currently active SDI-12 Object | ||
bool wasActive = _SDI12Internal.isActive(); | ||
// if (wasActive) {MS_DBG(F(" SDI-12 instance for"), getSensorNameAndLocation(), | ||
// F("was already active!"));} | ||
// If it wasn't active, activate it now. | ||
// Use begin() instead of just setActive() to ensure timer is set correctly. | ||
if (!wasActive) _SDI12Internal.begin(); | ||
// Empty the buffer | ||
_SDI12Internal.clearBuffer(); | ||
|
||
MS_DBG(getSensorNameAndLocation(), F("is reporting:")); | ||
String getDataCommand = ""; | ||
getDataCommand += _SDI12address; | ||
getDataCommand += "D0!"; // SDI-12 command to get data [address][D][dataOption][!] | ||
_SDI12Internal.sendCommand(getDataCommand); | ||
delay(50); // It just needs this little delay | ||
MS_DBG(F(" >>>"), getDataCommand); | ||
|
||
uint32_t start = millis(); | ||
while (_SDI12Internal.available() < 3 && (millis() - start) < 1500) {} | ||
MS_DBG(F(" Receiving results from"), getSensorNameAndLocation()); | ||
_SDI12Internal.read(); // ignore the repeated SDI12 address | ||
// First variable returned is the raw count value. This gets convertd into dielectric ea | ||
raw = _SDI12Internal.parseFloat(); | ||
if (raw < 0 || raw > 5000) raw = -9999; | ||
if (raw != -9999) | ||
{ | ||
ea = ((2.887e-9*(raw*raw*raw))-(2.08e-5*(raw*raw))+(5.276e-2 *raw)-43.39)*((2.887e-9*(raw*raw*raw))-(2.08e-5*(raw*raw))+(5.276e-2 *raw)-43.39); | ||
} | ||
// Second variable returned is the temperature in °C | ||
temp = _SDI12Internal.parseFloat(); | ||
if (temp < -50 || temp > 60) temp = -9999; // Range is - 40°C to + 50°C | ||
// the "third" variable of VWC is actually calculated (Topp equation for mineral soils), not returned by the sensor! | ||
if (ea != -9999) | ||
{ | ||
VWC = (4.3e-6*(ea*ea*ea)) | ||
- (5.5e-4*(ea*ea)) | ||
+ (2.92e-2 * ea) | ||
- 5.3e-2 ; | ||
VWC *= 100; // Convert to actual percent | ||
} | ||
|
||
//VWC = 3.879e-4*raw-0.6956; // equation for mineral soils | ||
|
||
if (VWC < 0) VWC = 0; | ||
if (VWC > 100) VWC = 100; | ||
|
||
// String sdiResponse = _SDI12Internal.readStringUntil('\n'); | ||
// sdiResponse.trim(); | ||
// _SDI12Internal.clearBuffer(); | ||
// MS_DBG(F(" <<<"), sdiResponse); | ||
|
||
// Empty the buffer again | ||
_SDI12Internal.clearBuffer(); | ||
|
||
// De-activate the SDI-12 Object | ||
// Use end() instead of just forceHold to un-set the timers | ||
_SDI12Internal.end(); | ||
|
||
MS_DBG(F(" Dialectric E:"), ea); | ||
MS_DBG(F(" Temperature:"), temp); | ||
MS_DBG(F(" Volumetric Water Content:"), VWC); | ||
|
||
success = true; | ||
} | ||
else | ||
{ | ||
MS_DBG(getSensorNameAndLocation(), F("is not currently measuring!")); | ||
} | ||
|
||
verifyAndAddMeasurementResult(TM_EA_VAR_NUM, ea); | ||
verifyAndAddMeasurementResult(TM_TEMP_VAR_NUM, temp); | ||
verifyAndAddMeasurementResult(TM_VWC_VAR_NUM, VWC); | ||
|
||
// Unset the time stamp for the beginning of this measurement | ||
_millisMeasurementRequested = 0; | ||
// Unset the status bits for a measurement request (bits 5 & 6) | ||
_sensorStatus &= 0b10011111; | ||
|
||
return success; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
/* | ||
*MeterTeros11.h | ||
*This file is part of the EnviroDIY modular sensors library for Arduino | ||
* | ||
*Written by Anthony Aufdenkampe <[email protected]>, based on | ||
*Initial library developement done by Sara Damiano ([email protected]). | ||
* | ||
*This file is for the Meter Teros 11 Advanced Soil Moisture probe | ||
*It is dependent on the EnviroDIY SDI-12 library and the SDI12Sensors super class. | ||
* | ||
*Documentation for the SDI-12 Protocol commands and responses | ||
*for the Meter Teros 11 can be found at: | ||
* http://publications.metergroup.com/Integrator%20Guide/18224%20TEROS%2011-12%20Integrator%20Guide.pdf | ||
* | ||
* For Ea and VWC: | ||
* Resolution is 0.001 m3/m3 (0.1% VWC) from 0 – 70% VWC | ||
* Accuracy for Generic calibration equation: ± 0.03 m3/m3 (± 3% VWC) typ | ||
* Accuracy for Medium Specific Calibration: ± 0.01 to 0.02 m3/m3 (± 1-2% VWC) | ||
* Range is 0 – 1 m3/m3 (0 – 100% VWC) | ||
* | ||
* For Temperature: | ||
* Resolution is 0.1°C | ||
* Accuracy is ± 0.5°C, from - 40°C to 0°C | ||
* Accuracy is ± 0.3°C, from 0°C to + 60°C | ||
* | ||
* Warm-up time in SDI-12 mode: 245ms typical, assume stability at warm-up | ||
* Measurement duration: 25 ms to 50 ms | ||
* | ||
* Supply Voltage (VCC to GND), 4.0 to 15.0 VDC | ||
* Digital Input Voltage (logic high), 2.8 to 3.9 V (3.6 typical) | ||
* Digital Output Voltage (logic high), 3.6 typical | ||
*/ | ||
|
||
// Header Guards | ||
#ifndef MeterTeros11_h | ||
#define MeterTeros11_h | ||
|
||
// Debugging Statement | ||
// #define MS_MeterTeros11_DEBUG | ||
|
||
#ifdef MS_MeterTeros11_DEBUG | ||
#define MS_DEBUGGING_STD "MeterTeros11" | ||
#endif | ||
|
||
// Included Dependencies | ||
#include "ModSensorDebugger.h" | ||
#undef MS_DEBUGGING_STD | ||
#include "VariableBase.h" | ||
#include "sensors/SDI12Sensors.h" | ||
|
||
// Sensor Specific Defines | ||
#define TM_NUM_VARIABLES 3 | ||
#define TM_WARM_UP_TIME_MS 250 | ||
#define TM_STABILIZATION_TIME_MS 50 | ||
#define TM_MEASUREMENT_TIME_MS 50 | ||
|
||
#define TM_EA_RESOLUTION 5 | ||
// adding extra digit to resolution for averaging | ||
#define TM_EA_VAR_NUM 0 | ||
|
||
#define TM_TEMP_RESOLUTION 2 | ||
// adding extra digit to resolution for averaging | ||
#define TM_TEMP_VAR_NUM 1 | ||
|
||
#define TM_VWC_RESOLUTION 3 | ||
// adding extra digit to resolution for averaging | ||
#define TM_VWC_VAR_NUM 2 | ||
|
||
// The main class for the Decagon 5TM | ||
class MeterTeros11 : public SDI12Sensors | ||
{ | ||
public: | ||
// Constructors with overloads | ||
MeterTeros11(char SDI12address, int8_t powerPin, int8_t dataPin, uint8_t measurementsToAverage = 1) | ||
: SDI12Sensors(SDI12address, powerPin, dataPin, measurementsToAverage, | ||
"MeterTeros11", TM_NUM_VARIABLES, | ||
TM_WARM_UP_TIME_MS, TM_STABILIZATION_TIME_MS, TM_MEASUREMENT_TIME_MS) | ||
{} | ||
MeterTeros11(char *SDI12address, int8_t powerPin, int8_t dataPin, uint8_t measurementsToAverage = 1) | ||
: SDI12Sensors(SDI12address, powerPin, dataPin, measurementsToAverage, | ||
"MeterTeros11", TM_NUM_VARIABLES, | ||
TM_WARM_UP_TIME_MS, TM_STABILIZATION_TIME_MS, TM_MEASUREMENT_TIME_MS) | ||
{} | ||
MeterTeros11(int SDI12address, int8_t powerPin, int8_t dataPin, uint8_t measurementsToAverage = 1) | ||
: SDI12Sensors(SDI12address, powerPin, dataPin, measurementsToAverage, | ||
"MeterTeros11", TM_NUM_VARIABLES, | ||
TM_WARM_UP_TIME_MS, TM_STABILIZATION_TIME_MS, TM_MEASUREMENT_TIME_MS) | ||
{} | ||
// Destructor | ||
~MeterTeros11(){} | ||
|
||
virtual bool addSingleMeasurementResult(void) override; | ||
}; | ||
|
||
|
||
// Defines the Ea/Matric Potential Variable | ||
class MeterTeros11_Ea : public Variable | ||
{ | ||
public: | ||
MeterTeros11_Ea(Sensor *parentSense, | ||
const char *uuid = "", | ||
const char *varCode = "SoilEa") | ||
: Variable(parentSense, | ||
(const uint8_t)TM_EA_VAR_NUM, | ||
(uint8_t)TM_EA_RESOLUTION, | ||
"permittivity", "faradPerMeter", | ||
varCode, uuid) | ||
{} | ||
MeterTeros11_Ea() | ||
: Variable((const uint8_t)TM_EA_VAR_NUM, | ||
(uint8_t)TM_EA_RESOLUTION, | ||
"permittivity", "faradPerMeter", "SoilEa") | ||
{} | ||
~MeterTeros11_Ea(){} | ||
}; | ||
|
||
|
||
// Defines the Temperature Variable | ||
class MeterTeros11_Temp : public Variable | ||
{ | ||
public: | ||
MeterTeros11_Temp(Sensor *parentSense, | ||
const char *uuid = "", | ||
const char *varCode = "SoilTemp") | ||
: Variable(parentSense, | ||
(const uint8_t)TM_TEMP_VAR_NUM, | ||
(uint8_t)TM_TEMP_RESOLUTION, | ||
"temperature", "degreeCelsius", | ||
varCode, uuid) | ||
{} | ||
MeterTeros11_Temp() | ||
: Variable((const uint8_t)TM_TEMP_VAR_NUM, | ||
(uint8_t)TM_TEMP_RESOLUTION, | ||
"temperature", "degreeCelsius", "SoilTemp") | ||
{} | ||
~MeterTeros11_Temp(){} | ||
}; | ||
|
||
|
||
// Defines the Volumetric Water Content Variable | ||
class MeterTeros11_VWC : public Variable | ||
{ | ||
public: | ||
MeterTeros11_VWC(Sensor *parentSense, | ||
const char *uuid = "", | ||
const char *varCode = "SoilVWC") | ||
: Variable(parentSense, | ||
(const uint8_t)TM_VWC_VAR_NUM, | ||
(uint8_t)TM_VWC_RESOLUTION, | ||
"volumetricWaterContent", "percent", | ||
varCode, uuid) | ||
{} | ||
MeterTeros11_VWC() | ||
: Variable((const uint8_t)TM_VWC_VAR_NUM, | ||
(uint8_t)TM_VWC_RESOLUTION, | ||
"volumetricWaterContent", "percent", "SoilVWC") | ||
{} | ||
~MeterTeros11_VWC(){} | ||
}; | ||
|
||
#endif // Header Guard |