Home | About | Apps | Github | Rss
This is a follow up to Part 2 of my Mark2 design and build of Plant watering system.
Fortunately the first two learnings can be incorporated by some software changes. Following are the goals I set out to accomplish in the new firmware and the code to achieve it.
MotorConf
structs.whosNext()
computes which motor is to be activated. It does so by checking if the delta time from last run exceeded the runtime+waittime.#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/power.h>
#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off)
#define adc_enable() (ADCSRA |= (1<<ADEN)) // re-enable ADC
#define led 4
#define MPIN_1 1
#define MPIN_2 0
#define MPIN_EXT_1 3
#define MPIN_EXT_2 2
#define setHigh(pin) pinMode(pin, OUTPUT); digitalWrite(pin, HIGH);
#define setLow(pin) pinMode(pin, OUTPUT); digitalWrite(pin, LOW);
unsigned int lpCntr=0;
unsigned int isOn=0;
struct MotorConf {
byte pin;
byte onInterval;
unsigned short offInterval;
unsigned long lastUsed;
}
const unsigned int offInterval_2hours = 2 * 60 * 60; //(60 * 60 * 6) - onInterval; //round it off to 6 hours
const unsigned int offInterval_4hours = 4 * 60 * 60; //(60 * 60 * 6) - onInterval; //round it off to 6 hours
const unsigned int onInterval_2secs = 2; // 2 sleep cycles
const unsigned int repInterval = onInterval_2secs + offInterval_2hours;
struct MotorConf motorState[] = {
{ 1, 2, offInterval_2hours, 0 },
{ 0, 2, offInterval_4hours, 0 },
}
unsigned int currMotor = -1;
unsigned int maxMotors = 2;
void setup() {
clock_prescale_set(clock_div_16);
for(int i=0; i<6; i++) {
pinMode(i, INPUT);
digitalWrite(i, LOW);
}
pinMode(led, OUTPUT);
for(int i=0; i<2; i++) {
digitalWrite(led, HIGH);
delay(50);
digitalWrite(led, LOW);
delay(50);
}
digitalWrite(led, LOW);
adc_disable();
wdt_reset(); //watchdog reset
wdt_enable(WDTO_1S); //1s watchdog timer
WDTCR |= _BV(WDIE); //Interrupts watchdog enable
sei(); //enable interrupts
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}
int whosNext() {
unsigned long currTime = millis() / 1000;
for(int i=0; i<maxMotors; i++) {
struct MotorConf currConf = motorState[i];
if( (currTime - currConf.lastUsed) > (currConf.onInterval+currConf.offInterval) ) {
return i;
}
}
return -1;
}
void loop() {
// Main loop
int nextMotor = whosNext();
if( nextMotor >= 0 && nextMotor <= maxMotors ) {
struct MotorConf currConf = motorState[i];
setHigh(currConf.pin);
delay(currConf.onInterval);
setLow(currConf.pin);
currConf.lastUsed = millis() / 1000;
}
sleep_enable();
sleep_cpu();
}
ISR (WDT_vect) {
WDTCR |= _BV(WDIE);
}
Mark 2 provided fair amount of learnings. However it was plagued with limitations. Here are some improvmenets planned in Mark 3 re-design
Use ESP8266 along with MCP23017 GPIO Expander. * ESP8266 will aid in improving the configurability as well as observability.
Ports for 8x Motors, 8x Soil input sensors
NodeMCU compatibility along with support for ESP8266 12-E bare IC. The former helps with programming, the later with power consumption.