Problema con un codice

Ciao a tutti, sono un ragazzo autodidatta che sta cercando di fare un progetto su Arduino anche se non ho molte competenze in questo campo; a scuola purtroppo non abbiamo mai fatto nulla riguardo alla programmazione etc. anche se conosco alcuni linguaggi di programmazione (Python, Batch, JavaScript, ...) ma non Java, C o C++. Riguardo alla parte di elettronica invece ho delle basi.

Sto provando a creare un tastierino numerico ( so che ne esistono di già fatti ma a me piace complicarmi la vita :upside_down_face:) che possa registrare un numero a 4 cifre per poi confrontarlo con un altro ( tipo un codice di sblocco ); in più volevo aggiungere un LCD che mi scriva i numeri dopo che li digito e, se il numero corrisponde all'altro, far comparire una scritta tipo 'corretto' e se non corrisponde 'errato'.
Ho già fatto la parte del circuito ma ho qualche problema con il codice:

#include <LiquidCrystal.h>
const int rs = 12;
const int en = 14;
const int d4 = 15;
const int d5 = 16;
const int d6 = 17;
const int d7 = 18;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const int D1 = 11;
const int D2 = 10;
const int D3 = 9;
const int D4 = 8;
const int D5 = 7;
const int D6 = 6;
const int D7 = 5;
const int D8 = 4;
const int D9 = 3;
const int D0 = 2;

void setup() { 

  lcd.begin(16, 2);
  pinMode(D1, INPUT_PULLUP);
  pinMode(D2, INPUT_PULLUP);
  pinMode(D3, INPUT_PULLUP);
  pinMode(D4, INPUT_PULLUP);
  pinMode(D5, INPUT_PULLUP);
  pinMode(D6, INPUT_PULLUP);
  pinMode(D7, INPUT_PULLUP);
  pinMode(D8, INPUT_PULLUP);
  pinMode(D9, INPUT_PULLUP);
  pinMode(D0, INPUT_PULLUP);  

}

void loop() {

  if (digitalRead(11) == LOW) {
	  
	  int Risultato = 1;
	  
  }
  
  if (digitalRead(10) == LOW) {
	  
	  int Risultato = 2;
	  
  }
  
  if (digitalRead(9) == LOW) {
	  
	  int Risultato = 3;
	  
  }
  
  if (digitalRead(8) == LOW) {
	  
	  int Risultato = 4;
	  
  }
  
  if (digitalRead(7) == LOW) {
	  
	  int Risultato = 5;
	  
  }
  
  if (digitalRead(6) == LOW) {
	  
	  int Risultato = 6;
	  
  }
  
  if (digitalRead(5) == LOW) {
	  
	  int Risultato = 7;
	  
  }
  
  if (digitalRead(4) == LOW) {
	  
	  int Risultato = 8;
	  
  }
  
  if (digitalRead(3) == LOW) {
	  
	  int Risultato = 9;
	  
  }
  
  if (digitalRead(2) == LOW) {
	  
	  int Risultato = 0;
	  
  }
}

come potete vedere è incompleto e sicuramente anche sbagliato.
Ringrazio in anticipo chiunque mi aiuti :slightly_smiling_face:

Buonasera e benvenuto, :slight_smile:
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 succitato REGOLAMENTO ... Grazie. :slight_smile:

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nel rispetto del suddetto regolamento nessuno ti risponderà (eventuali risposte verrebbero cancellate), quindi ti consiglio di farla al più presto. :wink:

La ho fatta ancora 4g fa

ciao.
un paio di cose:

  • all'inizio definisci i pin dei pulsanti che usi nei pinMode, ma poi nelle digitalRead usi i numeri...
  • la variabile Risultato dichiarala globale fuori dal loop() e inizializzala a 0 e dentro gli if usala senza int davanti
  • se vuoi leggere un numero a 4 cifre devi "sommare" le cifre... qualcosa del tipo
Risultato *= 10; // "sposto" le cifre che già ci sono a sinistra di una posizione
Risultato += 1; // in ogni if cambi il numero... 1 o 2 o 3 ecc
Risultato %= 10000; // tieni solo le ultime 4 cifre
  • da qualche parte devi scrivere sul lcd se vuoi visualizzare il codice inserito.
1 Like

... già, ma quando ti ho scritto io NON l'avevi fatta, l'hai fatta il giorno dopo :wink:

Guglielmo

Grazie mille, anche se ho dato solo un'occhiata veloce perché purtroppo non sono a casa mi sono accorto di aver fatto degli errori. Domani provo a sistemare; speriamo bene. :crossed_fingers:

Ciao, ho sistemato le variabili come mi hai consigliato anche se non ho ancora aggiunto il discorso delle somme sul risultato perché per il momento non funziona nemmeno con una cifra :sweat_smile:. La stessa cosa vale per l'LCD, volevo prima vedere se funzionava facendomi dare il risultato dal monitor seriale prima di passare il risultato sull'LCD.
Ho capito anche perché non stampava nel monitor il risultato e ho risolto aggiungendo in void setup:

  Serial.begin(9600);

Solo che ora quando avvio la simulazione (prima di montare tutto su Arduino sto usando Tinkercad) sul monitor comincia a scrivere 000000000000000000..... all'infinito. Ho fatto delle prove e ho visto che stampa il valore che viene attribuito alla variabile "risultato" nell'ultimo if cioè questo:

if (digitalRead(D0) == LOW) {
	  
	  risultato = 0;

che nel codice che ho messo all'inizio corrisponde a:

if (digitalRead(2) == LOW) {
	  
	  int Risultato = 0;

Ho pensato ad una possibilità:

  • Ad ogni if la variabile prende il valore assegnato fino ad arrivare all'ultimo che viene stampato; questo, secondo me, perché il bottone è impostato di default su LOW e non su HIGH come avevo pensato io. In tal caso dove dovrei impostare ogni bottone su HIGH? su void setup o su void loop?

Molto probabilmente mi sbaglio ma in ogni caso non riesco a venirne a capo :roll_eyes:.
Ti ringrazio ancora per il tuo aiuto.

È più semplice capire cosa stai facendo se ogni volta posti l'intero codice che stai provando.

Se il pulsante è collegata tra pin 2 e gnd quando non premuto la digitalRead(2) restituisce HIGH a causa dalla pinMode(2, INPUT_PULLUP). Questo è corretto poiché quando premi il pulsante entra nella if. Tradotto la condizione sarebbe if ( LOW == LOW) si lo è per cui entra nel corpo della if cioè tra {}.

Ciao.

Il pulsante non si imposta, si collega in un certo modo (chiusura verso Vcc o verso GND) e quando viene letto fornisce un certo livello logico 0 o 1 (alias LOW HIGH) a seconda di come è stato collegato, se è premuto o meno, e se è del tipo normalmente aperto o normalmente chiuso. Questa è una configurazione hardware, e nel software si tiene conto di questa configurazione.

Se so che con il mio collegamento hardware il pulsante viene letto come LOW quando premuto, allora trovo comodo definire una costante:

const byte LIVELLO_PREMUTO = LOW;

e nel programma ragionare più ad alto livello senza più preoccuparmi dei livelli:

bool premuto = (digitalRead(PIN_INGRESSO) == LIVELLO_PREMUTO);

if (premuto) { ..... }

if (!premuto) { ..... }

Se cambio i collegamenti hardware, cambio solo la costante e il resto della logica rimane invariato.

PS: void (vuoto) è il tipo di ritorno di una funzione che non ritorna nulla, come int, float bool ecc.

1 Like

E' cambiato poco dall'ultima volta comunque eccolo qui.

#include <LiquidCrystal.h>
const int rs = 12;
const int en = 14;
const int d4 = 15;
const int d5 = 16;
const int d6 = 17;
const int d7 = 18;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const int D1 = 11;
const int D2 = 10;
const int D3 = 9;
const int D4 = 8;
const int D5 = 7;
const int D6 = 6;
const int D7 = 5;
const int D8 = 4;
const int D9 = 3;
const int D0 = 2;

int risultato = 0;

void setup() { 

  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.setCursor(0,1);
  pinMode(D1, INPUT_PULLUP);
  pinMode(D2, INPUT_PULLUP);
  pinMode(D3, INPUT_PULLUP);
  pinMode(D4, INPUT_PULLUP);
  pinMode(D5, INPUT_PULLUP);
  pinMode(D6, INPUT_PULLUP);
  pinMode(D7, INPUT_PULLUP);
  pinMode(D8, INPUT_PULLUP);
  pinMode(D9, INPUT_PULLUP);
  pinMode(D0, INPUT_PULLUP);

}

void loop() {

  if (digitalRead(D1) == LOW) {
	  
	  risultato = 1;
  }
  
  if (digitalRead(D2) == LOW) {
	  
	  risultato = 2;
  }
  
  if (digitalRead(D3) == LOW) {
	  
	  risultato = 3;
  }
  
  if (digitalRead(D4) == LOW) {
	  
	  risultato = 4;	  
  }
  
  if (digitalRead(D5) == LOW) {
	  
	  risultato = 5; 
  }
  
  if (digitalRead(D6) == LOW) {
	  
	  risultato = 6;
  }
  
  if (digitalRead(D7) == LOW) {
	  
	  risultato = 7;
  }
  
  if (digitalRead(D8) == LOW) {
	  
	  risultato = 8;
  }
  
  if (digitalRead(D9) == LOW) {
	  
	  risultato = 9;
  }
  
  if (digitalRead(D0) == LOW) {
	  
	  risultato = 0;
  }
  Serial.print(risultato);
}

Grazie mille, ho verificato dove sono collegati i pulsanti e sono da una parte collegati a GND e dall'altra collegati ai rispettivi digital pin; solo che purtroppo non sono riuscito a risolvere il fatto dell'output che mi da 0000000000..... all'infinito.

Hai messo il Serial.print nel loop()... E il loop() continua a ciclare all'infinito... Quindi è normale che il valore della variabile venga stampato all'infinito...

Puoi risolvere in 2 modi:

  • stampi solo se il valore attuale è diverso dal precedente
  • metti Serial.print dentro ogni if
1 Like

Con il secondo la stampa continua a raffica finché il pulsante rimane premuto. Con il primo invece si rileva solo il momento della pressione e si ottiene automaticamente anche il debounce senza bisogno di altri accorgimenti, ma il limite è che non può riconoscere più pressioni in sequenza sullo stesso pulsante.

1 Like
if (risultato != -1) {
    Serial.print(risultato);
    risultato = -1;
}

Il codice qui sopra al posto del tuo Serial.print(...

Devi anche modificare questa:

int risultato = 0;   // deve essere -1

Una variante con valenza didattica è prevede queste modifiche:

void loop() {
risultato = -1;

// qui in mezzo le tue if (digitalRead ...



if (risultato != -1) {  // risultato ha assunto un valore lecito 0÷9 stampa
    Serial.print(risultato);
}

Ad ogni ciclo della funzione loop() (la quale termina e comincia all'infinito) alla variabile risultato viene assegnato il valore -1 (valore fuori dal range lecito 0÷9), se nussuna delle if viene verificata "vera" la variabile risultato ha ancora valore -1. Diversamente se una delle if viene verificata "vera" la variabile "risultato" assumera un valore nel range lecito 0÷9.

PS: non escludere le altre soluzioni suggerite poiché tornano sempre utili.

Ciao.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.