From d425d6fcd5479a77596e740fdb5f28c7e823e8f9 Mon Sep 17 00:00:00 2001 From: jdh Date: Tue, 26 Sep 2023 14:08:19 -0400 Subject: [PATCH] adding anya actuator branch --- CHANGELOG.md | 4 +- platformio.ini | 6 +- src/datalogger.cpp | 91 ++++++---- src/datalogger.h | 4 +- src/main.cpp | 14 +- src/sensors/drivers/BME280_driver.cpp | 146 ++++++++++++++++ src/sensors/drivers/BME280_driver.h | 76 ++++++++ src/sensors/drivers/adafruit_ahtx0.cpp | 152 ++++++++++++++++ src/sensors/drivers/adafruit_ahtx0.h | 77 +++++++++ src/sensors/drivers/adafruit_dht22.cpp | 18 ++ src/sensors/drivers/air_pump.cpp | 210 +++++++++++++++++++++++ src/sensors/drivers/air_pump.h | 121 +++++++++++++ src/sensors/drivers/atlas_co2_driver.cpp | 24 +++ src/sensors/drivers/atlas_ec.cpp | 2 +- src/sensors/drivers/driver_template.cpp | 80 +++++---- src/sensors/drivers/generic_actuator.cpp | 156 +++++++++++++++++ src/sensors/drivers/generic_actuator.h | 92 ++++++++++ src/sensors/drivers/registry.cpp | 28 +-- src/sensors/drivers/registry.h | 5 + src/sensors/sensor.cpp | 12 +- src/sensors/sensor.h | 21 ++- src/system/command.cpp | 55 +++++- src/system/command.h | 6 + src/system/hardware.cpp | 59 ++++++- src/system/hardware.h | 23 ++- src/utilities/rrivmath 2.h | 7 + 26 files changed, 1384 insertions(+), 105 deletions(-) create mode 100644 src/sensors/drivers/BME280_driver.cpp create mode 100644 src/sensors/drivers/BME280_driver.h create mode 100644 src/sensors/drivers/adafruit_ahtx0.cpp create mode 100644 src/sensors/drivers/adafruit_ahtx0.h create mode 100644 src/sensors/drivers/air_pump.cpp create mode 100644 src/sensors/drivers/air_pump.h create mode 100644 src/sensors/drivers/generic_actuator.cpp create mode 100644 src/sensors/drivers/generic_actuator.h create mode 100644 src/utilities/rrivmath 2.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f94a1a..a771a40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,8 +26,8 @@ * upgraded to maple 14.0.0 ([23a4d48](https://github.com/WaterBearSondes/waterbear-firmware/commit/23a4d48ed5a4cde8f87365d09ca46ac12acf1145)) * upgraded to maple v14.0.0 ([bea4157](https://github.com/WaterBearSondes/waterbear-firmware/commit/bea4157acd4f2feaba3784daeb0e8326a756bda9)) - -# [1.1.0](https://github.com/WaterBearSondes/waterbear-firmware/compare/v1.0.10...v1.1.0) (2021-05-22) +# + [1.1.0](https://github.com/WaterBearSondes/waterbear-firmware/compare/v1.0.10...v1.1.0) (2021-05-22) ### Bug Fixes diff --git a/platformio.ini b/platformio.ini index 1f9abc4..a400892 100644 --- a/platformio.ini +++ b/platformio.ini @@ -24,7 +24,8 @@ build_unflags = -O2 #build_unflags = -std=gnu++11 board_build.f_cpu = 64000000L lib_deps = - https://github.com/ZavenArra/ModularSensors#stm32f1 + ; git@github.com:ZavenArra/ModularSensors.git#stm32f1 + https://github.com/ZavenArra/ModularSensors.git#stm32f1 ; https://github.com/deepwinter/Adafruit_BluefruitLE_nRF51.git https://github.com/WaterBearSondes/DS3231.git https://github.com/WaterBearSondes/atlas_OEM.git @@ -32,9 +33,10 @@ lib_deps = https://github.com/DaveGamble/cJSON.git https://github.com/ZavenArra/CmdArduino.git https://github.com/adafruit/DHT-sensor-library.git + https://github.com/adafruit/Adafruit_AHTX0.git + https://github.com/adafruit/Adafruit_BME280_Library.git ;adafruit/DHT sensor library monitor_speed = 115200 debug_port = /dev/ttyACM0 check_tool = cppcheck check_flags = --enable=all - diff --git a/src/datalogger.cpp b/src/datalogger.cpp index eac8696..b0f0185 100644 --- a/src/datalogger.cpp +++ b/src/datalogger.cpp @@ -29,6 +29,11 @@ #include "utilities/STM32-UID.h" #include "scratch/dbgmcu.h" #include "system/logs.h" +#include "sensors/drivers/air_pump.h" +#include "sensors/drivers/generic_actuator.h" + +// #include "sensors/drivers/air_pump.h" +// #include "sensors/drivers/generic_actuator.h" void Datalogger::sleepMCU(uint32 milliseconds) { @@ -96,12 +101,15 @@ Datalogger::Datalogger(datalogger_settings_type *settings) { powerCycle = true; - // defaults + //defaults if (settings->interval < 1) { settings->interval = 1; } + + + memcpy(&this->settings, settings, sizeof(datalogger_settings_type)); switch (settings->mode) @@ -165,15 +173,19 @@ bool Datalogger::processReadingsCycle() { writeRawMeasurementToLogFile(); } + if (shouldContinueBursting()) { + // sleep for maximum time before next reading // ask all drivers for maximum time until next burst reading // ask all drivers for maximum time until next available reading // sleep for whichever is less + notify(minMillisecondsUntilNextReading()); sleepMCU(minMillisecondsUntilNextReading()); + return true; } @@ -189,8 +201,7 @@ bool Datalogger::processReadingsCycle() if (settings.interBurstDelay > 0) { - notify(F("burst delay")); - int interBurstDelay = settings.interBurstDelay; + int interBurstDelay = settings.interBurstDelay * 60; // convert to seconds // todo: we should sleep any sensors that can be slept without re-warming // this could be called 'standby' mode // placeSensorsInStandbyMode(); @@ -199,9 +210,9 @@ bool Datalogger::processReadingsCycle() } initializeBurst(); + return true; } - return false; } @@ -210,6 +221,7 @@ void Datalogger::testMeasurementCycle() initializeMeasurementCycle(); fileSystemWriteCache->setOutputToSerial(true); // another way to do this would be to set a special write cache while(processReadingsCycle()){ + fileSystemWriteCache->flushCache(); outputLastMeasurement(); } @@ -227,7 +239,8 @@ void Datalogger::loop() } if (inMode(logging)) - { + { + //AE actuate hook before measurement could go here if (powerCycle) { @@ -248,18 +261,20 @@ void Datalogger::loop() if (shouldExitLoggingMode()) { - notify("Should exit logging mode"); changeMode(interactive); return; } - if(processReadingsCycle()) + if(processReadingsCycle() == true) // nothing changes if this true/false { return; } // otherwise go to sleep fileSystemWriteCache->flushCache(); + + //AE actuator hook could go here: is this before or after measurement? + SLEEP: stopAndAwaitTrigger(); initializeMeasurementCycle(); @@ -335,13 +350,13 @@ void Datalogger::loadSensorConfigurations() } if (sensorCount == 0) { - notify("no sensor configurations found"); + notify("no sensor config"); } notify("FREE MEM"); printFreeMemory(); // construct the drivers - notify("construct drivers"); + // notify("construct drivers"); drivers = (SensorDriver **)malloc(sizeof(SensorDriver *) * sensorCount); int j = 0; for (int i = 0; i < EEPROM_TOTAL_SENSOR_SLOTS; i++) @@ -458,6 +473,8 @@ void Datalogger::initializeBurst() void Datalogger::initializeMeasurementCycle() { + //AE actuate hook before measurement could go here + // notify(F("setting base time")); currentEpoch = timestamp(); offsetMillis = millis(); @@ -473,10 +490,9 @@ void Datalogger::initializeMeasurementCycle() // delay(20000); // startCustomWatchDog(); - notify(F("wait for start up delay")); int startUpDelay = settings.startUpDelay*60; // convert to seconds and print // startUpDelay = 2; - notify(startUpDelay); + // notify(startUpDelay); sleepMCU(startUpDelay * 1000); // convert seconds to milliseconds notify("sleep done"); } @@ -487,7 +503,7 @@ void Datalogger::initializeMeasurementCycle() sensorsWarmedUp = true; for (unsigned short i = 0; i < sensorCount; i++) { - notify("check isWarmed"); + // notify("check isWarmed"); if (!drivers[i]->isWarmedUp()) { // TODO: enhancement, ask the sensor driver if we should sleep MCU for a while @@ -496,11 +512,15 @@ void Datalogger::initializeMeasurementCycle() } } } + //AE actuator call could go here + } void Datalogger::measureSensorValues(bool performingBurst) { + // notify("in measure senosr values\n"); + if (settings.externalADCEnabled) { // get readings from the external ADC @@ -511,11 +531,14 @@ void Datalogger::measureSensorValues(bool performingBurst) for (unsigned int i = 0; i < sensorCount; i++) { + if (drivers[i]->takeMeasurement()) { + if (performingBurst) { drivers[i]->incrementBurst(); // burst bookkeeping + } } } @@ -677,7 +700,7 @@ void Datalogger::setConfiguration(cJSON *config) { strcpy(settings.deploymentIdentifier, deploymentIdentifierJSON->valuestring); } else { - notify("Invalid deployment identifier"); + notify("Invalid deployment ID"); } const cJSON * intervalJson = cJSON_GetObjectItemCaseSensitive(config, "interval"); @@ -745,6 +768,7 @@ void Datalogger::setSensorConfiguration(char *type, cJSON *json) { return; } + if (driver->getProtocol() == i2c) { ((I2CProtocolSensorDriver *)driver)->setWire(&WireTwo); @@ -788,8 +812,10 @@ void Datalogger::setSensorConfiguration(char *type, cJSON *json) } free(drivers); drivers = updatedDrivers; + } } + } void Datalogger::clearSlot(unsigned short slot) @@ -910,7 +936,7 @@ void Datalogger::calibrate(unsigned short slot, char *subcommand, int arg_cnt, c if (strcmp(subcommand, "init") == 0) { - notify("calling init"); + // notify("calling init"); driver->initCalibration(); } else @@ -958,8 +984,9 @@ bool Datalogger::deploy() notifyDebugStatus(); if (checkDebugSystemDisabled() == false) { - notify("**** ABORTING DEPLOYMENT *****"); - notify("**** PLEASE POWER CYCLE THIS UNIT AND TRY AGAIN *****"); + // notify("**** ABORTING DEPLOYMENT *****"); + // notify("**** PLEASE POWER CYCLE THIS UNIT AND TRY AGAIN *****"); + notify("ABORT TRY AGAIN"); return false; } @@ -1248,31 +1275,27 @@ const char *Datalogger::getUUIDString() } -int Datalogger::minMillisecondsUntilNextReading() +unsigned int Datalogger::minMillisecondsUntilNextReading() { - unsigned int minimumNextRequestedReading = MAX_REQUESTED_READING_DELAY; + unsigned int minimumDelayUntilNextRequestedReading = MAX_REQUESTED_READING_DELAY; + unsigned int maxDelayUntilNextAvailableReading = 0; for(int i=0; imillisecondsUntilNextRequestedReading()); - } + // retrieve the fastest time requested for sampling + minimumDelayUntilNextRequestedReading = min(minimumDelayUntilNextRequestedReading, drivers[i]->millisecondsUntilNextRequestedReading()); - unsigned int maxDelayUntilNextAvailableReading = 0; - for(int i=0; imillisecondsUntilNextReadingAvailable()); } - - // we want to read as fast the speed requested by the fastest sensor - // or as slow as the slowest sensor has a new reading available - if(maxDelayUntilNextAvailableReading == 0) - { - return minimumNextRequestedReading; - } - else - { - return min(minimumNextRequestedReading, maxDelayUntilNextAvailableReading); - } + // return max to prioritize sampling as soon as ALL sensors are ready to sample + return max(minimumDelayUntilNextRequestedReading, maxDelayUntilNextAvailableReading); + // return min to prioritize sampling at desired speed for ONE specific sensor + // if (maxDelayUntilNextAvailableReading == 0) // meaning all sensors have no delay between readings available + // { + // return minimumDelayUntilNextRequestedReading; + // } + // return min(minimumDelayUntilNextRequestedReading, maxDelayUntilNextAvailableReading); } diff --git a/src/datalogger.h b/src/datalogger.h index 309e3bc..e1b2b7f 100644 --- a/src/datalogger.h +++ b/src/datalogger.h @@ -51,7 +51,7 @@ typedef struct datalogger_settings { char loggerName[8]; // 8 bytes unsigned long deploymentTimestamp; // 8 bytes unsigned short interval; // 2 bytes minutes - unsigned short burstNumber; // 2 bytes + unsigned short burstNumber; // 2 bytes unsigned short startUpDelay; // 2 bytes minutes unsigned short interBurstDelay; // 2 bytes minutes char mode; // 1 byte i(interactive), d(debug), l(logging), t(deploy on trigger) @@ -178,7 +178,7 @@ class Datalogger void storeSensorConfiguration(SensorDriver * driver); void sleepMCU(uint32 milliseconds); - int minMillisecondsUntilNextReading(); + unsigned int minMillisecondsUntilNextReading(); // run loop void initializeFilesystem(); diff --git a/src/main.cpp b/src/main.cpp index 9625c9a..77b10fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,6 +29,7 @@ #include "system/eeprom.h" #include "system/logs.h" + // Setup and Loop Datalogger *datalogger; void printWelcomeMessage(datalogger_settings_type *dataloggerSettings); @@ -56,6 +57,16 @@ void setup(void) enableI2C1(); delay(500); + + + + + + + + + + debug("creating datalogger"); datalogger_settings_type *dataloggerSettings = (datalogger_settings_type *)malloc(sizeof(datalogger_settings_type)); Datalogger::readConfiguration(dataloggerSettings); @@ -77,6 +88,7 @@ void setup(void) { notify("Device will enter logging mode in 5 seconds"); notify("Type 'i' to exit to interactive mode"); + Serial2.print("CMD >> "); int start = timestamp(); int now = start; @@ -153,7 +165,7 @@ Type 'help' for command list. // space to work our development details -void workspace() +void workspace() { // notify(sizeof(long long)); // notify(sizeof(sone)); diff --git a/src/sensors/drivers/BME280_driver.cpp b/src/sensors/drivers/BME280_driver.cpp new file mode 100644 index 0000000..4842c50 --- /dev/null +++ b/src/sensors/drivers/BME280_driver.cpp @@ -0,0 +1,146 @@ +/* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +#include "sensors/drivers/BME280_driver.h" +#include "system/logs.h" // for debug() and notify() +// #include "system/measurement_components.h" // if external adc is used + +BME280Driver::BME280Driver() +{ + // debug("allocating driver template"); +} + +BME280Driver::~BME280Driver(){} + +const char * BME280Driver::getSensorTypeString() +{ + return sensorTypeString; +} +configuration_bytes_partition BME280Driver::getDriverSpecificConfigurationBytes() +{ + configuration_bytes_partition partition; + memcpy(&partition, &configuration, sizeof(driver_config)); + return partition; +} + +void BME280Driver::configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurationPartition) +{ + memcpy(&configuration, &configurationPartition, sizeof(driver_config)); +} + +void BME280Driver::appendDriverSpecificConfigurationJSON(cJSON * json) +{ + // debug("appeding driver specific driver template json"); + + //driver specific config, customize + addCalibrationParametersToJSON(json); +} + +void BME280Driver::setup() +{ + BME280ptr = new Adafruit_BME280(); + +} + +void BME280Driver::stop() +{ + // debug("stop/delete DriverTemplate"); +} + +bool BME280Driver::takeMeasurement() +{ + // debug("taking measurement from driver template"); + //return true if measurement taken store in class value(s), false if not + + bool measurementTaken = false; //temporarily setting to always true + temperature = BME280ptr->readTemperature(); + // if(isnan(temperature)) + // { + // notify("Error reading temperature)"); + // } + // else + // { + // measurementTaken = true; + // } + pressure = BME280ptr->readPressure(); + // if(isnan(pressure)) + // { + // notify("Error reading pressure"); + // } + // else + // { + // measurementTaken = true; + // } + measurementTaken = true; + // if(measurementTaken) + // { + // addValueToBurstSummaryMean("temperature", temperature); + // addValueToBurstSummaryMean("pressure", pressure); + // } + + return measurementTaken; +} + +const char *BME280Driver::getRawDataString() +{ + // debug("configuring driver template dataString"); + // process data string for .csv + //sprintf(dataString, "%0.3f, %0.3f",temperature, pressure); + sprintf(dataString, "%.2f,%.2f", temperature, pressure); + return dataString; +} + +const char *BME280Driver::getSummaryDataString() +{ + //double burstSummaryMean = getBurstSummaryMean("var"); + sprintf(dataString, "%.2f,%.2f", temperature, pressure); + return dataString; +} + +const char *BME280Driver::getBaseColumnHeaders() +{ + // for debug column headers defined in the .h + // debug("getting driver template base column headers"); + return baseColumnHeaders; +} + +void BME280Driver::initCalibration() +{ + // debug("init driver template sensor calibration"); +} + +void BME280Driver::calibrationStep(char *step, int arg_cnt, char ** args) +{ + // for intermediary steps of calibration process + // debug("driver template calibration steps"); +} + + + + +bool BME280Driver::configureDriverFromJSON(cJSON *json) +{ + return true; +} + + +void BME280Driver::addCalibrationParametersToJSON(cJSON *json) +{ + // follows structure of calibration parameters in .h + // debug("add driver template calibration parameters to json"); + cJSON_AddNumberToObject(json, CALIBRATION_TIME_STRING, configuration.cal_timestamp); +} diff --git a/src/sensors/drivers/BME280_driver.h b/src/sensors/drivers/BME280_driver.h new file mode 100644 index 0000000..1f9f519 --- /dev/null +++ b/src/sensors/drivers/BME280_driver.h @@ -0,0 +1,76 @@ +/* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +#ifndef WATERBEAR_BME280 +#define WATERBEAR_BME280 + +#include "sensors/sensor.h" +#include + +#define BME280_TYPE_STRING "BME280" + +class BME280Driver : public I2CProtocolSensorDriver +{ + + typedef struct + { + unsigned long long cal_timestamp; // 8 bytes for epoch time of calibration + } driver_config; + + public: + // Constructor + BME280Driver(); + ~BME280Driver(); + + + const char * getSensorTypeString(); + void setup(); + void stop(); + bool takeMeasurement(); + const char * getRawDataString(); + const char * getSummaryDataString(); + const char * getBaseColumnHeaders(); + void initCalibration(); + void calibrationStep(char *step, int arg_cnt, char ** args); + + configuration_bytes_partition getDriverSpecificConfigurationBytes(); + void configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurations); + + protected: + + bool configureDriverFromJSON(cJSON *json); + void appendDriverSpecificConfigurationJSON(cJSON *json); + void setDriverDefaults(); + + private: + //sensor specific variables, functions, etc. + const char *sensorTypeString = BME280_TYPE_STRING; + driver_config configuration; + Adafruit_BME280 *BME280ptr; + void addCalibrationParametersToJSON(cJSON *json); + + /*value(s) to be placed in dataString, should correspond to number of + column headers and entries in dataString*/ + float temperature; // sensor raw return(s) to be added to dataString + float pressure; + const char *baseColumnHeaders = "C,hPa "; // will be written to .csv + char dataString[30]; // will be written to .csv + + +}; + +#endif \ No newline at end of file diff --git a/src/sensors/drivers/adafruit_ahtx0.cpp b/src/sensors/drivers/adafruit_ahtx0.cpp new file mode 100644 index 0000000..49c9286 --- /dev/null +++ b/src/sensors/drivers/adafruit_ahtx0.cpp @@ -0,0 +1,152 @@ +/* + * RRIV - Open Source Environmental ata Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +#include "adafruit_ahtx0.h" +#include "system/logs.h" +#include "system/measurement_components.h" +#include "system/eeprom.h" // TODO: ideally not included in this scope +#include "system/clock.h" // TODO: ideally not included in this scope + +AdaAHTX0::AdaAHTX0() +{ + // debug("allocation AtlasECDriver"); +} +AdaAHTX0::~AdaAHTX0(){} + +const char * AdaAHTX0::getSensorTypeString() +{ + return sensorTypeString; +} + +configuration_bytes_partition AdaAHTX0::getDriverSpecificConfigurationBytes() +{ + configuration_bytes_partition partition; + memcpy(&partition, &configuration, sizeof(driver_configuration)); + return partition; +} + + +void AdaAHTX0::configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurationPartition) +{ + memcpy(&configuration, &configurationPartition, sizeof(driver_configuration)); +} + +void AdaAHTX0::appendDriverSpecificConfigurationJSON(cJSON * json) +{ + // debug("getting AdaAHTX0 json"); + //driver specific config, customize + addCalibrationParametersToJSON(json); +} + + + +void AdaAHTX0::setup() +{ + // notify("aht setup"); + aht = new Adafruit_AHTX0(); + if(!aht->begin(wire,1,AHTX0_I2CADDR_DEFAULT)){ + // notify("aht setup fail"); + } +} + +void AdaAHTX0::stop() +{ + delete aht; +} + +bool AdaAHTX0::takeMeasurement() +{ + // notify("in aht sensor driver take measurement\n"); + sensors_event_t hum, temp; + bool measurementTaken = false; + aht->getEvent(&hum, &temp); + humidity = hum.relative_humidity; + temperature = temp.temperature; + if(isnan(humidity)){ + notify("Error reading humidity"); + } else{ + measurementTaken = true; + } + if(isnan(temperature)){ + notify("Error reading temperature"); + } else{ + measurementTaken = true; + } + if(measurementTaken) + { + // notify("measurement read"); + addValueToBurstSummaryMean("temperature", temperature); + addValueToBurstSummaryMean("humidity", humidity); + lastSuccessfulReadingMillis = millis(); + // Serial2.print("temp t %d\n",temp.timestamp); + } + + return measurementTaken; +} +const char *AdaAHTX0::getSummaryDataString() +{ + // debug("configuring AdaAHTX0 dataString"); + // process data string for .csv + // TODO: just reporting the last value, not a true summary + sprintf(dataString, "%.2f", getBurstSummaryMean("aht")); + return dataString; +} + +const char *AdaAHTX0::getBaseColumnHeaders() +{ + // for debug column headers defined in the .h + // debug("getting AdaAHTX0 base column headers"); + return baseColumnHeaders; +} +void AdaAHTX0::initCalibration() +{ + // debug("init AdaAHTX0 calibration"); +} +void AdaAHTX0::calibrationStep(char *step, int arg_cnt, char ** args) +{ + // for intermediary steps of calibration process + // debug("AdaAHTX0 calibration steps"); +} +bool AdaAHTX0::configureDriverFromJSON(cJSON *json) +{ + return true; +} +void AdaAHTX0::setDriverDefaults() +{ + // debug("setting AdaAHTX0 driver defaults"); + // set default values for driver struct specific values + configuration.cal_timestamp = 0; +} + +void AdaAHTX0::addCalibrationParametersToJSON(cJSON *json) +{ + // follows structure of calibration parameters in .h + // debug("add AdaAHTX0 calibration parameters to json"); + cJSON_AddNumberToObject(json, CALIBRATION_TIME_STRING, configuration.cal_timestamp); +} + +const char * AdaAHTX0::getRawDataString() +{ + sprintf(dataString, "%.2f,%.2f", temperature, humidity); + return dataString; +} +unsigned int AdaAHTX0::millisecondsUntilNextReadingAvailable() +{ + + return (30000 - (millis() - lastSuccessfulReadingMillis)); // return min by default, a larger number in driver implementation causes correct delay +} diff --git a/src/sensors/drivers/adafruit_ahtx0.h b/src/sensors/drivers/adafruit_ahtx0.h new file mode 100644 index 0000000..0bef2a8 --- /dev/null +++ b/src/sensors/drivers/adafruit_ahtx0.h @@ -0,0 +1,77 @@ +/* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +#ifndef WATERBEAR_ADAFRUIT_AHTX0 +#define WATERBEAR_ADAFRUIT_AHTX0 + +#include "sensors/sensor.h" +#include + + +#define ADAFRUIT_DHTX0_TYPE_STRING "adafruit_ahtx0" + +class AdaAHTX0 : public I2CProtocolSensorDriver +{ + typedef struct // 32 bytes max + { + unsigned long long cal_timestamp; // 8byte epoch timestamp at calibration // TODO: move to common + } driver_configuration; + public: + //Constrcutor + AdaAHTX0(); + ~AdaAHTX0(); + const char * getSensorTypeString(); + + bool takeMeasurement(); + const char * getRawDataString(); + const char * getSummaryDataString(); + const char * getBaseColumnHeaders(); + + void initCalibration(); + void calibrationStep(char * step, int arg_cnt, char ** args); + void addCalibrationParametersToJSON(cJSON * json); + + void setup(); + void stop(); + + protected: + void configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurations); + configuration_bytes_partition getDriverSpecificConfigurationBytes(); + bool configureDriverFromJSON(cJSON *json); + void appendDriverSpecificConfigurationJSON(cJSON *json); + void setDriverDefaults(); + unsigned int millisecondsUntilNextReadingAvailable(); + + private: + const char *sensorTypeString = ADAFRUIT_DHTX0_TYPE_STRING; + driver_configuration configuration; + Adafruit_AHTX0 *aht; //pointer to I2C driver for Adafruit_AHTX0 + + float temperature; + float humidity; + const char * baseColumnHeaders = "C,RH"; + char dataString[16]; // local storage for data string + + unsigned long long lastSuccessfulReadingMillis = 0; + + + + +}; + +#endif \ No newline at end of file diff --git a/src/sensors/drivers/adafruit_dht22.cpp b/src/sensors/drivers/adafruit_dht22.cpp index 063f97a..eb04ebf 100644 --- a/src/sensors/drivers/adafruit_dht22.cpp +++ b/src/sensors/drivers/adafruit_dht22.cpp @@ -1,3 +1,20 @@ +/* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ #include "sensors/drivers/adafruit_dht22.h" #include "system/logs.h" // for debug() and notify() #include "system/hardware.h" // for pin names @@ -69,6 +86,7 @@ void AdaDHT22::stop() bool AdaDHT22::takeMeasurement() { + // notify("in driver take measurement\n"); // debug("taking measurement from AdaDHT22"); sensors_event_t event; bool measurementTaken = false; diff --git a/src/sensors/drivers/air_pump.cpp b/src/sensors/drivers/air_pump.cpp new file mode 100644 index 0000000..fa72a7a --- /dev/null +++ b/src/sensors/drivers/air_pump.cpp @@ -0,0 +1,210 @@ +/* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +#include "sensors/drivers/air_pump.h" +#include "system/logs.h" // for debug() and notify() +#include "system/hardware.h" + +// #include "system/measurement_components.h" // if external adc is used + + +AirPump::AirPump() +{ + // debug("allocating generic actuator"); +} + +AirPump::~AirPump(){} + + + +const char * AirPump::getSensorTypeString() +{ + return sensorTypeString; +} + +void AirPump::setup() +{ + //setup struct using JSON? + + +} + + +bool AirPump::takeMeasurement() +{ + //AE temp fix: measurement turns pump on & off + //notify(F("in take measurement")); + digitalWrite(GPIO_PIN_6, HIGH); + //delay(configuration.dutyCycle*configuration.timeCycle*1000); + delay(5000); + digitalWrite(GPIO_PIN_6, LOW); + delay(5000); + // delay((1-configuration.dutyCycle)*configuration.timeCycle*1000); + + + // // debug("taking measurement from driver template"); + // //return true if measurement taken store in class value(s), false if not + addValueToBurstSummaryMean("actuate", 1); // use the default option for computing the burst summary value + // return measurementTaken; + + //for actuators, no measurement taken + return true; +} + +const char *AirPump::getRawDataString() +{ + // // debug("configuring driver template dataString"); + // // process data string for .csv + sprintf(dataString, "%d",1); + return dataString; + +} + +const char *AirPump::getSummaryDataString() +{ + // //actuators likely don't need bursts / burst sumary? + // double burstSummaryMean = getBurstSummaryMean("var"); + // sprintf(dataString, "%0.3f,%0.3f", burstSummaryMean, burstSummaryMean*31.83); + // return dataString; + sprintf(dataString, "%d",1); + return dataString; +} + +const char *AirPump::getBaseColumnHeaders() +{ + // for debug column headers defined in the .h + // debug("getting driver template base column headers"); + return baseColumnHeaders; +} + +void AirPump::initCalibration() +{ + // debug("init driver template sensor calibration"); +} + +void AirPump::calibrationStep(char *step, int arg_cnt, char ** args) +{ + // for intermediary steps of calibration process + // debug("driver template calibration steps"); +} + + +// unsigned int AirPump::millisecondsUntilNextReadingAvailable() +// { +// return ((1-configuration.dutyCycle)*configuration.timeCycle*1000); +// //return 5000; // return min by default, a larger number in driver implementation causes correct delay +// } + +unsigned int AirPump::millisecondsUntilNextRequestedReading() +{ + //return ((1-configuration.dutyCycle)*configuration.timeCycle*1000); // as slow as possible by default, a smaller number in driver implementation forces faster read + return(10000); +} + +void AirPump::stop() +{ + //stop + digitalWrite(GPIO_PIN_6, LOW); +} + +bool isWarmedUp() +{ + return true; +} + + +//actuator funcs + void AirPump::actuateBeforeWarmUp() +{ + + // for(int i = 0; i < numIterations; i++) + // { + // digitalWrite(GPIO_PIN_6, HIGH); + // delay(configuration.dutyCycle*configuration.timeCycle*1000); + // digitalWrite(GPIO_PIN_6, LOW); + // delay((1-configuration.dutyCycle)*configuration.timeCycle*1000); + // } + + +} + + +void AirPump::configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurationPartition) +{ + memcpy(&configuration, &configurationPartition, sizeof(driver_configuration)); +} + +configuration_bytes_partition AirPump::getDriverSpecificConfigurationBytes() +{ + configuration_bytes_partition partition; + memcpy(&partition, &configuration, sizeof(driver_configuration)); + return partition; +} + +bool AirPump::configureDriverFromJSON(cJSON *json) +{ + // const cJSON *dutyCycleJSON = cJSON_GetObjectItemCaseSensitive(json, "duty_cycle"); + // const cJSON *flowRateJSON = cJSON_GetObjectItemCaseSensitive(json, "flow_rate"); + // const cJSON *volumeEvacuateJSON = cJSON_GetObjectItemCaseSensitive(json, "volume_evacuate"); + // const cJSON *timeCycleJSON = cJSON_GetObjectItemCaseSensitive(json, "time_cycle"); + // configuration.dutyCycle = (byte)dutyCycleJSON->valueint; + // configuration.flowRate = (byte)flowRateJSON->valueint; + // configuration.volumeEvacuate = (byte)volumeEvacuateJSON->valueint; + // configuration.timeCycle = (byte)timeCycleJSON->valueint; + + + return true; +} + +void AirPump::appendDriverSpecificConfigurationJSON(cJSON * json) +{ + // debug("appeding driver specific driver template json"); + + //driver specific config, customize + addCalibrationParametersToJSON(json); +} + +void AirPump::setDriverDefaults() +{ + // debug("setting driver template driver defaults"); + // set default values for driver struct specific values + //configuration.cal_timestamp = 0; + // configuration.dutyCycle = 0.5; + // configuration.flowRate = 1; + configuration.cal_timestamp = 0; + +} + +// void AirPump::calcIterations(int* iterations, float duty, float rate, float vol, int cycle) +// { +// //*numIterations = 5; //ceil((configuration.volEvacuate/(configuration.flowRate/60))/(configuration.dutyCycle*configuration.timeCycle)); + +// } + + + +void AirPump::addCalibrationParametersToJSON(cJSON *json) +{ + // follows structure of calibration parameters in .h + // debug("add driver template calibration parameters to json"); + //cJSON_AddNumberToObject(json, CALIBRATION_TIME_STRING, configuration.cal_timestamp); + //cJSON_AddNumberToObject(json, DUTY_CYCLE_TYPE_STRING, configuration.dutyCycle); + cJSON_AddNumberToObject(json, CALIBRATION_TIME_STRING, configuration.cal_timestamp); +} + + diff --git a/src/sensors/drivers/air_pump.h b/src/sensors/drivers/air_pump.h new file mode 100644 index 0000000..008746d --- /dev/null +++ b/src/sensors/drivers/air_pump.h @@ -0,0 +1,121 @@ + /* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +#ifndef WATERBEAR_AIR_PUMP +#define WATERBEAR_AIR_PUMP + +#include "sensors/sensor.h" +#include "generic_actuator.h" + +#define AIR_PUMP_TYPE_STRING "air_pump" + +//for json stuff? +#define DUTY_CYCLE_TYPE_STRING reinterpret_cast(F("duty_cycle")) +#define FLOW_RATE_TYPE_STRING reinterpret_cast(F("flow_rate")) +#define VOLUME_TYPE_STRING reinterpret_cast(F("volume_evacuate")) +#define TIME_CYCLE_TYPE_STRING reinterpret_cast(F("time_cycle")) + +class AirPump : public GenericActuator +{ + typedef struct + { + //unsigned long long cal_timestamp; // 8 bytes for epoch time of calibration (optional) + //short sensor_pin : 5; //4 bits (16 states) (this is GPIO pin?) + + //note maxiumum duty cycle maximum is 1 + //note for this air pump maximum time on is 5 seconds, so maximum time cycle 10. + // float dutyCycle = 0.5; + // float flowRate = 2.5; // needs to be in L / min + // float volumeEvacuate = 7.57; //needs to be in L + // int timeCycle = 4; //total time of 1 on off cycle in seconds + + //float timeOn = (volumeEvacuate/(flowRate/60))*dutyCycle; + //float timeOn = dutyCycle*totalTimeCycle; //in seconds, based off maximum rating (not consistent for all types air pumps? ) + + //float timeOff = (volumeEvacuate/(flowRate/60))*(1-dutyCycle); + //float timeOff = (1-dutyCycle)*totalTimeCycle; + // int numIterations = ceil((volumeEvacuate/(flowRate/60))/(dutyCycle*timeCycle)); + // int numIterations = 37; + unsigned long long cal_timestamp; + + + } driver_configuration; + + public: + //Constructor + AirPump(); + ~AirPump(); + + const char * getSensorTypeString(); + void setup(); + void stop(); + bool takeMeasurement(); + const char * getRawDataString(); + const char * getSummaryDataString(); + const char * getBaseColumnHeaders(); + void initCalibration(); + void calibrationStep(char *step, int arg_cnt, char ** args); + + + //unsigned int millisecondsUntilNextReadingAvailable(); + unsigned int millisecondsUntilNextRequestedReading(); + + + + + void actuateBeforeWarmUp(); + void actuateAfterMeasurementCycle(); + //needs renaiming, function for actuators every X measurement cycles + void actuatePeriodicalyMeasurementCycle(); + + protected: + void configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurations); + configuration_bytes_partition getDriverSpecificConfigurationBytes(); + bool configureDriverFromJSON(cJSON *json); //name correct?? + bool configureFromJSON(cJSON *json); + void appendDriverSpecificConfigurationJSON(cJSON *json); + void setDriverDefaults(); + + + + private: + const char *sensorTypeString = AIR_PUMP_TYPE_STRING; + driver_configuration configuration; + + // float dutyCycle; //rating of duty cycle + // float flowRate; //in Liters / Min + // float volumeEvacuate; //total volume to evacuate + //float totalTime; //total time air pump needs to be on + // float timeOn; //time air pump on + // float timeOff; //time air pump off + //int numIterations = ceil((configuration.volEvacuate/(configuration.flowRate/60))/(configuration.dutyCycle*configuration.timeCycle)); + + + + //void calcIterations(int* iterations, float duty, float rate, float vol, int cycle); + // int value; // sensor raw return(s) to be added to dataString + const char *baseColumnHeaders = "actuate"; // will be written to .csv + char dataString[16]; // will be written to .csv + + + void addCalibrationParametersToJSON(cJSON *json); + + +}; + +#endif \ No newline at end of file diff --git a/src/sensors/drivers/atlas_co2_driver.cpp b/src/sensors/drivers/atlas_co2_driver.cpp index c058b9c..e854371 100644 --- a/src/sensors/drivers/atlas_co2_driver.cpp +++ b/src/sensors/drivers/atlas_co2_driver.cpp @@ -1,3 +1,20 @@ +/* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ #include "sensors/drivers/atlas_co2_driver.h" #include "system/logs.h" // for debug() and notify() @@ -85,6 +102,13 @@ const char * AtlasCO2Driver::getSummaryDataString() sprintf(dataString, "%0.2f", getBurstSummaryMean(CO2_TAG)); return dataString; } +// const char *AtlasCO2Driver::getRawDataString() +// { +// // debug("configuring driver template dataString"); +// // process data string for .csv +// sprintf(dataString, "%d,%d",value,0); +// return dataString; +// } const char *AtlasCO2Driver::getBaseColumnHeaders() { diff --git a/src/sensors/drivers/atlas_ec.cpp b/src/sensors/drivers/atlas_ec.cpp index e70f32a..0917dee 100644 --- a/src/sensors/drivers/atlas_ec.cpp +++ b/src/sensors/drivers/atlas_ec.cpp @@ -1,5 +1,5 @@ /* - * RRIV - Open Source Environmental Data Logging Platform + * RRIV - Open Source Environmental ata Logging Platform * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com * * This program is free software: you can redistribute it and/or modify diff --git a/src/sensors/drivers/driver_template.cpp b/src/sensors/drivers/driver_template.cpp index edc5b2d..52bd9fb 100644 --- a/src/sensors/drivers/driver_template.cpp +++ b/src/sensors/drivers/driver_template.cpp @@ -1,3 +1,20 @@ +/* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ #include "sensors/drivers/driver_template.h" #include "system/logs.h" // for debug() and notify() // #include "system/measurement_components.h" // if external adc is used @@ -16,38 +33,12 @@ const char * DriverTemplate::getSensorTypeString() return sensorTypeString; } -configuration_bytes_partition DriverTemplate::getDriverSpecificConfigurationBytes() -{ - configuration_bytes_partition partition; - memcpy(&partition, &configuration, sizeof(driver_configuration)); - return partition; -} - -bool DriverTemplate::configureDriverFromJSON(cJSON *json) -{ - return true; -} - - -void DriverTemplate::configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurationPartition) -{ - memcpy(&configuration, &configurationPartition, sizeof(driver_configuration)); -} - -void DriverTemplate::appendDriverSpecificConfigurationJSON(cJSON * json) -{ - // debug("appeding driver specific driver template json"); - - //driver specific config, customize - addCalibrationParametersToJSON(json); -} - void DriverTemplate::setup() { // debug("setup DriverTemplate"); } -void DriverTemplate::stop() +void DriverTemplate::stop() { // debug("stop/delete DriverTemplate"); } @@ -99,11 +90,29 @@ void DriverTemplate::calibrationStep(char *step, int arg_cnt, char ** args) // debug("driver template calibration steps"); } -void DriverTemplate::addCalibrationParametersToJSON(cJSON *json) +void DriverTemplate::configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurationPartition) { - // follows structure of calibration parameters in .h - // debug("add driver template calibration parameters to json"); - cJSON_AddNumberToObject(json, CALIBRATION_TIME_STRING, configuration.cal_timestamp); + memcpy(&configuration, &configurationPartition, sizeof(driver_configuration)); +} + +configuration_bytes_partition DriverTemplate::getDriverSpecificConfigurationBytes() +{ + configuration_bytes_partition partition; + memcpy(&partition, &configuration, sizeof(driver_configuration)); + return partition; +} + +bool DriverTemplate::configureDriverFromJSON(cJSON *json) +{ + return true; +} + +void DriverTemplate::appendDriverSpecificConfigurationJSON(cJSON * json) +{ + // debug("appeding driver specific driver template json"); + + //driver specific config, customize + addCalibrationParametersToJSON(json); } void DriverTemplate::setDriverDefaults() @@ -111,4 +120,11 @@ void DriverTemplate::setDriverDefaults() // debug("setting driver template driver defaults"); // set default values for driver struct specific values configuration.cal_timestamp = 0; -} \ No newline at end of file +} + +void DriverTemplate::addCalibrationParametersToJSON(cJSON *json) +{ + // follows structure of calibration parameters in .h + // debug("add driver template calibration parameters to json"); + cJSON_AddNumberToObject(json, CALIBRATION_TIME_STRING, configuration.cal_timestamp); +} diff --git a/src/sensors/drivers/generic_actuator.cpp b/src/sensors/drivers/generic_actuator.cpp new file mode 100644 index 0000000..a792cba --- /dev/null +++ b/src/sensors/drivers/generic_actuator.cpp @@ -0,0 +1,156 @@ +/* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +#include "sensors/drivers/generic_actuator.h" +#include "system/logs.h" // for debug() and notify() +// #include "system/measurement_components.h" // if external adc is used + +GenericActuator::GenericActuator() +{ + // debug("allocating generic actuator"); +} + +GenericActuator::~GenericActuator(){} + +protocol_type GenericActuator::getProtocol() +{ + return genericactuator; //actuators don't have protocol type ? +} + +const char * GenericActuator::getSensorTypeString() +{ + return sensorTypeString; +} + +void GenericActuator::setup() +{ + // debug("setup DriverTemplate"); + +} + +void GenericActuator::stop() +{ + // debug("stop/delete DriverTemplate"); +} + +bool GenericActuator::takeMeasurement() +{ + // debug("taking measurement from driver template"); + //return true if measurement taken store in class value(s), false if not + // bool measurementTaken = false; + // if(true) + // { + // value = 42; //why 42? + // measurementTaken = true; + // } + // addValueToBurstSummaryMean("var", value); // use the default option for computing the burst summary value + // return measurementTaken; + + //for actuators, no measurement taken + return true; +} + +const char *GenericActuator::getRawDataString() +{ + // debug("configuring driver template dataString"); + // process data string for .csv + //sprintf(dataString, "%d,%0.3f",value,value*31.83); + //return dataString; + + sprintf(dataString, "%d", value); + return dataString; +} + +const char *GenericActuator::getSummaryDataString() +{ + //actuators likely don't need bursts / burst sumary? + // double burstSummaryMean = getBurstSummaryMean("var"); + // sprintf(dataString, "%0.3f,%0.3f", burstSummaryMean, burstSummaryMean*31.83); + //return dataString + sprintf(dataString, "%d", value); + return dataString; + +} + +const char *GenericActuator::getBaseColumnHeaders() +{ + // for debug column headers defined in the .h + // debug("getting driver template base column headers"); + return baseColumnHeaders; +} + +void GenericActuator::initCalibration() +{ + // debug("init driver template sensor calibration"); +} + +void GenericActuator::calibrationStep(char *step, int arg_cnt, char ** args) +{ + // for intermediary steps of calibration process + // debug("driver template calibration steps"); +} + +//actuaotor funcs +void GenericActuator::actuateBeforeWarmUp() +{ + +} + +void GenericActuator::actuateAfterMeasurementCycle() +{ + +} + + +void GenericActuator::actuatePeriodicalyMeasurementCycle() +{ +} + +void GenericActuator::configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurationPartition) +{ + //memcpy(&configuration, &configurationPartition, sizeof(driver_configuration)); +} + +configuration_bytes_partition GenericActuator::getDriverSpecificConfigurationBytes() +{ + configuration_bytes_partition partition; + //memcpy(&partition, &configuration, sizeof(driver_configuration)); + return partition; +} + +bool GenericActuator::configureDriverFromJSON(cJSON *json) +{ + return true; +} + +void GenericActuator::appendDriverSpecificConfigurationJSON(cJSON * json) +{ + +} + +void GenericActuator::setDriverDefaults() +{ + +} + +void GenericActuator::addCalibrationParametersToJSON(cJSON *json) +{ + // follows structure of calibration parameters in .h + // debug("add driver template calibration parameters to json"); + //cJSON_AddNumberToObject(json, CALIBRATION_TIME_STRING, configuration.cal_timestamp); +} + diff --git a/src/sensors/drivers/generic_actuator.h b/src/sensors/drivers/generic_actuator.h new file mode 100644 index 0000000..fe65db0 --- /dev/null +++ b/src/sensors/drivers/generic_actuator.h @@ -0,0 +1,92 @@ +/* + * RRIV - Open Source Environmental Data Logging Platform + * Copyright (C) 20202 Zaven Arra zaven.arra@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +#ifndef WATERBEAR_GENERIC_ACTUATOR +#define WATERBEAR_GENERIC_ACTUATOR + +#include "sensors/sensor.h" + +#define GENERIC_ACTUATOR_TYPE_STRING "generic_actuator" + + +class GenericActuator: public GenericActuatorProtocolSensorDriver +{ + + typedef struct + { + unsigned long long cal_timestamp; // 8 bytes for epoch time of calibration + //unsigned int GPIO_pin : 6; //is this number of bits or the pin number? + + } driver_configuration; + + public: + //constructor + GenericActuator(); + ~GenericActuator(); + + protocol_type getProtocol(); + const char * getSensorTypeString(); //is this necessary? + virtual void setup(); + virtual void stop(); + bool turnOn(); + bool takeMeasurement(); //for actuators measurement is turning pump on / off + const char * getRawDataString(); + const char * getBaseColumnHeaders(); + const char * getSummaryDataString(); + void initCalibration(); //needed? + void calibrationStep(char *step, int arg_cnt, char ** args); //do actuators need to be calibrated? + + + //temp for treating air pump as sensor + // virtual unsigned int millisecondsUntilNextReadingAvailable(); + // virtual unsigned int millisecondsUntilNextRequestedReading(); + //void setPulseWidth(); + //void setLoopFrequency(); // frequency of occurences in data logging loop + + virtual void actuateBeforeWarmUp(); + virtual void actuateAfterMeasurementCycle(); + virtual void actuatePeriodicalyMeasurementCycle(); + + + + protected: + void configureSpecificConfigurationsFromBytes(configuration_bytes_partition configurations); + configuration_bytes_partition getDriverSpecificConfigurationBytes(); + bool configureDriverFromJSON(cJSON *json); + void appendDriverSpecificConfigurationJSON(cJSON *json); + void setDriverDefaults(); + + + + private: + //actuator specific variables, functions, etc. + const char *sensorTypeString = GENERIC_ACTUATOR_TYPE_STRING; + driver_configuration configuration; + + + /*FROM DRIVER TEMPLATE. MAY NOT BE NEEDED. ACTUATORS DON'T WRITE TO CSV? : + value(s) to be placed in dataString, should correspond to number of + column headers and entries in dataString*/ + int value; // sensor raw return(s) to be added to dataString + const char *baseColumnHeaders = "raw,cal"; // will be written to .csv + char dataString[16]; // will be written to .csv + + void addCalibrationParametersToJSON(cJSON *json); + +}; + +#endif \ No newline at end of file diff --git a/src/sensors/drivers/registry.cpp b/src/sensors/drivers/registry.cpp index 7a4c355..c070470 100644 --- a/src/sensors/drivers/registry.cpp +++ b/src/sensors/drivers/registry.cpp @@ -5,38 +5,42 @@ // Follow steps to add a new sensor driver // -// Step 1: Include the header for your driver in registry.h - +// Step 1: Include the header for your driver in sensor_map.h +//include in registry.h not sensor_map.h?? #define GENERIC_ANALOG_SENSOR 0x0000 #define ATLAS_EC_OEM_SENSOR 0x0001 #define ADAFRUIT_DHT22_SENSOR 0x0002 #define ATLAS_CO2_SENSOR 0x0003 +#define GENERIC_ACTUATOR 0x0004 +#define AIR_PUMP 0x0005 +#define BME280 0x0006 +#define ADAFRUIT_AHTX0_SENSOR 0x0007 // Step 2: Add a #define for the next available integer code #define DRIVER_TEMPLATE 0xFFFE #define NO_SENSOR 0xFFFF - - void buildDriverSensorMap() { setupSensorMaps(GENERIC_ANALOG_SENSOR, F(GENERIC_ANALOG_DRIVER_TYPE_STRING)); - // setupSensorMaps(ATLAS_EC_OEM_SNSOR, F(ATLAS_EC_OEM_TYPE_STRING)); + //setupSensorMaps(ATLAS_EC_OEM_SNSOR, F(ATLAS_EC_OEM_TYPE_STRING)); - // setupSensorMaps(DRIVER_TEMPLATE, F(DRIVER_TEMPLATE_TYPE_STRING)); + //setupSensorMaps(DRIVER_TEMPLATE, F(DRIVER_TEMPLATE_TYPE_STRING)); - setupSensorMaps(ADAFRUIT_DHT22_SENSOR, F(ADAFRUIT_DHT22_TYPE_STRING)); + // setupSensorMaps(ADAFRUIT_DHT22_SENSOR, F(ADAFRUIT_DHT22_TYPE_STRING)); // setupSensorMaps(ATLAS_CO2_SENSOR, F(ATLAS_CO2_DRIVER_TYPE_STRING)); - // Step 3: call setupSensorMaps with the class name, code, and type string for your sensor - // setupSensorMaps<$CLASS_NAME>($SENSOR_CODE, F($SENSOR_STRING_NAME)); - // $CLASS_NAME is the C++ class of the sensor - // $SENSOR_CODE is the define added in step 2 above for this sensor - // $SENSOR_STRING_NAME is the define for human readable sensor name found in the .h for this sensor driver + // setupSensorMaps(GENERIC_ACTUATOR, F(GENERIC_ACTUATOR_TYPE_STRING)); + + // setupSensorMaps(AIR_PUMP, F(AIR_PUMP_TYPE_STRING)); + + //setupSensorMaps(BME280, F(BME280_TYPE_STRING)); + setupSensorMaps(ADAFRUIT_AHTX0_SENSOR, F(ADAFRUIT_DHTX0_TYPE_STRING)); + //Step 3: call setupSensorMaps with the class name, code, and type string for your sensor } diff --git a/src/sensors/drivers/registry.h b/src/sensors/drivers/registry.h index 7bceea2..60e2b8b 100644 --- a/src/sensors/drivers/registry.h +++ b/src/sensors/drivers/registry.h @@ -5,6 +5,11 @@ #include "atlas_ec.h" #include "driver_template.h" #include "adafruit_dht22.h" +#include "generic_actuator.h" +#include "air_pump.h" +#include "BME280_driver.h" +#include "adafruit_ahtx0.h" + #define MAX_SENSOR_TYPE 0xFFFE diff --git a/src/sensors/sensor.cpp b/src/sensors/sensor.cpp index 0779ca7..dbce367 100644 --- a/src/sensors/sensor.cpp +++ b/src/sensors/sensor.cpp @@ -219,7 +219,7 @@ void SensorDriver::configureFromBytes(configuration_bytes configurationBytes) void SensorDriver::setup() { // by default no setup - return; + //return; } void SensorDriver::stop() @@ -312,6 +312,14 @@ DriverTemplateProtocolSensorDriver::~DriverTemplateProtocolSensorDriver(){} protocol_type DriverTemplateProtocolSensorDriver::getProtocol() { - // debug("getting driver template protocol"); + // debug("getting driver template"); return drivertemplate; } + +GenericActuatorProtocolSensorDriver::~GenericActuatorProtocolSensorDriver(){} + +protocol_type GenericActuatorProtocolSensorDriver::getProtocol() +{ + // debug("getting generic actuator template"); + return genericactuator; +} \ No newline at end of file diff --git a/src/sensors/sensor.h b/src/sensors/sensor.h index e28d75b..67ddcc9 100644 --- a/src/sensors/sensor.h +++ b/src/sensors/sensor.h @@ -32,7 +32,8 @@ typedef enum protocol analog, i2c, gpio, - drivertemplate + drivertemplate, + genericactuator, } protocol_type; #define SENSOR_CONFIGURATION_SIZE 64 @@ -60,7 +61,7 @@ typedef struct unsigned short int sensor_type; // 2 bytes unsigned short int warmup; // 2 bytes - in seconds (65535 max value/60=1092 min) byte slot; // 1 byte - byte burst_size; // 1 byte + byte burst_size; // 1 byte // reading_count } common_sensor_driver_config; @@ -96,6 +97,8 @@ class SensorDriver void clearConfigurationNeedsSave(); bool getNeedsSave(); + + protected: common_sensor_driver_config commonConfigurations; @@ -189,6 +192,8 @@ class SensorDriver virtual unsigned int millisecondsUntilNextReadingAvailable(); virtual unsigned int millisecondsUntilNextRequestedReading(); + + protected: @@ -203,6 +208,7 @@ class SensorDriver virtual void setDriverDefaults() = 0; + }; #include "base/analog_protocol_driver.h" @@ -240,8 +246,19 @@ class DriverTemplateProtocolSensorDriver : public SensorDriver ~DriverTemplateProtocolSensorDriver(); protocol_type getProtocol(); }; +/* +* Base class for actuators (for now?) AE +*/ + +class GenericActuatorProtocolSensorDriver : public SensorDriver +{ +public: + ~GenericActuatorProtocolSensorDriver(); + protocol_type getProtocol(); +}; void getDefaultsCommon(common_sensor_driver_config *fillValues); void readCommonConfigOnly(common_sensor_driver_config *readValues); // not made //TODO: what is this + #endif diff --git a/src/system/command.cpp b/src/system/command.cpp index 4f6db93..b4c219a 100644 --- a/src/system/command.cpp +++ b/src/system/command.cpp @@ -24,6 +24,9 @@ #include "utilities/qos.h" #include "scratch/dbgmcu.h" #include "system/logs.h" +#include "sensors/drivers/air_pump.h" +#include "sensors/drivers/generic_actuator.h" + #define MAX_REQUEST_LENGTH 70 // serial commands @@ -444,7 +447,7 @@ void setSlotConfig(int arg_cnt, char **args) { notify(F("set slot config")); if(arg_cnt < 2){ - invalidArgumentsMessage(F("set-slot-config SLOT_CONFIG_JSON")); + invalidArgumentsMessage(F("set-slot-config SLOT_CONFIG_JSON")); // TODO: kinda useless, tell user json structure return; } @@ -675,6 +678,29 @@ void help(int arg_cnt, char**args) CommandInterface::instance()->_help(); } +void airpumptest (int arg_cnt, char**args) +{ + CommandInterface::instance()->_airpumptest(); +} + +void CommandInterface::_airpumptest() +{ + + // AirPump ap; + // ap.actuateBeforeWarmUp(); + // for(int i = 0; i < 5; i++) //only doing 2 cycles before stoping WHY + // { + // digitalWrite(GPIO_PIN_6, HIGH); + // //delay(dutyCycle*total*1000); //totalTimeCycle not not "declared in scope" other variables are fine tho + // delay(0.5*10*1000); + // digitalWrite(GPIO_PIN_6, LOW); + // // delay((1-dutyCycle)*timeFullCycle*1000); + // delay((1-0.5)*10*1000); + // } + + +} + void CommandInterface::_help() { char commands[] = "Command List:\n" @@ -687,6 +713,7 @@ void CommandInterface::_help() "clear-slot\n" "set-rtc\n" "get-rtc\n" + "gpio-test\n" "restart\n" "set-site-name\n" "set-deployment-identifier\n" @@ -709,7 +736,11 @@ void CommandInterface::_help() "reload-sensors\n" "switched-power-off\n" "enter-stop\n" + + "airpump-test\n" + "mcu-debug-status\n"; + notify(commands); } @@ -721,24 +752,31 @@ void gpiotest(int arg_cnt, char**args) void CommandInterface::_gpiotest() { - // TODO: currently hardcoded pin test, change to allow user input with command - if (digitalRead(GPIO_PIN_6) == HIGH) + + if (digitalRead(GPIO_PIN_6) == HIGH ) { digitalWrite(GPIO_PIN_6, LOW); - else + + } + else { digitalWrite(GPIO_PIN_6, HIGH); + + } + } + void reloadSensorConfigurations(int arg_cnt, char**args) { CommandInterface::instance()->_reloadSensorConfigurations(); } - void CommandInterface::_reloadSensorConfigurations() { this->datalogger->reloadSensorConfigurations(); } + + void CommandInterface::setup(){ cmdAdd("version", printVersion); cmdAdd("show-warranty", printWarranty); @@ -786,11 +824,14 @@ void CommandInterface::setup(){ cmdAdd("mcu-debug-status", mcuDebugStatus); cmdAdd("help", help); - + cmdAdd("airpump-test", airpumptest); cmdAdd("gpio-test", gpiotest); + cmdAdd("airpump-test", airpumptest); -} + + // cmdAdd("step-test", steptest); +} diff --git a/src/system/command.h b/src/system/command.h index f996f89..8a211ae 100644 --- a/src/system/command.h +++ b/src/system/command.h @@ -27,6 +27,8 @@ #include "datalogger.h" + + // Forward declaration of class class Datalogger; @@ -125,9 +127,13 @@ class CommandInterface void _enterStop(); void _help(); + void _mcuDebugStatus(); void _gpiotest(); // toggles gpio pin state (low/high) + void _airpumptest(); + + diff --git a/src/system/hardware.cpp b/src/system/hardware.cpp index eb5efde..0276317 100644 --- a/src/system/hardware.cpp +++ b/src/system/hardware.cpp @@ -41,7 +41,7 @@ void startSerial2() { delay(100); } - notify(F("Begin Serial2")); + // notify(F("Begin Serial2")); } void setupInternalRTC() @@ -61,18 +61,67 @@ void setupHardwarePins() // Moved to generic_analog driver for INPUT_ANALOG mode // Need to test and see if these pins can also be used as GPIO for actuator drivers - /* + pinMode(ANALOG_INPUT_1_PIN, INPUT_ANALOG); pinMode(ANALOG_INPUT_2_PIN, INPUT_ANALOG); pinMode(ANALOG_INPUT_3_PIN, INPUT_ANALOG); pinMode(ANALOG_INPUT_4_PIN, INPUT_ANALOG); pinMode(ANALOG_INPUT_5_PIN, INPUT_ANALOG); - */ + + // //testing as output + // pinMode(ANALOG_INPUT_1_PIN, OUTPUT); + // pinMode(ANALOG_INPUT_2_PIN, OUTPUT); + // pinMode(ANALOG_INPUT_3_PIN, OUTPUT); + // pinMode(ANALOG_INPUT_4_PIN, OUTPUT); + // pinMode(ANALOG_INPUT_5_PIN, OUTPUT); pinMode(ONBOARD_LED_PIN, OUTPUT); // This is the onboard LED ? Turns out this is also the SPI1 clock. niiiiice. - pinMode(GPIO_PIN_6, OUTPUT); // GPIO pin available + //pinMode(GPIO_PIN_6, OUTPUT); // GPIO pin available pinMode(GPIO_PIN_3, OUTPUT); // in use for 5v booster - // pinMode(GPIO_PIN_5, OUTPUT); // in use for DHT22 [INPUT_PULLUP] + + //testing all pins + pinMode(PC10, OUTPUT); //no + pinMode(PC11, OUTPUT); + pinMode(PC12, OUTPUT); // yes + //pinMode(PA13, OUTPUT); //no Labeled SWDIO in KiCad + pinMode(GPIO_PIN_17, OUTPUT); // no + pinMode(PC13, OUTPUT); //yes + pinMode(PC14, OUTPUT); //no + pinMode(PC15, OUTPUT); //no + pinMode(PA1, OUTPUT); + + + //pinMode(GPIO_PIN_29, OUTPUT); //not in board.h + //pinMode(GPIO_PIN_31, OUTPUT); //not in board.h + pinMode(PB4, OUTPUT); + pinMode(PB4, OUTPUT); //no + pinMode(PB3, OUTPUT); //no + pinMode(PB12, OUTPUT); //yes + pinMode(PB2, OUTPUT); //yes + + + + //testing all pins + pinMode(PC10, OUTPUT); //no + pinMode(PC11, OUTPUT); + pinMode(PC12, OUTPUT); // yes + //pinMode(PA13, OUTPUT); //no Labeled SWDIO in KiCad + pinMode(GPIO_PIN_17, OUTPUT); // no + pinMode(PC13, OUTPUT); //yes + pinMode(PC14, OUTPUT); //no + pinMode(PC15, OUTPUT); //no + pinMode(PA1, OUTPUT); + + + //pinMode(GPIO_PIN_29, OUTPUT); //not in board.h + //pinMode(GPIO_PIN_31, OUTPUT); //not in board.h + pinMode(PB4, OUTPUT); + pinMode(PB4, OUTPUT); //no + pinMode(PB3, OUTPUT); //no + pinMode(PB12, OUTPUT); //yes + pinMode(PB2, OUTPUT); //yes + + // pinMode(PA4, INPUT_PULLDOWN); // mosfet for battery measurement - should be OUTPUT ?? diff --git a/src/system/hardware.h b/src/system/hardware.h index 56516eb..d68cec0 100644 --- a/src/system/hardware.h +++ b/src/system/hardware.h @@ -46,9 +46,6 @@ #define ONBOARD_LED_PIN PA5 -// #define GPIO_PIN_2 PC11 // using for DHT22 -// #define GPIO_PIN_3 PC12 // CN7 3 -// #define GPIO_PIN_4 PB8 // CN10 3, not using bluetooth currently #define GPIO_PIN_1 PA1 #define GPIO_PIN_2 PB2 @@ -58,6 +55,26 @@ #define GPIO_PIN_6 PC12 // actuator tests #define GPIO_PIN_7 PC13 +//available for usage +// #define GPIO_PIN_1 PC10 //doesn't work +// #define GPIO_PIN_2 PC11 // doesn't work +// #define GPIO_PIN_3 PC12 //works, CN7 3 +//#define GPIO_PIN_13 PA13 //doesn't work, PA13 labeled "SWDIO" in KiCad +#define GPIO_PIN_17 PA15 //doesn't work +#define GPIO_PIN_23 PC13 //works, +#define GPIO_PIN_25 PC14 //doesn't work +#define GPIO_PIN_27 PC15 //doesn't work +//#define GPIO_PIN_29 PD0 //not in board.h +//#define GPIO_PIN_31 PD1 //not in board.h +#define GPIO_PIN_30 PA1 //works +#define GPIO_PIN_27_R PB4 //doesn't work +#define GPIO_PIN_31 PB3 //doesn't work +#define GPIO_PIN_16 PB12 //works +#define GPIO_PIN_22 PB2 //works +//A2-A6 work as GPIO, currently used + + + #define EXADC_RESET PC5 // Bluefruit on SPI diff --git a/src/utilities/rrivmath 2.h b/src/utilities/rrivmath 2.h new file mode 100644 index 0000000..a2be1fe --- /dev/null +++ b/src/utilities/rrivmath 2.h @@ -0,0 +1,7 @@ +namespace rrivmath +{ + float power(float x, int y); + double ln(double x); + double log10( double x ); + float floor(float x); +} \ No newline at end of file