Created
October 1, 2023 05:13
-
-
Save deva-eecs/b7fa10d9ce9e0cf087bbc78e7062501b to your computer and use it in GitHub Desktop.
Pomodoro watch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <avr/interrupt.h> | |
#include <avr/sleep.h> | |
#include <avr/power.h> | |
#include <avr/wdt.h> | |
#include <util/delay.h> | |
const byte motorPin = 1; | |
const byte buttonPin = 0; | |
const byte R = 4; | |
const byte G = 3; | |
// R+G = Y | |
volatile uint8_t pb0Pressed = 0; | |
volatile unsigned long wdCounter = 1; // Volatile tells compiler to reload each time instead of optimizing | |
unsigned long motorDuration = 500000; | |
unsigned long motorDuration_startend = 300000; | |
unsigned long waitDuration = 0; | |
unsigned long wdCounterTarget = 345;//345; as i hve 2min variatioin //15*YOUR MIN gives the input value 15*3 =45 =3mins | |
unsigned long wdCounterTarget_breaktime = 67;//67; // 5min break 67 is better than 75 because of the innacuracy | |
unsigned long timeDelayStarted = 0; | |
bool isInDelay = false; //flag | |
void setup () { | |
pinMode (motorPin, OUTPUT); | |
ADCSRA &= (~(1 << ADEN)); // Turn off the ADC | |
startMotorSequence(); // Run the motor once on startup | |
sleepNow(); | |
pinMode(5,INPUT_PULLUP);//unused pin | |
pinMode(6,INPUT_PULLUP);//unused pin | |
pinMode(R,OUTPUT); | |
pinMode(G,OUTPUT); | |
pinMode(2,INPUT_PULLUP);//unused pin | |
pinMode(buttonPin, INPUT_PULLUP); | |
GIMSK = 0b00100000; // General Interrupt Mask Register | |
PCMSK = 0b00000001; //only enable it on pin0 | |
} | |
void loop () { | |
if ( wdCounter == wdCounterTarget ) { // Check if counter has reached target. | |
wdCounter = 0; | |
timeDelayStarted = micros(); | |
isInDelay = true; // Now in delay mode | |
} | |
// Continue to loop until enough time has passed to reach waitDuration | |
if ( isInDelay | |
&& micros() - timeDelayStarted >= waitDuration) { | |
startMotorSequence(); // Run the motor sequence | |
wdCounter = 0; | |
isInDelay = false; // End delay mode | |
} | |
if ( !isInDelay ) { | |
sleepNow(); | |
} | |
if ( wdCounter == wdCounterTarget_breaktime) { // this is for break time | |
wdCounter = 0; | |
timeDelayStarted = micros(); | |
isInDelay = true; // Now in delay mode | |
} | |
// Continue to loop until enough time has passed to reach waitDuration | |
if ( isInDelay | |
&& micros() - timeDelayStarted >= waitDuration) { | |
startMotorSequence_break(); // Run the motor sequence for break | |
wdCounter = 0; | |
isInDelay = false; // End delay mode | |
} | |
if ( !isInDelay ) { | |
sleepNow(); | |
} | |
} | |
void startMotorSequence() { | |
digitalWrite( motorPin, HIGH ); | |
_delay_us(motorDuration); // Blocking function delay | |
digitalWrite ( motorPin, LOW ); | |
} | |
void startMotorSequence_break() { | |
digitalWrite( motorPin, HIGH ); | |
_delay_us(motorDuration_startend); // Blocking function delay | |
digitalWrite ( motorPin, LOW ); | |
} | |
void sleepNow () { | |
set_sleep_mode ( SLEEP_MODE_PWR_DOWN ); // set sleep mode to Power Down. The most energy efficient setting. | |
power_all_disable (); // Turn power off to TIMER 1, TIMER 2, and Serial Interface | |
noInterrupts (); // Turn off interrupts as a precaution. Timed sequence follows | |
resetWatchDog (); // Reset watchdog, making sure every flag is properly set | |
sleep_enable (); // Allows the system to be commanded to sleep | |
interrupts (); // Turn on interrupts. Guarantees next instruction is executed | |
sleep_cpu (); // Goodnight, ATTiny85 | |
sleep_disable (); // Returns here after Watchdog ISR fires. | |
power_all_enable (); // Turn on power to TIMER1, TIMER 2, and Serial Interface | |
} | |
void resetWatchDog () { | |
MCUSR = 0; // Clear various "reset" flags | |
WDTCR = bit ( WDCE ) | bit ( WDE ) | bit ( WDIF ); // Allow changes, disable reset, clear existing interrupt | |
WDTCR = bit ( WDIE ) | 1 << WDP3 | 0 << WDP2 | 0 << WDP1 | 0 << WDP0; // 4s timeout first bit 1 | |
wdt_reset (); // Reset the watchdog using the parameters | |
} | |
ISR ( WDT_vect ) { | |
wdt_disable(); // Disable the watchdog timer | |
wdCounter++; // Increase the watchdog firing counter. | |
} | |
ISR(PCINT0_vect) { | |
pb0Pressed = digitalRead(PIN_PB0) == LOW; | |
// Mask to set LED pins based on conditions //0.25 = 1sec for every 5min 25sec loss | |
uint8_t ledMask = (pb0Pressed && (wdCounter <= 137)) * (1 << G) | // <= 10min = 137 | |
(pb0Pressed && (wdCounter >137 & wdCounter< 275 )) * ((1 << R) | (1 << G)) | // >10 and <20min = 137 and 275 | |
(pb0Pressed && (wdCounter >= 275 & wdCounter <=345)) * (1 << R); // 275&345 20min and 25 | |
// Set LED pins using bitwise OR and bitwise AND to preserve other pin states | |
PORTB = (PORTB & ~((1 << R) | (1 << G))) | ledMask; | |
} |
Author
deva-eecs
commented
Oct 1, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment