#include <Encoder.h> // https://www.pjrc.com/teensy/td_libs_Encoder.html
#include <Wire.h>
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
hd44780_I2Cexp lcd(0x27); // declare lcd object at address 0x27 (use i2c address zero to auto locate address)
const byte relaiPin = 9; // le relai
const byte buzPin = 10; // un buzzer pour le fun
const byte encoderCLKPin = 2; // encoder encoder CLK
const byte encoderDTPin = 3; // encoder encoder DT
const byte tickShift = 2; // nombre de décalages à faire sur la valeur (puissance de 2) ici 2**2 => 4 ticks pour 1 valeur
const long minBPM = 0;
const unsigned long dureeImpulsion = 100; // ms
const long maxBPM = 60000ul / dureeImpulsion; // pour que la pause soit toujours positive
long currentBPM = 60;
unsigned long chrono;
Encoder encoder(encoderDTPin, encoderCLKPin);
bool encoderChanged() {
long newPosition = encoder.read() >> tickShift;
if (newPosition != currentBPM) {
if (newPosition < minBPM) {
currentBPM = minBPM;
encoder.write(currentBPM << tickShift);
}
else if (newPosition > maxBPM) {
currentBPM = maxBPM;
encoder.write(currentBPM << tickShift);
}
else currentBPM = newPosition;
return true;
}
return false;
}
void tickEncoder() {
lcd.setCursor(4, 0);
lcd.print(" ");
lcd.setCursor(4, 0);
lcd.print(currentBPM);
}
void configuration() {
pinMode(relaiPin, OUTPUT);
pinMode(buzPin, OUTPUT);
Serial.begin(115200);
encoder.write(currentBPM << tickShift);
int status = lcd.begin(16, 2);
if (status != 0) hd44780::fatalError(status); // does not return
lcd.print("BPM:");
lcd.print(currentBPM);
chrono = millis();
Serial.println("Pret!");
}
void interface() {
if (encoderChanged()) tickEncoder();
}
void animation() {
static bool enImpulsion = false;
if (currentBPM != 0) {
if (enImpulsion) {
if (millis() - chrono >= dureeImpulsion) {
digitalWrite(relaiPin, LOW);
enImpulsion = false;
chrono = millis();
}
} else {
unsigned long dureePause = (60000ul / currentBPM) - dureeImpulsion;
if (millis() - chrono >= dureePause) {
digitalWrite(relaiPin, HIGH);
tone(buzPin, 1000, dureeImpulsion);
enImpulsion = true;
chrono = millis();
}
}
}
}
void setup() {
configuration();
}
void loop() {
interface();
animation();
}