Salve a tutti, ho la necessità di interfacciare un arduino mega che mi gestisce una interfaccia utente con vari pulsanti, led, relè e display, e un arduino nano che mi gestisce un timer count down, vorrei che nelle prime due righe del display continui arduino mega a scrivere e nelle altre due righe a scrivere arduino nano, questo perchè il listato del timer è bloccante inserito nel mega e ovviamente non mi permette di usare l'interfaccia utente nel tempo in cui il timer opera il conto alla rovescia da qui l'utilizzo di un altro arduino, secondo la vostra esperienza si può comandare un unico display con due arduino?
-
Devi scriverti un protocollo di comunicazione (immagino seriale) tra i due Arduini, in modo che quello con il display faccia da server per l'altro (in sostanza sempre il mega scrive).
-
In alternativa scrivi un timer/countdown non bloccante e fai girare tutto su un solo Arduino.
-
Se invece vuoi proprio scrivere fisicamente sullo stesso display, come se fosse ora collegato al mega e ora al nano, beh, bisogna comunque coordinare tra loro gli Arduini per suddividerei i tempi di accesso alla risorsa condivisa, e bisogna progettare un'interfaccia hardware a porte logiche per lo switch dei segnali fisici.
Personalmente la due mi sembra la più semplice, e la tre la più brigosa
Sinceramente anche io opterei per la numero 2 ma come? Vorresti dare un occhiata ai 2 listati per vedere cosa non va?
La soluzione 1, essendo il timer bloccante non è praticabile, nel senso che se è bloccante non potrà gestire la comunicazione
La soluzione tre secondo me è pressoché impossibile
Rimane la due e/o la due-bis
Riunificare i due programmi per usare un arduino unico
questo è il listato del timer che risulta bloccante per il mega
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f, 16, 2); // Set the LCD I2C address
#define Start 4 // start button
#define pausa 8 // pausa button
#define resetforzato 9 // resetforzato
int hours = 0;
int minutes = 0;
int seconds = 0;
boolean timeState = false;
#define encoderPinA 2 // right
#define encoderPinB 3 // left
#define encoderButton 5 // switch
int HMS = 0;
int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 1; // change management
static boolean rotating = false; // debounce management
boolean A_set = false;
boolean B_set = false;
#define led 6 // output
#define allarm 7 // buzzer
int contatoreFineTempo;
void setup() {
pinMode(Start, INPUT_PULLUP);
pinMode(pausa, INPUT_PULLUP);
pinMode(resetforzato, INPUT_PULLUP);
pinMode(encoderPinA, INPUT_PULLUP); //enabling pullups
pinMode(encoderPinB, INPUT_PULLUP);
pinMode(encoderButton, INPUT_PULLUP);
pinMode(led, OUTPUT);
pinMode(allarm, OUTPUT);
attachInterrupt(0, doEncoderA, CHANGE); //pin 2
attachInterrupt(1, doEncoderB, CHANGE); //pin 3
Serial.begin(9600); // output
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
lcd.setCursor(4, 1);
lcd.print("00:00:00");
digitalWrite(led, LOW);
digitalWrite(allarm, LOW);
}
void loop() {
if (digitalRead(encoderButton) == LOW)
{
HMS = HMS + 1;
if (HMS == 4)
{
HMS = 1;
}
delay(1000);
if (HMS == 1) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set ora");
}
else if (HMS == 2) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set minuti");
}
else if (HMS == 3) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set secondi");
}
}
rotating = true; // reset the debouncer
encoderPos = constrain(encoderPos, -1, 1);
if (lastReportedPos != encoderPos) {
if (HMS == 1) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set ora");
hours = hours + encoderPos;
hours = constrain(hours, 0, 47);
lcd.setCursor(4, 1);
}
else if (HMS == 2) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set minuti");
minutes = minutes + encoderPos;
minutes = constrain(minutes, 0, 59);
lcd.setCursor(8, 1);
}
else if (HMS == 3) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set secondi");
seconds = seconds + encoderPos;
seconds = constrain(seconds, 0, 59);
lcd.setCursor(12, 1);
}
Serial.println(encoderPos); // for testing
Serial.print("hours");
Serial.println(hours);
Serial.print("minutes");
Serial.println(minutes);
Serial.print("seconds");
Serial.println(seconds);
Serial.println(" ");
lcd.setCursor(4, 1);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
encoderPos = 0;
lastReportedPos = encoderPos;
}
if (digitalRead(Start) == LOW) { //start count down timer
delay(100);
digitalWrite(led, HIGH);
timeState = true;
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
//delay(1000);
while (timeState == true) {
if (minutes == 0 and hours == 0 and seconds == 0) { //count down alarm
while (timeState == true) {
contatoreFineTempo++;
Serial.println(contatoreFineTempo);
digitalWrite(led, LOW);
digitalWrite(allarm, HIGH);
tone(11, 600, 250);
delay(250);
digitalWrite(allarm, LOW);
delay(250);
if (contatoreFineTempo >= 10) {
contatoreFineTempo = 0;
if (contatoreFineTempo == 0) {
Serial.println("TEMPO SCADUTO");
digitalWrite(allarm, LOW);
timeState = false;
seconds = 1;
break;
}
}
if (digitalRead(Start) == LOW) { // allarme off
delay(100);
timeState = false;
seconds = 1;
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
lcd.setCursor(4, 1);
lcd.print("00:00:00");
digitalWrite(allarm, LOW);
break;
}
}
}
if (digitalRead(pausa) == LOW) { // metti in pausa
delay(100);
digitalWrite(led, LOW);
timeState = false;
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
lcd.setCursor(4, 1);
lcd.print("IN PAUSA");
Serial.println("IN PAUSA");
break;
}
if (digitalRead(resetforzato) == LOW) { // reset forzato
delay(100);
digitalWrite(led, LOW);
(minutes = 0);
(hours = 0);
(seconds = 0);
timeState = false;
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
lcd.setCursor(1, 1);
lcd.print("RESET FORZATO");
delay(2000);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
lcd.setCursor(4, 1);
lcd.print("00:00:00");
Serial.println("RESET FORZATO");
break;
}
delay(992);
seconds = seconds - 1;
if (seconds == -1) {
seconds = 59;
minutes = minutes - 1;
}
if (minutes == -1) {
minutes = 59;
hours = hours - 1;
}
Serial.print("hours"); // for testing
Serial.println(hours);
Serial.print("minutes");
Serial.println(minutes);
Serial.print("seconds");
Serial.println(seconds);
Serial.println(" ");
lcd.setCursor(4, 1);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
}
}
}
// Interrupt on A changing state
void doEncoderA() {
// debounce
if ( rotating ) delay (1); // wait a little until the bouncing is done
// Test transition, did things really change?
if ( digitalRead(encoderPinA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set and !B_set )
encoderPos = -1;
rotating = false; // no more debouncing until loop() hits again
}
}
// Interrupt on B changing state
void doEncoderB() {
if ( rotating ) delay (1);
if ( digitalRead(encoderPinB) != B_set ) {
B_set = !B_set;
// adjust counter – 1 if B leads A
if ( B_set and !A_set )
encoderPos = 1;
rotating = false;
}
}
come si può modificare per ovviare a questo problema?
Non si tratta di una modifica, ma di riscrivere l'intera procedura in modo non bloccante (tramite una macchina a stati) e misurare i tempi con la funzione millis (che comunque se usata bene ha un errore di circa cinque secondi all'ora, meglio dei molti minuti all'ora del tuo sistema con delay).
Sono due argomenti da affrontare assolutamente se si vuole fare qualcosa di appena più che elementare (anzi secondo me andrebbero affrontati già all'inizio così non ci si troverebbe ogni volta a dover riscrivere tutto o usare tanti Arduini per fare cose che uno solo basta e avanza... memoria e terminali permettendo).
mizzica!!!! e come verrebbe adesso il listato?
ok proverò a buttare giù qualcosa
qualche delucidazione però, a livello di logica, come faccio ad incastrare la funzione millis nei "case" vari? usando un encoder come nel mio listato come ultilizzo i "case" per modificare il tempo?
Se ne sta parlando anche qui.
I case / stati che ti servono sono le situazioni / fasi di funzionamento in cui ti puoi trovare: riposo, regolazione, conteggio, allarme, pausa ecc.
Gli eventi sono le pressioni dei pulsanti e/o le variazioni encoder e timeout vari.
Esempio
case CONTEGGIO:
if (millis()-tempoInizio >= 1000) // evento timeout 1 sec
{
tempoInizio += 1000;
...aggiorna variabili orarie...
...aggiorna display...
}
if (minutes == 0 and hours == 0 and seconds == 0) // evento fine countdown
{
stato = ALLARME;
}
break;
Ah, naturalmente non è da scrivere solo il timer con questa logica, ma anche tutto il resto.
ok butto giù il listato
ma secondo te Claudio_FF posso lasciare tutta questa parte?
if (digitalRead(encoderButton) == LOW)
{
HMS = HMS + 1;
if (HMS == 4)
{
HMS = 1;
}
delay(1000);
if (HMS == 1) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set ora");
}
else if (HMS == 2) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set minuti");
}
else if (HMS == 3) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set secondi");
}
}
rotating = true; // reset the debouncer
encoderPos = constrain(encoderPos, -1, 1);
if (lastReportedPos != encoderPos) {
if (HMS == 1) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set ora");
hours = hours + encoderPos;
hours = constrain(hours, 0, 47);
lcd.setCursor(4, 1);
}
else if (HMS == 2) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set minuti");
minutes = minutes + encoderPos;
minutes = constrain(minutes, 0, 59);
lcd.setCursor(8, 1);
}
else if (HMS == 3) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Set secondi");
seconds = seconds + encoderPos;
seconds = constrain(seconds, 0, 59);
lcd.setCursor(12, 1);
}
Serial.println(encoderPos); // for testing
Serial.print("hours");
Serial.println(hours);
Serial.print("minutes");
Serial.println(minutes);
Serial.print("seconds");
Serial.println(seconds);
Serial.println(" ");
lcd.setCursor(4, 1);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
encoderPos = 0;
lastReportedPos = encoderPos;
}
if (digitalRead(Start) == LOW) { //start count down timer
delay(100);
digitalWrite(led, HIGH);
timeState = true;
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
//delay(1000);
while (timeState == true) {
if (minutes == 0 and hours == 0 and seconds == 0) { //count down alarm
while (timeState == true) {
contatoreFineTempo++;
Serial.println(contatoreFineTempo);
digitalWrite(led, LOW);
digitalWrite(allarm, HIGH);
tone(11, 600, 250);
delay(250);
digitalWrite(allarm, LOW);
delay(250);
if (contatoreFineTempo >= 10) {
contatoreFineTempo = 0;
if (contatoreFineTempo == 0) {
Serial.println("TEMPO SCADUTO");
digitalWrite(allarm, LOW);
timeState = false;
seconds = 1;
break;
}
}
if (digitalRead(Start) == LOW) { // allarme off
delay(100);
timeState = false;
seconds = 1;
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
lcd.setCursor(4, 1);
lcd.print("00:00:00");
digitalWrite(allarm, LOW);
break;
}
}
}
if (digitalRead(pausa) == LOW) { // metti in pausa
delay(100);
digitalWrite(led, LOW);
timeState = false;
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
lcd.setCursor(4, 1);
lcd.print("IN PAUSA");
Serial.println("IN PAUSA");
break;
}
if (digitalRead(resetforzato) == LOW) { // reset forzato
delay(100);
digitalWrite(led, LOW);
(minutes = 0);
(hours = 0);
(seconds = 0);
timeState = false;
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
lcd.setCursor(1, 1);
lcd.print("RESET FORZATO");
delay(2000);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("COUNT DOWN TIMER");
lcd.setCursor(4, 1);
lcd.print("00:00:00");
Serial.println("RESET FORZATO");
break;
}
e togliere solo questa
delay(992);
seconds = seconds - 1;
if (seconds == -1) {
seconds = 59;
minutes = minutes - 1;
}
if (minutes == -1) {
minutes = 59;
hours = hours - 1;
}
Serial.print("hours"); // for testing
Serial.println(hours);
Serial.print("minutes");
Serial.println(minutes);
Serial.print("seconds");
Serial.println(seconds);
Serial.println(" ");
lcd.setCursor(4, 1);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
}
}
che secondo me è la parte "bloccante"
e lasciare anche la parte che gestisce gli encoder
void doEncoderA() {
// debounce
if ( rotating ) delay (1); // wait a little until the bouncing is done
// Test transition, did things really change?
if ( digitalRead(encoderPinA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set and !B_set )
encoderPos = -1;
rotating = false; // no more debouncing until loop() hits again
}
}
// Interrupt on B changing state
void doEncoderB() {
if ( rotating ) delay (1);
if ( digitalRead(encoderPinB) != B_set ) {
B_set = !B_set;
// adjust counter – 1 if B leads A
if ( B_set and !A_set )
encoderPos = 1;
rotating = false;
}
}
tu che dici?
RoccoStragapede:
ma secondo te Claudio_FF posso lasciare tutta questa parte?
È vero che la maggior parte del tempo è persa su quel delay 992, ma è anche tutto racchiuso in un while che non termina finché la variabile 'timeState' rimane true. Quel, anzi quei while sono parti di codice bloccanti perché non restituiscono il controllo al resto del loop finché non sono terminate.
Le due funzioni di lettura encoder sotto interrupt ovviamente devono rimanere come sono.
Più che cercare di "ricucire un listato" va ripensato/riprogettato tutto sotto forma di stati/situazioni, eventi a cui rispondere in ogni stato, e azioni da compiere in risposta agli eventi. POI si traduce il tutto in un nuovo listato (tenendo comunque buoni i singoli frammenti già pronti che realizzano le singole operazioni).
L'encoder, se letto bene, non necessita di antirimbalzo, perché devi rilevare il passaggio da una combinazione all'altra fra 4 stati diversi: se consideri uno scatto in senso orario il passaggio da 3 a 4 e uno scatto in senso antiorario il passaggio da 2 a 1, il rimbalzo è impossibile. L'encoder esce con una sequenza in codice Gray:
A B
1. 0 0
2. 0 1
3. 1 1
4. 1 0
1. 0 0
...
Rotazione oraria: da 11 a 10
Rotazione antioraria: da 01 a 00
buongiorno a tutti, ho modificato il listato affinchè non risultasse bloccante, ci sono riuscito ma quando per esempio sono nella situazione per esempio 01:01:01 gli zero lampeggiano non in maniera significativa ad ogni secondo, secondo voi da cosa è dovuto?
ecco il listato
if ((unsigned long) millis() - time1 > 1000 and mask == 1) {
lcd.setCursor(0, 3);
lcd.print(hours);
lcd.setCursor(2, 3);
lcd.print(':');
lcd.setCursor(3, 3);
lcd.print(minutes);
lcd.setCursor(5, 3);
lcd.print(':');
lcd.setCursor(6, 3);
lcd.print(seconds);
if(minutes == 0 and hours == 0 and seconds == 0) { //When Timer Finish
digitalWrite(led, LOW);
myDigitalWrite(ledPinOFF, HIGH);
myDigitalWrite(ledPinON, LOW);
mask = 0;
lcd.setCursor(0, 3);
lcd.print("Finished");
digitalWrite (buzzer, HIGH);
delay(250);
lcd.setCursor(0, 3);
lcd.print(" ");
digitalWrite (buzzer, LOW);
delay(250);
lcd.setCursor(0, 3);
lcd.print("Finished");
digitalWrite (buzzer, HIGH);
delay(250);
lcd.setCursor(0, 3);
lcd.print(" ");
digitalWrite (buzzer, LOW);
delay(250);
lcd.setCursor(0, 3);
lcd.print("Finished");
digitalWrite (buzzer, HIGH);
delay(250);
lcd.setCursor(0, 3);
lcd.print(" ");
digitalWrite (buzzer, LOW);
delay(250);
lcd.setCursor(0, 3);
lcd.print("Finished");
digitalWrite (buzzer, HIGH);
delay(250);
lcd.setCursor(0, 3);
lcd.print(" ");
digitalWrite (buzzer, LOW);
delay(250);
lcd.setCursor(0, 3);
lcd.print("Finished");
digitalWrite (buzzer, HIGH);
delay(250);
lcd.setCursor(0, 3);
lcd.print(" ");
digitalWrite (buzzer, LOW);
delay(250);
lcd.setCursor(0, 3);
lcd.print("00:00:00");
if (ledState16 == HIGH) {
hours = EEPROM.read(1);
minutes = EEPROM.read(2);
seconds = EEPROM.read(3);
}
} else
seconds --;
if (seconds < 0) {
seconds = 59;
minutes --;
}
if (minutes < 0) {
minutes = 59;
hours --;
}
time1 = millis();
}
//Check which Push button pressed
if (digitalRead(encoderButton) == LOW and mask == 0)
{
HMS = HMS + 1;
if (HMS == 4)
/*
if (HMS == 5)
*/
{
HMS = 1;
}
delay(1000);
if (HMS == 1) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-1, 2);
lcd.print("Set hours");
}
else if (HMS == 2) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-1, 2);
lcd.print("Set minutes");
}
else if (HMS == 3) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-1, 2);
lcd.print("Set seconds");
}
/*
else if (HMS == 4) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-4, 2);
lcd.print("Timer Count Down");
}
*/
}
rotating = true; // reset the debouncer
encoderPos = constrain(encoderPos, -1, 1);
if (lastReportedPos != encoderPos) {
if (HMS == 1) {
if (encoderPos == 1)
hours++;
if (encoderPos == -1)
hours--;
if (hours > 59) hours = 0;
if (hours < 0) hours = 59;
lcd.setCursor(0, 3);
lcd.print(hours);
Serial.print ("hours");
Serial.println (hours);
} else if (HMS == 2) {
if (encoderPos == 1)
minutes++;
if (encoderPos == -1)
minutes--;
if (minutes > 59) minutes = 0;
if (minutes < 0) minutes = 59;
lcd.setCursor(3, 3);
lcd.print(minutes);
Serial.print ("minutes");
Serial.println (minutes);
} else if (HMS == 3) {
if (encoderPos == 1)
seconds++;
if (encoderPos == -1)
seconds--;
if (seconds > 59) seconds = 0;
if (seconds < 0) seconds = 59;
lcd.setCursor(6, 3);
lcd.print(seconds);
Serial.print ("seconds");
Serial.println (seconds);
}
lcd.setCursor(0, 3);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{;
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
if (ledState16 == HIGH) {
EEPROM.update(1, hours);
EEPROM.update(2, minutes);
EEPROM.update(3, seconds);
}
encoderPos = 0;
lastReportedPos = encoderPos;
}
if(digitalRead(Start) == LOW) {
while (digitalRead(Start) == LOW);
if (minutes > 0 or hours > 0 or seconds > 0) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-4, 2);
lcd.print("Timer Count Down");
lcd.setCursor(0, 3);
lcd.print(" ");
delay(500);
lcd.setCursor(2, 3);
lcd.print("Start");
delay(1000);
HMS = 0;
starting = 1;
mask = 1;
Serial.print("start");
Serial.println(Start);
Serial.print("mask");
Serial.println(mask);
digitalWrite(led,HIGH);
if (starting == 1 and mask == 1) {
myDigitalWrite (ledPinON, HIGH);
myDigitalWrite (ledPinOFF, LOW);
eravamoAccesi = HIGH;
toggle = 0;
pos = 0;
}
if (starting == 0) {
myDigitalWrite (ledPinOFF, HIGH);
myDigitalWrite (ledPinON, LOW);
eravamoAccesi = LOW;
}
}
}
lcd.setCursor(0, 3);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
if (buttonStatus1 == HIGH or buttonStatus2 == HIGH) {
mask = 0;
}
if (buttonStatus3 == HIGH) {
if (minutes > 0 or hours > 0 or seconds > 0) {
mask = 1;
}
}
if (digitalRead(Pause) == LOW) {
delay(100);
if (minutes > 0 or hours > 0 or seconds > 0) {
if (digitalRead(ledPinON) == HIGH) {
pause = 1;
mask = 0;
if (mask == 0) {
myDigitalWrite (ledPinOFF, HIGH);
myDigitalWrite (ledPinON, LOW);
eravamoAccesi = LOW;
}
if (pause == 1) {
lcd.setCursor(0, 3);
lcd.print(" ");
delay(10);
lcd.setCursor(2, 3);
lcd.print("Pause");
delay(1000);
lcd.setCursor(0, 3);
lcd.print(hours);
lcd.setCursor(2, 3);
lcd.print(':');
lcd.setCursor(3, 3);
lcd.print(minutes);
lcd.setCursor(5, 3);
lcd.print(':');
lcd.setCursor(6, 3);
lcd.print(seconds);
pause = 0;
}
}
}
}
if (digitalRead(Reset) == LOW) {
delay(100);
reset = 1;
mask = 0;
digitalWrite(led, LOW);
if (reset == 1) {
myDigitalWrite (ledPinOFF, HIGH);
myDigitalWrite (ledPinON, LOW);
eravamoAccesi = LOW;
if (minutes > 0 or hours > 0 or seconds > 0) {
minutes = 0;
hours = 0;
seconds = 0;
lcd.setCursor(0, 3);
lcd.print(" ");
delay(10);
lcd.setCursor(2, 3);
lcd.print("Reset");
delay(1000);
lcd.setCursor(0, 3);
lcd.print("00:00:00");
reset = 0;
if (ledState16 == HIGH) {
hours = EEPROM.read(1);
minutes = EEPROM.read(2);
seconds = EEPROM.read(3);
}
}
}
}
}
void doEncoderA() {
// debounce
if (rotating) delay(1); // wait a little until the bouncing is done
// Test transition, did things really change?
if (digitalRead(encoderPinA) != A_set) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if (A_set and !B_set)
encoderPos = -1;
rotating = false; // no more debouncing until loop() hits again
}
}
// Interrupt on B changing state
void doEncoderB() {
if (rotating) delay (1);
if (digitalRead(encoderPinB) != B_set) {
B_set = !B_set;
// adjust counter – 1 if B leads A
if (B_set and !A_set)
encoderPos = 1;
rotating = false;
}
}
Hai 10 delay(250); in fila, quindi 2 secondi e mezzo per eseguire tutto quel pezzo di codice.
Questo è ancora codice bloccante. Se inserisci questa logica dentro la mega, avrai comunque pause da 2,5s.
Per renderlo non bloccante devi eliminare tutti i delay, non solo quelli più lunghi.
Dividi quel codice in 10 pezzi ed eseguine uno in sequenza ogni 250ms cadenzando con millis.
La macchina a stati ti aiuta a capire a che punto dell'esecuzione sei arrivato.
Per questo caso potrebbe essere fatta con una variabile contatore che conta il passo da eseguire e lo incrementa una volta eseguito resettandosi quando arriva a 10.
il loop principale deve sempre girare alla velocità massima possibile e ad ogni giro eseguire al massimo un passo della tua macchina a stati rimandando tutto il resto al prossimo giro di loop.
Ok, in qualche caso per come viene strutturato il codice, potresti anche incastrare più di un passo, ma sono più coincidenze che altro. In generale assumi un passo per giro di loop.
Maurizio
grazie Maurizio della risposta, considera però il fatto che ho voluto strutturare il codice così, anche se ci sono tutti quei delay non importa perchè in quel frangente arduino non dovrà fare niente, il tutto gira bene l'unica cosa che non va è il lampeggio più o meno siginificativo degli zero, volevo solo sapere dove e come spostare questo spezzone di codice
lcd.setCursor(0, 3);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{;
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
ho modificato ulteriormente il codice togliendo un po di delay, ma il lampeggio degli zero è rimasta, non c'è proprio nessuno che può aiutarmi?
ecco il codice, è chiaro che non compilerà perchè ci sono delle variabili del listato completo
void loop() {
if ((unsigned long) millis() - time1 > 1000 and mask == 1) {
lcd.setCursor(0, 3);
lcd.print(hours);
lcd.setCursor(2, 3);
lcd.print(':');
lcd.setCursor(3, 3);
lcd.print(minutes);
lcd.setCursor(5, 3);
lcd.print(':');
lcd.setCursor(6, 3);
lcd.print(seconds);
if(minutes == 0 and hours == 0 and seconds == 0) { //When Timer Finish
digitalWrite(led, LOW);
myDigitalWrite(ledPinOFF, HIGH);
myDigitalWrite(ledPinON, LOW);
while(mask = 1) {
contatoreFineTempo++;
Serial.print("contatore");
Serial.println(contatoreFineTempo);
lcd.setCursor(0, 3);
lcd.print("Finished");
digitalWrite (buzzer, HIGH);
delay(250);
lcd.setCursor(0, 3);
lcd.print(" ");
digitalWrite (buzzer, LOW);
delay(250);
if (contatoreFineTempo >= 5) {
contatoreFineTempo = 0;
if (contatoreFineTempo == 0) {
mask = 0;
break;
}
}
}
lcd.setCursor(0, 3);
lcd.print("00:00:00");
if (ledState16 == HIGH) {
hours = EEPROM.read(1);
minutes = EEPROM.read(2);
seconds = EEPROM.read(3);
}
} else
seconds --;
if (seconds < 0) {
seconds = 59;
minutes --;
}
if (minutes < 0) {
minutes = 59;
hours --;
}
time1 = millis();
}
if (digitalRead(encoderButton) == LOW and mask == 0) {
while (digitalRead(encoderButton) == LOW);
HMS = HMS + 1;
if (HMS == 4)
/*
if (HMS == 5)
*/
{
HMS = 1;
}
delay(100);
if (HMS == 1) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-1, 2);
lcd.print("Set hours");
}
else if (HMS == 2) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-1, 2);
lcd.print("Set minutes");
}
else if (HMS == 3) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-1, 2);
lcd.print("Set seconds");
}
/*
else if (HMS == 4) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-4, 2);
lcd.print("Timer Count Down");
}
*/
}
rotating = true; // reset the debouncer
encoderPos = constrain(encoderPos, -1, 1);
if (lastReportedPos != encoderPos) {
if (HMS == 1) {
if (encoderPos == 1)
hours++;
if (encoderPos == -1)
hours--;
if (hours > 59) hours = 0;
if (hours < 0) hours = 59;
lcd.setCursor(0, 3);
lcd.print(hours);
Serial.print ("hours");
Serial.println (hours);
} else if (HMS == 2) {
if (encoderPos == 1)
minutes++;
if (encoderPos == -1)
minutes--;
if (minutes > 59) minutes = 0;
if (minutes < 0) minutes = 59;
lcd.setCursor(3, 3);
lcd.print(minutes);
Serial.print ("minutes");
Serial.println (minutes);
} else if (HMS == 3) {
if (encoderPos == 1)
seconds++;
if (encoderPos == -1)
seconds--;
if (seconds > 59) seconds = 0;
if (seconds < 0) seconds = 59;
lcd.setCursor(6, 3);
lcd.print(seconds);
Serial.print ("seconds");
Serial.println (seconds);
}
lcd.setCursor(0, 3);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{;
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
if (ledState16 == HIGH) {
EEPROM.update(1, hours);
EEPROM.update(2, minutes);
EEPROM.update(3, seconds);
}
encoderPos = 0;
lastReportedPos = encoderPos;
}
if(digitalRead(Start) == LOW) {
while (digitalRead(Start) == LOW);
if (minutes > 0 or hours > 0 or seconds > 0) {
lcd.setCursor(-4, 2);
lcd.print(" ");
lcd.setCursor(-4, 2);
lcd.print("Timer Count Down");
lcd.setCursor(0, 3);
lcd.print(" ");
delay(500);
lcd.setCursor(2, 3);
lcd.print("Start");
delay(1000);
HMS = 0;
starting = 1;
mask = 1;
Serial.print("start");
Serial.println(Start);
Serial.print("mask");
Serial.println(mask);
digitalWrite(led,HIGH);
if (starting == 1 and mask == 1) {
myDigitalWrite (ledPinON, HIGH);
myDigitalWrite (ledPinOFF, LOW);
eravamoAccesi = HIGH;
toggle = 0;
pos = 0;
}
if (starting == 0) {
myDigitalWrite (ledPinOFF, HIGH);
myDigitalWrite (ledPinON, LOW);
eravamoAccesi = LOW;
}
}
}
lcd.setCursor(0, 3);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
if (buttonStatus1 == HIGH or buttonStatus2 == HIGH) {
mask = 0;
}
if (buttonStatus3 == HIGH) {
if (minutes > 0 or hours > 0 or seconds > 0) {
mask = 1;
}
}
if (digitalRead(Pause) == LOW) {
delay(100);
if (minutes > 0 or hours > 0 or seconds > 0) {
if (digitalRead(ledPinON) == HIGH) {
pause = 1;
mask = 0;
if (mask == 0) {
myDigitalWrite (ledPinOFF, HIGH);
myDigitalWrite (ledPinON, LOW);
eravamoAccesi = LOW;
}
if (pause == 1) {
lcd.setCursor(0, 3);
lcd.print(" ");
delay(10);
lcd.setCursor(2, 3);
lcd.print("Pause");
delay(1000);
lcd.setCursor(0, 3);
lcd.print(hours);
lcd.setCursor(2, 3);
lcd.print(':');
lcd.setCursor(3, 3);
lcd.print(minutes);
lcd.setCursor(5, 3);
lcd.print(':');
lcd.setCursor(6, 3);
lcd.print(seconds);
pause = 0;
}
}
}
}
if (digitalRead(Reset) == LOW) {
delay(100);
reset = 1;
mask = 0;
digitalWrite(led, LOW);
if (reset == 1) {
myDigitalWrite (ledPinOFF, HIGH);
myDigitalWrite (ledPinON, LOW);
eravamoAccesi = LOW;
if (minutes > 0 or hours > 0 or seconds > 0) {
minutes = 0;
hours = 0;
seconds = 0;
lcd.setCursor(0, 3);
lcd.print(" ");
delay(10);
lcd.setCursor(2, 3);
lcd.print("Reset");
delay(1000);
lcd.setCursor(0, 3);
lcd.print("00:00:00");
reset = 0;
if (ledState16 == HIGH) {
hours = EEPROM.read(1);
minutes = EEPROM.read(2);
seconds = EEPROM.read(3);
}
}
}
}
}
}
void doEncoderA() {
if (rotating) delay(1);
if (digitalRead(encoderPinA) != A_set) {
A_set = !A_set;
if (A_set and !B_set)
encoderPos = -1;
rotating = false;
}
}
void doEncoderB() {
if (rotating) delay (1);
if (digitalRead(encoderPinB) != B_set) {
B_set = !B_set;
if (B_set and !A_set)
encoderPos = 1;
rotating = false;
}
}
Si chiamano side effects, quando due (o più) parti diverse del programma nello stesso ciclo di elaborazione vanno a toccare le stesse risorse (variabili, periferiche, altro) interferendo tra loro.
Nel caso in questione ad ogni ciclo scrivi sempre e comunque il display, ma una volta al secondo lo vai anche a scrivere prima in modo diverso. Queste due scritture diverse nello stesso ciclo appaiono come flickering degli zeri.
In un programma progettato correttamente come macchina a stati espliciti queste interferenze non ci sarebbero, perché ad ogni ciclo sarebbero effettuate solo ed esclusivamente le operazioni riguardanti lo stato corrente.