main
This commit is contained in:
@ -0,0 +1,164 @@
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Countdown Timer using a PCF8523 RTC connected via I2C and Wire lib
|
||||
with the INT/SQW pin wired to an interrupt-capable input.
|
||||
|
||||
According to the data sheet, the PCF8523 can run countdown timers
|
||||
from 244 microseconds to 10.625 days:
|
||||
https://www.nxp.com/docs/en/data-sheet/PCF8523.pdf#page=34
|
||||
|
||||
This sketch sets a countdown timer, and executes code when it reaches 0,
|
||||
then blinks the built-in LED like BlinkWithoutDelay, but without millis()!
|
||||
|
||||
NOTE:
|
||||
You must connect the PCF8523's interrupt pin to your Arduino or other
|
||||
microcontroller on an input pin that can handle interrupts, and that has a
|
||||
pullup resistor. The pin will be briefly pulled low each time the countdown
|
||||
reaches 0. This example will not work without the interrupt pin connected!
|
||||
|
||||
On Adafruit breakout boards, the interrupt pin is labeled 'INT' or 'SQW'.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#include "RTClib.h"
|
||||
|
||||
RTC_PCF8523 rtc;
|
||||
|
||||
// Input pin with interrupt capability
|
||||
// const int timerInterruptPin = 2; // Most Arduinos
|
||||
const int timerInterruptPin = 5; // Adafruit Feather M0/M4/nRF52840
|
||||
|
||||
// Variables modified during an interrupt must be declared volatile
|
||||
volatile bool countdownInterruptTriggered = false;
|
||||
volatile int numCountdownInterrupts = 0;
|
||||
|
||||
void setup () {
|
||||
Serial.begin(57600);
|
||||
|
||||
#ifndef ESP8266
|
||||
while (!Serial); // wait for serial port to connect. Needed for native USB
|
||||
#endif
|
||||
|
||||
if (! rtc.begin()) {
|
||||
Serial.println("Couldn't find RTC");
|
||||
Serial.flush();
|
||||
while (1) delay(10);
|
||||
}
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
// Set the pin attached to PCF8523 INT to be an input with pullup to HIGH.
|
||||
// The PCF8523 interrupt pin will briefly pull it LOW at the end of a given
|
||||
// countdown period, then it will be released to be pulled HIGH again.
|
||||
pinMode(timerInterruptPin, INPUT_PULLUP);
|
||||
|
||||
Serial.println(F("\nStarting PCF8523 Countdown Timer example."));
|
||||
Serial.print(F("Configured to expect PCF8523 INT/SQW pin connected to input pin: "));
|
||||
Serial.println(timerInterruptPin);
|
||||
Serial.println(F("This example will not work without the interrupt pin connected!\n\n"));
|
||||
|
||||
// Timer configuration is not cleared on an RTC reset due to battery backup!
|
||||
rtc.deconfigureAllTimers();
|
||||
|
||||
Serial.println(F("First, use the PCF8523's 'Countdown Timer' with an interrupt."));
|
||||
Serial.println(F("Set the countdown for 10 seconds and we'll let it run for 2 rounds."));
|
||||
Serial.println(F("Starting Countdown Timer now..."));
|
||||
|
||||
// These are the PCF8523's built-in "Timer Source Clock Frequencies".
|
||||
// They are predefined time periods you choose as your base unit of time,
|
||||
// depending on the length of countdown timer you need.
|
||||
// The minimum length of your countdown is 1 time period.
|
||||
// The maximum length of your countdown is 255 time periods.
|
||||
//
|
||||
// PCF8523_FrequencyHour = 1 hour, max 10.625 days (255 hours)
|
||||
// PCF8523_FrequencyMinute = 1 minute, max 4.25 hours
|
||||
// PCF8523_FrequencySecond = 1 second, max 4.25 minutes
|
||||
// PCF8523_Frequency64Hz = 1/64 of a second (15.625 milliseconds), max 3.984 seconds
|
||||
// PCF8523_Frequency4kHz = 1/4096 of a second (244 microseconds), max 62.256 milliseconds
|
||||
//
|
||||
//
|
||||
// These are the PCF8523's optional 'Low Pulse Widths' of time the interrupt
|
||||
// pin is held LOW at the end of every countdown (frequency 64Hz or longer).
|
||||
//
|
||||
// PCF8523_LowPulse3x64Hz = 46.875 ms 3/64ths second (default)
|
||||
// PCF8523_LowPulse4x64Hz = 62.500 ms 4/64ths second
|
||||
// PCF8523_LowPulse5x64Hz = 78.125 ms 5/64ths second
|
||||
// PCF8523_LowPulse6x64Hz = 93.750 ms 6/64ths second
|
||||
// PCF8523_LowPulse8x64Hz = 125.000 ms 8/64ths second
|
||||
// PCF8523_LowPulse10x64Hz = 156.250 ms 10/64ths second
|
||||
// PCF8523_LowPulse12x64Hz = 187.500 ms 12/64ths second
|
||||
// PCF8523_LowPulse14x64Hz = 218.750 ms 14/64ths second
|
||||
//
|
||||
//
|
||||
// Uncomment an example below:
|
||||
|
||||
// rtc.enableCountdownTimer(PCF8523_FrequencyHour, 24); // 1 day
|
||||
// rtc.enableCountdownTimer(PCF8523_FrequencyMinute, 150); // 2.5 hours
|
||||
rtc.enableCountdownTimer(PCF8523_FrequencySecond, 10); // 10 seconds
|
||||
// rtc.enableCountdownTimer(PCF8523_Frequency64Hz, 32); // 1/2 second
|
||||
// rtc.enableCountdownTimer(PCF8523_Frequency64Hz, 16); // 1/4 second
|
||||
// rtc.enableCountdownTimer(PCF8523_Frequency4kHz, 205); // 50 milliseconds
|
||||
|
||||
attachInterrupt(digitalPinToInterrupt(timerInterruptPin), countdownOver, FALLING);
|
||||
|
||||
// This message proves we're not blocked while counting down!
|
||||
Serial.println(F(" While we're waiting, a word of caution:"));
|
||||
Serial.println(F(" When starting a new countdown timer, the first time period is not of fixed"));
|
||||
Serial.println(F(" duration. The amount of inaccuracy for the first time period is up to one full"));
|
||||
Serial.println(F(" clock frequency. Example: just the first second of the first round of a new"));
|
||||
Serial.println(F(" countdown based on PCF8523_FrequencySecond may be off by as much as 1 second!"));
|
||||
Serial.println(F(" For critical timing, consider starting actions on the first interrupt."));
|
||||
}
|
||||
|
||||
// Triggered by the PCF8523 Countdown Timer interrupt at the end of a countdown
|
||||
// period. Meanwhile, the PCF8523 immediately starts the countdown again.
|
||||
void countdownOver () {
|
||||
// Set a flag to run code in the loop():
|
||||
countdownInterruptTriggered = true;
|
||||
numCountdownInterrupts++;
|
||||
}
|
||||
|
||||
// Triggered by the PCF8523 Second Timer every second.
|
||||
void toggleLed () {
|
||||
// Run certain types of fast executing code here:
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
}
|
||||
|
||||
void loop () {
|
||||
if (countdownInterruptTriggered && numCountdownInterrupts == 1) {
|
||||
Serial.println(F("1st countdown interrupt triggered. Accurate timekeeping starts now."));
|
||||
countdownInterruptTriggered = false; // don't come in here again
|
||||
} else if (countdownInterruptTriggered && numCountdownInterrupts == 2) {
|
||||
Serial.println(F("2nd countdown interrupt triggered. Disabling countdown and detaching interrupt.\n\n"));
|
||||
rtc.disableCountdownTimer();
|
||||
detachInterrupt(digitalPinToInterrupt(timerInterruptPin));
|
||||
delay(2000);
|
||||
|
||||
|
||||
Serial.println(F("Now, set up the PCF8523's 'Second Timer' to toggle the built-in LED at 1Hz..."));
|
||||
attachInterrupt(digitalPinToInterrupt(timerInterruptPin), toggleLed, FALLING);
|
||||
rtc.enableSecondTimer();
|
||||
Serial.println(F("Look for the built-in LED to flash 1 second ON, 1 second OFF, repeat. "));
|
||||
Serial.println(F("Meanwhile this program will use delay() to block code execution briefly"));
|
||||
Serial.println(F("before moving on to the last example. Notice the LED keeps blinking!\n\n"));
|
||||
delay(20000); // less accurate, blocks execution here. Meanwhile Second Timer keeps running.
|
||||
rtc.disableSecondTimer();
|
||||
detachInterrupt(digitalPinToInterrupt(timerInterruptPin));
|
||||
|
||||
|
||||
Serial.println(F("Lastly, set up a Countdown Timer that works without attaching an interrupt..."));
|
||||
rtc.enableCountdownTimer(PCF8523_Frequency64Hz, 32, PCF8523_LowPulse8x64Hz);
|
||||
Serial.println(F("Look for the LED to turn on every 1/2 second and stay lit for 1/8th of a second."));
|
||||
Serial.println(F("The countdown was set to a source clock frequency of 64 Hz (1/64th of a second)"));
|
||||
Serial.println(F("for a length of 32 time periods. 32 * 1/64th of a second is 1/2 of a second."));
|
||||
Serial.println(F("The low pulse duration was set to 125 ms, or 1/8th of a second."));
|
||||
Serial.println(F("The loop() keeps the built-in LED set to the opposite state of the INT/SQW pin."));
|
||||
|
||||
|
||||
countdownInterruptTriggered = false; // don't come in here again
|
||||
}
|
||||
|
||||
// While countdown running, INT/SQW pullup to HIGH, set LED to LOW (off)
|
||||
// When countdown is over, INT/SQW pulled down LOW, set LED to HIGH (on)
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(timerInterruptPin));
|
||||
}
|
Reference in New Issue
Block a user