Home › Forums › Environmental Sensors › Using Modular Sensors for METER Teros 12 › Reply To: Using Modular Sensors for METER Teros 12
2023-07-13 at 6:57 PM
#17975
@srgdamiano could I get your help with these h/cpp files I created for the Teros 12 sensors? I am having some issues with my sensors not getting values other than -9999 when I have multiple Teros 12 sensors connected. When I use the Teros 11 modules, they all record together, which leads me to believe I set up my h/cpp files wrong. Could I get your help on this? Here is my cpp file to start:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
/** * @file MeterTeros12.cpp * @copyright 2017-2022 Stroud Water Research Center * Part of the EnviroDIY ModularSensors library for Arduino * @author Written By: Anthony Aufdenkampe <aaufdenkampe@limno.com> * Edited by Sara Geleskie Damiano <sdamiano@stroudcenter.org> * * @brief Implements the MeterTeros12 class. */ #include "MeterTeros12.h" bool MeterTeros12::getResults(void) { // Set up the float variables for receiving data float raw = -9999; float temp = -9999; float ec = -9999; // Check if this the currently active SDI-12 Object bool wasActive = _SDI12Internal.isActive(); // 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; // SDI-12 command to get data [address][D][dataOption][!] getDataCommand += "D0!"; _SDI12Internal.sendCommand(getDataCommand, _extraWakeTime); delay(30); // It just needs this little delay MS_DEEP_DBG(F(" >>>"), getDataCommand); // Wait for the first few charaters to arrive. The response from a data // request should always have more than three characters uint32_t start = millis(); while (_SDI12Internal.available() < 3 && (millis() - start) < 1500) { // wait } // read the returned address to remove it from the buffer auto returnedAddress = static_cast<char>(_SDI12Internal.read()); // print out a warning if the address doesn't match up if (returnedAddress != _SDI12address) { MS_DBG(F("Warning, expecting data from"), _SDI12address, F("but got data from"), returnedAddress); } // Start printing out the returned data MS_DEEP_DBG(F(" <<<"), returnedAddress); // read the '+' out of the buffer, and print it if we're debugging #ifdef MS_SDI12SENSORS_DEBUG_DEEP MS_DEEP_DBG(F(" <<<"), static_cast<char>(_SDI12Internal.read())); #else _SDI12Internal.read(); #endif // Read the raw VWC counts raw = _SDI12Internal.parseFloat(SKIP_NONE); MS_DEEP_DBG(F(" <<<"), String(raw, 10)); // read the next '+' out of the buffer #ifdef MS_SDI12SENSORS_DEBUG_DEEP MS_DEEP_DBG(F(" <<<"), static_cast<char>(_SDI12Internal.read())); #else _SDI12Internal.read(); #endif // Now read the temperature temp = _SDI12Internal.parseFloat(SKIP_NONE); MS_DEEP_DBG(F(" <<<"), String(temp, 10)); // read the next '+' out of the buffer #ifdef MS_SDI12SENSORS_DEBUG_DEEP MS_DEEP_DBG(F(" <<<"), static_cast<char>(_SDI12Internal.read())); #else _SDI12Internal.read(); #endif // Now read the electrical conductivity ec = _SDI12Internal.parseFloat(SKIP_NONE); MS_DEEP_DBG(F(" <<<"), String(ec, 10)); // read and dump anything else while (_SDI12Internal.available()) { #ifdef MS_SDI12SENSORS_DEBUG_DEEP MS_DEEP_DBG(F(" <<<"), static_cast<char>(_SDI12Internal.read())); #else _SDI12Internal.read(); #endif } // Empty the buffer again _SDI12Internal.clearBuffer(); // De-activate the SDI-12 Object // Use end() instead of just forceHold to un-set the timers if (!wasActive) _SDI12Internal.end(); MS_DBG(F("Raw VWC Counts:"), raw); MS_DBG(F("Raw Temperature Value:"), temp); MS_DBG(F("Raw Electrical Conductivity Value:"), ec); // Set up the float variables for calculated variable float ea = -9999; float VWC = -9999; // Calculate the dielectric EA from the raw count value. // Equation 8 from the Teros 12 user manual: // http://publications.metergroup.com/Manuals/20587_TEROS11-12_Manual_Web.pdf if (raw < 0 || raw > 5000) { MS_DBG( F("WARNING: raw results out of range (0-5000)! Cannot calculate " "Ea or VWC")); 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); MS_DBG(F("Calculated Ea:"), ea); } // Calculate the VWC from EA using the Topp equation // range check if (ea < 0 || ea > 350) { MS_DBG(F("WARNING: Ea results out of range (0-350)! Cannot calculate " "VWC")); ea = -9999; } // calculate 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 MS_DBG(F("Calculated VWC:"), ea); if (VWC < 0) { VWC = 0; MS_DBG(F("Setting negative VWC to 0")); } if (VWC > 100) { VWC = 100; MS_DBG(F("Setting VWC >100 to 100")); } } // VWC = 3.879e-4*raw-0.6956; // equation for mineral soils // range check on temp; range is - 40°C to + 50°C if (temp < -50 || temp > 60) { temp = -9999; MS_DBG(F("WARNING: temperature results out of range (-50-60)!")); } verifyAndAddMeasurementResult(TEROS12_COUNT_VAR_NUM, raw); verifyAndAddMeasurementResult(TEROS12_TEMP_VAR_NUM, temp); verifyAndAddMeasurementResult(TEROS12_EA_VAR_NUM, ea); verifyAndAddMeasurementResult(TEROS12_VWC_VAR_NUM, VWC); verifyAndAddMeasurementResult(TEROS12_EC_VAR_NUM, ec); return temp != -9999; } |