diff --git a/ChangeLog.md b/ChangeLog.md index a8c183b..bfb9b96 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -16,6 +16,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed ### Fixed + +*** + +## [0.4.0] 2022-10-27 +Add Y700 Water Level; fix Y4000 Sonde; restore calibrators. + +### Changed +- Restored calibrator spreadsheets, which is partial reversal of commit f4b0de0, because we developed the offline calibrator spreadsheets to help the community calibrate YosemiTech sensors. + +### Added +- Support for Y700 Pressure/Depth sensor #29 +- Minor improvements to `GetValues.ino` example. + +### Fixed +- Fixed issue with Y4000 not outputing Chl & BGA readings #13 - Specified python version for GitHub actions (used by PlatformIO) *** @@ -37,7 +52,7 @@ Version bump only for reindexing by PlatformIO and Arduino library managers. ## [0.3.0] 2021-12-15 -Add Y551 COD and Y560 Ammonium sensor support Latest +Add Y551 COD and Y560 Ammonium sensor support ### Added - Added support for the Y551 COD Sensor, which makes a UV254 light absorption and translates it to estimates of Chemical Oxygen Demand (COD) (or Total Organic Carbon (TOC)) and Turbidity. diff --git a/VERSION b/VERSION index 9fc80f9..60a2d3e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.2 \ No newline at end of file +0.4.0 \ No newline at end of file diff --git a/examples/GetValues-TimingTest/GetValues-TimingTest.ino b/examples/GetValues-TimingTest/GetValues-TimingTest.ino deleted file mode 100644 index b1d64bc..0000000 --- a/examples/GetValues-TimingTest/GetValues-TimingTest.ino +++ /dev/null @@ -1,265 +0,0 @@ -/***************************************************************************** -GetValues-TimingTest.ino - -This prints basic meta-data about a sensor to the first serial port and then -begins taking measurements from the sensor. - -The sensor model and address can easily be modified to use this sketch with any -Yosemitech modbus sensor. - -Modified from `GetValues.ino` to test optimal timing for the sensor timing settings -used by the ModularSensors library, similar to: - #define Y511_WARM_UP_TIME_MS 8000 // - #define Y511_STABILIZATION_TIME_MS 40000 // - #define Y511_MEASUREMENT_TIME_MS 4000 // -*****************************************************************************/ - -// --------------------------------------------------------------------------- -// Include the base required libraries -// --------------------------------------------------------------------------- -#include -// #include -#include -#include - - -// --------------------------------------------------------------------------- -// Set up the sensor specific information -// ie, pin locations, addresses, calibrations and related settings -// --------------------------------------------------------------------------- - -// Define the sensor type -yosemitechModel model = Y560; // The sensor model number - -// Define the sensor's modbus address -byte modbusAddress = 0x01; // The sensor's modbus address, or SlaveID -// Yosemitech ships sensors with a default ID of 0x01. - -// Define pin number variables -const int sensorPwrPin = 10; // The pin sending power to the sensor -const int adapterPwrPin = 22; // The pin sending power to the RS485 adapter -const int DEREPin = -1; // The pin controlling Recieve Enable and Driver Enable - // on the RS485 adapter, if applicable (else, -1) - // Setting HIGH enables the driver (arduino) to send text - // Setting LOW enables the receiver (sensor) to send text -// const int SSRxPin = 10; // Recieve pin for software serial (Rx on RS485 adapter) -// const int SSTxPin = 11; // Send pin for software serial (Tx on RS485 adapter) - -// Construct software serial object for Modbus -// SoftwareSerial modbusSerial(SSRxPin, SSTxPin); -AltSoftSerial modbusSerial; - -// Construct the Yosemitech modbus instance -yosemitech sensor; -bool success; - -// --------------------------------------------------------------------------- -// Main setup function -// --------------------------------------------------------------------------- -void setup() -{ - - pinMode(sensorPwrPin, OUTPUT); - digitalWrite(sensorPwrPin, HIGH); - pinMode(adapterPwrPin, OUTPUT); - digitalWrite(adapterPwrPin, HIGH); - - if (DEREPin > 0) pinMode(DEREPin, OUTPUT); - - Serial.begin(115200); // Main serial port for debugging via USB Serial Monitor - modbusSerial.begin(9600); // The modbus serial stream - Baud rate MUST be 9600. - - // Start up the sensor - sensor.begin(model, modbusAddress, &modbusSerial, DEREPin); - - // Turn on debugging - // sensor.setDebugStream(&Serial); - - // Start up note - Serial.print("Yosemitech "); - Serial.print(sensor.getModel()); - Serial.print(" sensor for "); - Serial.println(sensor.getParameter()); - - // Allow the sensor and converter to warm up - // DO responds within 275-300ms; - // Turbidity and pH within 500ms - // Conductivity doesn't respond until 1.15-1.2s - Serial.println("Waiting for sensor and adapter to be ready."); - - // Warmup time for sensor to respond to modbus commands - delay(200); - - // Get the sensor's hardware and software version - Serial.println("Getting sensor version."); - float hardwareV, softwareV; - sensor.getVersion(hardwareV, softwareV); - Serial.print(" Current Hardware Version: "); - Serial.println(hardwareV); - Serial.print(" Current Software Version: "); - Serial.println(softwareV); - - // Get the sensor serial number - Serial.println("Getting sensor serial number."); - String SN = sensor.getSerialNumber(); - Serial.print(" Serial Number: "); - Serial.println(SN); - - // Get the sensor calibration equation / status (pH only) - switch(model) - { - case Y532: // pH, calibration status - { - Serial.println("Getting sensor calibration status."); - byte status = sensor.pHCalibrationStatus(); - Serial.print(" Status: 0x0"); - Serial.println(status, HEX); - } - case Y4000: - { - Serial.println("For Y4000, use YosemiTech software to get calibration parameters."); - break; - } - default: // Get the sensor's current calibration values - { - Serial.println("Getting sensor calibration equation."); - float Kval = 0; - float Bval = 0; - sensor.getCalibration(Kval, Bval); - Serial.print(" Current Calibration Equation: final = "); - Serial.print(Kval); - Serial.print("*raw + "); - Serial.println(Bval); - } - } - - // Get/set the sensor brush status (for sensors with brushes). - // NOTE: Not implemented for Y4000 - if (model == Y511 || model == Y513 || model == Y514 || model == Y551 || model == Y560) - { - // Check the wiper timing - Serial.println("Getting sensor cleaning interval."); - uint16_t interval = sensor.getBrushInterval(); - Serial.print(" Sensor auto-cleaning interval: "); - Serial.print(interval); - Serial.println(" minutes"); - - // Reset the wiper interval to 30 minutes, the default - Serial.println("Resetting cleaning interval to 30 minutes."); - success = sensor.setBrushInterval(30); - if (success) Serial.println(" Reset."); - else Serial.println(" Set interval failed!"); - } - - // Tell the sensor to start taking measurements - Serial.println("Starting sensor measurements"); - success = sensor.startMeasurement(); - if (success) Serial.println(" Measurements started."); - else Serial.println(" Failed to start measuring!"); - - // Skip stabilization and brush cycle to test for timing - - - // Print table headers - switch (model) - { - case Y4000: - { - Serial.print("Time, "); - Serial.println(sensor.getParameter()); - // "DO, Turb, Cond, pH, Temp, ORP, Chl, BGA" - Serial.print("ms, "); - Serial.println(sensor.getUnits()); - // "mg/L, NTU, mS/cm, pH, °C, mV, µg/L, µg/L" - break; - } - default: - { - Serial.print("Time(ms) "); - Serial.print("Temp(°C) "); - Serial.print(sensor.getParameter()); - Serial.print("("); - Serial.print(sensor.getUnits()); - Serial.print(")"); - if (model == Y532 || model == Y504) Serial.print(" Value"); - if (model == Y551) Serial.print(" Turbidity (NTU)"); - if (model == Y560) Serial.print(" pH"); - Serial.println(); - } - } - -} - -// --------------------------------------------------------------------------- -// Main loop function -// --------------------------------------------------------------------------- -void loop() -{ - // send the command to get the values - switch (model) - { - case Y4000: - { - float DOmgL, Turbidity, Cond, pH, Temp, ORP, Chlorophyll, BGA = -9999; - // byte errorCode = 0xFF; // Error! - - sensor.getValues(DOmgL, Turbidity, Cond, pH, Temp, ORP, Chlorophyll, BGA); - - Serial.print(millis()); - Serial.print(" "); - Serial.print(DOmgL); - Serial.print(" "); - Serial.print(Turbidity); - Serial.print(" "); - Serial.print(Cond); - Serial.print(" "); - Serial.print(pH); - Serial.print(" "); - Serial.print(Temp); - Serial.print(" "); - Serial.print(ORP); - Serial.print(" "); - Serial.print(Chlorophyll); - Serial.print(" "); - Serial.print(BGA); - Serial.println(); - break; - } - default: - { - float parmValue, tempValue, thirdValue = -9999; - sensor.getValues(parmValue, tempValue, thirdValue); - - Serial.print(millis()); - Serial.print(" "); - Serial.print(tempValue); - Serial.print(" "); - Serial.print(parmValue); - if (model == Y532 || model == Y504 || model == Y551 || model == Y560) - { - Serial.print(" "); - Serial.print(thirdValue); - } - Serial.println(); - } - } - - - - // Delay between readings - // Modbus manuals recommend the following re-measure times: - // 2 s for chlorophyll - // 2 s for turbidity - // 3 s for conductivity - // 1 s for DO - // 2 s for COD - // 2 s for Ammonium - - // The turbidity and DO sensors appear return new readings about every 1.6 seconds. - // The pH sensor returns new readings about every 1.8 seconds. - // The conductivity sensor only returns new readings about every 2.7 seconds. - - // The temperature sensors can take readings much more quickly. The same results - // can be read many times from the registers between the new sensor readings. - delay(500); -} diff --git a/examples/GetValues/GetValues.ino b/examples/GetValues/GetValues.ino index 6327e4e..051c6c9 100644 --- a/examples/GetValues/GetValues.ino +++ b/examples/GetValues/GetValues.ino @@ -11,61 +11,133 @@ Yosemitech modbus sensor. // --------------------------------------------------------------------------- // Include the base required libraries // --------------------------------------------------------------------------- -#if defined ESP8266 -#include -#include -#endif + #include +#include + #if defined __AVR__ -#include #include +// #include #endif -#include -// --------------------------------------------------------------------------- -// Set up the sensor specific information -// ie, pin locations, addresses, calibrations and related settings -// --------------------------------------------------------------------------- +#if defined ESP8266 +#include +#include +#endif + +// Turn on debugging outputs (i.e. raw Modbus requests & responsds) +// by uncommenting next line (i.e. `#define DEBUG`) +// #define DEBUG + +// ========================================================================== +// Sensor Settings +// ========================================================================== // Define the sensor type -yosemitechModel model = Y560; // The sensor model number +yosemitechModel model = Y700; // The sensor model number + +// Define the sensor's modbus address, or SlaveID +// NOTE: YosemiTech Windows software presents SlaveID as an integer (decimal), +// whereas EnviroDIY and most other modbus systems present it in hexadecimal form. +// Use an online "HEX to DEC Converter". +byte modbusAddress = 0x01; // Yosemitech ships sensors with a default ID of 0x01. + +// Sensor Timing +// Edit these to explore +#define WARM_UP_TIME 1000 // milliseconds for sensor to respond to commands. + // DO responds within 275-300ms; + // Turbidity and pH within 500ms + // Conductivity doesn't respond until 1.15-1.2s + +#define BRUSH_TIME 10000 // milliseconds for readings to stablize. + // On wipered (self-cleaning) models, the brush immediately activates after + // getting power and takes approximately 10-15 seconds to finish. + // Turbidity takes 10-11 s + // Ammonium takes 15 s + // No readings should be taken during this time. + +#define STABILIZATION_TIME 4000 // milliseconds for readings to stablize. + // The modbus manuals recommend the following stabilization times between starting + // measurements and requesting values (times include brushing time): + // 2 s for whipered chlorophyll + // 20 s for turbidity, including 11 s to complete a brush cycle + // 10 s for conductivity + // 2 s for COD + // 20 s for Ammonium, including 15 s to complete a brush cycle + + // pH returns values after ~4.5 seconds + // Conductivity returns values after about 2.4 seconds, but is not stable + // until ~10 seconds. + // DO does not return values until ~8 seconds + // Turbidity takes ~22 seconds to get stable values. + // Y700 Water Level takes 4 s to get stability <1 mm, but 12 s for <0.1 mm + +#define MEASUREMENT_TIME 1000 // milliseconds to complete a measurement. + // Modbus manuals recommend the following re-measure times: + // 2 s for chlorophyll + // 2 s for turbidity + // 3 s for conductivity + // 1 s for DO + // 2 s for COD + // 2 s for Ammonium + // The turbidity and DO sensors appear return new readings about every 1.6 seconds. + // The pH sensor returns new readings about every 1.8 seconds. + // The conductivity sensor only returns new readings about every 2.7 seconds. + // The temperature sensors can take readings much more quickly. The same results + // can be read many times from the registers between the new sensor readings. -// Define the sensor's modbus address -byte modbusAddress = 0x01; // The sensor's modbus address, or SlaveID -// Yosemitech ships sensors with a default ID of 0x01. + +// ========================================================================== +// Data Logging Options +// ========================================================================== +const int32_t serialBaud = 115200; // Baud rate for serial monitor // Define pin number variables -const int sensorPwrPin = 10; // The pin sending power to the sensor +const int sensorPwrPin = 11; // The pin sending power to the sensor const int adapterPwrPin = 22; // The pin sending power to the RS485 adapter const int DEREPin = -1; // The pin controlling Recieve Enable and Driver Enable // on the RS485 adapter, if applicable (else, -1) // Setting HIGH enables the driver (arduino) to send text // Setting LOW enables the receiver (sensor) to send text +// Pins for `SoftwareSerial` only. Not for `AltSoftSerial`, which uses fixed pins. const int SSRxPin = 13; // Receive pin for software serial (Rx on RS485 adapter) const int SSTxPin = 14; // Send pin for software serial (Tx on RS485 adapter) // Construct software serial object for Modbus #if defined __AVR__ -// SoftwareSerial modbusSerial(SSRxPin, SSTxPin); -AltSoftSerial modbusSerial; + // SoftwareSerial modbusSerial(SSRxPin, SSTxPin); + AltSoftSerial modbusSerial; #elif defined ESP8266 -SoftwareSerial modbusSerial; + SoftwareSerial modbusSerial; #elif defined(NRF52832_FEATHER) || defined(ARDUINO_NRF52840_FEATHER) -#include -HardwareSerial& modbusSerial = Serial1; + #include + HardwareSerial& modbusSerial = Serial1; #elif !defined(NO_GLOBAL_SERIAL1) -HardwareSerial& modbusSerial = Serial1; + HardwareSerial& modbusSerial = Serial1; #else -HardwareSerial& modbusSerial = Serial; + HardwareSerial& modbusSerial = Serial; #endif // Construct the Yosemitech modbus instance yosemitech sensor; bool success; -// --------------------------------------------------------------------------- -// Main setup function -// --------------------------------------------------------------------------- + +// ========================================================================== +// Working Functions +// ========================================================================== +// A function for pretty-printing the Modbuss Address, from ModularSensors +String sensorLocation(byte _modbusAddress) { + String sensorLocation = F("0x"); + if (_modbusAddress < 0x10) sensorLocation += "0"; + sensorLocation += String(_modbusAddress, HEX); + return sensorLocation; +} + + +// ========================================================================== +// Arduino Setup Function +// ========================================================================== void setup() { if (sensorPwrPin > 0) { pinMode(sensorPwrPin, OUTPUT); @@ -82,34 +154,68 @@ void setup() { if (DEREPin > 0) pinMode(DEREPin, OUTPUT); - Serial.begin(115200); // Main serial port for debugging via USB Serial Monitor -#if defined ESP8266 - modbusSerial.begin(9600, SWSERIAL_8N1, SSRxPin, SSTxPin, false, 256); // The modbus serial stream - Baud rate MUST be 9600. -#else - modbusSerial.begin(9600); // The modbus serial stream - Baud rate MUST be 9600. -#endif + Serial.begin(serialBaud); // Main serial port for debugging via USB Serial Monitor + + // Setup Modbus serial stream + #if defined ESP8266 + modbusSerial.begin(9600, SWSERIAL_8N1, SSRxPin, SSTxPin, false, 256); // The modbus serial stream - Baud rate MUST be 9600. + #else + modbusSerial.begin(9600); // The modbus serial stream - Baud rate MUST be 9600. + #endif // Start up the sensor sensor.begin(model, modbusAddress, &modbusSerial, DEREPin); // Turn on debugging - sensor.setDebugStream(&Serial); + #ifdef DEBUG + sensor.setDebugStream(&Serial); + #endif // Start up note - Serial.print("Yosemitech "); + Serial.print("\nYosemitech "); Serial.print(sensor.getModel()); Serial.print(" sensor for "); Serial.println(sensor.getParameter()); // Allow the sensor and converter to warm up - // DO responds within 275-300ms; - // Turbidity and pH within 500ms - // Conductivity doesn't respond until 1.15-1.2s - Serial.println("Waiting for sensor and adapter to be ready."); - delay(1500); + Serial.println("\nWaiting for sensor and adapter to be ready."); + Serial.print(" Warm up time (ms): "); + Serial.println(WARM_UP_TIME); + delay(WARM_UP_TIME); + + // Confirm Modbus Address + Serial.println("\nSelected modbus address:"); + Serial.print(" integer: "); + Serial.print(modbusAddress, DEC); + Serial.print(", hexidecimal: "); + Serial.println(sensorLocation(modbusAddress)); + + Serial.println("Discovered modbus address."); + Serial.print(" integer: "); + byte id = sensor.getSlaveID(); + Serial.print(id, DEC); + Serial.print(", hexidecimal: "); + // Serial.print(id, HEX); + Serial.println(sensorLocation(id)); + + if (id != modbusAddress){ + Serial.print("Updating sensor modbus address to: "); + modbusAddress = id; + Serial.println(sensorLocation(modbusAddress)); + Serial.println(); + // Restart the sensor + sensor.begin(model, modbusAddress, &modbusSerial, DEREPin); + delay(1500); + }; + // Get the sensor serial number + Serial.println("\nGetting sensor serial number."); + String SN = sensor.getSerialNumber(); + Serial.print(" Serial Number: "); + Serial.println(SN); + // Get the sensor's hardware and software version - Serial.println("Getting sensor version."); + Serial.println("Getting sensor version numbers."); float hardwareV, softwareV; sensor.getVersion(hardwareV, softwareV); Serial.print(" Current Hardware Version: "); @@ -117,12 +223,6 @@ void setup() { Serial.print(" Current Software Version: "); Serial.println(softwareV); - // Get the sensor serial number - Serial.println("Getting sensor serial number."); - String SN = sensor.getSerialNumber(); - Serial.print(" Serial Number: "); - Serial.println(SN); - // Get the sensor calibration equation / status (pH only) switch(model) { @@ -149,6 +249,7 @@ void setup() { Serial.print("*raw + "); Serial.println(Bval); } + Serial.println(); } // Get/set the sensor brush status (for sensors with brushes). @@ -156,7 +257,7 @@ void setup() { if (model == Y511 || model == Y513 || model == Y514 || model == Y551 || model == Y560) { // Check the wiper timing - Serial.println("Getting sensor cleaning interval."); + Serial.println("\nGetting sensor cleaning interval."); uint16_t interval = sensor.getBrushInterval(); Serial.print(" Sensor auto-cleaning interval: "); Serial.print(interval); @@ -169,44 +270,7 @@ void setup() { else Serial.println(" Set interval failed!"); } - // Tell the sensor to start taking measurements - Serial.println("Starting sensor measurements"); - success = sensor.startMeasurement(); - if (success) Serial.println(" Measurements started."); - else Serial.println(" Failed to start measuring!"); - - // The modbus manuals recommend the following warm-up times between starting - // measurements and requesting values : - // 2 s for whipered chlorophyll - // 20 s for turbidity - // 10 s for conductivity - // 2 s for COD - // 20 s for Ammonium, due to 15 s to complete a brush cycle - - - // On wipered (self-cleaning) models, the brush immediately activates after - // getting power and takes approximately 10-11 seconds to finish. No - // readings should be taken during this time. - - // pH returns values after ~4.5 seconds - // Conductivity returns values after about 2.4 seconds, but is not stable - // until ~10 seconds. - // DO does not return values until ~8 seconds - // Turbidity takes ~22 seconds to get stable values. - Serial.println("Allowing sensor to stabilize.."); - for (int i = 10; i > 0; i--) - { - Serial.print(i); - delay (250); - Serial.print("."); - delay (250); - Serial.print("."); - delay (250); - Serial.print("."); - delay (250); - } - Serial.println("\n"); - + // Activate the brush, for sensors that have a brush. if (model == Y511 || model == Y513 || model == Y514 || model == Y551 || model == Y560 || model == Y4000) // Y4000 activates brush when powered on { @@ -216,11 +280,13 @@ void setup() { if (success) Serial.println(" Brush activated."); else Serial.println(" Failed to activate brush!"); } - + // Additional stabilization time for sensors that have a brush to complete a brush cycle. if (model == Y511 || model == Y513 || model == Y514 || model == Y551 || model == Y560 || model == Y4000 || model == Y510) { - Serial.println("Continuing to stabilize.."); - for (int i = 12; i > 0; i--) + Serial.println("Waiting to complete brushing cycle.."); + Serial.print(" Brush time (ms): "); + Serial.println(BRUSH_TIME); + for (int i = (BRUSH_TIME+500)/1000; i > 0; i--) // +500 to round up { Serial.print(i); delay (250); @@ -234,21 +300,45 @@ void setup() { Serial.println("\n"); } + // Tell the sensor to start taking measurements + Serial.println("Starting sensor measurements"); + success = sensor.startMeasurement(); + if (success) Serial.println(" Measurements started."); + else Serial.println(" Failed to start measuring!"); + + Serial.println("Waiting for sensor to stabilize.."); + Serial.print(" Stabilization time (ms): "); + Serial.println(STABILIZATION_TIME); + for (int i = (STABILIZATION_TIME+500)/1000; i > 0; i--) // +500 to round up + { + Serial.print(i); + delay (250); + Serial.print("."); + delay (250); + Serial.print("."); + delay (250); + Serial.print("."); + delay (250); + } + Serial.println("\n"); + + // Print table headers switch (model) { case Y4000: { - Serial.print("Time, "); + Serial.print("Time(ms) "); Serial.println(sensor.getParameter()); // "DO, Turb, Cond, pH, Temp, ORP, Chl, BGA" - Serial.print("ms, "); + Serial.print("ms "); Serial.println(sensor.getUnits()); // "mg/L, NTU, mS/cm, pH, °C, mV, µg/L, µg/L" break; } default: { + Serial.print("Time(ms) "); Serial.print("Temp(°C) "); Serial.print(sensor.getParameter()); Serial.print("("); @@ -260,12 +350,11 @@ void setup() { Serial.println(); } } - } -// --------------------------------------------------------------------------- -// Main loop function -// --------------------------------------------------------------------------- +// ========================================================================== +// Arduino Loop Function +// ========================================================================== void loop() { // send the command to get the values @@ -279,22 +368,22 @@ void loop() sensor.getValues(DOmgL, Turbidity, Cond, pH, Temp, ORP, Chlorophyll, BGA); Serial.print(millis()); + Serial.print(" "); + Serial.print(DOmgL, 4); Serial.print(" "); - Serial.print(DOmgL); + Serial.print(Turbidity, 4); Serial.print(" "); - Serial.print(Turbidity); + Serial.print(Cond, 4); Serial.print(" "); - Serial.print(Cond); + Serial.print(pH, 4); Serial.print(" "); - Serial.print(pH); + Serial.print(Temp, 4); Serial.print(" "); - Serial.print(Temp); + Serial.print(ORP, 4); Serial.print(" "); - Serial.print(ORP); + Serial.print(Chlorophyll, 4); Serial.print(" "); - Serial.print(Chlorophyll); - Serial.print(" "); - Serial.print(BGA); + Serial.print(BGA, 4); Serial.println(); break; } @@ -302,34 +391,21 @@ void loop() { float parmValue, tempValue, thirdValue = -9999; sensor.getValues(parmValue, tempValue, thirdValue); - Serial.print(tempValue); - Serial.print(" "); - Serial.print(parmValue); + + Serial.print(millis()); + Serial.print(" "); + Serial.print(tempValue, 4); + Serial.print(" "); + Serial.print(parmValue, 4); if (model == Y532 || model == Y504 || model == Y551 || model == Y560) { - Serial.print(" "); - Serial.print(thirdValue); + Serial.print(" "); + Serial.print(thirdValue, 4); } Serial.println(); } } - - // Delay between readings - // Modbus manuals recommend the following re-measure times: - // 2 s for chlorophyll - // 2 s for turbidity - // 3 s for conductivity - // 1 s for DO - // 2 s for COD - // 2 s for Ammonium - - // The turbidity and DO sensors appear return new readings about every 1.6 seconds. - // The pH sensor returns new readings about every 1.8 seconds. - // The conductivity sensor only returns new readings about every 2.7 seconds. - - // The temperature sensors can take readings much more quickly. The same results - // can be read many times from the registers between the new sensor readings. - delay(5000); + delay(MEASUREMENT_TIME); } diff --git a/library.json b/library.json index 8afb886..36af640 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "YosemitechModbus", - "version": "0.3.2", + "version": "0.4.0", "keywords": "Yosemitech, Modbus, communication, bus, sensor", "description": "Arduino library for communication with Yosemitech sensors via Modbus.", "repository": { diff --git a/library.properties b/library.properties index 62c6b41..e32f478 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=YosemitechModbus -version=0.3.2 +version=0.4.0 author=Sara Damiano maintainer=Sara Damiano sentence=Arduino library for communication with Yosemitech sensors via Modbus. diff --git a/src/YosemitechModbus.cpp b/src/YosemitechModbus.cpp index b3af4a4..dfa5899 100644 --- a/src/YosemitechModbus.cpp +++ b/src/YosemitechModbus.cpp @@ -47,6 +47,7 @@ String yosemitech::getModel(void) case Y550: {return "Y550";} case Y551: {return "Y551";} case Y560: {return "Y560";} + case Y700: {return "Y700";} case Y4000: {return "Y4000";} default: {return "Unknown";} } @@ -71,6 +72,7 @@ String yosemitech::getParameter(void) case Y550: {return "COD";} case Y551: {return "COD";} case Y560: {return "Ammonium";} + case Y700: {return "Pressure";} case Y4000: {return "DO, Turb, Cond, pH, Temp, ORP, Chl, BGA";} default: {return "Unknown";} } @@ -95,6 +97,7 @@ String yosemitech::getUnits(void) case Y550: {return "mg/L, NTU";} case Y551: {return "mg/L, NTU";} case Y560: {return "mg/L";} + case Y700: {return "mm H2O";} case Y4000: {return "mg/L, NTU, mS/cm, pH, °C, mV, µg/L, µg/L";} default: {return "Unknown";} } @@ -109,8 +112,9 @@ byte yosemitech::getSlaveID(void) byte command[8] = {0xFF, 0x03, 0x30, 0x00, 0x00, 0x01, 0x9E, 0xD4}; int respSize = modbus.sendCommand(command, 8); - if (respSize == 7) return modbus.responseBuffer[3]; - else return 0x01; // This is the default address + // if (respSize == 7) return modbus.responseBuffer[3]; + // else return 0x01; // This is the default address + return modbus.responseBuffer[3]; } @@ -136,8 +140,8 @@ String yosemitech::getSerialNumber(void) SN = modbus.StringFromRegister(0x03, 0x0900, 14); break; // for all sensors except Y4000 } - // Strip out the initial ')' that seems to come with some responses - if (SN.startsWith(")")) + // Strip out the initial ')' or '$' that seems to come with some responses + if (SN.startsWith(")") || SN.startsWith("$")) { SN = SN.substring(1); } @@ -154,10 +158,12 @@ String yosemitech::getSerialNumber(void) if (modelSS == 9) _model = Y520; // 09 means conductivity sensor if (modelSS == 10) _model = Y510; // 10 means turbidity sensor if (modelSS == 29) _model = Y511; // 29 means self-cleaning turbidity sensor + if (modelSS == 61) _model = Y513; // 61 means Blue Green Algae (BGA) if (modelSS == 48) _model = Y514; // 48 means chlorophyll if (modelSS == 43) _model = Y532; // 43 must mean pH if (modelSS == 47) _model = Y551; // 47 must mean COD if (modelSS == 68) _model = Y560; // 68 must mean Ammonium + if (modelSS == 24) _model = Y700; // 24 must mean Pressure/Depth if (modelSS == 38) _model = Y4000; // 38 must mean MultiParameter Sonde } @@ -213,12 +219,14 @@ bool yosemitech::startMeasurement(void) if (respSize == 8 && modbus.responseBuffer[0] == _slaveID) return true; else return false; } - // Y532 (pH), Y533 (ORP), Y560 (Ammonium) ion selective elctrodes do not - // require Start/Stop functions, which are not listed in their Modbus Manuals. + // Y532 (pH), Y533 (ORP), Y560 (Ammonium) ion selective elctrodes, and + // Y700 (Pressure/Depth) sensors do not require Start/Stop functions. + // These commands are not in their Modbus Manuals. // However, Start/Stop functions are required to get these to work in ModularSensors. case Y532: case Y533: case Y560: + case Y700: { return true; } @@ -243,12 +251,14 @@ bool yosemitech::stopMeasurement(void) { switch (_model) { - // Y532 (pH), Y533 (ORP), Y560 (Ammonium) ion selective elctrodes do not - // require Start/Stop functions, which are not listed in their Modbus Manuals. + // Y532 (pH), Y533 (ORP), Y560 (Ammonium) ion selective elctrodes, and + // Y700 (Pressure/Depth) sensors do not require Start/Stop functions. + // These commands are not in their Modbus Manuals. // However, Start/Stop functions are required to get these to work in ModularSensors. case Y532: case Y533: case Y560: + case Y700: { return true; } @@ -438,6 +448,19 @@ bool yosemitech::getValues(float &parmValue, float &tempValue, float &thirdValue } break; } + // Y700 Pressure/Depth + case Y700: + { + if (modbus.getRegisters(0x03, 0x2600, 6)) + { + parmValue = modbus.float32FromFrame(littleEndian, 7); + errorCode = modbus.byteFromFrame(11); + // Get temperature at register 0x2400, after Frame is read + tempValue = modbus.float32FromRegister(0x03, 0x2400, littleEndian); + return true; + } + break; + } // Everybody else other than Y4000 Sonde; Y551 COD; Y532 (pH); Y533 (ORP); Y502 & Y504 (DO) default: { @@ -481,7 +504,9 @@ bool yosemitech::getValues(float &parmValue) return getValues(parmValue, errorCode); } -// Get 8 values for the multiparameter sonde, with or without error flag +// Get 8 values for the Y4000 multiparameter sonde, with or without error flag +// Note that only 6 sensors can be connected at a time, +// so only 7 values (including temperature) will be returned. bool yosemitech::getValues(float &DOmgL, float &Turbidity, float &Cond, float &pH, float &Temp, float &ORP, float &Chlorophyll, float &BGA, byte &errorCode) @@ -502,7 +527,7 @@ bool yosemitech::getValues(float &DOmgL, float &Turbidity, float &Cond, case Y4000: // Y4000 Multiparameter sonde { // Sonde's 8 values begin in register 260 - if (modbus.getRegisters(0x03, 0x2601, 10)) + if (modbus.getRegisters(0x03, 0x2601, 16)) // Modbus manual has error! { DOmgL = modbus.float32FromFrame(littleEndian, 3); // DOmgL Turbidity = modbus.float32FromFrame(littleEndian, 7); // Turbidity diff --git a/src/YosemitechModbus.h b/src/YosemitechModbus.h index 8f6d49d..35cd4d2 100644 --- a/src/YosemitechModbus.h +++ b/src/YosemitechModbus.h @@ -43,6 +43,8 @@ typedef enum yosemitechModel // http://en.yosemitech.com/aspcms/product/2020-5-8/94.html Y560, // NH4 Probe // http://en.yosemitech.com/aspcms/product/2020-4-23/61.html + Y700, // Water Pressure/Depth Sensor + // Prototype developed for Clean Water Services Y4000, // Multiparameter Sonde // http://en.yosemitech.com/aspcms/product/2020-5-8/95.html UNKNOWN // Use if the sensor model is unknown. Doing this is generally a