Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update RainCounterIC2 to support reed-switch anemometer #384

Merged
merged 4 commits into from
Oct 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

****
## v0.30.1 (2021-10-01) Add support for TippingBucketRainCounter v0.2.0

### Improvements
- Added support for [v0.2.0](https://github.com/EnviroDIY/TippingBucketRainCounter/releases) of the [EnviroDIY/TippingBucketRainCounter](https://github.com/EnviroDIY/TippingBucketRainCounter) device firmware, which added capability to count rotations on a reed-switch anemometer and fixed a critical bug that failed to count high rainfall rates. For details, see:
- https://github.com/EnviroDIY/TippingBucketRainCounter/releases/tag/v0.2.0


## v0.30.0 (2021-07-06) Remove support for SoftwareWire for Atlas sensors

### New Features
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.30.0
v0.30.1
2 changes: 1 addition & 1 deletion docs/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = ModularSensors
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 0.30.0
PROJECT_NUMBER = 0.30.1

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "EnviroDIY_ModularSensors",
"version": "0.30.0",
"version": "0.30.1",
"description": "A library that allows access to multiple sensors through a unified interface. This allows the user to simply access many sensors to log the data or send the data to data repositories like the EnviroDIY data portal.",
"keywords": "modular, sensor, sensors, datalogger, logger, low power, sleeping, EnviroDIY, ModularSensors, Mayfly, WikiWatershed, Monitor My Watershed, ThingSpeak",
"platforms": "atmelavr, atmelsam",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=EnviroDIY_ModularSensors
version=0.30.0
version=0.30.1
author=Sara Damiano <[email protected]>, Shannon Hicks <[email protected]>
maintainer=Sara Damiano <[email protected]>
sentence=A library that allows access to multiple sensors through a unified interface.
Expand Down
270 changes: 270 additions & 0 deletions sensor_tests/RainCounter_simple_logging/RainCounter_simple_logging.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
/** =========================================================================
* @file RainCounter_simple_logging.ino
* @brief Test improvements to RainCounterI2C, based on simple logging example.
*
* @author Sara Geleskie Damiano <[email protected]>
* @author Anthony Aufdenkampe <[email protected]>
* @copyright (c) 2017-2020 Stroud Water Research Center (SWRC)
* and the EnviroDIY Development Team
* This example is published under the BSD-3 license.
*
* Build Environment: Atom with PlatformIO Core 5.1.1·Home 3.3.4
* Modular Sensors v0.28.3 as of April 5, 2021
* Hardware Platform: EnviroDIY Mayfly Arduino Datalogger
*
* DISCLAIMER:
* THIS CODE IS PROVIDED "AS IS" - NO WARRANTY IS GIVEN.
* ======================================================================= */

// ==========================================================================
// Include the libraries required for any data logger
// ==========================================================================
/** Start [includes] */
// The Arduino library is needed for every Arduino program.
#include <Arduino.h>

// EnableInterrupt is used by ModularSensors for external and pin change
// interrupts and must be explicitly included in the main program.
#include <EnableInterrupt.h>

// To get all of the base classes for ModularSensors, include LoggerBase.
// NOTE: Individual sensor definitions must be included separately.
#include <LoggerBase.h>
/** End [includes] */


// ==========================================================================
// Data Logging Options
// ==========================================================================
/** Start [logging_options] */
// The name of this program file
const char* sketchName = "RainCounter_simple_logging.ino";
// Logger ID, also becomes the prefix for the name of the data file on SD card
const char* LoggerID = "RainCounter_Tester";
// How frequently (in minutes) to log data
const uint8_t loggingInterval = 1;
// Your logger's timezone.
const int8_t timeZone = -6; // Eastern Standard Time
// NOTE: Daylight savings time will not be applied! Please use standard time!

// Set the input and output pins for the logger
// NOTE: Use -1 for pins that do not apply
const int32_t serialBaud = 115200; // Baud rate for debugging
const int8_t greenLED = 8; // Pin for the green LED
const int8_t redLED = 9; // Pin for the red LED
const int8_t buttonPin = 21; // Pin for debugging mode (ie, button pin)
const int8_t wakePin = A7; // MCU interrupt/alarm pin to wake from sleep
// Set the wake pin to -1 if you do not want the main processor to sleep.
// In a SAMD system where you are using the built-in rtc, set wakePin to 1
const int8_t sdCardPwrPin = -1; // MCU SD card power pin
const int8_t sdCardSSPin = 12; // SD card chip select/slave select pin
const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power
/** End [logging_options] */


// ==========================================================================
// Using the Processor as a Sensor
// ==========================================================================
/** Start [processor_sensor] */
#include <sensors/ProcessorStats.h>

// Create the main processor chip "sensor" - for general metadata
const char* mcuBoardVersion = "v0.5b";
ProcessorStats mcuBoard(mcuBoardVersion);
/** End [processor_sensor] */


// ==========================================================================
// Maxim DS3231 RTC (Real Time Clock)
// ==========================================================================
/** Start [ds3231] */
#include <sensors/MaximDS3231.h> // Includes wrapper functions for Maxim DS3231 RTC

// Create a DS3231 sensor object, using this constructor function:
MaximDS3231 ds3231(1);
/** End [ds3231] */


// ==========================================================================
// Settings for Additional Sensors
// ==========================================================================

// ==========================================================================
// External I2C Rain Tipping Bucket Counter, connected to an anemometer
// ==========================================================================
/** Start [i2c_rain] */
#include <sensors/RainCounterI2C.h>

const uint8_t RainCounterI2CAddress = 0x08;
// I2C Address for EnviroDIY external tip counter; 0x08 by default
const float depthPerTipEvent = 0.2; // rain depth in mm per tip event

// Create a Rain Counter sensor object
RainCounterI2C tbi2c(RainCounterI2CAddress, depthPerTipEvent);

// Create number of tips and rain depth variable pointers for the tipping bucket
Variable* tbi2cTips =
new RainCounterI2C_Tips(&tbi2c, "12345678-abcd-1234-ef00-1234567890ab");
// Variable* tbi2cDepth =
// new RainCounterI2C_Depth(&tbi2c, "12345678-abcd-1234-ef00-1234567890ab");
/** End [i2c_rain] */


// ==========================================================================
// Calculated Variables
// ==========================================================================

// Create the function to give your calculated result.
// The function should take no input (void) and return a float.
// You can use any named variable pointers to access values by way of
// variable->getValue()

float calculateWindSpeed(void) {
float windSpeed = -9999; // Always safest to start with a bad value
float period = -9999; // seconds between gettting event counts
float frequency = -9999; // average event frequency in Hz
float eventCount = tbi2cTips->getValue();
if (eventCount != -9999) // make sure both inputs are good
{
period = loggingInterval * 60.0; // in seconds
frequency = eventCount/period; // average event frequency in Hz
windSpeed = frequency * 2.5 * 1.60934; // in km/h,
// 2.5 mph/Hz & 1.60934 kmph/mph and 2.5 mph/Hz conversion factor from
// https://www.store.inspeed.com/Inspeed-Version-II-Reed-Switch-Anemometer-Sensor-Only-WS2R.htm
}
return windSpeed;
}

// Properties of the calculated variable
// The number of digits after the decimal place
const uint8_t calculatedVarResolution = 3;
// This must be a value from http://vocabulary.odm2.org/variablename/
const char *calculatedVarName = "windSpeed";
// This must be a value from http://vocabulary.odm2.org/units/
const char *calculatedVarUnit = "KilometerPerHour";
// A short code for the variable
const char *calculatedVarCode = "WindSpeed";
// The (optional) universallly unique identifier
const char *calculatedVarUUID = "12345678-abcd-1234-ef00-1234567890ab";

// Create a calculated variable pointer and return a variable pointer to it
Variable *calculatedWindSpeed = new Variable(
calculateWindSpeed, calculatedVarResolution, calculatedVarName,
calculatedVarUnit, calculatedVarCode, calculatedVarUUID);


// ==========================================================================
// Creating the Variable Array[s] and Filling with Variable Objects
// ==========================================================================
/** Start [variable_arrays] */
Variable* variableList[] = {
new ProcessorStats_SampleNumber(&mcuBoard),
new ProcessorStats_FreeRam(&mcuBoard),
new ProcessorStats_Battery(&mcuBoard),
new MaximDS3231_Temp(&ds3231),
// Additional sensor variables can be added here, by copying the syntax
// for creating the variable pointer (FORM1) from the
// `menu_a_la_carte.ino` example
// The example code snippets in the wiki are primarily FORM2.
tbi2cTips,
calculatedWindSpeed,
};
// Count up the number of pointers in the array
int variableCount = sizeof(variableList) / sizeof(variableList[0]);

// Create the VariableArray object
VariableArray varArray;
/** End [variable_arrays] */


// ==========================================================================
// The Logger Object[s]
// ==========================================================================
/** Start [loggers] */
// Create a logger instance
Logger dataLogger;
/** End [loggers] */


// ==========================================================================
// Working Functions
// ==========================================================================
/** Start [working_functions] */
// Flashes the LED's on the primary board
void greenredflash(uint8_t numFlash = 4, uint8_t rate = 75) {
for (uint8_t i = 0; i < numFlash; i++) {
digitalWrite(greenLED, HIGH);
digitalWrite(redLED, LOW);
delay(rate);
digitalWrite(greenLED, LOW);
digitalWrite(redLED, HIGH);
delay(rate);
}
digitalWrite(redLED, LOW);
}
/** End [working_functions] */


// ==========================================================================
// Arduino Setup Function
// ==========================================================================
/** Start [setup] */
void setup() {
// Start the primary serial connection
Serial.begin(serialBaud);

// Print a start-up note to the first serial port
Serial.print(F("Now running "));
Serial.print(sketchName);
Serial.print(F(" on Logger "));
Serial.println(LoggerID);
Serial.println();

Serial.print(F("Using ModularSensors Library version "));
Serial.println(MODULAR_SENSORS_VERSION);

// Set up pins for the LED's
pinMode(greenLED, OUTPUT);
digitalWrite(greenLED, LOW);
pinMode(redLED, OUTPUT);
digitalWrite(redLED, LOW);
// Blink the LEDs to show the board is on and starting up
greenredflash();

// Set the timezones for the logger/data and the RTC
// Logging in the given time zone
Logger::setLoggerTimeZone(timeZone);
// It is STRONGLY RECOMMENDED that you set the RTC to be in UTC (UTC+0)
Logger::setRTCTimeZone(0);

// Set information pins
dataLogger.setLoggerPins(wakePin, sdCardSSPin, sdCardPwrPin, buttonPin,
greenLED);

// Begin the variable array[s], logger[s], and publisher[s]
varArray.begin(variableCount, variableList);
dataLogger.begin(LoggerID, loggingInterval, &varArray);

// Set up the sensors
Serial.println(F("Setting up sensors..."));
varArray.setupSensors();

// Create the log file, adding the default header to it
// Do this last so we have the best chance of getting the time correct and
// all sensor names correct
dataLogger.createLogFile(true); // true = write a new header

// Call the processor sleep
dataLogger.systemSleep();
}
/** End [setup] */


// ==========================================================================
// Arduino Loop Function
// ==========================================================================
/** Start [loop] */
void loop() {
dataLogger.logData();
}
/** End [loop] */
2 changes: 1 addition & 1 deletion src/ModularSensors.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* @brief The current library version number
*/
#define MODULAR_SENSORS_VERSION "0.30.0"
#define MODULAR_SENSORS_VERSION "0.30.1"

// To get all of the base classes for ModularSensors, include LoggerBase.
// NOTE: Individual sensor definitions must be included separately.
Expand Down
5 changes: 5 additions & 0 deletions src/SensorBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,11 @@ void Sensor::verifyAndAddMeasurementResult(uint8_t resultNumber,
float float_val = resultValue; // cast the int16_t to a float
verifyAndAddMeasurementResult(resultNumber, float_val);
}
void Sensor::verifyAndAddMeasurementResult(uint8_t resultNumber,
int32_t resultValue) {
float float_val = resultValue; // cast the int32_t to a float
verifyAndAddMeasurementResult(resultNumber, float_val);
}


void Sensor::averageMeasurements(void) {
Expand Down
6 changes: 6 additions & 0 deletions src/SensorBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,12 @@ class Sensor {
* @brief Average the results of all measurements by dividing the sum of
* all measurements by the number of measurements taken.
*/
void verifyAndAddMeasurementResult(uint8_t resultNumber,
int32_t resultValue);
/**
* @brief Average the results of all measurements by dividing the sum of
* all measurements by the number of measurements taken.
*/
void averageMeasurements(void);

/**
Expand Down
39 changes: 34 additions & 5 deletions src/sensors/RainCounterI2C.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,47 @@ bool RainCounterI2C::setup(void) {
bool RainCounterI2C::addSingleMeasurementResult(void) {
// intialize values
float rain = -9999; // Number of mm of rain
int16_t tips = -9999; // Number of tip events
int32_t tips = -9999; // Number of tip events, increased for anemometer

// Get data from external tip counter
// if the 'requestFrom' returns 0, it means no bytes were received
if (_i2c->requestFrom(static_cast<uint8_t>(_i2cAddressHex),
static_cast<uint8_t>(2))) {
static_cast<uint8_t>(4))) {
MS_DBG(getSensorNameAndLocation(), F("is reporting:"));

uint8_t Byte1 = _i2c->read(); // Low byte of data
uint8_t Byte2 = _i2c->read(); // High byte of data
uint8_t SerialBuffer[4]; // Create a byte array of 4 bytes
uint8_t byte_in = 0; // Start iterator for reading Bytes
while (Wire.available()) { // slave may send less than requested
SerialBuffer[byte_in] = Wire.read();
MS_DBG(F(" SerialBuffer["), byte_in, F("] = "),
SerialBuffer[byte_in]);
byte_in++; // increment by 1
}

// Concatenate bytes into uint32_t by bit-shifting
// https://thewanderingengineer.com/2015/05/06/sending-16-bit-and-32-bit-numbers-with-arduino-i2c/#
if ( (SerialBuffer[0] > 0)
) {
// for Slave with libVersion = v0.1.0, which only sends 1-byte
// NOTE: this can not be falsely selected because it would require
// > 16,777,216 counts from a v0.2.0 slave, which is not possible in 24 hours
MS_DBG(F(" Counted with slave libVersion = v0.1.0"));
tips = SerialBuffer[0];
} else if ( (SerialBuffer[1] == 0) &&
(SerialBuffer[2] == 255) ) {
// for Slave with libVersion = v0.1.0, in which no counts are made
// NOTE: this will be falsely selected if exactly 65535 counts
// were made by a v0.2.0 slave
MS_DBG(F(" No counts with slave libVersion = v0.1.0"));
tips = SerialBuffer[0];
} else {
// for Slave with libVersion >= v0.2.0
tips = SerialBuffer[0];
tips = (tips << 8) | SerialBuffer[1];
tips = (tips << 8) | SerialBuffer[2];
tips = (tips << 8) | SerialBuffer[3];
}

tips = (Byte2 << 8) | (Byte1); // Concatenate tip values
rain = static_cast<float>(tips) *
_rainPerTip; // Multiply by tip coefficient (0.2 by default)

Expand Down