Matrice per gestire display sette segmenti

Ciao a tutti, avrei bisogno di aiuto. Come da titolo vorrei accendere in sequenza i numeri da 0 a 9 di un display a sette segmenti, utilizzando un matrice formata da 10 colonne (i num. da 0-9) e 7 righe ( pin necessari per il display).
Nella parte Setup tramite un ciclo for imposto i pin come OUTPUT.
Nella parte Loop uso due variabili c (colonna) e r (riga)con du cicli for per muovermi nella matrice, e un terzo ciclo for per settare l'uscita dei 7 pin.
Il risultato è che cosi facendo quando carico lo sketch, si accendono tutti i 7 segmenti in sequenza e si spengono in sequenza in un loop infinito.
Sperando di essere stato chiaro allego anche lo sketch.

byte numSegmenti[10][7]={
                        {1,1,1,1,1,1,0},    //0
                        {0,1,1,0,0,0,0},    //1
                        {1,1,0,1,1,0,1},    //2
                        {1,1,1,1,0,0,1},    //3
                        {0,1,1,0,0,1,1},    //4
                        {1,0,1,1,0,1,1},    //5
                        {1,0,1,1,1,1,1},    //6
                        {1,1,1,0,0,0,0},    //7
                        {1,1,1,1,1,1,1},    //8
                        {1,1,1,1,0,1,1}     //9
                        }; 
const int indicePin=7;
byte pinSegmenti[indicePin]={2,3,4,5,6,7,8};
int cont=0;
void setup() {
  for(cont=0;cont<indicePin;cont++){
   pinMode(pinSegmenti[indicePin],OUTPUT); 
  }
}

void loop() {
  int c=0;
  int r=0;
  for(c=0;c<10;c++){
   for(r=0;r<7;r++){
    for(cont=0;cont<indicePin;cont++){
      digitalWrite(pinSegmenti[cont],numSegmenti[c][r]);
      delay(200);
    }
    }
  }
}

Ringrazio tutti per le risposte\suggerimenti

Non sono sicuro di aver capito.
Mi pare però che se hai 7 pin e nella matrice 7 numeri, hai un solo contatore, inutile avere 3 contatori, r e cont corrispondono

prova ad eliminare il ciclo for di r e al posto di r nella digitalWrite() metti cont

io ho 7 pin(da pin2 a pin8 ) per i segmenti (a,b,c,d,e,f,g) e devo scrivere 10 numeri (da 0 a 9)

byte numSegmenti[10][7]={
                        {1,1,1,1,1,1,0},    //0
                        {0,1,1,0,0,0,0},    //1
                        {1,1,0,1,1,0,1},    //2
                        {1,1,1,1,0,0,1},    //3
                        {0,1,1,0,0,1,1},    //4
                        {1,0,1,1,0,1,1},    //5
                        {1,0,1,1,1,1,1},    //6
                        {1,1,1,0,0,0,0},    //7
                        {1,1,1,1,1,1,1},    //8
                        {1,1,1,1,0,1,1}     //9
                        };

Lasciando stare quello che ho fatto io nel ciclo Loop, vorrei scrivere in sequenza i numeri (da 0 a 9) , ma non riesco a capire come impostare i pin per fare in modo che , ad esempio, per fare lo 0 devono accendersi in questa sequenza

pin2 pin3 pin4 pin5 pin5 pin7 pin8
1 1 1 1 1 1 0 =numero 0

E cosi via per tutti gli altri numeri.
Forse cosi mi sono spiegato meglio

nid69ita, grazie ho risolto.

Queste cose vengono bene con il Port Manipulation, che è la soluzione concettualmente esatta, poiché tutte le uscite della porta vengono scritte insieme. Scrivere un'uscita per volta è un artificio dell'ambiente di Arduino per semplificare l'attivazione di una singola uscita. Con il PORT, quindi, devi solo scrivere un valore binario per ogni cifra da visualizzare:

//                  abcdefg
byte segmenti[0]=0b00000000;
byte segmenti[1]=0b00110000;
// byte segmenti[2]=...
// ...

void setup()
{
DDRD=0x11111111; // Porta D: tutte uscite.
}

void loop()
{
for (byte i=0; i<10; i++)
  {
  PORTD=segmenti[i]; // Porta D: visualizza in sequenza da 0 a 9.
  delay(200);
  }
}

L'unica limitazione è il fatto che devi indirizzare direttamente i pin, quindi non puoi assegnarli e riassegnarli arbitrariamente, ma, si sa, la portabilità e la generalizzazione sono l'opposto dell'ottimizzazione... :slight_smile:

Quando le cose possono essere fatte bene e semplicemente, è inutile cominciare facendole in altri modi: ci sono tante altre cose, invece, che ha senso che vengano fatte in altri modi. :slight_smile:

void showNum(byte num) {
   for (byte idx=0; idx < 7; idx++) {
      digitalWrite(pinSegmenti[idx], numSegmenti[num][idx]);
   }
}

Nel loop poi chiami la funzione, così:

showNum(0);
delay(1000);
showNum(1);
delay(10000)

Occhio codice non testato.

Ciao.

Ringrazio Maurotec e Datman per i consigli , ma credo che per lo stato attuale a cui mi trovo siano um po avanzati.
Volevo chiedere un consiglio su questa parte di codice

unsigned lon t=0;
unsigned long t1=10;
unsigned long t2= 1000;

void loop() {
  int c=0;
  for(c=0;c<10;c++){
    for(cont=0;cont<indicePin;cont++){
      digitalWrite(pinSegmenti[cont],numSegmenti[c][cont]);
      if(millis()-t>t1){
        t=millis();}
    }
    delay(t2);
    }
  }

In pratica volevo inserire millis() al posto di delay(t1), delay(t2), ovvero con il primo inserisco un ritardo d 10ms per l'accensione di ogni segmento e con t2, una volta acceso tutti i 7 segmenti, attendo 1s prima di visualizzare il numero successivo.
Il mio problema è che il primo millis() per t1 sono riuscito ad integrarlo, ma il secondo per t2 non riesco a farlo funzionare.
Potete darmi qualche suggerimento?

Beh non è così che si usa millis(), non solo perché se lo metti dentro al for fa prima a finire il ciclo che a passare il tempo previsto, ma anche perché in genere alla verifica del tempo (millis()-t) poi nella if() fai quel "qualcosa" che va fatto eseguire a tempo, mentre tu hai solo aggiornato la variabile t. Per cui ti consiglio di cercare alcuni esempi di come si usa la millis() e sperimentare un poco con quelli prima di cimentarti ad inserirlo nel tuo codice.

Detto questo, scusa ma perché vuoi avere un ritardo tra l'accensione dei segmenti? Tu li accendi tutti, poi attendi 1 secondo (e qui usi delay() se il programma non deve far altro, il millis() lo userai successivamente quando avrai sperimentato un poco come ho suggerito sopra) e vai avanti con la cifra successiva. E poi indenta meglio, la graffa di chiusura mettila sempre allo stesso livello di quella di apertura altrimenti non si capisce bene cosa chiude cosa. Inoltre dai alle variabili dei nomi significativi, ad esempio "c" visto che contiene di fatto il numero da visualizzare chiamalo "num", e "cont" non è un contatore ma l'indice del segmento quindi chiamalo "seg"

Ad esempio quindi visto che le variabili t, t1 e t2 non servono, se vuoi fare un contasecondi ad una cifra ti basta scrivere:

void loop() {
  for(int num=0; num<=9; num++){
    cifra(num);
    delay(1000);
  }
}

void cifra(int cifra) {
  for(int seg=0;seg<=7;seg++)
    digitalWrite(pinSegmenti[seg],numSegmenti[cifra][seg]);
}

Grazie docdoc per i suggerimenti.

Avanzati?... Considera che quello che ho scritto al #4 è TUTTO il programma! (salvo dover copiare i numeri da 2 a 9 dal tuo array) :slight_smile: Devi solo usare le porte da D0 a D6 per i 7 segmenti da a a g, ma già hai fatto così.