BioController
This commit is contained in:
commit
c3121c907a
8 changed files with 3228 additions and 0 deletions
371
AutoHumidity.ino
Executable file
371
AutoHumidity.ino
Executable file
|
|
@ -0,0 +1,371 @@
|
|||
|
||||
|
||||
// #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;
|
||||
}
|
||||
}
|
||||
93
DataLogger.ino
Normal file
93
DataLogger.ino
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
|
||||
|
||||
// -------
|
||||
// ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 0.1875mV (default)
|
||||
// ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 0.125mV
|
||||
// ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 0.0625mV
|
||||
// ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.03125mV
|
||||
// ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.015625mV
|
||||
|
||||
|
||||
const int size = 150;
|
||||
const int voltNums = 4;
|
||||
const int voltMeters[voltNums] = {0x48, 0x49, 0x4A, 0x4B}; // 0x48, 0x49, 0x4A, 0x4B
|
||||
vReading adsArray[voltNums];
|
||||
float multiplier = 0.0078125F; // ADS1115 @ +/- 6.144V gain = 0.0078125mV/step
|
||||
unsigned long lastDataLoggerReading;
|
||||
int DataLoggerReadIntervalMs = 50;
|
||||
|
||||
void setupDataLogger(){
|
||||
lastDataLoggerReading = millis();
|
||||
for(int x = 0; x < voltNums; x++){
|
||||
adsArray[x].sensor.setGain(GAIN_SIXTEEN);
|
||||
adsArray[x].sensor.setDataRate(RATE_ADS1115_32SPS);
|
||||
adsArray[x].sensor.begin(voltMeters[x]);
|
||||
for (int y = 0; y < size - 1; y++){
|
||||
adsArray[x].readings1[y] = 0;
|
||||
adsArray[x].readings2[y] = 0;
|
||||
}
|
||||
}
|
||||
Serial.println("done DataLogger Init");
|
||||
}
|
||||
|
||||
|
||||
void updateDataLogger(){
|
||||
// Serial.print(" ------------------------------- ");
|
||||
for(int x = 0; x < (sizeof(voltMeters) / sizeof(voltMeters[0])); x++){
|
||||
adsArray[x].readings1[adsArray[x].readCnt] = adsArray[x].sensor.readADC_Differential_0_1() * multiplier; // read differential AIN0 - AIN1
|
||||
adsArray[x].readings2[adsArray[x].readCnt] = adsArray[x].sensor.readADC_Differential_2_3() * multiplier; // read differential AIN2 - AIN3
|
||||
|
||||
float diff1 = (adsArray[x].sensor.readADC_SingleEnded(1) * multiplier) - (adsArray[x].sensor.readADC_SingleEnded(0) * multiplier);
|
||||
float diff2 = (adsArray[x].sensor.readADC_SingleEnded(3) * multiplier) - (adsArray[x].sensor.readADC_SingleEnded(2) * multiplier);
|
||||
|
||||
// Serial.print(adsArray[x].readings1[adsArray[x].readCnt]);
|
||||
// Serial.print("mV Prong 1 Avr: ");
|
||||
// Serial.print(adsArray[x].avrProng1);
|
||||
// Serial.print(" N "); Serial.print(adsArray[x].sensor.readADC_SingleEnded(0) * multiplier);
|
||||
// Serial.print(" P "); Serial.println(adsArray[x].sensor.readADC_SingleEnded(1) * multiplier);
|
||||
// Serial.print(" Diff1 "); Serial.println(diff1);
|
||||
// Serial.print(adsArray[x].readings2[adsArray[x].readCnt]); Serial.print("mV Prong 2 Avr: "); Serial.print(adsArray[x].avrProng2);
|
||||
// Serial.print(" N "); Serial.print(adsArray[x].sensor.readADC_SingleEnded(2) * multiplier);
|
||||
// Serial.print(" P "); Serial.println(adsArray[x].sensor.readADC_SingleEnded(3) * multiplier);
|
||||
// Serial.print(" Diff2 "); Serial.println(diff2);
|
||||
|
||||
// Get the average
|
||||
unsigned long totalreadings1 = 0;
|
||||
unsigned long totalreadings2 = 0;
|
||||
for (unsigned char cnt = 0; cnt < size; cnt++){
|
||||
totalreadings1 += adsArray[x].readings1[cnt];
|
||||
totalreadings2 += adsArray[x].readings2[cnt];
|
||||
}
|
||||
adsArray[x].avrProng1 = totalreadings1 / size;
|
||||
adsArray[x].avrProng2 = totalreadings2 / size;
|
||||
adsArray[x].readCnt = adsArray[x].readCnt == size - 1 ? 0 : adsArray[x].readCnt + 1;
|
||||
}
|
||||
Serial.println();
|
||||
// Serial.print("----------------------------------------------------------------------");Serial.println((int16_t)0);
|
||||
}
|
||||
|
||||
void DataLoggerControlLoop() {
|
||||
unsigned long currentTime = millis();
|
||||
if(currentTime - lastDataLoggerReading >= DataLoggerReadIntervalMs){
|
||||
updateDataLogger();
|
||||
|
||||
lastDataLoggerReading = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float *getDataLoggerDump(float (& array)[8]){
|
||||
|
||||
array[0] = adsArray[0].avrProng1;
|
||||
array[1] = adsArray[0].avrProng2;
|
||||
array[2] = adsArray[1].avrProng1;
|
||||
array[3] = adsArray[1].avrProng2;
|
||||
array[4] = adsArray[2].avrProng1;
|
||||
array[5] = adsArray[2].avrProng2;
|
||||
array[6] = adsArray[3].avrProng1;
|
||||
array[7] = adsArray[3].avrProng2;
|
||||
}
|
||||
|
||||
|
||||
181
Incubator.ino
Executable file
181
Incubator.ino
Executable file
|
|
@ -0,0 +1,181 @@
|
|||
|
||||
|
||||
//Incubator
|
||||
/*
|
||||
Temp 1
|
||||
|
||||
Temp 2
|
||||
|
||||
HeatMat 1
|
||||
|
||||
HeatMat 2
|
||||
|
||||
*/
|
||||
|
||||
|
||||
OneWire t1(2);
|
||||
|
||||
DallasTemperature incubatorSensors(&t1);
|
||||
unsigned long lastIncubatorReading;
|
||||
int incubatorReadIntervalMs = 500;
|
||||
|
||||
// OneSensor tempPin1 = { {0, 0, 0, 0, 0}, 0, { 0x28, 0xEE, 0xD5, 0x64, 0x1A, 0x16, 0x02, 0xEC }, 0};
|
||||
// OneSensor tempPin2 = { {0, 0, 0, 0, 0}, 0, { 0x28, 0xEE, 0xD5, 0x64, 0x1A, 0x16, 0x02, 0xEC }, 0};
|
||||
int mainSectionPin = 11;
|
||||
int secondarySectionPin = 12;
|
||||
IncubatorDrain heatSection1 = {mainSectionPin, false, 'H', { {0, 0, 0, 0, 0}, 0, { 0x28, 0xF6, 0xF2, 0x96, 0xF0, 0x01, 0x3C, 0x47 }, 0}};
|
||||
IncubatorDrain heatSection2 = {secondarySectionPin, false, 'H', { {0, 0, 0, 0, 0}, 0, { 0x28, 0xEB, 0x74, 0x96, 0xF0, 0x01, 0x3C, 0x01 }, 0}};
|
||||
|
||||
|
||||
void setupIncubator(int goal1, int goal2){
|
||||
pinMode( heatSection1.pin, OUTPUT);
|
||||
pinMode( heatSection2.pin, OUTPUT);
|
||||
digitalWrite(heatSection1.pin, HIGH);
|
||||
digitalWrite(heatSection2.pin, HIGH);
|
||||
incubatorSensors.begin();
|
||||
lastIncubatorReading = millis();
|
||||
initDrainSensor(heatSection1);
|
||||
initDrainSensor(heatSection2);
|
||||
setAllGoalTemps(goal1, goal2);
|
||||
|
||||
}
|
||||
|
||||
void IncubatorControlLoop () {
|
||||
unsigned long currentTime = millis();
|
||||
if(currentTime - lastIncubatorReading >= incubatorReadIntervalMs){
|
||||
updateIncubatorSensors();
|
||||
updateIncubatorDrains();
|
||||
|
||||
lastIncubatorReading = currentTime;
|
||||
}
|
||||
}
|
||||
void updateIncubatorDrains(){
|
||||
if(abs(heatSection1.sensor.goalVal - heatSection1.sensor.currentAgg) > HEAT_DELTA){
|
||||
if(heatSection1.sensor.goalVal > heatSection1.sensor.currentAgg){
|
||||
turnOnIncubatorDrain(heatSection1);
|
||||
}else if(heatSection1.sensor.goalVal < heatSection1.sensor.currentAgg){
|
||||
turnOffIncubatorDrain(heatSection1);
|
||||
}
|
||||
}
|
||||
|
||||
if(abs(heatSection2.sensor.goalVal - heatSection2.sensor.currentAgg) > HEAT_DELTA){
|
||||
if(heatSection2.sensor.goalVal > heatSection2.sensor.currentAgg){
|
||||
turnOnIncubatorDrain(heatSection2);
|
||||
}else if(heatSection2.sensor.goalVal < heatSection2.sensor.currentAgg){
|
||||
turnOffIncubatorDrain(heatSection2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void turnOnIncubatorDrain(IncubatorDrain &device)
|
||||
{
|
||||
if(!device.isActive){
|
||||
device.isActive = true;
|
||||
digitalWrite(device.pin, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
void turnOffIncubatorDrain(IncubatorDrain &device)
|
||||
{
|
||||
if(device.isActive){
|
||||
device.isActive = false;
|
||||
digitalWrite(device.pin, HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
void initDrainSensor(IncubatorDrain &device)
|
||||
{
|
||||
float tempC = incubatorSensors.getTempC(device.sensor.address);
|
||||
device.sensor.currentAgg = tempC;
|
||||
device.sensor.history[0] = tempC;
|
||||
device.sensor.history[1] = tempC;
|
||||
device.sensor.history[2] = tempC;
|
||||
device.sensor.history[3] = tempC;
|
||||
device.sensor.history[4] = tempC;
|
||||
}
|
||||
|
||||
void updateIncubatorSensors(){
|
||||
incubatorSensors.requestTemperatures();
|
||||
getTemperature(heatSection1);
|
||||
getTemperature(heatSection2);
|
||||
}
|
||||
|
||||
void setMainChamber(float goal){
|
||||
heatSection1.sensor.goalVal = goal;
|
||||
}
|
||||
|
||||
void setSecondaryChamber(float goal){
|
||||
heatSection2.sensor.goalVal = goal;
|
||||
}
|
||||
|
||||
void setAllGoalTemps(float g1, float g2){
|
||||
heatSection1.sensor.goalVal = g1;
|
||||
heatSection2.sensor.goalVal = g2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float *getSectionData(String isMain, float (& array)[8]){
|
||||
if(isMain.equals("Main")){
|
||||
array[0] = heatSection1.sensor.currentAgg;
|
||||
array[1] = heatSection1.sensor.history[0];
|
||||
array[2] = heatSection1.sensor.history[1];
|
||||
array[3] = heatSection1.sensor.history[2];
|
||||
array[4] = heatSection1.sensor.history[3];
|
||||
array[5] = heatSection1.sensor.history[4];
|
||||
array[6] = heatSection1.sensor.goalVal;
|
||||
array[7] = heatSection1.isActive ? 1 : 0;
|
||||
}else {
|
||||
array[0] = heatSection2.sensor.currentAgg;
|
||||
array[1] = heatSection2.sensor.history[0];
|
||||
array[2] = heatSection2.sensor.history[1];
|
||||
array[3] = heatSection2.sensor.history[2];
|
||||
array[4] = heatSection2.sensor.history[3];
|
||||
array[5] = heatSection2.sensor.history[4];
|
||||
array[6] = heatSection2.sensor.goalVal;
|
||||
array[7] = heatSection2.isActive ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void setTemperature(String isMain, float goal){
|
||||
if(isMain.equals("Main")){
|
||||
setMainChamber(goal);
|
||||
}else {
|
||||
setSecondaryChamber(goal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void getTemperature(IncubatorDrain &device)
|
||||
{
|
||||
float tempC = incubatorSensors.getTempC(device.sensor.address);
|
||||
if(abs(device.sensor.history[0] - tempC) > WARNING_LOG_DELTA_THRESHOLD){
|
||||
//SOME SORT OF LOGGING HERE
|
||||
}
|
||||
if(tempC > -120){ //-127c is disconnected
|
||||
for(byte i = (sizeof(device.sensor.history) / sizeof(device.sensor.history[0])) - 1; i >= 1; i--){
|
||||
device.sensor.history[i] = device.sensor.history[i - 1];
|
||||
}
|
||||
device.sensor.history[0] = tempC;
|
||||
float sum = 0;
|
||||
for(byte i = 0; i < (sizeof(device.sensor.history) / sizeof(device.sensor.history[0])); i++){
|
||||
sum += device.sensor.history[i];
|
||||
}
|
||||
float newAgg = sum / (sizeof(device.sensor.history) / sizeof(device.sensor.history[0]));
|
||||
device.sensor.currentAgg = newAgg;
|
||||
printTemperature(device.sensor.address);
|
||||
}else {
|
||||
Serial.println("DHT Sensor disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
void printTemperature(DeviceAddress deviceAddress)
|
||||
{
|
||||
float tempC = incubatorSensors.getTempC(deviceAddress);
|
||||
Serial.print(tempC);
|
||||
Serial.print((char)176);
|
||||
Serial.println("C ");
|
||||
// Serial.print(DallasTemperature::toFahrenheit(tempC));
|
||||
// Serial.print((char)176);
|
||||
// Serial.println("F");
|
||||
}
|
||||
462
MainController.ino
Executable file
462
MainController.ino
Executable file
|
|
@ -0,0 +1,462 @@
|
|||
#include <aJSON.h>
|
||||
#include <SPI.h>
|
||||
#include <Ethernet.h>
|
||||
#include "aWOT.h"
|
||||
#include "StaticFiles.h"
|
||||
#include <DallasTemperature.h>
|
||||
#include <utility/w5100.h>
|
||||
#include <Adafruit_SCD30.h>
|
||||
#include <Wire.h>
|
||||
#include <Arduino.h>
|
||||
#include <OneWire.h>
|
||||
#include <CCS811.h>
|
||||
#include <Adafruit_AHTX0.h>
|
||||
#include <Adafruit_ADS1X15.h>
|
||||
#include <Wire.h>
|
||||
|
||||
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
EthernetServer server(80);
|
||||
Application app;
|
||||
unsigned long connectTime[MAX_SOCK_NUM];
|
||||
int WARNING_LOG_DELTA_THRESHOLD = 5; // > 5c temp diff in 0.500s is alarming and should be logged as anamolous
|
||||
float HEAT_DELTA = 0.2; // Delta from goal Temp to neccessitate a change
|
||||
float HUM_DELTA = 1; // Delta from goal Humidity to neccessitate a change
|
||||
short UV_UP_TIME = 6; // 6/10
|
||||
// const String ip = "10.0.0.28";
|
||||
//272911496883
|
||||
IPAddress ip(10,0,0,28);
|
||||
byte gateway[] = { 10, 0, 0, 1 };
|
||||
byte subnet[] = { 255, 255, 255, 0 };
|
||||
|
||||
struct OneSensor {
|
||||
float history[5];
|
||||
float currentAgg;
|
||||
uint8_t address[8];
|
||||
float goalVal;
|
||||
};
|
||||
struct GasSensor {
|
||||
int history[5];
|
||||
int currentAgg;
|
||||
int goalVal;
|
||||
Adafruit_SCD30 sensor;
|
||||
float currentTemp;
|
||||
float currentHum;
|
||||
};
|
||||
|
||||
struct LvlSensor {
|
||||
float history[5];
|
||||
float currentAgg;
|
||||
int trig;
|
||||
int echo;
|
||||
float goalVal;
|
||||
};
|
||||
|
||||
struct IncubatorDrain {
|
||||
int pin;
|
||||
bool isActive;
|
||||
char type; // "L" light, "P" pump, "H" heat
|
||||
OneSensor sensor;
|
||||
};
|
||||
struct HTSensor {
|
||||
float tempHistory[5];
|
||||
float currentAggTemp;
|
||||
float goalValTemp;
|
||||
float humHistory[5];
|
||||
float currentAggHum;
|
||||
float goalValHum;
|
||||
Adafruit_AHTX0 aht;
|
||||
};
|
||||
|
||||
struct MarthaDrain {
|
||||
int pin;
|
||||
bool isActive;
|
||||
char type; // "L" light, "P" pump, "H" heat
|
||||
};
|
||||
struct vReading {
|
||||
int16_t readings1[size] = {0};
|
||||
int16_t readings2[size] = {0};
|
||||
Adafruit_ADS1115 sensor;
|
||||
// ADC object at I2C address 0x48 for addr pin = GND
|
||||
float avrProng1 = 0;
|
||||
float avrProng2 = 0;
|
||||
unsigned char readCnt = 0;
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
setupIncubator(22, 22);
|
||||
setupAutoHumidity(18, 80);
|
||||
setupDataLogger();
|
||||
// pinMode(46,OUTPUT) ;
|
||||
// pinMode(44,OUTPUT) ;
|
||||
// digitalWrite(44, LOW);
|
||||
// digitalWrite(44, HIGH);
|
||||
Ethernet.begin(mac, ip, gateway, subnet);
|
||||
// while (!Ethernet.begin(mac, ip)) {
|
||||
// delay(500);
|
||||
// Serial.print(".");
|
||||
// }
|
||||
// Serial.println(Ethernet.localIP());
|
||||
app.get("/Incubator/Section", &getIncubatorSectionData);
|
||||
app.put("/Incubator/Section", &setIncubatorSectionData);
|
||||
app.put("/Martha/Temp", &setMarthGoalTemp);
|
||||
app.put("/Martha/Hum", &setMarthGoalHum);
|
||||
app.get("/Martha", &getMarthaData);
|
||||
app.get("/Connection", &getMarthaData);
|
||||
app.get("/Logger", &getDataLogger);
|
||||
// app.get("/", &index);
|
||||
app.use(staticFiles());
|
||||
Serial.println((int16_t)0);
|
||||
server.begin();
|
||||
unsigned long thisTime = millis();
|
||||
|
||||
for(int i=0;i<MAX_SOCK_NUM;i++) {
|
||||
connectTime[i] = thisTime;
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
EthernetClient client = server.available();
|
||||
AutoControlLoop();
|
||||
IncubatorControlLoop();
|
||||
DataLoggerControlLoop();
|
||||
if (client.available()) {
|
||||
Serial.println(F("new client"));
|
||||
app.process(&client);
|
||||
client.stop();
|
||||
}
|
||||
|
||||
// int connectLoop = 0;
|
||||
// bool processed = false;
|
||||
// while(client.connected())
|
||||
// {
|
||||
// while(client.available())
|
||||
// {
|
||||
// if(!processed){
|
||||
// processed = true;
|
||||
// app.process(&client);
|
||||
// }
|
||||
// // inChar = client.read();
|
||||
// Serial.println(client.read());
|
||||
// // set connectLoop to zero if a packet arrives
|
||||
// connectLoop = 0;
|
||||
// }
|
||||
|
||||
// connectLoop++;
|
||||
|
||||
// // if more than 10000 milliseconds since the last packet
|
||||
// if(connectLoop > 750)
|
||||
// {
|
||||
// // then close the connection from this end.
|
||||
// Serial.println();
|
||||
// Serial.println(F("Timeout"));
|
||||
// client.flush();
|
||||
// client.stop();
|
||||
// }
|
||||
// delay(1);
|
||||
// }
|
||||
// client.flush();
|
||||
// client.stop();
|
||||
|
||||
checkSockStatus();
|
||||
delay(1);
|
||||
// Ethernet.begin(mac, ip, gateway, subnet);
|
||||
// server.begin();
|
||||
// delay(100);
|
||||
}
|
||||
|
||||
|
||||
byte socketStat[MAX_SOCK_NUM];
|
||||
void checkSockStatus()
|
||||
{
|
||||
unsigned long thisTime = millis();
|
||||
|
||||
for (int i = 0; i < MAX_SOCK_NUM; i++) {
|
||||
uint8_t s = W5100.readSnSR(i);
|
||||
// Serial.println(s);
|
||||
|
||||
if((s == 0x17) || (s == 0x1C)) {
|
||||
if(thisTime - connectTime[i] > 5000UL) {
|
||||
Serial.print(F("\r\nSocket frozen: "));
|
||||
Serial.println(i);
|
||||
W5100.execCmdSn(i, Sock_CLOSE);
|
||||
}
|
||||
}
|
||||
else connectTime[i] = thisTime;
|
||||
|
||||
socketStat[i] = W5100.readSnSR(i);
|
||||
}
|
||||
}
|
||||
|
||||
void getSystemConnection(Request &req, Response &res){
|
||||
Serial.println("**********************************");
|
||||
char goalVal[64];
|
||||
req.query("goalVal", goalVal, 64);
|
||||
Serial.println(atof(goalVal));
|
||||
setAllGoalTemps(atof(goalVal));
|
||||
aJsonObject *root;
|
||||
root=aJson.createObject();
|
||||
aJson.addStringToObject(root, "status", "success");
|
||||
|
||||
res.set("Content-Type", "application/json");
|
||||
aJsonStream stream(&req);
|
||||
aJson.print(root, &stream);
|
||||
res.end();
|
||||
aJson.deleteItem(root);
|
||||
Serial.println("**********************************");
|
||||
}
|
||||
|
||||
void setMarthGoalHum(Request &req, Response &res){
|
||||
Serial.println("**********************************");
|
||||
char goalVal[64];
|
||||
req.query("goalVal", goalVal, 64);
|
||||
Serial.println(atof(goalVal));
|
||||
setAllGoalHum(atof(goalVal));
|
||||
aJsonObject *root;
|
||||
root=aJson.createObject();
|
||||
aJson.addStringToObject(root, "status", "success");
|
||||
|
||||
res.set("Content-Type", "application/json");
|
||||
aJsonStream stream(&req);
|
||||
aJson.print(root, &stream);
|
||||
res.end();
|
||||
aJson.deleteItem(root);
|
||||
Serial.println("**********************************");
|
||||
}
|
||||
|
||||
void setMarthGoalTemp(Request &req, Response &res){
|
||||
Serial.println("**********************************");
|
||||
char goalVal[64];
|
||||
req.query("goalVal", goalVal, 64);
|
||||
Serial.println(atof(goalVal));
|
||||
setAllGoalTemps(atof(goalVal));
|
||||
aJsonObject *root;
|
||||
root=aJson.createObject();
|
||||
aJson.addStringToObject(root, "status", "success");
|
||||
|
||||
res.set("Content-Type", "application/json");
|
||||
aJsonStream stream(&req);
|
||||
aJson.print(root, &stream);
|
||||
res.end();
|
||||
aJson.deleteItem(root);
|
||||
Serial.println("**********************************");
|
||||
}
|
||||
|
||||
|
||||
void setIncubatorSectionData(Request &req, Response &res){
|
||||
Serial.println("**********************************");
|
||||
char sectionName[64];
|
||||
char goalVal[64];
|
||||
req.query("sectionName", sectionName, 64);
|
||||
req.query("goalVal", goalVal, 64);
|
||||
Serial.println(sectionName);
|
||||
Serial.println(atof(goalVal));
|
||||
if(strcmp(sectionName, "Main") == 0){
|
||||
setTemperature("Main", atof(goalVal));
|
||||
}else if(strcmp(sectionName, "Secondary") == 0){
|
||||
setTemperature("Secondary", atof(goalVal));
|
||||
}
|
||||
aJsonObject *root;
|
||||
root=aJson.createObject();
|
||||
aJson.addStringToObject(root, "status", "success");
|
||||
|
||||
res.set("Content-Type", "application/json");
|
||||
aJsonStream stream(&req);
|
||||
aJson.print(root, &stream);
|
||||
res.end();
|
||||
aJson.deleteItem(root);
|
||||
Serial.println("**********************************");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void getDataLogger(Request &req, Response &res){
|
||||
|
||||
float mainArray[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
Serial.println("**********************************");
|
||||
|
||||
getDataLoggerDump(mainArray);
|
||||
aJsonObject *root;
|
||||
root=aJson.createObject();
|
||||
|
||||
aJson.addNumberToObject(root, "LoggerA", mainArray[0]);
|
||||
aJson.addNumberToObject(root, "LoggerB", mainArray[1]);
|
||||
aJson.addNumberToObject(root, "LoggerC", mainArray[2]);
|
||||
aJson.addNumberToObject(root, "LoggerD", mainArray[3]);
|
||||
aJson.addNumberToObject(root, "LoggerE", mainArray[4]);
|
||||
aJson.addNumberToObject(root, "LoggerF", mainArray[5]);
|
||||
aJson.addNumberToObject(root, "LoggerG", mainArray[6]);
|
||||
aJson.addNumberToObject(root, "LoggerH", mainArray[7]);
|
||||
|
||||
res.set("Content-Type", "application/json");
|
||||
aJsonStream stream(&req);
|
||||
aJson.print(root, &stream);
|
||||
res.end();
|
||||
aJson.deleteItem(root);
|
||||
Serial.println("**********************************");
|
||||
}
|
||||
|
||||
|
||||
void getIncubatorSectionData(Request &req, Response &res){
|
||||
|
||||
float mainArray[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
float secondArray[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
Serial.println("**********************************");
|
||||
char sectionName[64];
|
||||
req.query("sectionName", sectionName, 64);
|
||||
Serial.println(sectionName);
|
||||
// if(strcmp(sectionName, "Main") == 0){
|
||||
// getSectionData("Main", mainArray);
|
||||
// }else if(strcmp(sectionName, "Secondary") == 0){
|
||||
// getSectionData("Secondary", mainArray);
|
||||
// }
|
||||
getSectionData("Main", mainArray);
|
||||
getSectionData("Secondary", secondArray);
|
||||
aJsonObject *root,*tmps, *firstRt, *secondRt, *secondTmps, *drainStates;
|
||||
root=aJson.createObject();
|
||||
|
||||
aJson.addItemToObject(root, "mainSection", firstRt = aJson.createObject());
|
||||
aJson.addNumberToObject(firstRt, "avrTemp", mainArray[0]);
|
||||
aJson.addNumberToObject(firstRt, "goalTemp", mainArray[6]);
|
||||
// aJson.addBooleanToObject(firstRt, "isActive", mainArray[7] == 0.0? false : true);
|
||||
aJson.addItemToObject(root, "DrainStates", drainStates = aJson.createObject());
|
||||
aJson.addBooleanToObject(drainStates, "mainSection", mainArray[7] == 0.0? false : true);
|
||||
aJson.addBooleanToObject(drainStates, "secondSection", secondArray[7] == 0.0? false : true);
|
||||
// aJson.addItemToObject(firstRt, "temps", tmps = aJson.createArray());
|
||||
// aJson.addItemToArray(tmps, aJson.createItem(mainArray[1]));
|
||||
// aJson.addItemToArray(tmps, aJson.createItem(mainArray[2]));
|
||||
// aJson.addItemToArray(tmps, aJson.createItem(mainArray[3]));
|
||||
// aJson.addItemToArray(tmps, aJson.createItem(mainArray[4]));
|
||||
// aJson.addItemToArray(tmps, aJson.createItem(mainArray[5]));
|
||||
|
||||
aJson.addItemToObject(root, "secondSection", secondRt = aJson.createObject());
|
||||
aJson.addNumberToObject(secondRt, "avrTemp", secondArray[0]);
|
||||
aJson.addNumberToObject(secondRt, "goalTemp", secondArray[6]);
|
||||
// aJson.addBooleanToObject(secondRt, "isActive", secondArray[7] == 0.0? false : true);
|
||||
// aJson.addItemToObject(secondRt, "temps", secondTmps = aJson.createArray());
|
||||
// aJson.addItemToArray(secondTmps, aJson.createItem(secondArray[1]));
|
||||
// aJson.addItemToArray(secondTmps, aJson.createItem(secondArray[2]));
|
||||
// aJson.addItemToArray(secondTmps, aJson.createItem(secondArray[3]));
|
||||
// aJson.addItemToArray(secondTmps, aJson.createItem(secondArray[4]));
|
||||
// aJson.addItemToArray(secondTmps, aJson.createItem(secondArray[5]));
|
||||
|
||||
res.set("Content-Type", "application/json");
|
||||
aJsonStream stream(&req);
|
||||
aJson.print(root, &stream);
|
||||
res.end();
|
||||
aJson.deleteItem(root);
|
||||
Serial.println("**********************************");
|
||||
}
|
||||
|
||||
void getMarthaData(Request &req, Response &res){
|
||||
|
||||
float upperSensor[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
float lowerSensor[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
float co2Sensor[7] = {0, 0, 0, 0, 0, 0, 0};
|
||||
bool heatState = false;
|
||||
bool UVState = false;
|
||||
bool foggerState = false;
|
||||
Serial.println("**********************************");
|
||||
getMarthaData(upperSensor, lowerSensor, co2Sensor, heatState, foggerState, UVState);
|
||||
|
||||
res.set("Content-Type", "application/json");
|
||||
aJsonStream stream(&req);
|
||||
|
||||
aJsonObject *root, *upper, *upperTmps, *upperHum, *lower, *lowerTmps, *lowerHum, *co2, *co2Hist, *drainStates;
|
||||
root=aJson.createObject();
|
||||
aJson.addBooleanToObject(root, "fogger", foggerState);
|
||||
aJson.addBooleanToObject(root, "heat", heatState);
|
||||
aJson.addBooleanToObject(root, "uv", UVState);
|
||||
aJson.addItemToObject(root, "DrainStates", drainStates = aJson.createObject());
|
||||
aJson.addBooleanToObject(drainStates, "fogger", foggerState);
|
||||
aJson.addBooleanToObject(drainStates, "heat", heatState);
|
||||
aJson.addBooleanToObject(drainStates, "uv", UVState);
|
||||
aJson.addItemToObject(root, "CO2", co2 = aJson.createObject());
|
||||
|
||||
aJson.addNumberToObject(co2, "avrCO2", co2Sensor[0]);
|
||||
aJson.addNumberToObject(co2, "goalCO2", co2Sensor[6]);
|
||||
// aJson.addItemToObject(co2, "history", co2Hist = aJson.createArray());
|
||||
// aJson.addItemToArray(co2Hist, aJson.createItem(co2Sensor[1]));
|
||||
// aJson.addItemToArray(co2Hist, aJson.createItem(co2Sensor[2]));
|
||||
// aJson.addItemToArray(co2Hist, aJson.createItem(co2Sensor[3]));
|
||||
// aJson.addItemToArray(co2Hist, aJson.createItem(co2Sensor[4]));
|
||||
// aJson.addItemToArray(co2Hist, aJson.createItem(co2Sensor[5]));
|
||||
|
||||
|
||||
aJson.addItemToObject(root, "UpperSensor", upper = aJson.createObject());
|
||||
|
||||
aJson.addNumberToObject(upper, "avrTemp", upperSensor[0]);
|
||||
aJson.addNumberToObject(upper, "goalTemp", upperSensor[6]);
|
||||
// aJson.addItemToObject(upper, "temps", upperTmps = aJson.createArray());
|
||||
// aJson.addItemToArray(upperTmps, aJson.createItem(upperSensor[1]));
|
||||
// aJson.addItemToArray(upperTmps, aJson.createItem(upperSensor[2]));
|
||||
// aJson.addItemToArray(upperTmps, aJson.createItem(upperSensor[3]));
|
||||
// aJson.addItemToArray(upperTmps, aJson.createItem(upperSensor[4]));
|
||||
// aJson.addItemToArray(upperTmps, aJson.createItem(upperSensor[5]));
|
||||
|
||||
aJson.addNumberToObject(upper, "avrHum", upperSensor[7]);
|
||||
aJson.addNumberToObject(upper, "goalHum", upperSensor[13]);
|
||||
// aJson.addItemToObject(upper, "hum", upperHum = aJson.createArray());
|
||||
// aJson.addItemToArray(upperHum, aJson.createItem(upperSensor[8]));
|
||||
// aJson.addItemToArray(upperHum, aJson.createItem(upperSensor[9]));
|
||||
// aJson.addItemToArray(upperHum, aJson.createItem(upperSensor[10]));
|
||||
// aJson.addItemToArray(upperHum, aJson.createItem(upperSensor[11]));
|
||||
// aJson.addItemToArray(upperHum, aJson.createItem(upperSensor[12]));
|
||||
|
||||
aJson.addItemToObject(root, "WaterSensor", lower = aJson.createObject());
|
||||
|
||||
aJson.addNumberToObject(lower, "avrLevel", lowerSensor[0]);
|
||||
aJson.addNumberToObject(lower, "goalLevel", lowerSensor[6]);
|
||||
// aJson.addItemToObject(lower, "temps", lowerTmps = aJson.createArray());
|
||||
// aJson.addItemToArray(lowerTmps, aJson.createItem(lowerSensor[1]));
|
||||
// aJson.addItemToArray(lowerTmps, aJson.createItem(lowerSensor[2]));
|
||||
// aJson.addItemToArray(lowerTmps, aJson.createItem(lowerSensor[3]));
|
||||
// aJson.addItemToArray(lowerTmps, aJson.createItem(lowerSensor[4]));
|
||||
// aJson.addItemToArray(lowerTmps, aJson.createItem(lowerSensor[5]));
|
||||
|
||||
// aJson.addNumberToObject(lower, "avrHum", lowerSensor[7]);
|
||||
// aJson.addNumberToObject(lower, "goalHum", lowerSensor[13]);
|
||||
// aJson.addItemToObject(lower, "hum", lowerHum = aJson.createArray());
|
||||
// aJson.addItemToArray(lowerHum, aJson.createItem(lowerSensor[8]));
|
||||
// aJson.addItemToArray(lowerHum, aJson.createItem(lowerSensor[9]));
|
||||
// aJson.addItemToArray(lowerHum, aJson.createItem(lowerSensor[10]));
|
||||
// aJson.addItemToArray(lowerHum, aJson.createItem(lowerSensor[11]));
|
||||
// aJson.addItemToArray(lowerHum, aJson.createItem(lowerSensor[12]));
|
||||
aJson.print(root, &stream);
|
||||
res.end();
|
||||
aJson.deleteItem(root);
|
||||
Serial.println("**********************************");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Controls Mushroom Grow tent
|
||||
/*
|
||||
Fogger + (main Fan) (controlled)
|
||||
UV light (controlled)
|
||||
|
||||
Humidity / Temp 1
|
||||
|
||||
Humidity / Temp 2
|
||||
|
||||
HeatMat (controlled)
|
||||
|
||||
Co2 sensor + Air supply Fan (constantly on)
|
||||
|
||||
General Circulation Fan (controlled)
|
||||
|
||||
|
||||
*/
|
||||
//Incubator
|
||||
/*
|
||||
Temp 1
|
||||
|
||||
Temp 2
|
||||
|
||||
HeatMat 1 (controlled)
|
||||
|
||||
HeatMat 2 (controlled)
|
||||
|
||||
*/
|
||||
//Shrimp Aquaponica
|
||||
21
StaticFiles.h
Executable file
21
StaticFiles.h
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
void static_index(Request &req, Response &res) {
|
||||
P(index) =
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
"<title>Some thing isnt supposed to be here</title>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
"<h1>Wuzzup?</h1>\n"
|
||||
"</body>\n"
|
||||
"</html>";
|
||||
|
||||
res.set("Content-Type", "text/html");
|
||||
res.printP(index);
|
||||
}
|
||||
|
||||
Router staticFileRouter;
|
||||
|
||||
Router * staticFiles() {
|
||||
staticFileRouter.get("/", &static_index);
|
||||
return &staticFileRouter;
|
||||
}
|
||||
343
aWOT.h
Executable file
343
aWOT.h
Executable file
|
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
aWOT, Express.js inspired microcontreller web framework for the Web of Things
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef AWOT_H_
|
||||
#define AWOT_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Client.h"
|
||||
|
||||
#define CRLF "\r\n"
|
||||
|
||||
#if defined(__AVR_ATmega328P__) || defined(__AVR_Atmega32U4__) || \
|
||||
defined(__AVR_ATmega16U4__) || defined(_AVR_ATmega328__)
|
||||
#define LOW_MEMORY_MCU
|
||||
#endif
|
||||
|
||||
#ifndef SERVER_URL_BUFFER_SIZE
|
||||
#if defined(LOW_MEMORY_MCU)
|
||||
#define SERVER_URL_BUFFER_SIZE 64
|
||||
#else
|
||||
#define SERVER_URL_BUFFER_SIZE 512
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SERVER_PUSHBACK_BUFFER_SIZE
|
||||
#if defined(LOW_MEMORY_MCU)
|
||||
#define SERVER_PUSHBACK_BUFFER_SIZE 32
|
||||
#else
|
||||
#define SERVER_PUSHBACK_BUFFER_SIZE 128
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SERVER_OUTPUT_BUFFER_SIZE
|
||||
#if defined(LOW_MEMORY_MCU)
|
||||
#define SERVER_OUTPUT_BUFFER_SIZE 32
|
||||
#else
|
||||
#define SERVER_OUTPUT_BUFFER_SIZE 1024
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SERVER_MAX_HEADERS
|
||||
#define SERVER_MAX_HEADERS 10
|
||||
#endif
|
||||
|
||||
#ifdef __AVR__
|
||||
#define P(name) static const unsigned char name[] __attribute__(( section(".progmem." #name) ))
|
||||
#else
|
||||
#define P(name) static const unsigned char name[] PROGMEM
|
||||
#endif
|
||||
|
||||
namespace awot {
|
||||
|
||||
class StreamClient : public Client {
|
||||
private:
|
||||
Stream* s;
|
||||
|
||||
public:
|
||||
StreamClient(Stream* stream) : s(stream){};
|
||||
int connect(IPAddress, uint16_t){return 1;};
|
||||
int connect(const char*, uint16_t){return 1;};
|
||||
size_t write(uint8_t byte){return s->write(byte);};
|
||||
size_t write(const uint8_t* buffer, size_t length){return s->write(buffer, length);};
|
||||
int available(){return s->available();};
|
||||
int read() {return s->read();};
|
||||
int read(uint8_t* buffer, size_t length) {
|
||||
size_t count = 0;
|
||||
|
||||
while (count < length) {
|
||||
int c = read();
|
||||
if (c < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
*buffer++ = (uint8_t)c;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
int peek(){return s->peek();};
|
||||
void flush(){return s->flush();};
|
||||
void stop(){};
|
||||
uint8_t connected(){return 1;};
|
||||
operator bool(){return true;};
|
||||
};
|
||||
|
||||
class Response : public Print {
|
||||
friend class Application;
|
||||
friend class Router;
|
||||
|
||||
public:
|
||||
int availableForWrite();
|
||||
int bytesSent();
|
||||
void beginHeaders();
|
||||
void end();
|
||||
void endHeaders();
|
||||
bool ended();
|
||||
void flush();
|
||||
const char* get(const char* name);
|
||||
bool headersSent();
|
||||
void printP(const unsigned char* string);
|
||||
void printP(const char* string);
|
||||
void sendStatus(int code);
|
||||
void set(const char* name, const char* value);
|
||||
void setDefaults();
|
||||
void status(int code);
|
||||
int statusSent();
|
||||
size_t write(uint8_t data);
|
||||
size_t write(uint8_t* buffer, size_t bufferLength);
|
||||
void writeP(const unsigned char* data, size_t length);
|
||||
|
||||
private:
|
||||
Response(Client* client, uint8_t * writeBuffer, int writeBufferLength);
|
||||
|
||||
void m_printStatus(int code);
|
||||
bool m_shouldPrintHeaders();
|
||||
void m_printHeaders();
|
||||
void m_printCRLF();
|
||||
void m_flushBuf();
|
||||
void m_finalize();
|
||||
|
||||
Client* m_stream;
|
||||
struct Headers {
|
||||
const char* name;
|
||||
const char* value;
|
||||
} m_headers[SERVER_MAX_HEADERS];
|
||||
bool m_contentLenghtSet;
|
||||
bool m_contentTypeSet;
|
||||
bool m_keepAlive;
|
||||
int m_statusSent;
|
||||
bool m_headersSent;
|
||||
bool m_sendingStatus;
|
||||
bool m_sendingHeaders;
|
||||
int m_headersCount;
|
||||
char* m_mime;
|
||||
int m_bytesSent;
|
||||
bool m_ended;
|
||||
uint8_t * m_buffer;
|
||||
int m_bufferLength;
|
||||
int m_bufFill;
|
||||
};
|
||||
|
||||
class Request : public Stream {
|
||||
friend class Application;
|
||||
friend class Router;
|
||||
|
||||
public:
|
||||
enum MethodType { UNKNOWN, GET, HEAD, POST, PUT, DELETE, PATCH, OPTIONS, ALL };
|
||||
void* context;
|
||||
|
||||
int available();
|
||||
int availableForWrite();
|
||||
int bytesRead();
|
||||
Stream* stream();
|
||||
void flush();
|
||||
bool form(char* name, int nameLength, char* value, int valueLength);
|
||||
char* get(const char* name);
|
||||
int left();
|
||||
MethodType method();
|
||||
char* path();
|
||||
int peek();
|
||||
void push(uint8_t ch);
|
||||
char* query();
|
||||
bool query(const char* name, char* buffer, int bufferLength);
|
||||
int read();
|
||||
int read(uint8_t* buf, size_t size);
|
||||
bool route(const char* name, char* buffer, int bufferLength);
|
||||
bool route(int number, char* buffer, int bufferLength);
|
||||
int minorVersion();
|
||||
size_t write(uint8_t data);
|
||||
size_t write(uint8_t* buffer, size_t bufferLength);
|
||||
|
||||
private:
|
||||
struct HeaderNode {
|
||||
const char* name;
|
||||
char* buffer;
|
||||
int bufferLength;
|
||||
HeaderNode* next;
|
||||
};
|
||||
|
||||
Request(Client* client, Response* m_response, HeaderNode* headerTail,
|
||||
char* urlBuffer, int urlBufferLength, unsigned long timeout,
|
||||
void* context);
|
||||
bool m_processMethod();
|
||||
bool m_readURL();
|
||||
bool m_readVersion();
|
||||
void m_processURL();
|
||||
bool m_processHeaders();
|
||||
bool m_headerValue(char* buffer, int bufferLength);
|
||||
bool m_readInt(int& number);
|
||||
void m_setRoute(const char* route, const char* pattern);
|
||||
int m_getUrlPathLength();
|
||||
bool m_expect(const char* expected);
|
||||
bool m_expectP(const unsigned char* expected);
|
||||
bool m_skipSpace();
|
||||
void m_reset();
|
||||
int m_timedRead();
|
||||
bool m_timedout();
|
||||
|
||||
Client* m_stream;
|
||||
Response* m_response;
|
||||
MethodType m_method;
|
||||
int m_minorVersion;
|
||||
unsigned char m_pushback[SERVER_PUSHBACK_BUFFER_SIZE];
|
||||
int m_pushbackDepth;
|
||||
bool m_readingContent;
|
||||
int m_left;
|
||||
int m_bytesRead;
|
||||
HeaderNode* m_headerTail;
|
||||
char* m_query;
|
||||
int m_queryLength;
|
||||
bool m_readTimedout;
|
||||
char* m_path;
|
||||
int m_pathLength;
|
||||
const char* m_pattern;
|
||||
const char* m_route;
|
||||
};
|
||||
|
||||
class Router {
|
||||
friend class Application;
|
||||
|
||||
public:
|
||||
typedef void Middleware(Request& request, Response& response);
|
||||
|
||||
Router();
|
||||
~Router();
|
||||
|
||||
void del(const char* path, Middleware* middleware);
|
||||
void del(Middleware* middleware);
|
||||
void get(const char* path, Middleware* middleware);
|
||||
void get(Middleware* middleware);
|
||||
void head(const char* path, Middleware* middleware);
|
||||
void head(Middleware* middleware);
|
||||
void options(const char* path, Middleware* middleware);
|
||||
void options(Middleware* middleware);
|
||||
void patch(const char* path, Middleware* middleware);
|
||||
void patch(Middleware* middleware);
|
||||
void post(const char* path, Middleware* middleware);
|
||||
void post(Middleware* middleware);
|
||||
void put(const char* path, Middleware* middleware);
|
||||
void put(Middleware* middleware);
|
||||
void use(const char* path, Router* router);
|
||||
void use(Router* router);
|
||||
void use(const char* path, Middleware* middleware);
|
||||
void use(Middleware* middleware);
|
||||
|
||||
private:
|
||||
struct MiddlewareNode {
|
||||
const char* path;
|
||||
Middleware* middleware;
|
||||
Router* router;
|
||||
Request::MethodType type;
|
||||
MiddlewareNode* next;
|
||||
};
|
||||
|
||||
void m_addMiddleware(Request::MethodType type, const char* path,
|
||||
Middleware* middleware);
|
||||
void m_mountMiddleware(MiddlewareNode *tail);
|
||||
void m_setNext(Router* next);
|
||||
Router* m_getNext();
|
||||
void m_dispatchMiddleware(Request& request, Response& response, int urlShift = 0);
|
||||
bool m_routeMatch(const char* route, const char* pattern);
|
||||
|
||||
MiddlewareNode* m_head;
|
||||
};
|
||||
|
||||
class Application {
|
||||
public:
|
||||
Application();
|
||||
~Application();
|
||||
|
||||
static int strcmpi(const char* s1, const char* s2);
|
||||
static int strcmpiP(const char* s1, const unsigned char* s2);
|
||||
|
||||
void del(const char* path, Router::Middleware* middleware);
|
||||
void del(Router::Middleware* middleware);
|
||||
void finally(Router::Middleware* middleware);
|
||||
void get(const char* path, Router::Middleware* middleware);
|
||||
void get(Router::Middleware* middleware);
|
||||
void head(const char* path, Router::Middleware* middleware);
|
||||
void head(Router::Middleware* middleware);
|
||||
void header(const char* name, char* buffer, int bufferLength);
|
||||
void notFound(Router::Middleware* middleware);
|
||||
void options(const char* path, Router::Middleware* middleware);
|
||||
void options(Router::Middleware* middleware);
|
||||
void patch(const char* path, Router::Middleware* middleware);
|
||||
void patch(Router::Middleware* middleware);
|
||||
void post(const char* path, Router::Middleware* middleware);
|
||||
void post(Router::Middleware* middleware);
|
||||
void put(const char* path, Router::Middleware* middleware);
|
||||
void put(Router::Middleware* middleware);
|
||||
void process(Client* client, void* context = NULL);
|
||||
void process(Client* client, char* urlbuffer, int urlBufferLength, void* context = NULL);
|
||||
void process(Client* client, char* urlBuffer, int urlBufferLength, uint8_t * writeBuffer, int writeBufferLength, void* context = NULL);
|
||||
void process(Stream* stream, void* context = NULL);
|
||||
void process(Stream* stream, char* urlbuffer, int urlBufferLength, void* context = NULL);
|
||||
void process(Stream* stream, char* urlBuffer, int urlBufferLength, uint8_t * writeBuffer, int writeBufferLength, void* context = NULL);
|
||||
|
||||
void setTimeout(unsigned long timeoutMillis);
|
||||
void use(const char* path, Router* router);
|
||||
void use(Router* router);
|
||||
void use(const char* path, Router::Middleware* middleware);
|
||||
void use(Router::Middleware* middleware);
|
||||
|
||||
private:
|
||||
void m_process(Request &req, Response &res);
|
||||
|
||||
Router::Middleware* m_final;
|
||||
Router::Middleware* m_notFound;
|
||||
Router m_defaultRouter;
|
||||
Request::HeaderNode* m_headerTail;
|
||||
unsigned long m_timeout;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef ENABLE_AWOT_NAMESPACE
|
||||
using namespace awot;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
21
olStatic.txt
Executable file
21
olStatic.txt
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
void static_index(Request &req, Response &res) {
|
||||
P(index) =
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
"<title>Hello World!</title>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
"<h1>Greetings middle earth!</h1>\n"
|
||||
"</body>\n"
|
||||
"</html>";
|
||||
|
||||
res.set("Content-Type", "text/html");
|
||||
res.printP(index);
|
||||
}
|
||||
|
||||
Router staticFileRouter;
|
||||
|
||||
Router * staticFiles() {
|
||||
staticFileRouter.get("/", &static_index);
|
||||
return &staticFileRouter;
|
||||
}
|
||||
Loading…
Reference in a new issue