Skip to content

Instantly share code, notes, and snippets.

@deva-eecs
Created October 1, 2023 05:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deva-eecs/b7fa10d9ce9e0cf087bbc78e7062501b to your computer and use it in GitHub Desktop.
Save deva-eecs/b7fa10d9ce9e0cf087bbc78e7062501b to your computer and use it in GitHub Desktop.
Pomodoro watch
#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;
}
@deva-eecs
Copy link
Author

Schematic_Pomodoro watch_2023-10-01

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment