Muito útil para definir períodos de foco e descanso durante as atividades diárias, a técnica de Pomodoro pode ser implementada de várias formas. Neste post vamos criar um utilizando o arduino:
/***/
Componentes:
- 1 Arduino Uno;
- 1 Display LCD 16×2 com interface I2C;
- 1 Sensor de toque/capacitivo;
- 1 Resistor de 10 Ohms;
- 1 Buzzer passivo;
- 1 Protoboard;
/***/
Esquema de ligação:

Iremos conectar o pino de 5V do arduino no barramento azul da protoboard e o GND1 no barramento vermelho. O 5V representará o nosso positivo e o GND o nosso negativo.

Um dos terminais do resistor de 10 Ohms deve ser ligado no negativo (barramento vermelho da protoboard) e o outro no pino /GND do buzzer. A posição do pino pode variar conforme o fabricante conforme imagem abaixo. Iremos utilizar este resistor para controlar o volume do buzzer.

O pino “S”/”VCC2“ do buzzer deve ser ligado no pino 3 do arduino. O pino 3 enviará os sinais responsáveis pela ativação e desativação do sinal sonoro.
Iremos conectar o pino “VCC” do sensor de toque no positivo (barramento azul da protoboard) e o “GND” no negativo (barramento vermelho da protoboard). O pino “SIG/OUT3“ deverá ser ligado no pino 2 do arduino. Ao encostar o dedo neste sensor será gerado um sinal elétrico que será comunicado para o arduino.

No display de LCD iremos conectar o pino “GND” no negativo (barramento vermelho da protoboard) e o pino “VCC” no positivo (barramento azul da protoboard) para a sua alimentação. O pino “SDA” deverá ser ligado no pino “A4” do arduino. O pino “SCL” deverá ser ligado no pino “A5” do arduino. Os pinos “SDA” e “SCL” são utilizados para a comunicação via protocolo “I2C4“.

/***/
Código:
#include <stdbool.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define COLUNS 16
#define LINES 2
#define ADDRESS 0x27
#define TOUCH 2
#define BUZZER 3
LiquidCrystal_I2C lcd(ADDRESS, COLUNS, LINES);
int lastState = LOW;
bool start = false;
bool work = false;
bool breakTime = false;
bool longBreakTime = false;
//in seconds
int timeToBreak = 300;
int timeToWork = 1500;
int timeToLongBreak = 600;
int cycle = 1;
int count = 0;
void bip(){
int melody[] = { 660, 660, 0, 660, 0, 510, 660, 0, 770 };
int duration[] = { 100, 100, 100, 100, 100, 100, 100, 100, 100 };
for (int i = 0; i < 9; i++) {
if (melody[i] == 0) {
delay(duration[i]);
} else {
tone(BUZZER, melody[i], duration[i]);
delay(duration[i] * 1.30);
noTone(BUZZER);
}
}
}
void setup(){
lcd.init();
lcd.backlight();
lcd.clear();
pinMode(TOUCH, INPUT);
pinMode(BUZZER, OUTPUT);
}
void printLongBreak(LiquidCrystal_I2C lcd, int cycle, int count){
char buffer[COLUNS];
char bufferAux[COLUNS];
lcd.clear();
lcd.setCursor(0,0);
sprintf(bufferAux, "Long Break >.<", cycle);
lcd.print(bufferAux);
lcd.setCursor(0,1);
sprintf(buffer, "%d seconds", count);
lcd.print(buffer);
}
void printBreak(LiquidCrystal_I2C lcd, int cycle, int count){
char buffer[COLUNS];
char bufferAux[COLUNS];
lcd.clear();
lcd.setCursor(0,0);
sprintf(bufferAux, "Break %dC", cycle);
lcd.print(bufferAux);
lcd.setCursor(0,1);
sprintf(buffer, "%d seconds", count);
lcd.print(buffer);
}
void printWork(LiquidCrystal_I2C lcd, int cycle, int count){
char buffer[COLUNS];
char bufferAux[COLUNS];
lcd.clear();
lcd.setCursor(0,0);
sprintf(bufferAux, "Work %dC", cycle);
lcd.print(bufferAux);
lcd.setCursor(0,1);
sprintf(buffer, "%d seconds", count);
lcd.print(buffer);
}
bool isPressed(int lastState){
int currentState = digitalRead(TOUCH);
if(lastState == LOW && currentState == HIGH){
return true;
}
return false;
}
void printPauseTimer(LiquidCrystal_I2C lcd){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Pomodoro Timer");
lcd.setCursor(0,1);
lcd.print("Pause");
}
void printStartTimer(LiquidCrystal_I2C lcd){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Pomodoro Timer");
lcd.setCursor(0,1);
lcd.print("Start!");
}
void printWaitStartTimer(LiquidCrystal_I2C lcd){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Pomodoro Timer");
lcd.setCursor(0,1);
lcd.print("Wait start >");
}
void menu(bool *start, bool *work, int count, int lastState){
if(isPressed(lastState) && !*start && count == 0){
*start = true;
*work = true;
printStartTimer(lcd);
bip();
}else if(isPressed(lastState) && *start){
*start = false;
}else if(isPressed(lastState) && !*start){
*start = true;
}else if(!*start && count != 0){
printPauseTimer(lcd);
}else{
printWaitStartTimer(lcd);
}
}
void loop(){
lcd.clear();
menu(&start, &work, count, lastState);
if(start){
if(work){
printWork(lcd, cycle, count);
if(count == timeToWork){
count = 0;
work = false;
breakTime = true;
bip();
}
}
if(breakTime){
if(cycle == 3){
longBreakTime = true;
}else{
printBreak(lcd, cycle, count);
if(count == timeToBreak){
count = 0;
cycle++;
work = true;
breakTime = false;
bip();
}
}
}
if(longBreakTime){
printLongBreak(lcd, cycle, count);
if(count == timeToLongBreak){
count = 0;
cycle = 1;
work = true;
breakTime = false;
longBreakTime = false;
bip();
}
}
count++;
}
lastState = digitalRead(TOUCH);
delay(1000);
}
O código também está disponível no github.
/***/
Funcionamento:
As variáveis timeToBreak, timeToWork e timeToLongBreak determinam os tempos, em segundos, para o foco (Work) e pausa (Break). A cada 3 ciclos de foco iremos executar uma pausa longa (Long Break).

Ao executar, o temporizador precisa ser iniciado através do sensor de toque. Ao tocar o sensor novamente o timer será pausado.

Quando iniciado será exibido o contador, a fase (Work, Break ou Long Break) e o ciclo. A cada virada de ciclo um som será emitido pelo buzzer. A melodia é uma pequena parte do tema Super Mário 😆 que gerei via ChatGpt.

Bem, é isso ai. Existem muitos pontos de melhoria. Faça a sua versão e compartilhe!
Boa diversão 😁

1 GND vem do inglês “Ground” que representa o terra/negativo.
2 VCC significa “Volts em Corrente Contínua”, também pode ser chamada de “DC”.
3 SIG/OUT é a abreviação de Sinal e Output.
4 I2C protocolo e comunicação serial mestre-escravo criado pela Philips.