Hi
I'm a complete beginner with Arduino programming, so apologies in advance if anything below isn't clear. I'm trying to build a device for an automatic feeder that activates a solenoid via a relay every day at a specific time. It's battery powered, so I'm using a DS3231 RTC to wake it from a powered down state and trigger the relay, before going back to powered down.
I've put together the code below, and have managed to get the alarm to close the relay switch at the set time and activate the solenoid. However, instead of then opening the switch after a second, the relay stays closed and the solenoid activated.
My understanding is that it should return to line 90 after executing activateRelay.
Any help appreciated.
//SPECIFIC TIME TRIGGER SOLENOID
//low power - alarm wakes up - activate relay (on then off after 1000ms) loop to start
#include <DS3231.h>
#include <Wire.h>
#include <LowPower.h>
#define wakeUpPin 2
#define relayPin 4
DS3231 Clock;
byte alarmDay;
byte alarmHour;
byte alarmMinute;
byte alarmSecond;
byte alarmBits;
bool alarmDayIsDay;
bool alarmH12;
bool alarmPM;
void setup() {
Serial.begin(57600);
Serial.println("Hello");
//rtc.begin();
//not needed
pinMode(relayPin, OUTPUT);
pinMode(wakeUpPin, INPUT);
Wire.begin();
alarmDay = 0;
alarmHour = 12;
alarmMinute = 51;
alarmSecond = 0;
alarmBits = 0b00001000;
alarmDayIsDay = false;
alarmH12 = false;
alarmPM = false;
Serial.println("Setting alarm for");
Serial.println(alarmHour);
Serial.println(alarmMinute);
Clock.turnOffAlarm(1);
Clock.setA1Time(
alarmDay, alarmHour, alarmMinute, alarmSecond,
alarmBits, alarmDayIsDay, alarmH12, alarmPM);
// enable Alarm 1 interrupts
Clock.turnOnAlarm(1);
// clear Alarm 1 flag
Clock.checkIfAlarm(1);
Serial.println("Alarm set");
Clock.turnOffAlarm(2);
pinMode(wakeUpPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), activateRelay, LOW);
//byte ALRM2_SET = ALRM2_MATCH_HR_MIN;
// int ALARM_BITS = ALRM2_SET;
//ALARM_BITS <<= 4;
//ALARM_BITS |= ALRM2_SET;
// Prevent Alarm 2 altogether by assigning a
// nonsensical alarm minute value that cannot match the clock time,
// and an alarmBits value to activate "when minutes match".
//alarmMinute = 0xFF; // a value that will never match the time
//alarmBits = 0b01100000; // Alarm 2 when minutes match, i.e., never
// Upload the parameters to prevent Alarm 2 entirely
//Serial.println("Clearing alarm 2");
//Clock.setA2Time(
// alarmDay, alarmHour, alarmMinute,
// alarmBits, alarmDayIsDay, alarmH12, alarmPM);
// disable Alarm 2 interrupt
//Clock.turnOffAlarm(2);
// clear Alarm 2 flag
// Clock.checkIfAlarm(2);
// Serial.println("Alarm 2 cleared");
// NOTE: both of the alarm flags must be clear
// to enable output of a FALLING interrupt
}
void loop() {
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
Serial.println("Waking up");
delay(1000);
digitalWrite(relayPin, LOW);
detachInterrupt(wakeUpPin);
}
void activateRelay(){
digitalWrite(relayPin, HIGH);
}
An example loop from the documentation shows how and when to attach and detach the interrupt:
void loop()
{
// Allow wake up pin to trigger interrupt on low.
attachInterrupt(0, wakeUp, LOW);
// Enter power down state with ADC and BOD module disabled.
// Wake up when wake up pin is low.
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
// Disable external pin interrupt on wake up pin.
detachInterrupt(0);
// Do something here
// Example: Read sensor, data logging, data transmission.
}
TBH I've never understood attaching and detaching alla time, but everyone does it, so.
I have a separate problem with the Serial printer - it shows fragments of the text, but also random ASCII symbols (questions marks and boxes mostly). The monitor is set to 57600 baud, so I'm not sure why it does that.
I've moved the attach interrupt into the loop, so it's now:
Thanks, adding that has resolved the issue with the monitor - I can now see that it is just repeating "Waking up" over and over, but doesn't set the relay pin to low.
Forgive the noob question, but in a separate post or in this one? Here is the current code in any case. Serial monitor alternately prints "Waking up" "Deactiviting"
//SPECIFIC TIME TRIGGER SOLENOID
//low power - alarm wakes up - activate relay (on then off after 1000ms) loop to start
#include <DS3231.h>
#include <Wire.h>
#include <LowPower.h>
#define wakeUpPin 2
#define relayPin 4
DS3231 Clock;
byte alarmDay;
byte alarmHour;
byte alarmMinute;
byte alarmSecond;
byte alarmBits;
bool alarmDayIsDay;
bool alarmH12;
bool alarmPM;
void setup() {
Serial.begin(57600);
Serial.println("Hello");
//rtc.begin();
//not needed
pinMode(relayPin, OUTPUT);
pinMode(wakeUpPin, INPUT);
Wire.begin();
alarmDay = 0;
alarmHour = 14;
alarmMinute = 37;
alarmSecond = 00;
alarmBits = 0b00001000;
alarmDayIsDay = false;
alarmH12 = false;
alarmPM = false;
Serial.println("Setting alarm for");
Serial.println(alarmHour);
Serial.println(alarmMinute);
Clock.turnOffAlarm(1);
Clock.setA1Time(
alarmDay, alarmHour, alarmMinute, alarmSecond,
alarmBits, alarmDayIsDay, alarmH12, alarmPM);
// enable Alarm 1 interrupts
Clock.turnOnAlarm(1);
// clear Alarm 1 flag
Clock.checkIfAlarm(1);
Serial.println("Alarm set");
Clock.turnOffAlarm(2);
//byte ALRM2_SET = ALRM2_MATCH_HR_MIN;
// int ALARM_BITS = ALRM2_SET;
//ALARM_BITS <<= 4;
//ALARM_BITS |= ALRM2_SET;
// Prevent Alarm 2 altogether by assigning a
// nonsensical alarm minute value that cannot match the clock time,
// and an alarmBits value to activate "when minutes match".
//alarmMinute = 0xFF; // a value that will never match the time
//alarmBits = 0b01100000; // Alarm 2 when minutes match, i.e., never
// Upload the parameters to prevent Alarm 2 entirely
//Serial.println("Clearing alarm 2");
//Clock.setA2Time(
// alarmDay, alarmHour, alarmMinute,
// alarmBits, alarmDayIsDay, alarmH12, alarmPM);
// disable Alarm 2 interrupt
//Clock.turnOffAlarm(2);
// clear Alarm 2 flag
// Clock.checkIfAlarm(2);
// Serial.println("Alarm 2 cleared");
// NOTE: both of the alarm flags must be clear
// to enable output of a FALLING interrupt
}
void loop() {
pinMode(wakeUpPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), activateRelay, LOW);
Serial.flush();
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
delay(300);
Serial.println("Waking up");
delay(1000);
Serial.println("Deactivating");
digitalWrite(relayPin, LOW);
delay(300);
detachInterrupt(wakeUpPin);
}
void activateRelay(){
digitalWrite(relayPin, HIGH);
}