Go Down

Topic: Costruzione Orologio a led da parete - guida per dummies (Read 66584 times) previous topic - next topic

Etemenanki

Non ho ancora guardato il codice (sai che sono un "meccanico", non un programmatore :D) ... gli daro' un'occhiata stasera ... ma cosi ad occhio, direi che il modo piu semplice sia fare delle funzioni che visualizzano le varie cose (esempio, una per l'ora, una per la data, e cosi via), e poi nel loop richiamarle con degli if temporizzati ed una flag ... tipo, molto grossolanamente:

nel setup, fra le altre cose, imposto la flag al valore iniziale 0 ... e la variabile del tempo precedente a millis() ...

se nel loop premo qualche pulsante per impostare data/ora/ecc, metto la flag (ad esempio) al valore 9 ... poi ...

se la flag e' a 0 e non sono ancora trascorsi 30 secondi, chiamo la funzione ore ... quando i 30 secondi sono trascorsi, metto la flag a 1 e resetto la variabile del tempo precedente a millis() ...

se la flag e' ad 1 e non sono ancora trascorsi 5 secondi, chiamo la funzione data, quando i 5 secondi sono trascorsi, metto la flag a 2 e resetto la variabile del tempo precedente a millis() ...

se la flag e' a 2 e non sono ancora trascorsi i 5 secondi, chiamo la funzione temperatura, se i 5 secondi sono trascorsi metto la flag a 0  e resetto la variabile del tempo precedente a millis() ... (solo se si vuole anche la temperatura) ...

se la flag vale 9 (vuol dire che ho premuto qualche pulsante per fare delle variazioni), chiamo la funzione imposta data/ora/ecc ... in questa funzione rimetto la flag a 0 solo quando ho finito e ne esco ...

... e cosi via ... in questo modo hai una struttura relativamente flessibile, dove per fare qualche altra modifica, bastera' aggiungere (o modificare) una o piu funzioni, ed inserire le relative chiamate se le avrai aggiunte, senza stravolgere l'intero sketch ...
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

ghezzia

Questo è il codice usato e funzionante:
Code: [Select]


#include <Wire.h>
#define CLOCK_PIN 2
#define LATCH_PIN 3
#define DATA_PIN  4
#define MIN_PULS  5
#define HOUR_PULS 6
//-----------------------------------------------------------------------------
// Variabili di lavoro globali (28 byte)
//-----------------------------------------------------------------------------
typedef struct {
    uint32_t time;
    byte     stat;
} button_t;

button_t minPulsData = {millis(), 0};   // dati pulsante minuti
button_t hourPulsData = {millis(), 0};  // dati pulsante ora
uint32_t tempoPunti = millis();         // tempi di partenza
byte     point = 1;                     // variabile per lampeggio punti
byte     error = false;                 // true se errore lettura RTC
byte     minuti = 0;                    // minuti correnti
byte     ore = 0;                       // ore correnti
byte     tabella[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66,
                        0xB6, 0xBE, 0xE0, 0xFE, 0xF6};
//-----------------------------------------------------------------------------
// Rileva click su tasti con debounch 60 ms e autorepeat dopo 1 s
//-----------------------------------------------------------------------------
bool click(byte pin, ::button_t* data){
    uint32_t elapsed = millis() - data->time;
    bool press = digitalRead(pin);
    switch (data->stat)
    {
        case 0:                             // attesa pressione
            if (press){                     // se premuto
                data->stat = 1;             // passa ad antirimbalzo
                data->time = millis();
            }
            return false;


        case 1:                             // antirimbalzo pressione
            if (!press){                    // se non premuto
                data->stat = 0;             // ritorna ad attesa
                return false;
            }
            if (elapsed > 60){              // primo click
                data->stat = 2;
                data->time = millis();
                return true;
            }
            return false;


        case 2:                             // attesa inizio autorepeat
            if (!press){                    // se non premuto
                data->stat = 3;
                data->time = millis();
                return false;
            }
            if (elapsed > 1000){            // inizio autorepeat dopo 1 s
                data->stat = 4;
                data->time = millis();
                return true;                // primo autoclick
            }
            return false;


        case 3:                             // antirimbalzo rilascio
            if (press){                     // se premuto
                data->stat = 2;
                data->time = millis();
                return false;
            }
            if (elapsed > 60)               // rilasciato
                data->stat = 0;             // torna ad attesa
            return false;


        case 4:                             // autorepeat
            if (!press){                    // se non premuto
                data->stat = 5;
                data->time = millis();
                return false;
            }
            if (elapsed > 100){             // successivi click ogni 100 ms
                data->time = millis();
                return true;
            }
            return false;


        case 5:                             // antirimbalzo rilascio
            if (press){                     // se premuto
                data->stat = 4;
                data->time = millis();
                return false;
            }
            if (elapsed >= 60)              // rilasciato
                data->stat = 0;             // torna ad attesa
            return false;
    }
}

//-----------------------------------------------------------------------------
byte binBCD(byte n){
    return ((n / 10) << 4) | (n % 10);
}
//-----------------------------------------------------------------------------
void impostaRTC(){
    Wire.beginTransmission(0x68);   // <--- indirizzo RTC su bus i2c
    Wire.write(0);                  // <--- punta al registro 0
    Wire.write(0);                  // <--- azzera secondi RTC
    Wire.write(binBCD(minuti));     // <--- imposta minuti RTC
    Wire.write(binBCD(ore));        // <--- imposta ore RTC
    Wire.endTransmission();
}
//-----------------------------------------------------------------------------
void avanzaOra(){
    ore = (ore + 1) % 24;
}
//-----------------------------------------------------------------------------
void avanzaMinuto(){
    if (++minuti == 60){
        minuti = 0;
        avanzaOra();
    }
}
//-----------------------------------------------------------------------------
void blinkPunti(){
    if (millis() - tempoPunti >= 500){
        tempoPunti += 500;
        point ^= 1;
    }
}
//-----------------------------------------------------------------------------
byte BCDbin(byte n){
    return ((n >> 4) * 10) + (n & 0x0F);
}
//-----------------------------------------------------------------------------
void leggiRTC(){
    Wire.beginTransmission(0x68);   // <--- indirizzo RTC su bus i2c
    Wire.write(1);                  // <--- punta al registro 1
    if (Wire.endTransmission()){    // <--- errore di connessione
        error = true;
        return;
    }
    Wire.requestFrom(0x68, 2);      // <--- due registri da leggere
    if (Wire.available() != 2){
        error = true;               // <--- errore di ricezione
        return;
    }
    minuti = BCDbin(Wire.read());
    ore = BCDbin(Wire.read());
    error = false;
}
//-----------------------------------------------------------------------------
// Scrittura su display con blanking primo zero e lampeggio se errore
//-----------------------------------------------------------------------------
void visualizza(){
    digitalWrite(LATCH_PIN, LOW);
    if (error && !point){
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, 0);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, 0);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, 0);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, 0);
    }else{
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, tabella[minuti%10]);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, tabella[minuti/10]);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, tabella[ore%10]|point);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, (ore/10) ? tabella[ore/10] : 0);
    }
    digitalWrite(LATCH_PIN, HIGH);
}
//-----------------------------------------------------------------------------
// Impostazione sistema
//-----------------------------------------------------------------------------
void setup(){
    Wire.begin();                   // inizializza bus i2c
    pinMode(MIN_PULS,  INPUT);
    pinMode(HOUR_PULS, INPUT);
    pinMode(LATCH_PIN, OUTPUT);
    pinMode(CLOCK_PIN, OUTPUT);
    pinMode(DATA_PIN,  OUTPUT);
    digitalWrite(CLOCK_PIN, LOW);
    visualizza();                   // prima scrittura su display
}
//-----------------------------------------------------------------------------
// Ciclo principale eseguito circa 800 volte al secondo
//-----------------------------------------------------------------------------
void loop(){
    leggiRTC();                     // lettura ora corrente da RTC
    blinkPunti();                   // lampeggio punti 1 Hz

    if (click(MIN_PULS, &minPulsData)){     // se premuto puls.minuti
        avanzaMinuto();                     // regola minuti
        impostaRTC();
    }

    if (click(HOUR_PULS, &hourPulsData)){   // se premuto puls.ore
        avanzaOra();                        // regola ora
        impostaRTC();
    }

    visualizza();                   // aggiorna display
}

dove e come posso inserire i tuoi suggerimenti?

ricki158

Intanto devi fare in modo che la funzione visualizza() sia indipendente dalle variabili minuti e ore. Cioè quando tu chiami la funzione visualizza è per mettere 4 cifre su un display, non per mettere minuti e ore. In questo modo generalizzi la funzione. In questo modo puoi fare in modo di chiamare sempre la stessa funzione ma che ha come argomenti le variabili che ti interessa "stampare" sul display.

Etemenanki

Oppure, in alternativa, fare una diversa funzione di visualizzazione per ogni condizione (una che visualizza ore e minuti, una che visualizza la data, eccetera), e poi richiamarle quando servono ... ;)
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

Go Up