allow sensor type selection per plant, changed calculations to use PCT values, due to different raw value meaning
This commit is contained in:
@@ -93,6 +93,9 @@
|
||||
#define MOIST_SENSOR_MAX_FRQ 10000 // 10kHz (as never more then 3000 was measured)
|
||||
#define MOIST_SENSOR_MIN_FRQ 1000 // 1kHz (500Hz margin)
|
||||
|
||||
#define ANALOG_SENSOR_MAX_MV 1000
|
||||
#define ANALOG_SENSOR_MIN_MV 100
|
||||
|
||||
#define SOLAR_VOLT_FACTOR 11
|
||||
#define BATTSENSOR_INDEX_SOLAR 0
|
||||
#define BATTSENSOR_INDEX_BATTERY 1
|
||||
|
@@ -101,6 +101,7 @@ HomieSetting<const char *> ntpServer("ntpServer", "NTP server (pool.ntp.org as d
|
||||
|
||||
#define GENERATE_PLANT(plant, strplant) \
|
||||
HomieSetting<double> mSensorDry##plant = HomieSetting<double>("dry" strplant, "Plant " strplant "- Moist sensor dry %"); \
|
||||
HomieSetting<long> pSensorType##plant = HomieSetting<long>("sensoryType" strplant, "sensor" strplant " - sensortype"); \
|
||||
HomieSetting<long> mPumpAllowedHourRangeStart##plant = HomieSetting<long>("hourstart" strplant, "Plant" strplant " - Range pump allowed hour start (0-23)"); \
|
||||
HomieSetting<long> mPumpAllowedHourRangeEnd##plant = HomieSetting<long>("hourend" strplant, "Plant" strplant " - Range pump allowed hour end (0-23)"); \
|
||||
HomieSetting<bool> mPumpOnlyWhenLowLight##plant = HomieSetting<bool>("lowLight" strplant, "Plant" strplant " - Enable the Pump only, when there is no sunlight"); \
|
||||
@@ -108,7 +109,7 @@ HomieSetting<const char *> ntpServer("ntpServer", "NTP server (pool.ntp.org as d
|
||||
HomieSetting<long> pPumpDuration##plant = HomieSetting<long>("pumpDuration" strplant, "Plant" strplant " - time seconds to water when pump is active"); \
|
||||
HomieSetting<long> pPumpMl##plant = HomieSetting<long>("pumpAmount" strplant, "Plant" strplant " - ml (if using flowmeter) to water when pump is active"); \
|
||||
HomieSetting<long> pPowerLevel##plant = HomieSetting<long>("powerLevel" strplant, "Plant" strplant " - pwm duty cycle in percent"); \
|
||||
PlantSettings_t mSetting##plant = {&mSensorDry##plant, &mPumpAllowedHourRangeStart##plant, &mPumpAllowedHourRangeEnd##plant, &mPumpOnlyWhenLowLight##plant, &mPumpCooldownInMinutes##plant, &pPumpDuration##plant, &pPowerLevel##plant, &pPumpMl##plant}; \
|
||||
PlantSettings_t mSetting##plant = {&mSensorDry##plant, &pSensorType##plant, &mPumpAllowedHourRangeStart##plant, &mPumpAllowedHourRangeEnd##plant, &mPumpOnlyWhenLowLight##plant, &mPumpCooldownInMinutes##plant, &pPumpDuration##plant, &pPowerLevel##plant, &pPumpMl##plant}; \
|
||||
/**< Generate all settings for one plant \
|
||||
* \
|
||||
* Feature to start pumping only at morning: @link{SOLAR_CHARGE_MIN_VOLTAGE} and @link{SOLAR_CHARGE_MAX_VOLTAGE} \
|
||||
|
@@ -13,6 +13,10 @@
|
||||
|
||||
#include <Homie.h>
|
||||
|
||||
#define SENSOR_NONE 0
|
||||
#define SENSOR_CAPACITIVE_FREQUENCY_MOD 1
|
||||
#define SENSOR_ANALOG_RESISTANCE_PROBE 2
|
||||
|
||||
//plant pump is deactivated, but sensor values are still recorded and published
|
||||
#define DEACTIVATED_PLANT -1
|
||||
//special value to indicate a missing sensor when the plant is not deactivated but no valid sensor value was read
|
||||
@@ -23,6 +27,7 @@
|
||||
typedef struct PlantSettings_t
|
||||
{
|
||||
HomieSetting<double> *pSensorDry;
|
||||
HomieSetting<long> *pSensorMode;
|
||||
HomieSetting<long> *pPumpAllowedHourRangeStart;
|
||||
HomieSetting<long> *pPumpAllowedHourRangeEnd;
|
||||
HomieSetting<bool> *pPumpOnlyWhenLowLight;
|
||||
|
@@ -21,6 +21,9 @@
|
||||
#define LOG_HARDWARECOUNTER_ERROR_MESSAGE "PCNR returned error"
|
||||
#define LOG_HARDWARECOUNTER_ERROR_CODE -4
|
||||
|
||||
#define LOG_SENSORMODE_UNKNOWN "Unknown sensor mode requested"
|
||||
#define LOG_SENSORMODE_UNKNOWN_CODE -5
|
||||
|
||||
#define LOG_PUMP_AND_DOWNLOADMODE "Download mode, ignoring pump request"
|
||||
#define LOG_PUMP_AND_DOWNLOADMODE_CODE 2
|
||||
|
||||
|
@@ -3,5 +3,6 @@
|
||||
|
||||
|
||||
bool equalish(double x, double y);
|
||||
double mapf(double x, double in_min, double in_max, double out_min, double out_max);
|
||||
|
||||
#endif
|
@@ -17,19 +17,21 @@
|
||||
#include "ControllerConfiguration.h"
|
||||
#include "RunningMedian.h"
|
||||
#include "MathUtils.h"
|
||||
#include "MQTTUtils.h"
|
||||
#include "LogDefines.h"
|
||||
|
||||
#define MOISTURE_MEASUREMENT_DURATION 400 /** ms */
|
||||
#define ANALOG_REREADS 5
|
||||
#define MOISTURE_MEASUREMENT_DURATION 400 /** ms */
|
||||
#define PWM_FREQ 50000
|
||||
#define PWM_BITS 8
|
||||
|
||||
|
||||
class Plant
|
||||
{
|
||||
|
||||
private:
|
||||
HomieNode *mPlant = NULL;
|
||||
HomieInternals::PropertyInterface mPump;
|
||||
int32_t mMoisture_freq = 0;
|
||||
RunningMedian mMoisture_raw = RunningMedian(ANALOG_REREADS);
|
||||
int mPinSensor = 0; /**< Pin of the moist sensor */
|
||||
int mPinPump = 0; /**< Pin of the pump */
|
||||
bool mConnected = false;
|
||||
@@ -52,10 +54,9 @@ public:
|
||||
|
||||
void advertise(void);
|
||||
|
||||
/**
|
||||
* @brief Measure a new analog moister value
|
||||
*
|
||||
*/
|
||||
//for sensor that might take any time
|
||||
void blockingMoistureMeasurement(void);
|
||||
//for sensor that need a start and a end in defined timing
|
||||
void startMoistureMeasurement(void);
|
||||
void stopMoistureMeasurement(void);
|
||||
|
||||
@@ -63,10 +64,15 @@ public:
|
||||
|
||||
void activatePump(void);
|
||||
|
||||
|
||||
bool isHydroponic(){
|
||||
bool isHydroponic()
|
||||
{
|
||||
long current = this->mSetting->pSensorDry->get();
|
||||
return equalish(current,HYDROPONIC_MODE);
|
||||
return equalish(current, HYDROPONIC_MODE);
|
||||
}
|
||||
|
||||
long isSensorMode(int sensorMode)
|
||||
{
|
||||
return this->mSetting->pSensorMode->get() == sensorMode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,36 +83,27 @@ public:
|
||||
*/
|
||||
bool isPumpRequired()
|
||||
{
|
||||
if(isHydroponic()){
|
||||
if (isHydroponic())
|
||||
{
|
||||
//hydroponic only uses timer based controll
|
||||
return true;
|
||||
}
|
||||
bool isDry = getCurrentMoisture() > getSetting2Moisture();
|
||||
bool isDry = getCurrentMoisturePCT() < getTargetMoisturePCT();
|
||||
bool isActive = isPumpTriggerActive();
|
||||
return isDry && isActive;
|
||||
}
|
||||
}
|
||||
|
||||
bool isPumpTriggerActive()
|
||||
{
|
||||
long current = this->mSetting->pSensorDry->get();
|
||||
return !equalish(current,DEACTIVATED_PLANT);
|
||||
return !equalish(current, DEACTIVATED_PLANT);
|
||||
}
|
||||
|
||||
float getCurrentMoisture()
|
||||
{
|
||||
if(mMoisture_freq < MOIST_SENSOR_MIN_FRQ){
|
||||
return MISSING_SENSOR;
|
||||
}
|
||||
return mMoisture_freq;
|
||||
}
|
||||
|
||||
long getSetting2Moisture()
|
||||
float getTargetMoisturePCT()
|
||||
{
|
||||
if (this->mSetting->pSensorDry != NULL)
|
||||
if (isPumpTriggerActive())
|
||||
{
|
||||
//1 is totally wet, 0 is try, 0 is MOIST_SENSOR_MAX_FRQ, 1 is MOIST_SENSOR_MIN_FRQ
|
||||
float factor = (this->mSetting->pSensorDry->get());
|
||||
return map(factor,0,100,MOIST_SENSOR_MAX_FRQ,MOIST_SENSOR_MIN_FRQ);
|
||||
return this->mSetting->pSensorDry->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -114,6 +111,38 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
float getCurrentMoisturePCT()
|
||||
{
|
||||
if (isSensorMode(SENSOR_NONE))
|
||||
{
|
||||
return DEACTIVATED_PLANT;
|
||||
}
|
||||
if (isSensorMode(SENSOR_CAPACITIVE_FREQUENCY_MOD))
|
||||
{
|
||||
return mapf(mMoisture_raw.getMedian(), MOIST_SENSOR_MAX_FRQ, MOIST_SENSOR_MIN_FRQ, 0, 100);
|
||||
}
|
||||
else if (isSensorMode(SENSOR_ANALOG_RESISTANCE_PROBE))
|
||||
{
|
||||
return mapf(mMoisture_raw.getMedian(), ANALOG_SENSOR_MAX_MV, ANALOG_SENSOR_MIN_MV, 0, 100);
|
||||
} else {
|
||||
log(LOG_LEVEL_ERROR, LOG_SENSORMODE_UNKNOWN, LOG_SENSORMODE_UNKNOWN_CODE);
|
||||
return DEACTIVATED_PLANT;
|
||||
}
|
||||
}
|
||||
|
||||
float getCurrentMoistureRaw()
|
||||
{
|
||||
if (isSensorMode(SENSOR_CAPACITIVE_FREQUENCY_MOD))
|
||||
{
|
||||
if (mMoisture_raw.getMedian() < MOIST_SENSOR_MIN_FRQ)
|
||||
{
|
||||
return MISSING_SENSOR;
|
||||
}
|
||||
}
|
||||
|
||||
return mMoisture_raw.getMedian();
|
||||
}
|
||||
|
||||
HomieInternals::SendingPromise &setProperty(const String &property) const
|
||||
{
|
||||
return mPlant->setProperty(property);
|
||||
@@ -121,7 +150,8 @@ public:
|
||||
|
||||
void init(void);
|
||||
|
||||
long getCooldownInSeconds() {
|
||||
long getCooldownInSeconds()
|
||||
{
|
||||
return this->mSetting->pPumpCooldownInSeconds->get();
|
||||
}
|
||||
|
||||
@@ -130,7 +160,8 @@ public:
|
||||
*
|
||||
* @return hour
|
||||
*/
|
||||
int getHoursStart() {
|
||||
int getHoursStart()
|
||||
{
|
||||
return this->mSetting->pPumpAllowedHourRangeStart->get();
|
||||
}
|
||||
|
||||
@@ -139,13 +170,15 @@ public:
|
||||
*
|
||||
* @return hour
|
||||
*/
|
||||
int getHoursEnd() {
|
||||
int getHoursEnd()
|
||||
{
|
||||
return this->mSetting->pPumpAllowedHourRangeEnd->get();
|
||||
}
|
||||
|
||||
bool isAllowedOnlyAtLowLight(void)
|
||||
{
|
||||
if(this->isHydroponic()){
|
||||
if (this->isHydroponic())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return this->mSetting->pPumpOnlyWhenLowLight->get();
|
||||
@@ -153,11 +186,12 @@ public:
|
||||
|
||||
void publishState(String state);
|
||||
|
||||
bool switchHandler(const HomieRange& range, const String& value);
|
||||
bool switchHandler(const HomieRange &range, const String &value);
|
||||
|
||||
void setSwitchHandler(HomieInternals::PropertyInputHandler f);
|
||||
|
||||
long getPumpDuration() {
|
||||
long getPumpDuration()
|
||||
{
|
||||
return this->mSetting->pPumpDuration->get();
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user