La Grove Bar ha una libreria orribile che usa il portmapping, quindi l'ho adattata per utilizzare due pin arbitrari: la trovate qui: http://github.com/ciromattia/Grove_LED_Bar
Quando ho tempo provo a capire perché ne vuole per forza due e non gliene basta uno solo come per il 7 segmenti.
I collegamenti sono gli stessi del mio tranne la barra a led su 2-3 e il display su 1.
Codice: Seleziona tutto
/*
Darkroom timer with programmable functions
Model: DL0002
This sketch implements a darkroom timer with various modes.
It's developed after Daniele Lucarelli's version on analogica.it
(http://www.analogica.it/upgrade-timer-con-keypad-t6797.html)
To build this sketch you need, besides core libraries, the
Keypad library: http://playground.arduino.cc/code/Keypad
and my modified version of the
Grove LED_Bar library: http://github.com/ciromattia/Grove_LED_Bar
The circuit:
* Arduino UNO/Duemilanove
* 7-Segment 4 number serial LCD display
* 4x4 keypad
* buzzer
* pushbutton
* female 1/4" jack and pedal (optional)
* 220V relay
* a toggle switch
* a 10K resistor
* a 330 resistor
The wiring scheme should come with this sketch, if not drop me a line.
### Pin Map Recap ###
D0: 7-Segment RX
D1: 7-Segment TX
D2: DI led bar
D3: DCKI led bar
D8: buzzer
D9: progression switch (linear or f/stop) - maybe superfluous?
D10: Relay signal
D11, D12, A0-A6: 4x4 keypad
D13: main button (pedal/pushbutton)
created 11 Nov 2013
by Daniele Lucarelli
adapted with LCD 16x2 display 5 Dec 2013
by Ciro Mattia Gonano <[email protected]>
This code is in the public domain.
*/
#include <SoftwareSerial.h>
#include <Keypad.h>
#include <avr/eeprom.h>
#include <LED_Bar.h>
// Constants
const byte ROWS = 4; // keypad: 4 rows
const byte COLS = 4; // keypad: 4 cols
const byte buzzer = 8; // buzzer pin
const byte mainbtn = 13; // main button (pushbutton/pedal) pin
const byte relay = 10; // relay pin
const byte selector = 9; // progression switch pin
const int tone_up = 600;
const int tone_down = 300;
const int scrollTime = 250;
const int waitTime = 800;
// modes
const byte MODLINFREE = 0b00000;
const byte MODLINUP = 0b00010;
const byte MODLINDOWN = 0b00100;
const byte MODLINDDS = 0b00110;
const byte MODFSTFREE = 0b00001;
const byte MODFSTPREC = 0b00011;
const byte MODFSTTEST = 0b00101;
const byte MODFSTDOWN = 0b00111;
// TODO: allow setting a buzzer interval for linear countdown (for test strips)
// TODO: implement eventListener for keyboard to manage key HOLDing
// IDEE: Sul provino a scalare fstop il tasto # potrebbe servire per passare dalla modalità continua scoprendo alla modalità riespongo tutto spostando la carta
// IDEE: Sul count down e cont down dds il tasto # potrebbe servire per passare dalla modalità count dowm a quella conut up spengendo il timer a time finito
// Multiplier formula for f/stop progression (thanks to Gergio)
// mult = 2^(1/precision)
// Variables
int i = 0;
int time = 0;
int time_succ;
int appo_time;
int time_countdown;
int time_dds;
int time_fsttest;
int time_fstdown;
byte timer_mode = MODLINFREE; // timer mode (0 = lin.A, 1 = lin.B, 2 = lin.C, 3 = lin.D, 4 = fst.A, 5 = fst.B, 6 = fst.C, 7 = fst.D)
long last_time = 0;
long errlet = 0;
int btnstatus = 0; // main button status
int lastbtnstatus = LOW; // last main button status
int selstatus = LOW;
int lastselstatus = LOW;
boolean running = false;
boolean btnhigh = false;
boolean firstpress = true;
boolean mute = false;
float mult = 1.0;
int precis = 1;
char _buffer[17];
/* init 7Segment */
SoftwareSerial Serial7Segment(0, 1);
LED_Bar myLED(3,2); //DCKI Pin 3 - DI Pin 2
/* init matrix keypad */
char keys[ROWS][COLS] = {
{1,2,3,'A' },
{4,5,6,'B' },
{7,8,9,'C' },
{'*','0','#','D' }
};
byte rowPins[ROWS] = {A4, A5, 11, 12}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A0, A1, A2, A3}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup() {
//Serial.begin(9600);
//Serial.println(">>> Debug <<<");
/* ensure analog pins are set to INPUT */
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(A3, INPUT);
pinMode(A4, INPUT);
pinMode(A5, INPUT);
pinMode(buzzer, OUTPUT); // Buzzer pin in Output
pinMode(relay, OUTPUT); // Relé pin in Output
pinMode(mainbtn, INPUT); // Pedale/pulsante pin in Input
pinMode(selector, INPUT); // Selettore modalità (lineare/fstop) in Input
// read from EEPROM stored values
load_eeprom();
// Setup LCD
setup_display();
// init fstop/linear mode
selstatus = digitalRead(selector);
lastselstatus = selstatus;
if (selstatus == HIGH) {
bitSet(timer_mode,0); // f/stop mode
} else {
bitClear(timer_mode,0); // linear mode
}
// TODO: add event listener for keypad
//keypad.addEventListener(keypadEvent);
// cleanup and get ready to start
delay(waitTime);
init_timermode();
errlet = millis();
digitalWrite(relay, LOW); // shut down the relay
}
void loop() {
if (millis() - errlet <= 20) {
} else {
btnstatus = digitalRead(mainbtn);
if (btnstatus != lastbtnstatus) {
// main button has been toggled
if (btnstatus == HIGH) {
// main button has been pressed
btnhigh = true;
}
lastbtnstatus = btnstatus;
}
errlet = millis();
}
selstatus = digitalRead(selector);
if (selstatus != lastselstatus) {
// mode change
lastselstatus = selstatus;
timer_mode = (selstatus == HIGH) ? MODFSTFREE : MODLINFREE;
say_timermode();
}
if (running && btnhigh) {
// shut down the relay and pause the timer
digitalWrite(relay, LOW);
btnhigh = false;
running = false;
if (timer_mode == MODLINDDS && firstpress) {
firstpress = false;
}
} else if (running && !btnhigh) {
switch (timer_mode) {
case MODLINFREE:
off();
break;
case MODLINUP:
stopwatch();
break;
case MODLINDOWN:
countdown();
break;
case MODLINDDS:
firstpress ? off() : countdown();
break;
case MODFSTFREE:
off();
break;
case MODFSTPREC:
off();
break;
case MODFSTTEST:
test_strip();
break;
case MODFSTDOWN:
countdown();
break;
}
} else if (!running && btnhigh) { // not running
btnhigh = false;
switch (timer_mode) {
case MODLINFREE:
case MODFSTFREE:
digitalWrite(relay, HIGH); // powerup the relay
running = true;
off();
break;
case MODLINUP:
digitalWrite(relay, HIGH); // powerup the relay
running = true;
last_time = millis(); // reset timer counter
stopwatch();
break;
case MODLINDOWN:
time_countdown = appo_time;
eeprom_write_word((uint16_t *)1, time_countdown);
if (time > 0) {
digitalWrite(relay, HIGH); // powerup the relay
running = true;
last_time = millis(); // reset timer counter
countdown();
}
break;
case MODLINDDS:
time_dds = appo_time;
eeprom_write_word((uint16_t *)3, time_dds);
if (time > 0) {
digitalWrite(relay, HIGH); // powerup the relay
running = true;
if (firstpress == true) {
off();
} else {
last_time = millis(); // reset timer counter
countdown();
}
}
break;
case MODFSTPREC:
off();
break;
case MODFSTTEST:
time_fsttest = appo_time;
eeprom_write_word((uint16_t *)5, time_fsttest);
digitalWrite(relay, HIGH); // powerup the relay
running = true;
last_time = millis(); // reset timer counter
if (time < 10)
time = 10;
time_succ = time;
time = 0;
test_strip();
break;
case MODFSTDOWN:
time_fstdown = appo_time;
eeprom_write_word((uint16_t *)7, time_fstdown);
if (time > 0) {
digitalWrite(relay, HIGH); // powerup the relay
running = true;
last_time = millis(); // reset timer counter
countdown();
}
break;
}
} else { // not running nor button released, so read keypad input
read_key();
}
}
void load_eeprom() {
timer_mode = eeprom_read_byte(0);
// if mode is not valid set the first one and return
if ((timer_mode & 0b11000) > 0) {
timer_mode = MODLINFREE;
return;
}
time_countdown = eeprom_read_word((uint16_t *)1); // 2 byte
time_dds = eeprom_read_word((uint16_t *)3); // 2 byte
time_fsttest = eeprom_read_word((uint16_t *)5); // 2 byte
time_fstdown = eeprom_read_word((uint16_t *)7); // 2 byte
precis = eeprom_read_word((uint16_t *)9); // 2 byte
}
void off() {
// no action taken
}
void countdown() {
if (time > 0 && (millis() - last_time >= 100)) {
last_time = millis();
time--;
metronome();
say_time();
if (time == 0) {
// if time reached 0, shut down the relay and reset the function
digitalWrite(relay, LOW);
running = false;
time = appo_time;
beep(tone_down, 75);
delay(150);
beep(tone_down, 75);
delay(150);
beep(tone_down, 150);
if (timer_mode == MODLINDDS) {
firstpress = true;
}
say_time();
}
}
}
void stopwatch() {
if (millis() - last_time >= 100) {
last_time = millis();
time++;
metronome();
say_time();
}
}
void test_strip() {
if (millis() - last_time >= 100) {
last_time = millis();
time++;
say_time();
if (time == time_succ) {
beep(tone_up, 150);
mult = pow(2.0,(1.0/precis));
time_succ = int(float(time) * mult);
}
if (time_succ - time <= 3) {
beep(tone_up, 50);
}
}
}
void reset() {
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write(0x77);
Serial7Segment.write(0b00000100);
time = 0;
appo_time = 0;
}
void init_timermode() {
switch (timer_mode) {
case MODLINDOWN:
time = time_countdown;
break;
case MODLINDDS:
time = time_dds;
firstpress = true;
break;
case MODFSTTEST:
time = time_fsttest;
break;
case MODFSTDOWN:
time = time_fstdown;
break;
case MODLINFREE:
case MODLINUP:
case MODFSTFREE:
case MODFSTPREC:
default:
break;
}
say_timermode();
}
/***************** DISPLAY functions *****************/
void setup_display() {
myLED.set_LED_Index(0b000001111111111);
// Setup 7SegmentDisplay
Serial7Segment.begin(9600); //Connessione con il display via Seriale a 9600 bps
Serial7Segment.write('v'); //Reset del display - si forza il cursore ad andare al primo carattere
Serial7Segment.write(0x7A); // Brightness control command
Serial7Segment.write((byte) 16); // Modificare questo valore per variare la luminosità
Serial7Segment.write('A');
myLED.set_LED_Index(0b000000111111111);
delay(scrollTime);
Serial7Segment.write('N');
myLED.set_LED_Index(0b000000011111111);
delay(scrollTime);
Serial7Segment.write('A');
myLED.set_LED_Index(0b000000001111111);
delay(scrollTime);
Serial7Segment.write('L');
myLED.set_LED_Index(0b000000000111111);
delay(scrollTime);
Serial7Segment.write('N');
Serial7Segment.write('A');
Serial7Segment.write('L');
Serial7Segment.write('O');
myLED.set_LED_Index(0b000000000011111);
delay(scrollTime);
Serial7Segment.write('A');
Serial7Segment.write('L');
Serial7Segment.write('O');
Serial7Segment.write('G');
myLED.set_LED_Index(0b000000000001111);
delay(scrollTime);
Serial7Segment.write('L');
Serial7Segment.write('O');
Serial7Segment.write('G');
Serial7Segment.write('I');
myLED.set_LED_Index(0b000000000000111);
delay(scrollTime);
Serial7Segment.write('O');
Serial7Segment.write('G');
Serial7Segment.write('I');
Serial7Segment.write('C');
myLED.set_LED_Index(0b000000000000011);
delay(scrollTime);
Serial7Segment.write('G');
Serial7Segment.write('I');
Serial7Segment.write('C');
Serial7Segment.write('A');
Serial7Segment.write(0x77);
Serial7Segment.write(0b00001000);
myLED.set_LED_Index(0b000000000000001);
delay(scrollTime);
Serial7Segment.write('I');
Serial7Segment.write('C');
Serial7Segment.write('A');
Serial7Segment.write(0x77);
Serial7Segment.write(0b00000100);
Serial7Segment.write('I');
myLED.set_LED_Index(0b000000000000000);
delay(scrollTime);
Serial7Segment.write('C');
Serial7Segment.write('A');
Serial7Segment.write(0x77);
Serial7Segment.write(0b00000010);
Serial7Segment.write('I');
Serial7Segment.write('T');
myLED.set_LED_Index(0b000001000000000);
delay(scrollTime);
myLED.set_LED_Index(0b000000000000000);
delay(scrollTime);
myLED.set_LED_Index(0b000001000000000);
delay(scrollTime);
Serial7Segment.write('A');
Serial7Segment.write(0x77);
Serial7Segment.write(0b00000001);
Serial7Segment.write('I');
Serial7Segment.write('T');
Serial7Segment.write(' ');
myLED.set_LED_Index(0b000000000000000);
delay(scrollTime);
Serial7Segment.write(0x77);
Serial7Segment.write(0b01000000);
Serial7Segment.write('I');
Serial7Segment.write('T');
Serial7Segment.write(' ');
Serial7Segment.write(' ');
myLED.set_LED_Index(0b000001000000000);
delay(scrollTime);
Serial7Segment.write('T');
Serial7Segment.write(' ');
Serial7Segment.write(' ');
Serial7Segment.write('0');
myLED.set_LED_Index(0b000000000000000);
delay(scrollTime);
Serial7Segment.write(' ');
Serial7Segment.write(' ');
Serial7Segment.write('0');
Serial7Segment.write('0');
myLED.set_LED_Index(0b000001000000000);
delay(scrollTime);
Serial7Segment.write(' ');
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write('0');
myLED.set_LED_Index(0b000000000000000);
delay(scrollTime);
reset();
delay(scrollTime);
delay(scrollTime);
myLED.set_LED_Index(0b000001000000000);
}
void say_timermode() {
switch (timer_mode) {
case MODLINFREE: say_free(); break;
case MODLINUP: say_up(); break;
case MODLINDOWN: say_down(); break;
case MODLINDDS: say_dds(); break;
case MODFSTFREE: say_fstop(); break;
case MODFSTPREC: say_precis(); break;
case MODFSTTEST: say_test_strip(); break;
case MODFSTDOWN: say_fstopdown(); break;
default: break;
}
}
void say_free() {
Serial7Segment.write('v');
Serial7Segment.write('L');
Serial7Segment.write('I');
Serial7Segment.write('N');
Serial7Segment.write('E');
beep(tone_up, 200);
delay(500);
say_cleartime();
eeprom_write_byte(0, MODLINFREE);
}
void say_up(){
Serial7Segment.write('v');
Serial7Segment.write('U');
Serial7Segment.write('p');
Serial7Segment.write(' ');
Serial7Segment.write(' ');
beep(tone_up, 200);
delay(500);
say_time();
eeprom_write_byte(0, MODLINUP);
}
void say_down(){
Serial7Segment.write('v');
Serial7Segment.write('D');
Serial7Segment.write('o');
Serial7Segment.write('u');
Serial7Segment.write('N');
beep(tone_down, 200);
delay(500);
say_time();
eeprom_write_byte(0, MODLINDOWN);
}
void say_dds() {
Serial7Segment.write('v');
Serial7Segment.write('D');
Serial7Segment.write('D');
Serial7Segment.write('S');
Serial7Segment.write(' ');
beep(tone_down, 200);
delay(500);
say_time();
eeprom_write_byte(0, MODLINDDS);
}
void say_fstop(){
Serial7Segment.write('v');
Serial7Segment.write('F');
Serial7Segment.write('-');
Serial7Segment.write('S');
Serial7Segment.write('T');
beep(tone_up, 200);
delay(500);
say_prec();
eeprom_write_byte(0, MODFSTFREE);
}
void say_precis() {
Serial7Segment.write('v');
Serial7Segment.write('p');
Serial7Segment.write('R');
Serial7Segment.write('E');
Serial7Segment.write('C');
beep(tone_down, 200);
delay(500);
say_prec();
eeprom_write_byte(0, MODFSTPREC);
}
void say_test_strip() {
Serial7Segment.write('v');
Serial7Segment.write('p');
Serial7Segment.write('R');
Serial7Segment.write('O');
Serial7Segment.write('S');
beep(tone_down, 200);
delay(500);
say_time();
eeprom_write_byte(0, MODFSTTEST);
}
void say_fstopdown() {
Serial7Segment.write('v');
Serial7Segment.write('C');
Serial7Segment.write('F');
Serial7Segment.write('S');
Serial7Segment.write('T');
beep(tone_down, 200);
delay(500);
say_time();
eeprom_write_byte(0, MODFSTDOWN);
}
void say_clearprecis() {
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write(0x77);
Serial7Segment.write(0b00000100);
}
void say_prec() {
say_clearprecis();
switch (precis) {
case 1:
myLED.set_LED_Index(0b000001000000000);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('1');
Serial7Segment.write(' ');
break;
case 2:
myLED.set_LED_Index(0b000000100000000);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('2');
Serial7Segment.write(' ');
break;
case 3:
myLED.set_LED_Index(0b000000010000000);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('3');
Serial7Segment.write(' ');
break;
case 4:
myLED.set_LED_Index(0b000000001000000);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('4');
Serial7Segment.write(' ');
break;
case 6:
myLED.set_LED_Index(0b000000000100000);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('6');
Serial7Segment.write(' ');
break;
case 8:
myLED.set_LED_Index(0b000000000010000);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('8');
Serial7Segment.write(' ');
break;
case 12:
myLED.set_LED_Index(0b000000000001000);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('1');
Serial7Segment.write('2');
break;
case 24:
myLED.set_LED_Index(0b000000000000100);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('2');
Serial7Segment.write('4');
break;
case 32:
myLED.set_LED_Index(0b000000000000010);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('3');
Serial7Segment.write('2');
break;
case 48:
myLED.set_LED_Index(0b000000000000001);
Serial7Segment.write('v');
Serial7Segment.write('1');
Serial7Segment.write('-');
Serial7Segment.write('4');
Serial7Segment.write('8');
break;
}
}
void say_cleartime() {
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write('0');
Serial7Segment.write(0x77);
Serial7Segment.write(0b00000100);
}
void say_time() {
say_cleartime();
Serial7Segment.write(0x77); //Codice per invio funzioni specifiche
Serial7Segment.write(0b00000100); //Accendo la virgola per 1 cifra decimale
sprintf(_buffer, "%04i", time); //Converte il tempo in una striga con gli zeri in testa
Serial7Segment.write(_buffer); // Stampo il tempo
}
void metronome() {
if (running && time%10 == 0) {
beep(tone_down, 50);
}
}
void beep(int this_tone, int duration) {
if (!mute)
tone(buzzer, this_tone, duration);
}
/*** Keypad management functions ***/
//void keypadEvent(KeypadEvent key) {}
void read_key() {
int key = keypad.getKey();
if (key == NO_KEY) return;
switch (key) {
case 'A': // Free mode
reset();
timer_mode = MODLINFREE | (timer_mode & 0b00001);
init_timermode();
break;
case 'B':
reset();
timer_mode = MODLINUP | (timer_mode & 0b00001);
init_timermode();
break;
case 'C':
reset();
timer_mode = MODLINDOWN | (timer_mode & 0b00001);
init_timermode();
break;
case 'D':
reset();
timer_mode = MODLINDDS | (timer_mode & 0b00001);
init_timermode();
break;
case '*': // reset for functions that need that
if (timer_mode == MODFSTDOWN) {
// Step down
mult = pow(2.0, (1.0/precis));
time = int(float(time) / mult);
if (time <= 1)
time = 1;
appo_time = time;
say_time();
}
break;
case '#': // Abilita disabilita suono su alcune modeioni
//mute = (timer_mode == MODLINUP || timer_mode == MODLINDOWN || timer_mode == MODLINDDS || timer_mode == MODFSTTEST);
if (timer_mode == MODFSTDOWN) {
// Step up
mult = pow(2.0, (1.0/precis));
time = int(float(time) * mult);
if (time >= 9999)
time = 9999;
appo_time = time;
say_time();
}
break;
default:
if (timer_mode == MODLINUP) { // stopwatch does not accept numbers input
say_up();
appo_time = time;
say_time();
} else if (timer_mode == MODFSTPREC) { // Imposta precisione decodifico i numeri
switch (key) {
case 1: precis = 1; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
case 2: precis = 2; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
case 3: precis = 3; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
case 4: precis = 4; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
case 5: precis = 6; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
case 6: precis = 8; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
case 7: precis = 12; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
case 8: precis = 24; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
case 9: precis = 32; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
case '0': precis = 48; say_prec(); eeprom_write_word((uint16_t *)9, precis); break;
default: break;
}
} else {
if (time < 1) {
time = key == '0' ? 0 : key;
} else {
time *= 10;
if (time > 9999)
time %= 10000;
if (key != '0')
time += key;
}
appo_time = time;
say_time();
}
}
}