371 lines
12 KiB
C++
Executable file
371 lines
12 KiB
C++
Executable file
|
|
|
|
// #define DHTTYPE DHT11 // DHT 11
|
|
|
|
//Controls Mushroom Grow tent
|
|
/*
|
|
Fogger (main Fan)
|
|
|
|
UV light
|
|
|
|
Humidity / Temp 1
|
|
|
|
Humidity / Temp 2
|
|
|
|
Heatemitter
|
|
|
|
Potential CO2 meter
|
|
|
|
*/
|
|
Adafruit_AHTX0 aht;
|
|
Adafruit_SCD30 scd30; // address: 0x61
|
|
// int upperDHT = 5;// address: 0x38
|
|
// int lowerDHT = 6;
|
|
int heatPin = 44;
|
|
int foggerFanPin = 46;
|
|
int uvPin = 7;
|
|
int mainFan = 42;
|
|
// DHT upper(upperDHT, DHTTYPE);
|
|
// DHT lower(lowerDHT, DHTTYPE);
|
|
GasSensor co2Sensor = { {0, 0, 0, 0, 0}, 0, 0, scd30};
|
|
HTSensor upperSensor = {{0, 0, 0, 0, 0}, 0, 0, {0, 0, 0, 0, 0}, 0, 0, aht};
|
|
LvlSensor waterSensor = { {0, 0, 0, 0, 0}, 0, 4, 3, 20};
|
|
// HTSensor lowerSensor = {{0, 0, 0, 0, 0}, 0, 0, {0, 0, 0, 0, 0}, 0, 0, lower};
|
|
MarthaDrain heatLamp = {heatPin, false, 'H'};
|
|
MarthaDrain fogger = {foggerFanPin, false, 'W'};
|
|
MarthaDrain UVLight = {uvPin, false, 'L'};
|
|
MarthaDrain AirFlowFan = {mainFan, false, 'F'};
|
|
unsigned long lastAutoReading;
|
|
int autoReadIntervalMs = 500;
|
|
unsigned long loopIndex = 0;
|
|
//TODO: add General Airflow fan
|
|
|
|
void setupAutoHumidity(float goal, float goalh){
|
|
aht.begin();
|
|
// lowerSensor.aht.begin() ;
|
|
pinMode(waterSensor.trig, OUTPUT); // Initializing Trigger Output and Echo Input
|
|
pinMode(waterSensor.echo, INPUT_PULLUP);
|
|
pinMode(heatLamp.pin, OUTPUT);
|
|
pinMode(fogger.pin, OUTPUT); //Fogger connects to the mister + fan
|
|
pinMode(UVLight.pin, OUTPUT);
|
|
pinMode(AirFlowFan.pin, OUTPUT);
|
|
digitalWrite(heatLamp.pin, HIGH);
|
|
digitalWrite(fogger.pin, HIGH);
|
|
digitalWrite(UVLight.pin, HIGH);
|
|
digitalWrite(AirFlowFan.pin, HIGH);
|
|
lastAutoReading = millis();
|
|
initHTSensor(upperSensor);
|
|
// initHTSensor(lowerSensor);
|
|
setAllGoalTemps(goal);
|
|
setAllGoalHum(goalh);
|
|
while(!co2Sensor.sensor.begin()){
|
|
Serial.println("failed to init chip, please check if the chip connection is fine");
|
|
delay(1000);
|
|
}
|
|
// co2Sensor.sensor.setMeasCycle(co2Sensor.sensor.eCycle_250ms);
|
|
|
|
turnOnAutoDrain(AirFlowFan);
|
|
}
|
|
void AutoControlLoop() {
|
|
unsigned long currentTime = millis();
|
|
if(currentTime - lastAutoReading >= autoReadIntervalMs){
|
|
loopIndex += 1;
|
|
updateAutoSensors();
|
|
updateAutoDrains();
|
|
updateWaterLevel();
|
|
if(loopIndex % 4 == 0){ //Updates every1.5 second
|
|
updateCO2Sensor();
|
|
}
|
|
|
|
lastAutoReading = currentTime;
|
|
}
|
|
}
|
|
|
|
void updateWaterLevel(){
|
|
digitalWrite(waterSensor.trig, LOW); // Set the trigger pin to low for 2uS
|
|
delayMicroseconds(2);
|
|
|
|
digitalWrite(waterSensor.trig, HIGH); // Send a 10uS high to trigger ranging
|
|
delayMicroseconds(20);
|
|
|
|
digitalWrite(waterSensor.trig, LOW); // Send pin low again
|
|
int distance = pulseIn(waterSensor.echo, HIGH,26000); // Read in times pulse
|
|
|
|
Serial.print("distance: ");
|
|
Serial.print(distance);
|
|
// distance= distance/58;
|
|
// Serial.print(", ");
|
|
// Serial.print(distance);
|
|
Serial.println("");
|
|
// if(abs(device.sensor.history[0] - tempC) > WARNING_LOG_DELTA_THRESHOLD){
|
|
// //SOME SORT OF LOGGING HERE
|
|
// }
|
|
for(byte i = (sizeof(waterSensor.history) / sizeof(waterSensor.history[0])) - 1; i >= 1; i--){
|
|
waterSensor.history[i] = waterSensor.history[i - 1];
|
|
}
|
|
waterSensor.history[0] = distance;
|
|
int sum = 0;
|
|
for(byte i = 0; i < (sizeof(waterSensor.history) / sizeof(waterSensor.history[0])); i++){
|
|
sum += waterSensor.history[i];
|
|
}
|
|
int newAgg = sum / (sizeof(waterSensor.history) / sizeof(waterSensor.history[0]));
|
|
waterSensor.currentAgg = newAgg;
|
|
|
|
}
|
|
|
|
void updateCO2Sensor(){
|
|
if(co2Sensor.sensor.dataReady() && co2Sensor.sensor.read()){ // handle not ready or error reading
|
|
int co2 = (int)co2Sensor.sensor.CO2;
|
|
float hum = co2Sensor.sensor.relative_humidity;
|
|
float temp = co2Sensor.sensor.temperature;
|
|
Serial.print("CO2: ");
|
|
Serial.print(co2);
|
|
Serial.print("ppm, Temp: ");
|
|
Serial.print(temp);
|
|
Serial.print(" C, Hum: ");
|
|
Serial.print(hum);
|
|
Serial.println("%");
|
|
|
|
// if(abs(device.sensor.history[0] - tempC) > WARNING_LOG_DELTA_THRESHOLD){
|
|
// //SOME SORT OF LOGGING HERE
|
|
// }
|
|
for(byte i = (sizeof(co2Sensor.history) / sizeof(co2Sensor.history[0])) - 1; i >= 1; i--){
|
|
co2Sensor.history[i] = co2Sensor.history[i - 1];
|
|
}
|
|
co2Sensor.history[0] = co2;
|
|
int sum = 0;
|
|
for(byte i = 0; i < (sizeof(co2Sensor.history) / sizeof(co2Sensor.history[0])); i++){
|
|
sum += co2Sensor.history[i];
|
|
}
|
|
int newAgg = sum / (sizeof(co2Sensor.history) / sizeof(co2Sensor.history[0]));
|
|
co2Sensor.currentAgg = newAgg;
|
|
co2Sensor.currentTemp = temp;
|
|
co2Sensor.currentHum = hum;
|
|
|
|
} else {
|
|
Serial.println("Data is not ready!");
|
|
if(!co2Sensor.sensor.begin()){
|
|
Serial.println("failed to init chip, please check if the chip connection is fine");
|
|
}
|
|
// co2Sensor.sensor.setMeasCycle(co2Sensor.sensor.eCycle_250ms);
|
|
}
|
|
/*!
|
|
* @brief Set baseline
|
|
* @param get from getBaseline.ino
|
|
*/
|
|
// co2Sensor.sensor.writeBaseLine(0x847B);
|
|
}
|
|
|
|
void updateAutoDrains(){
|
|
if(abs(upperSensor.goalValTemp - upperSensor.currentAggTemp) > HEAT_DELTA){
|
|
if(upperSensor.goalValTemp > upperSensor.currentAggTemp){
|
|
turnOnHeat();
|
|
}else if(upperSensor.goalValTemp < upperSensor.currentAggTemp){
|
|
turnOffHeat();
|
|
}
|
|
}
|
|
|
|
if(abs(upperSensor.goalValHum - upperSensor.currentAggHum) > HUM_DELTA){
|
|
if(upperSensor.goalValHum > upperSensor.currentAggHum){
|
|
// if(!fogger.isActive){
|
|
// Serial.println("*************FOGGER ON *************");
|
|
// fogger.isActive = true;
|
|
// // analogWrite(fogger.pin, 255);
|
|
// delay(1000);
|
|
// }
|
|
turnOnAutoDrain(fogger);
|
|
}else if(upperSensor.goalValHum < upperSensor.currentAggHum){
|
|
// if(fogger.isActive){
|
|
// Serial.println("*************FOGGER off *************");
|
|
// fogger.isActive = false;
|
|
// // analogWrite(fogger.pin, 0);
|
|
// delay(1000);
|
|
// }
|
|
turnOffAutoDrain(fogger);
|
|
}
|
|
}
|
|
if(loopIndex % 10 < UV_UP_TIME){ //
|
|
turnOnAutoDrain(UVLight);
|
|
}else{
|
|
turnOffAutoDrain(UVLight);
|
|
}
|
|
}
|
|
void updateAutoSensors(){
|
|
getHTData(upperSensor);
|
|
}
|
|
|
|
float *getMarthaData(float (& upperArray)[14], float (& lowerArray)[14], float (& co2Array)[7], bool (& heatState), bool (& foggerState), bool (& UVState)){
|
|
|
|
heatState = heatLamp.isActive;
|
|
foggerState = fogger.isActive;
|
|
UVState = UVLight.isActive;
|
|
upperArray[0] = upperSensor.currentAggTemp;
|
|
upperArray[1] = upperSensor.tempHistory[0];
|
|
upperArray[2] = upperSensor.tempHistory[1];
|
|
upperArray[3] = upperSensor.tempHistory[2];
|
|
upperArray[4] = upperSensor.tempHistory[3];
|
|
upperArray[5] = upperSensor.tempHistory[4];
|
|
upperArray[6] = upperSensor.goalValTemp;
|
|
upperArray[7] = upperSensor.currentAggHum;
|
|
upperArray[8] = upperSensor.humHistory[0];
|
|
upperArray[9] = upperSensor.humHistory[1];
|
|
upperArray[10] = upperSensor.humHistory[2];
|
|
upperArray[11] = upperSensor.humHistory[3];
|
|
upperArray[12] = upperSensor.humHistory[4];
|
|
upperArray[13] = upperSensor.goalValHum;
|
|
|
|
lowerArray[0] = waterSensor.currentAgg;
|
|
lowerArray[1] = waterSensor.history[0];
|
|
lowerArray[2] = waterSensor.history[1];
|
|
lowerArray[3] = waterSensor.history[2];
|
|
lowerArray[4] = waterSensor.history[3];
|
|
lowerArray[5] = waterSensor.history[4];
|
|
lowerArray[6] = waterSensor.goalVal;
|
|
|
|
co2Array[0] = co2Sensor.currentAgg;
|
|
co2Array[1] = co2Sensor.history[0];
|
|
co2Array[2] = co2Sensor.history[1];
|
|
co2Array[3] = co2Sensor.history[2];
|
|
co2Array[4] = co2Sensor.history[3];
|
|
co2Array[5] = co2Sensor.history[4];
|
|
co2Array[6] = co2Sensor.goalVal;
|
|
}
|
|
|
|
|
|
void getHTData(HTSensor &device)
|
|
{
|
|
sensors_event_t humidity, temp;
|
|
aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
|
|
Serial.print("Temperature: "); Serial.print(temp.temperature);
|
|
Serial.println(" degrees C");
|
|
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity);
|
|
Serial.println("% rH");
|
|
float h = humidity.relative_humidity;
|
|
float c = temp.temperature;
|
|
|
|
// Check if any reads failed
|
|
if (isnan(h) || isnan(c)) {
|
|
// Serial.println(F("Failed to read from DHT sensor!"));
|
|
}else {
|
|
if(abs(device.tempHistory[0] - c) > WARNING_LOG_DELTA_THRESHOLD){
|
|
//SOME SORT OF LOGGING HERE
|
|
|
|
}
|
|
for(byte i = (sizeof(device.tempHistory) / sizeof(device.tempHistory[0])) - 1; i >= 1; i--){
|
|
device.tempHistory[i] = device.tempHistory[i - 1];
|
|
device.humHistory[i] = device.humHistory[i - 1];
|
|
}
|
|
device.tempHistory[0] = c;
|
|
device.humHistory[0] = h;
|
|
float tempSum = 0;
|
|
float humSum = 0;
|
|
for(byte i = 0; i < (sizeof(device.tempHistory) / sizeof(device.tempHistory[0])); i++){
|
|
tempSum += device.tempHistory[i];
|
|
humSum += device.humHistory[i];
|
|
}
|
|
float newAggTemp = tempSum / (sizeof(device.tempHistory) / sizeof(device.tempHistory[0]));
|
|
float newAggHum = humSum / (sizeof(device.humHistory) / sizeof(device.humHistory[0]));
|
|
device.currentAggTemp = newAggTemp;
|
|
device.currentAggHum = newAggHum;
|
|
Serial.print("H ");
|
|
Serial.println(newAggHum);
|
|
}
|
|
}
|
|
|
|
void turnOnAutoDrain(MarthaDrain &device)
|
|
{
|
|
if(!device.isActive){
|
|
if(device.type == 'W'){ //water
|
|
turnOnAutoDrain(AirFlowFan);
|
|
}
|
|
device.isActive = true;
|
|
digitalWrite(device.pin, LOW);
|
|
}
|
|
}
|
|
|
|
void turnOffAutoDrain(MarthaDrain &device)
|
|
{
|
|
if(device.isActive){
|
|
if(device.type == 'W'){ //water
|
|
turnOffAutoDrain(AirFlowFan);
|
|
}
|
|
device.isActive = false;
|
|
digitalWrite(device.pin, HIGH);
|
|
}
|
|
}
|
|
void turnOnHeat()
|
|
{
|
|
if(!heatLamp.isActive){
|
|
heatLamp.isActive = true;
|
|
digitalWrite(heatLamp.pin, LOW);
|
|
}
|
|
}
|
|
|
|
void turnOffHeat()
|
|
{
|
|
if(heatLamp.isActive){
|
|
heatLamp.isActive = false;
|
|
digitalWrite(heatLamp.pin, HIGH);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void setAllGoalHum(float g1){
|
|
upperSensor.goalValHum = g1;
|
|
// lowerSensor.goalValHum = g1;
|
|
}
|
|
|
|
void setAllGoalTemps(float g1){
|
|
upperSensor.goalValTemp = g1;
|
|
// lowerSensor.goalValTemp = g1;
|
|
}
|
|
|
|
void setGoalCO2(int g){
|
|
co2Sensor.goalVal = g;
|
|
}
|
|
|
|
|
|
|
|
void initHTSensor(HTSensor &device)
|
|
{
|
|
sensors_event_t humidity, temp;
|
|
aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
|
|
Serial.print("Temperature: "); Serial.print(temp.temperature);
|
|
Serial.println(" degrees C");
|
|
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity);
|
|
Serial.println("% rH");
|
|
float h = humidity.relative_humidity;
|
|
float c = temp.temperature;
|
|
|
|
// Check if any reads failed
|
|
if (isnan(h) || isnan(c)) {
|
|
Serial.println(F("Failed to read from DHT sensor!"));
|
|
device.currentAggTemp = 0;
|
|
device.tempHistory[0] = 0;
|
|
device.tempHistory[1] = 0;
|
|
device.tempHistory[2] = 0;
|
|
device.tempHistory[3] = 0;
|
|
device.tempHistory[4] = 0;
|
|
device.currentAggHum = 0;
|
|
device.humHistory[0] = 0;
|
|
device.humHistory[1] = 0;
|
|
device.humHistory[2] = 0;
|
|
device.humHistory[3] = 0;
|
|
device.humHistory[4] = 0;
|
|
}else {
|
|
device.currentAggTemp = c;
|
|
device.tempHistory[0] = c;
|
|
device.tempHistory[1] = c;
|
|
device.tempHistory[2] = c;
|
|
device.tempHistory[3] = c;
|
|
device.tempHistory[4] = c;
|
|
device.currentAggHum = h;
|
|
device.humHistory[0] = h;
|
|
device.humHistory[1] = h;
|
|
device.humHistory[2] = h;
|
|
device.humHistory[3] = h;
|
|
device.humHistory[4] = h;
|
|
}
|
|
}
|