#include <Adafruit_NeoPixel.h> //include needed library for making ring-led's control easier
const byte S = 2;
const byte SW = 5;
const byte DT = 4;
const byte CLK = 3;
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>//Required for 16 MHz Adafruit Trinket
#endif
#define LED_COUNT 24//number of LEDs on the ring
#define LED_PIN 6
#define CHUNK 300
int focus_timer = (50); //default focus time in seconds
int break_timer = (10); //default break time in seconds
int number_of_sessions = 2; //default number of sessions
int mode = 0; //changes ui 0(focus), 1(break), 2(number of sessions)
int delta = 0; // decides if the value will increase or decrease
unsigned long last_run=0; // stops accidental double input
unsigned long second_counter=0; //core of the countdown, makes sure loops runned every second
int temp_focus = 0;//makes multiple sessions possible with the benefit of on-the-move focus-time changes
int temp_break = 0;//makes multiple sessions possible with the benefit of on-the-move break-time changes
int temp_session = 0;//makes multiple sessions possible with the benefit of on-the-move session quantity changes
int button_state = 1;//start position of the knob button
int last_button_state = 1; //start position of the knob button
int led_counter = 1;// number of LEDs that will light up
int second = 100;//delay on the countdown loop
Adafruit_NeoPixel pixels(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(9600);
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP);
pinMode(S,INPUT);
pixels.begin(); // INITIALIZE NeoPixel pixels object (REQUIRED)
pixels.show(); // Turn OFF all pixels ASAP
pixels.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
//INTERRUPTS ONLY WORK ON PIN 2 & 3 !!!
attachInterrupt(digitalPinToInterrupt(CLK), knob_turned, CHANGE);//interrupt the code when the knob is turned, and run the knob_turned Interrupt Service Routine (ISR)
attachInterrupt(digitalPinToInterrupt(S), countdown, RISING);//interrupt the code when the device is tilted, and run the countdown Interrupt Service Routine (ISR)
}
void loop(){
switch(mode){
case 0:{
pixels.clear();
led_counter = 2*((focus_timer + CHUNK-1) / CHUNK);//displays the time by 5 minutes chunks on the LED-ring
//Serial.println(led_counter); debug code for LED count
for(int l = 0; l < led_counter; l++) {
pixels.setPixelColor(l, pixels.Color(10, 0, 0));
}
pixels.show();
break;
}
case 1:{
pixels.clear();
led_counter = 2*((break_timer + CHUNK-1) / CHUNK);//displays the time by 5 minutes chunks on the LED-ring
//Serial.println(led_counter); debug code for LED count
for(int l = 0; l < led_counter; l++) {
pixels.setPixelColor(l, pixels.Color(0, 0, 10));
}
pixels.show();
break;
}
case 2:{
pixels.clear();
led_counter = number_of_sessions;
//Serial.println(led_counter); debug code for LED count
for(int l = 0; l < led_counter; l++) {//displays the number of sessions on the LED-ring
pixels.setPixelColor(l, pixels.Color(0, 10, 0));
}
pixels.show();
break;
}
}
if(millis()-last_run > 50){//to stop accidental double clicks the code will update every x milisecs
button_state=digitalRead(SW); //read the button state
if(button_state != last_button_state && button_state == 0){
mode++;
mode = mode % 3;
if(mode == 0){
Serial.println("Focus period");
}
else if(mode == 1){
Serial.println("Break period");
}
else if(mode == 2){
Serial.println("Number of sessions");
}
}
last_button_state = button_state;
}
//Serial.println(digitalRead(S));//Debug code for pin testing
}
void knob_turned(){
if(millis()-last_run >50){
if(digitalRead(CLK) != digitalRead(DT)){
delta++;
}
else{
delta--;
}
switch(mode) {
case 0:{
focus_timer = constrain((focus_timer+(delta*300)), 300, 3600);// changes the length of sessions
Serial.println((String)"New focus length is: " + focus_timer);
temp_focus=focus_timer;
break;
}
case 1:{
break_timer = constrain((break_timer+(delta*300)), 0, 3600); // changes the length of breaks
Serial.println((String)"New break length is: " + break_timer);
temp_break=break_timer;
break;
}
case 2:{
number_of_sessions = constrain((number_of_sessions+delta), 1, 24); //changes the number of session when it's in the session mode(2). Added 1, so there can't be a zero session.
Serial.println((String)"New number of sessions is: " + number_of_sessions);
temp_session=number_of_sessions;
break;
}
}
//Serial.println(delta);//debug code for delta
delta=0;
last_run=millis();
}
}
void countdown(){
for(number_of_sessions; number_of_sessions > 0; number_of_sessions--){
Serial.println((String)"Focus time");
for(focus_timer; focus_timer > 0; focus_timer--){
while(digitalRead(S) != HIGH){//puts the system into infinite loop when device is tilted back up to pause the countdown
delay(1);
}
mode = 0;
pixels.clear();
led_counter = 2*((focus_timer + CHUNK-1) / CHUNK);
for(int l = 0; l < led_counter; l++) {
pixels.setPixelColor(l, pixels.Color(10, 0, 0));
}
pixels.show();
Serial.println(focus_timer);//debug code for focus countdown
delay(second);
}
if(number_of_sessions > 1){//Last break is not needed
Serial.println((String)"Break time");
for(break_timer; break_timer > 0; break_timer--){
while(digitalRead(S) != HIGH){//puts the system into infinite loop when device is tilted back up to pause the countdown
delay(1);
}
mode = 1;
pixels.clear();
led_counter = 2*((break_timer + CHUNK-1) / CHUNK);
for(int l = 0; l < led_counter; l++) {
pixels.setPixelColor(l, pixels.Color(10, 0, 0));
}
pixels.show();
Serial.println(break_timer);//debug code for break countdown
delay(second);
}
}
if(number_of_sessions > 1){
Serial.println((String)(number_of_sessions-1) + " sessions left.");
}
else{
Serial.println((String)"No sessions left.");
}
}
}
I am trying to make myself a pomodoro timer using Arduino uno, NeoPixel 24-LED ring, mercuy tilt-sensor(S) and rotary encoder(SW DT CLK). Rotary encoder is used to set up the time periods and number of focus sessions. Mercury-tilt sensor is used to start the countdown when the device is turned upside down.
I want to be able to stop the countdown at any point, add or substract timer if i want to and continue the countdown. But i couldnt find a way to break the interrupt command block.
Can i make this work or should i move the countdown to the main loop and make the "settings" menu to an interrupt void


