Contatore con display 4 digit 7 segmenti

Ciao a tutti,
sono un nonno che con il nipotino di 9 anni vorrebbe costruire un contatore ( segna punti) con un
display 4 digit 7 segmenti.
Le mie conoscenze di elettronica sono buone ma quando devo scrivere un programma in "C" qui ho
delle grosse difficoltà.
Ho scritto questo programma, ma non riesco a controllare i due pulsanti ed il risultato che ottengo
e che la variabile " contatore" si incrementa progressivamente senza tener conto se il pulsante o pulsanti sono premuti.

Ringrazio tutti quelli che mi vorranno aiutare

Grazie Nonno Sergio e Fabio

// Contatore con display 4 digit 7 segmenti
// Con pulsante incrementa numeratore e pulsante decrementa numeeratore

// Dichiaro le variabili
int numeratore=0;

//------------------------------------------------------------------
#include <SevSeg.h> //Libreria controllo Display 4 digit 7 segmenti

#define COMMON_ANODE 1
#define COMMON_CATODE 0
//------------------------------------------------------------------
// definisco la mappa tra pin e segmenti
#define segA 6 // 11 PIN del display 7Segment x 4
#define segB 2 // 7 PIN del display 7Segment x 4
#define segC 10 // 4 PIN del display 7Segment x 4
#define segD 12 // 2 PIN del display 7Segment x 4
#define segE 13 // 1 PIN del display 7Segment x 4
#define segF 5 // 10 PIN del display 7Segment x 4
#define segG 9 // 5 PIN del display 7Segment x 4
#define segDP 11 // 3 PIN del display 7Segment x 4

#define digit1 7 // 12 PIN - PWM che Accende il primo digit
#define digit2 4 // 9 PIN - PWM che Accende il secondo digit
#define digit3 3 // 8 PIN - PWM che Accende il terzo digit
#define digit4 8 // 6 PIN - PWM che Accende il quarto digit
//-------------------------------------------------------------------
// definisco i PIN di imput
#define P1 1 // pulsante INCREMENTO NUMERATORE
#define P2 0 // pulsante DECREMENTO NUMERATORE
//-------------------------------------------------------------------
// Creo un'istanza dell'oggetto
SevSeg sevseg;
//-------------------------------------------------------------------
void setup()
{
pinMode(P1,INPUT);
pinMode(P2,INPUT);

Serial.begin (9600); //apro canale seriale

sevseg.Begin(COMMON_CATODE,digit1,digit2,digit3,digit4,segA,segB,segC,segD,segE,segF,segG,segDP);

sevseg.Brightness(50); // Imposto la luminosità del Display (valore da 0 a 100)
}

void loop()
{
// pulsante "se" premuto
if (P1== HIGH);
{
delay(100);
if (P1== HIGH); //antibounce
{
numeratore++; // incremento il contatore

if (numeratore>999) // se il contatore supera 999, lo azzero
{
numeratore=0;
}
}
}

// pulsante "giu" premuto
if (P2== HIGH)
{
delay(100);
if (P2== HIGH); // antibounce
{
if (numeratore==0)
{
numeratore=999;
}
else
{
numeratore--; // decremento il contatore
}
}
}

{
Serial.println(numeratore);
}

sevseg.PrintOutput(); // Mostra il valore sul Display
sevseg.NewNum(numeratore,(byte) 4);
}

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento: Regolamento

Il codice devi racchiuderlo nei tag code, vedi sezione 7 del regolamento, spiega bene come fare.
Altrimenti parte del codice può essere visualizzata male o mancare perchè interpretato come attributo del testo stesso.

Molto semplicemente NON leggi il pin (e togli tutti quei punto e virgola a fine if) :
if (P1== HIGH); non basta, devi usare digitalRead()

if( digitalRead(P1)== HIGH )
{

Funziona perfettamente
grazie mille

Ciao a tutti,
dal precedente post o continuato con il modificare il progetto, ed a oggi sono riuscito a gestire un doppio Display 7 segmenti 4 digit gestendolo con l'integrato MAX7219.
Ad oggi funziona che premendo il pulsante il numeratore sale di una unita per volta e con un altro pulsante lo decrementa di una unita.
Quello che vorrei implementare e al click incrementi o decrementi di una unita(e questo già lo fa e funziona)ma se tengo premuto il pulsante per più di un secondo l'incremento o il decremento si di 10 per volta.
Purtroppo le mie conoscenze di informatica sono scarsissime, c'è qualcuno che mi può aiutare.
grazie sergio
questo e quello che ho scritto:

#include "LedControl.h" 

//                      DIN, CLK, LOAD, Num max7219
LedControl lc=LedControl(12,  11,   10,  1); 

int v;
int d;
int c;
int e;
int f;
int ones;      // unutà
int tens;      // decine
int hundreds;  // centinaia

int v1;
int d1;
int c1;
int e1;
int f1;
int ones1;      // unutà
int tens1;      // decine
int hundreds1;  // centinaia

#define P1 8    // pulsante UP
#define P2 7    // pulsante DOWN
int val=0;


#define P3 6
#define P4 5
int val1=0;

void setup()
{
  pinMode(P1,INPUT);
  pinMode(P2,INPUT);
  pinMode(P3,INPUT);
  pinMode(P4,INPUT);
  
  lc.shutdown(0,false);
  lc.setIntensity(0,5);
  lc.clearDisplay(0);
  
  for(int index=0;index<lc.getDeviceCount();index++) 
  {
    lc.shutdown(index,false);
  }
}
void loop()
{
//====================Primo Dysplay ===============================================================
 val = digitalRead(P1);  // legge il valore di P1 e lo conserva  
   delay(35);
   if (val == HIGH) {  // controlla che l'input sia HIGH (pulsante premuto)
     v=v++; 
   }  
val = digitalRead(P2);  // legge il valore di P2 e lo conserva  
   delay(35);
   if (val == HIGH) {  // controlla che l'input sia HIGH (pulsante premuto)
   v=v--; 
   }  
 
  if (v>999)
  {
   v=0;
   c=0;
   f=0;
   }
      if (v>100)
      {
       e=d;
       e=e/10;
       f=e%10;
       }
           ones=v%10;
           if (v>=10)
           {
           d=v;
           d=d/10;
           c=d%10;
           }      
  lc.setDigit(0,2,f,false);
  lc.setDigit(0,1,c,true);
  lc.setDigit(0,0,(byte)ones,false);
  
//====================Secondo Display =============================================================
  val1 = digitalRead(P3);  // legge il valore di P3 e lo conserva  
   delay(35);
   if (val1 == HIGH) { // controlla che l'input sia HIGH (pulsante premuto) 
   v1=v1++; 
   }  
val1 = digitalRead(P4);  // legge il valore di P4  e lo conserva  
 delay(35);  
   if (val1 == HIGH) {  // controlla che l'input sia HIGH (pulsante premuto)
   v1=v1--; 
   }  
  
  if (v1>999)
  {
   v1=0;
   c1=0;
   f1=0;
   }
      if (v1>100)
      {
       e1=d1;
       e1=e1/10;
       f1=e1%10;
       }
           ones1=v1%10;
           if (v1>=10)
           {
           d1=v1;
           d1=d1/10;
           c1=d1%10;
           }
  lc.setDigit(0,6,f1,false);
  lc.setDigit(0,5,c1,true);
  lc.setDigit(0,4,(byte)ones1,false);
  {
delay(100);
  }
}

non vorrei passare per presuntuoso, ma il programma che ho scritto e frutto di spunti di altri progetti, scritti da persone molto più esperte di me in informatica

Dovresti usare la funzione di formattazione del codice presente nell'ide al fine di rendere il codice più leggibile. Con più 'leggibile' intendo; che invece di girare gli occhi e doverlo rileggere mille volte continuando a confondersi, si capisce subito cosa si vuole che faccia e cosa effettivamente fa.

Mi dispiace io non riesco a seguirlo il codice e non so perché non funziona, posso solo fare delle osservazioni utili.

v=v++;

La stessa cosa più chiara è il seguente codice:

v++;

o

++v;

++ è un operatore unario di incremento, il quale incrementa il valore di una variabile di una unità.

Ho come l'impressione che manchi uno o più 'else' nelle 'if', ma non ne sono sicuro.

  if (v>999)
  {
   v=0;
   c=0;
   f=0;
   } else 
      if (v>100)
      {
       e=d;
       e=e/10;
       f=e%10;
       } 
           ones=v%10;
           if (v>=10)
           {
           d=v;
           d=d/10;
           c=d%10;
           }

Ti ringrazio per i tuoi consigli, ne faro tesoro.
Ora o semplificato al massimo il codice, che funziona perfettamente.
Se premo il pulsante un click LL volta mi incrementa di una unita, se lo tengo premuto l'incremento
continua all' infinito.
Quello che vorrei fare e che se premo e rilascio mi continui a incrementare la variabile di 1,
se invece tengo premuto il pulsante l'incremento sia di 10 unita per volta.
Viste le mie scarsissime conoscenze di informatica non so come gestire la cosa.

#include "LedControl.h"

// DIN, CLK, LOAD, numero di integrati max7219
LedControl lc=LedControl(12, 11, 10, 1);

int v;
int d;
int c;
int e;
int f;
int ones; // unutà
int tens; // decine
int hundreds; // centinaia

#define P1 8
int val=0;

void setup()
{
pinMode(P1,INPUT);
pinMode(P2,INPUT);

lc.shutdown(0,false);
lc.setIntensity(0,5);
lc.clearDisplay(0);

for(int index=0;index<lc.getDeviceCount();index++)
{
lc.shutdown(index,false);
}
}
void loop()
{

val = digitalRead(P1); // legge il valore dell'input e lo conserva
delay(25);
if (val == HIGH) { // controlla che l'input sia HIGH (pulsante premuto)
v++;
}

if (v>999)
{
v=0;
c=0;
f=0;
}
if (v>100)
{
e=d;
e=e/10;
f=e%10;
}
ones=v%10;
if (v>10)
{
d=v;
d=d/10;
c=d%10;
}

lc.setDigit(0,2,f,false);
lc.setDigit(0,1,c,true);
lc.setDigit(0,0,(byte)ones,false);

}

Potresti fare così, dopo l if dove controlli che val è premuto aggiungi un while sempre puntato su val e internamente un controllo su millis. Quando millis raggiunge 1secondo reincrenenti val con val++ ed azzeri millis rifacendo il controllo. Fintanto che il pulsante è premuto con il while resti all'interno di questo loop ed incrementi una volta al secondo. Quando lo rilasci il programma procede come prima.
Mi rendo conto che letto così ti sembrerà difficile, ma se studi l'uso di millis abbinato al while ti sarà chiaro.
Poi logicamente ci possono essere infiniti altri modo per farlo, questo è il primo che mi è venuto in mente

ti ringrazio,
potresti scrivere due righe di codice perché come dici tu per me e un po' difficile.

grazie Sergio

Codice no, scusa sono su cell, ma pseudocodice si

Tempotrascorso=millis
While (val)
If millis==Tempotrascorso+1000
v+10
Tempotrascorso=millis

ti ringrazio,
potresti scrivere due righe di codice perché come dici tu per me e un po' difficile.

grazie Sergio

Potresti invece tu fornire una descrizione del codice?

A me ad intuito il codice mi fa pensare ad un programmatore assembler che scrive in c.
Se non sbaglio usi 'v' sia come contatore del tempo trascorso che per ricavare gli incrementi e questo è il tipico approccio assembler, dove diversamente si usano i registri general purpose al posto di tutte quelle variabili globali che impegnano memoria.

Ai fini didattici non è male, solo che io purtroppo con assembler non ci scrivo codice, l'ho solo studiato in passato e in questo frangente non mi torna in mente nulla di utile da suggerirti.

Testato ti suggerisce ciò che è considerato la best pratice quando si voglio eseguire porzioni di codice a tempo. La funzione millis() restituisce un valore il quale viene incrementato di una unità ad ogni millesimo di secondo.

Quando decidi di abbandonare il tuo approccio, studia il codice di esempio blinkwithoutdelay presente nell'ide.

Ciao.

Ringrazio tutti per l'aiuto.
Testato,Ora provo ad l'implementare il codice con il tuo consiglio.
Non sono un programmatore, ma un elettronico mi muovo meglio tra resistenze,integrati, condensatori ecc.
Ma sono IGNORANTISSIMO tra gli IF, WHILE ecc.
Sono una persona curiosa prendo spunto, mi informo , studio e chiedo aiuto.

Ciao

Ciao Testato,
ho modificato il codice come da tuo suggerimento usando While
ma sicuramente ho commesso degli errori perché il programma non mi da alcun valore
sul display perché "v" non si incrementa.
Aiuto chiedo scusa per la mia infinita ignoranza

Posto così il codice perché non mi si apre la Finestra dove inserirlo ``

#include "LedControl.h"

// DIN, CLK, LOAD, numero di max7219
LedControl lc=LedControl(12, 11, 10, 1);
unsigned long tempo = 0 ; // tempo trascorso
int intervallo = 1000; // intervallo di tempo
int v;
int val=0;
int u; // unita
int d; // decine
int c; // centinaia
#define P1 8 // pulsante incrementa numeratore

void setup()
{
pinMode(P1,INPUT);

lc.shutdown(0,false);
lc.setIntensity(0,5);
lc.clearDisplay(0);

for(int index=0;index<lc.getDeviceCount();index++)
{
lc.shutdown(index,false);
}
}
void loop(){

tempo=millis();

val = digitalRead(P1); // legge il valore dell'input e lo conserva
delay(15);
if (val == HIGH) { // controlla che l'input sia HIGH (pulsante premuto)
v++;

while (val=HIGH){
if (tempo - 0 >= intervallo == true){
v+10;
}
}
}
u=v%10; // Estrae unita
d=(v/10)%10; // Estrae decina
c=(v/100)%10; // Estrae centinaia

//========================
if (v>999){
u=0;
d=0;
c=0;
}
lc.setDigit(0,2,c,false);
lc.setDigit(0,1,d,false);
lc.setDigit(0,0,u,false);
}

il primo errore che vedo e' while (val=HIGH)
devi usare il doppio == oppure solo while(val)

inoltre questo non vuol dire nulla
if (tempo - 0 >= intervallo == true)

dovresti partire da una cosa del genere
if (millis() >= tempo+intervallo)

"v" non si incrementa comunque
sia che while interno al "if" o esterno
sembra che rimanga sempre dento al "while"

Testato ti ringrazio per la tua cortesia


void loop()
{
//====================Primo Dysplay ====================================
tempo=millis();
val = digitalRead(P1); // legge il valore dell'input e lo conserva
delay(15);
if (val == HIGH) { // controlla che l'input sia HIGH (pulsante premuto)
v++;
while (val==HIGH){
if (millis()>=tempo+intervallo){
v+10;
}
}
}

l'incremento lo devi fare con v=v+10, o anche v += 10
inoltre subito dopo l'incremento devi anche riresettare tempo
tempo=millis();

ultimo quesito:
ora al primo click del pulsante aumenta "v" di 1
dopodihe senza premere il pulsante inizia il ciclo while e incrementa "v" di 10 all' infinito
e non esegue il resto del codice

Mi arrendo !!

perche non mi si apre la finestra dove inserire il codice???


#include "LedControl.h"
//--------------------> DIN, CLK, LOAD, numero di max7219
LedControl lc=LedControl(12, 11, 10, 1);
unsigned long tempo; // tempo trascorso
int intervallo = 1000; // intervallo di tempo
int v=0;
int val=0;
int u; // unita
int d; // decine
int c; // centinaia
#define P1 8 // pulsante

void setup()
{
Serial.begin (9600);
pinMode(P1,INPUT);

lc.shutdown(0,false);
lc.setIntensity(0,5);
lc.clearDisplay(0);

for(int index=0;index<lc.getDeviceCount();index++)
{
lc.shutdown(index,false);
}
}
void loop()
{
//====================Primo Dysplay ====================================
tempo=millis();
val = digitalRead(P1); // legge il valore dell'input e lo conserva
delay(50);
if (val == HIGH) { // controlla che l'input sia HIGH (pulsante premuto)
v++;
}
while (val==HIGH){
if (millis()>=tempo+intervallo){
v+=10;
tempo=millis();
}
Serial.println(v);
}

u=v%10; // Estrae unita
d=(v/10)%10; // Estrae decina
c=(v/100)%10; // Estrae centinaia

//========================
if (v>999){
u=0;
d=0;
c=0;
}
lc.setDigit(0,2,c,false); // centinaia
lc.setDigit(0,1,d,false); // decine
lc.setDigit(0,0,u,false); // unita

}

a

Sergio_m:
a

"a" come lo dobbiamo interpretare ? :slight_smile:

spiega meglio cosa succede, tu lasci il pulsante ma v continua ad incrementarsi ?
si incrementa una volta al secondo ?
hai una R di pulldown sul pulsante ?

La a mi è scappata
Il pulsante e collegato in pull down. Resistenza 10KΩ su GND
La variabile si incrementa di 10 ogni secondo