Switch di animazioni dot matrix con pin 2

Ciao a tutti, sto lavorando su un progetto che usa un display dot matrix 8x8 controllate dal solito MAX7219, e ho 2 animazioni da fare visualizzare su questo display in maniera alternata all'attivarsi di una lampadina, sullo sketch che comandi devo usare per switchare da un animazione all'altra supponendo di far attivare il pin 2 digitale (all'accendersi della lampadina)?

Buongiorno,
essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il su citato REGOLAMENTO ... Grazie. :slight_smile:

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. :wink:

presentazione eseguita :relaxed:

devi monitorare una lampadina e in base a questa modificare il display?

devo far si che quando si accende la lampadina l'animazione cambi

paolinux78:
Ciao a tutti, sto lavorando su un progetto che usa un display dot matrix 8x8 controllate dal solito MAX7219, e ho 2 animazioni da fare visualizzare su questo display in maniera alternata all'attivarsi di una lampadina, sullo sketch che comandi devo usare per switchare da un animazione all'altra supponendo di far attivare il pin 2 digitale (all'accendersi della lampadina)?

Mi pare chiaro che o inizi a scrivere tu qualcosa, almeno per gestire le due animazioni anche se per ora solo sequenzialmente, e lo posti qui, oppure diventa difficile aiutarti senza partire da un TUO programmino di prova, seppure parzialmente funzionante...

docdoc:
Mi pare chiaro che o inizi a scrivere tu qualcosa, almeno per gestire le due animazioni anche se per ora solo sequenzialmente, e lo posti qui, oppure diventa difficile aiutarti senza partire da un TUO programmino di prova, seppure parzialmente funzionante...

certo! vi allego lo sketch che ho preparato in cui funzionano le 2 animazioni, la prima "animation" è quella che funziona di default, mentre "lock" è quella che si attiverà quando si accende la lampadina:

#include <LedControl.h>
int DIN = 10;
int CS =  9;
int CLK = 8;

LedControl lc=LedControl(DIN,CLK,CS,0);

void setup(){
lc.shutdown(0,false);       
lc.setIntensity(0,1);      //Adjust the brightness maximum is 1
lc.clearDisplay(0);    
}

void loop(){ 
   

   //animation
   byte r1[8]= {0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3};
   byte r2[8]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
   byte r3[8]= {0x00,0xC3,0xC3,0x00,0x00,0xC3,0xC3,0x00};
  
 
   
   //lock
   byte b1[8]= {0x60,0x60,0x60,0x60,0x60,0x60,0x7C,0x7C};
   byte b2[8]= {0x3C,0x7E,0x66,0x66,0x66,0x66,0x7E,0x3C};
   byte b3[8]= {0x3C,0x7E,0x60,0x60,0x60,0x60,0x7E,0x3C};
   byte b4[8]= {0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66};
   byte b5[8]= {0x88,0x94,0x94,0xC8,0x35,0x46,0x46,0x35};
  

//animation
   printByte(r2);
   delay(50);
   printByte(r3);
   delay(50);
   printByte(r2);
   delay(50);
   printByte(r3);
   delay(50);
   printByte(r2);
   delay(50);
   printByte(r3);
   delay(50);
   printByte(r2);
   delay(50);
   printByte(r3);
   delay(50);
   printByte(r2);
   delay(50);
   

//lock
   printByte(b1);
   delay(1000);
   printByte(b2);
   delay(1000);
   printByte(b3);
   delay(1000);
   printByte(b4);
   delay(1000);
   printByte(b5);
   delay(3000);
   
  

}

void printByte(byte character [])
{
 int i = 0;
 for(i=0;i<8;i++)
 {
   lc.setRow(0,i,character[i]);
 }
}

Allora, vedi questo codice, ricavato dal tuo, al quale ho fatto alcune modifiche, prova a descrivermi cosa ho fatto (così se non comprendi qualcosa proviamo a spiegartelo), e poi anche come funziona (non ho quel display quindi non l'ho provato, fai anche una prova e dimmi l'esito).

#include <LedControl.h>

// Definizione dei pin
#define DIN 10
#define CS 9
#define CLK 8
// Pin di ingresso del sensore lampadina (da simulare con un pulsante)
#define LAMP 7

// Definisce quale animazione mostrare
#define ANIM 0
@define LOCK 1
// Animazione iniziale è 0 ANIM
int mostra = ANIM;

//animation
const byte r1[8]= {0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3};
const byte r2[8]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const byte r3[8]= {0x00,0xC3,0xC3,0x00,0x00,0xC3,0xC3,0x00};

//lock
const byte b1[8]= {0x60,0x60,0x60,0x60,0x60,0x60,0x7C,0x7C};
const byte b2[8]= {0x3C,0x7E,0x66,0x66,0x66,0x66,0x7E,0x3C};
const byte b3[8]= {0x3C,0x7E,0x60,0x60,0x60,0x60,0x7E,0x3C};
const byte b4[8]= {0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66};
const byte b5[8]= {0x88,0x94,0x94,0xC8,0x35,0x46,0x46,0x35};

LedControl lc=LedControl(DIN,CLK,CS,0);

void setup()
{
  pinMode(LAMP,INPUT);
  lc.shutdown(0,false);       
  lc.setIntensity(0,1);      //Adjust the brightness maximum is 1
  lc.clearDisplay(0);    
}

void loop()
{
  if ( digitalRead(LAMP) == HIGH )
    mostra = LOCK;
  else
    mostra = ANIM;

  switch (mostra)
  {
    case ANIM:
      //animation
      printByte(r2);
      delay(50);
      printByte(r3);
      delay(50);
      printByte(r2);
      delay(50);
      printByte(r3);
      delay(50);
      printByte(r2);
      delay(50);
      printByte(r3);
      delay(50);
      printByte(r2);
      delay(50);
      printByte(r3);
      delay(50);
      printByte(r2);
      delay(50);
      break;

    case LOCK:
      printByte(b1);
      delay(1000);
      printByte(b2);
      delay(1000);
      printByte(b3);
      delay(1000);
      printByte(b4);
      delay(1000);
      printByte(b5);
      delay(3000);
      break;
  }
}

void printByte(byte character [])
{
 int i = 0;
 for(i=0;i<8;i++)
 {
   lc.setRow(0,i,character[i]);
 }
}

Chiaramente ci sono ancora alcune cosette che si possono modificare per renderlo migliore e più generico, ma per ora non voglio stravolgerti eccessivamente con troppi cambiamenti.

grazie docdoc per la risposta e per il codice, allora ho provato (avevo trovato un tuo errore #define ANIM 0
@define LOCK 1, avevi messo la chiocciola al posto del cancelletto) funziona bene, l'unica cosa con l'interruttore inserito mi da come animazione iniziale "LOCK" mentre se estraggo dal pin 7 l'interruttore parte la corretta animazione "ANIM", per il resto se tengo premuto l'interruttore lo switch di animazioni si attiva correttamente (ho notato stranamente che ogni tot cicli di animazione in loop di "LOCK" viene visualizzata per una volta l'animazione "ANIM"). Da quello che ho capito inserendo il comando "if ( digitalRead(LAMP) == HIGH )
mostra = LOCK;" si dice al display che quando viene attivato un interruttore di mostrare l'animazione lock, mentre quando si da il comando "else mostra = ANIM;" si attiva l'animazione "ANIM", sono sulla buona strada? PS: ho ora provato invece che con un interruttore, mandando dentro i 5v funziona correttamente

paolinux78:
avevo trovato un tuo errore #define ANIM 0
@define LOCK 1, avevi messo la chiocciola al posto del cancelletto

Ah vero, i tasti @ e # sono vicini e mi è sfuggito :wink:

Da quello che ho capito inserendo il comando "if ( digitalRead(LAMP) == HIGH )
mostra = LOCK;"
si dice al display che quando viene attivato un interruttore di mostrare l'animazione lock, mentre quando si da il comando "else mostra = ANIM;" si attiva l'animazione "ANIM", sono sulla buona strada?

Si :slight_smile: In pratica quella "if" dice "se il pin LAMP è HIGH allora imposta la visualizzazione LOCK, altrimenti mostra ANIM".

con l'interruttore inserito mi da come animazione iniziale "LOCK" mentre se estraggo dal pin 7 l'interruttore parte la corretta animazione "ANIM"

Dipende da come hai collegato l'interruttore, ossia se l'interruttore è da considerare attivo quando il pin è alto o basso.
Se stai simulando con un pulsante, come lo hai collegato? Se hai messo una resistenza "pull-down" (una resistenza da 10k tra il pin e massa) allora deve funzionare il codice che ti ho mandato, se invece hai messo una resistenza di "pull-up" (resistenza tra il pin e +5V) allora dato che se non lo premi leggerai HIGH e quando lo premi è LOW, devi invertire la logica ossia il confronto del valore:

if ( digitalRead(LAMP) == HIGH )

diventa:

if ( digitalRead(LAMP) == LOW )

Se non hai messo alcuna resistenza, fallo perché altrimenti quando non premi nulla il pin è "fluttuante" e non puoi avere certezza di cosa leggerai. Inoltre questa "simulazione" ovviamente soffre di due problemi:

  1. il "rimbalzo" del pulsante potrebbe non farti leggere correttamente lo stato (cerca "debounce" in questo forum o su Google...), ma riguarda solo i pulsanti fisici, per quello "vero" è possibile che non ti serva
  2. La lettura del pulsante avviene solamente tra un ciclo di animazione e l'altro, quindi ogni 4 decimi di secondo per ANIM, e ci potrebbe forse anche stare, e ben 7 secondi per LOCK!

Per il "vero" sensore (ma come lo stai pensando?) quindi il punto 1 potrebbe non essere influente, ma devi per prima cosa capire (o definire) se avrai un valore LOW quando la lampadina è spenta e HIGH quando è accesa, o viceversa, ed adeguare di conseguenza il codice.
La questione del punto 2 ad esempio implica che se al loop() il segnale non risulta inizialmente attivo inizia la sequenza ANIM, ma se il segnale dura meno di 4 decimi di secondo, non si attiverà mai LOCK ossia per quei 4 decimi di secondo il programma sarà "sordo" a cambiamenti di stato.
Così come se il segnale è attivo, e quindi parte LOCK, ed il segnale si disattiva subito, Arduino se ne accorgerà solo dopo 7 secondi.

Non so se sia quindi accettabile per te, tutto dipende da quale tipo di segnale ricevi, la sua durata, e se l'animazione debba interrompersi non appena rilevato il cambiamento (cose che però ti cambiano abbastanza la logica del programma, che non deve più lavorare con delay ma andare con temporizzazioni ossia la funzione "millis()").

Docdoc devo dire che ci hai azzeccato in pieno, ho risolto il problema di ritardo dell’animazione variando il codice e inserendo i millis al posto dei delay; ora però mi si pone un altro problema, ho scoperto che la lampadina è lampeggiante e col multimetro ho valori altalenanti di voltaggio, come faccio a stabilizzare il valore per farlo leggere correttamente al pin?

Dipende... Che frequenza ha il lampeggiamento? E comunque posta il nuovo codice così vediamo l'implementazione e magari si riesce a trovare un escamotage (es. se il lampeggiamento è di 2 al secondo, potresti attendere almeno 1 secondo prima di verificare nuovamente lo stato del pin per essere (quasi) sicuro di aver identificato quando cessa il lampeggiamento.

ho fatto un video per capire quante volte la lampada lampeggiava, risultato circa 6 volte al secondo.
Ecco il code, l'ho un po stravolto per le varie modifiche che ho fatto ma a parte la rilevazione per colpa della lampada lampeggiante funzia perfettamente, cosa suggerisci per far rilevare la lampadina lampeggiante?

#include <LedControl.h>
int DIN = 10;
int CS =  9;
int CLK = 8;

    
    //Frecce
    byte sing[8]=   {0x41,0x22,0x14,0x08,0x00,0x00,0x00,0x00};
    byte doppia[8]= {0x41,0x22,0x14,0x08,0x41,0x22,0x14,0x08};
    byte vuoto[8]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
   

    //animation
    byte r1[8]= {0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3};
    byte r2[8]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    byte r3[8]= {0x00,0xC3,0xC3,0x00,0x00,0xC3,0xC3,0x00};
   
  
    
    //lock
    byte b1[8]= {0x60,0x60,0x60,0x60,0x60,0x60,0x7C,0x7C};
    byte b2[8]= {0x3C,0x7E,0x66,0x66,0x66,0x66,0x7E,0x3C};
    byte b3[8]= {0x3C,0x7E,0x60,0x60,0x60,0x60,0x7E,0x3C};
    byte b4[8]= {0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66};
    byte b5[8]= {0x88,0x94,0x94,0xC8,0x35,0x46,0x46,0x35};
   

int statoPin = 0; //La variabile di lettura del pin collegato alla lampada
int vecchioStatoPin =0; // Memorizza il stato prima del cambio
int lampada = 2; //Pin dove è collegata la lampada
int passo = 1; //Tiene conto cosa deve fare
int ripeti = 1; //Tiene conto quante volte ripetere la serie

unsigned long tempoLetto = 0; //Variabile che tiene in memoria il tempo letto da millis();

LedControl lc=LedControl(DIN,CLK,CS,0);



void printByte(byte character [])
{
  int i = 0;
  for(i=0;i<8;i++)
  {
    lc.setRow(0,i,character[i]);
  }
}

void setup(){
 lc.shutdown(0,false);       
 lc.setIntensity(0,1);      //Adjust the brightness maximum is 1
 lc.clearDisplay(0);
 pinMode(lampada, INPUT); //Assegno lo stato del pin della lampada
}

void loop(){

  statoPin = digitalRead(lampada);
  if (statoPin != vecchioStatoPin)
  {
    passo = 1;
    ripeti = 1;
    vecchioStatoPin = statoPin;
  }

  if (statoPin == HIGH)
  {
    switch(passo)
    {
      case 1:
        //lock
        printByte(b1);
        if (millis() - tempoLetto >= 1000)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 2:
        //lock
        printByte(b2);
        if (millis() - tempoLetto >= 1000)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
       case 3:
        //lock
        printByte(b3);
        if (millis() - tempoLetto >= 1000)
          {
            passo++;
            tempoLetto = millis();
          }
      case 4:
        //lock
        printByte(b4);
        if (millis() - tempoLetto >= 1000)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 5:
        //lock
        printByte(b5);
        if (millis() - tempoLetto >= 3000)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 6:
        //lock
        printByte(sing);
        if (millis() - tempoLetto >= 1300)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 7:
        //lock
        printByte(doppia);
        if (millis() - tempoLetto >= 1300)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 8:
        //lock
        printByte(vuoto);
        if (millis() - tempoLetto >= 100)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 9:
        //lock
        printByte(doppia);
        if (millis() - tempoLetto >= 80)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
       case 10:
        printByte(vuoto);
        if (millis() - tempoLetto >= 80)
          {
            if (ripeti < 6)
            {
              passo = 9;
              ripeti++;
            }
            else
            {
              passo++;
              ripeti = 1;
            }
            tempoLetto = millis();
          }
        break;
      case 11:
        //lock
        printByte(doppia);
        if (millis() - tempoLetto >= 1300)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 12:
        //lock
        printByte(vuoto);
        if (millis() - tempoLetto >= 1000)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 13:
        //lock
        printByte(sing);
        if (millis() - tempoLetto >= 1300)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 14:
        //lock
        printByte(doppia);
        if (millis() - tempoLetto >= 1300)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 15:
        //lock
        printByte(vuoto);
        if (millis() - tempoLetto >= 100)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 16:
        //lock
        printByte(doppia);
        if (millis() - tempoLetto >= 80)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
       case 17:
        printByte(vuoto);
        if (millis() - tempoLetto >= 80)
          {
            if (ripeti < 6)
            {
              passo = 16;
              ripeti++;
            }
            else
            {
              passo++;
              ripeti = 1;
            }
            tempoLetto = millis();
          }
        break;
      case 18:
        //lock
        printByte(doppia);
        if (millis() - tempoLetto >= 1300)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 19:
        //lock
        printByte(vuoto);
        if (millis() - tempoLetto >= 1000)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 20:
        //lock
        printByte(sing);
        if (millis() - tempoLetto >= 1300)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 21:
        //lock
        printByte(doppia);
        if (millis() - tempoLetto >= 1300)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 22:
        //lock
        printByte(vuoto);
        if (millis() - tempoLetto >= 100)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 23:
        //lock
        printByte(doppia);
        if (millis() - tempoLetto >= 80)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
       case 24:
        printByte(vuoto);
        if (millis() - tempoLetto >= 80)
          {
            if (ripeti < 4)
            {
              passo = 23;
              ripeti++;
            }
            else
            {
              passo++;
              ripeti = 1;
            }
            tempoLetto = millis();
          }
        break;
      case 25:
        //lock
        printByte(doppia);
        if (millis() - tempoLetto >= 1300)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 26:
        //lock
        printByte(vuoto);
        if (millis() - tempoLetto >= 1000)
          {
            passo = 1;
            tempoLetto = millis();
          }
        break;
    }
  }
  else
  {
    switch(passo)
    {
      case 1:
        printByte(r2);
        if (millis() - tempoLetto >= 50)
          {
            passo++;
            tempoLetto = millis();
          }
        break;
      case 2:
        printByte(r3);
        if (millis() - tempoLetto >= 50)
          {
            if (ripeti < 11)
            {
              passo = 1;
              ripeti++;
            }
            else
            {
              passo++;
              ripeti = 1;
            }
            tempoLetto = millis();
          }
        break;
      case 3:
        printByte(r1);
        if (millis() - tempoLetto >= 3000)
          {
            passo = 1;
            tempoLetto = millis();
          }
        break;
    }
    
  }
}

Prova questo codice (te l'ho scritto "al volo" non l'ho provato né compilato, ma puoi provare a verificare ed eventualmente partire da questo), per capire le modifiche cerca il testo "BLINK".
(l'ho messo come allegato perché è troppo lungo per il forum)

Ovviamente se hai domande, dopo che lo avrai provato, sono qui.

PS: poi appena ti funziona ti faccio vedere come potresti ottimizzare quella sfilza di switch case....

Animazione.ino (8.76 KB)

Eccomi scusate il ritardo, docdoc mi sono accorto che non posso prendere l'impulso di cambiamento direttamente dalla lampada (come invece credevo) e allora lo farò con un fotoresistore, ho sviluppato il codice che funziona perfettamente con la lampada che resta fissa, chiedo il tuo aiuto per aggiungere il codice che attiverà lo switch delle 2 animazioni con la lampada lampeggiante, ho modificato il codice per farlo funzionare su attiny85 e ho programmato il pin 3 come pin analogico, ecco il codice:

fotoresistenza.ino (9.77 KB)

Se la risposta della fotoresistenza è sufficientemente rapida puoi anche usare il codice che ti avevo postato (a meno delle modifiche per l'Attiny e per un input analogico).

Ma temo che la fotoresistenza non sia proprio adatta a rilevare questi circa 6 Hz, comunque sia dovresti anche dirci come l'hai collegata (uno schemino) e poi dovresti provare semplicemente a fare un piccolo sketch che non faccia altro che riportare su seriale il valore letto dal pin analogico e tracciare quindi un grafico sul monitor seriale.