Conteggio di numero di impulsi (da 5V) su Pin Arduino

Buona sera,
premetto che sono alle prime armi con Arduino UNO e la programmazione di questo sistema.
Ma affascinato dalle potenzialità enormi di Arduino e volendone studiare alcune, ho iniziato con gli esercizi base... solo che poi inizi a pensare a cose che ancora non padroneggi e inizi a sbatterci il capo! :smiley: :smiley:

Comunque venendo a noi, volevo chiedervi di analizzare questo breve listato per capire dove sbaglio. In pratica sono riuscito a codificare l'algoritmo: premi pulsante -> accendi Led -> incrementa un contatore numerico, che parte da 0, di 1 -> visualizza il contatore su display LCD. Ripetendo l'operazione il ciclo si ripete e il contatore, ovviamente aumenta di 1.

Ora, poiché, mi servirebbe che questo contatore funzionasse, anziché col pulsante, con l'arrivo di un impulso di 5V+ su un PIN digitale (dichiarato in INPUT) ... ho iniziato a fare "cap a mur" (come si dice dalle mie parti :D) ..a scervellarmi!
Ma la cosa strana, almeno per me, è che eliminando la sezione hardware del pulsante e inserendo solo un filo di collegamento nel PIN (3 nel mio caso) ..senza collegamenti all'altro capo.. Il contatore va avanti da solo!!! :woozy_face: :crazy_face: Se tolgo quel filo.. si ferma!
Questo non mi fa procedere ... perché avevo pensato di inserire nel PIN (3) al posto del pulsante.. proprio il collegamento con l'impulso.
Vi allego il listato e i collegamenti fatti... e se qualche anima pia vi da un'occhiata.. gliene sarei grato e sarebbe un buona occasione per me .. per apprendere.
Grazie

Listato caricato in Arduino UNO:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define led 2 // dichiaro che il led è sul pin 2
#define pulsante 3 // dichiaro che il pulsante è sul pin 3
// #define impulso 4 // dichiaro che impulso è sul pin 4
int i; // variabile del conteggio
bool stato; // variabile di comodo
LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup() {
  // Serial.begin(9600);
  pinMode (led, OUTPUT); // il pin 2 è una uscita
  pinMode (pulsante, INPUT); // il pin 3 è un ingresso
  // pinMode (impulso, INPUT); // il pin 4 è un ingresso
    lcd.init();
  lcd.backlight();
  lcd.clear();
}

void loop () {
  if (digitalRead(pulsante) == true && stato == true){ // se è premuto il pulsante accendo il led e incremento "i"  di 1
    i ++; // contatore, i++ è un abbreviazione di i= i + 1;
    digitalWrite(led, HIGH); // accendo il led
    stato = false; // se questa è falsa non entra piu in questo if
  }

  else if (digitalRead(pulsante) == false) { // se il pulsante non è premuto
    digitalWrite(led, LOW); //  spengo il led
      stato = true; // una volta rilanciato il pulsante questa variabile diventa vera
      }
   
  lcd.setCursor(8, 1);
     lcd.print(i);
    delay(200); // pausa di 200 millisecondi
}

Ho letto la tua presentazione e anche io basic, clipper ecc. Il problema è banale ed è risolvibile in due modi:

  1. pin in input ma con resistenza di pull-up interna: al posto di INPUT ci metti INPUT_PULLUP.
  2. usi una resistenza esterna da 10k÷50k da collegare in pull-up o pull-down a scelta.

Il pin fa capo ad un circuito TTL ad alta impedenza e pertanto è suscettibile alle fluttuazioni elettromagnetiche, ciò accade con qualunque circuito ad alta impedenza.
Inoltre documentati sul rimbalzo dei contatti elettrici di cui sono afflitti tutti pulsanti e relay e il relativo circuito di debounce harware e soluzioni software.

Ciao.

Non c'è niente di sbagliato. Un ingresso digitale ad alta impedenza non deve mai restare collegato solo a un filo "antenna" che capta qualsiasi disturbo. Se lo colleghi all'uscita digitale che genera l'impulso si comporterà come deve (come con il pulsante, dove a pulsante aperto il livello in ingresso è stabilizzato a zero dalla resistenza di pull-down).

CMOS :slight_smile:

Innanzitutto, grazie a tutti per le cortesi risposte.

Dunque il problema potrebbe essere la resistenza di pull-up ..che va attivata internamente piuttosto che esternamente (come avevo messo io). Non immaginavo che quei PIN avessero tale sensibilità :sweat_smile:.
In effetti il mio scopo finale è quello di contare i cicli di un Timer per Time-Lapse fotografici che ho già realizzato con altro Hardware (ancora prima si scoprire Arduino). Una volta riuscito nell'intento mi dedicherò .. con le mie briciole di competenze.. alla realizzazione di un Timer a più canali (indipendenti o a cascata) programmabile ..con Arduino :sweat_smile::sweat_smile:. So che esistono soluzioni già pronte al di fuori di Arduino... ma lo sfizio è quello di realizzarlo con questo sistema e capire come funziona..tutta la programmazione del caso.
Nel frattempo ..domani.. terminato il turno di notte.. mi dedicherò alla modifica del conta cicli.
Vi terrò aggiornati.
Grazie

Scusa ma non l'ho vista la pull-down nell'immagine e quindi il problema sembra altrove, no aspetta per non lasciare il pin flottante una R che sia pull-down o pull-up deve esserci sempre. In ogni caso alla attuale resistenza esterna aggiungi un condensatore da 100nF (o poco più) per mitigare i rimbalzi dei contatti. Anche nel caso in cui colleghi il pin al tuo time-lapse sarebbe bene avere una pull-up (o down) nel caso in cui scolleghi il tuo time-lapse. Se usare una pull-up o pull-down dipende dall'hardware del time-lapse.

Ciao.

1 Like

Eccomi... sono venuto a capo dell'arcano.. grazie a voi e ad un po di misurazioni col tester :smiley:

Dunque .. inserendo, come suggerito da Maurotec, INPUT_PULLUP (quindi attivando la resistenza di pull-up interna) al PIN 3 al posto del semplice INPUT ho bloccato i "segnali d'antenna".. falsi che facevano partire il contatore da solo! :muscle: :muscle:
Ma collegando il cavetto dell'impulso al PIN 3 e accendendo il timer.. senza avviarlo il fenomeno si ripeteva :woozy_face: :woozy_face: ...
Ho attivato quei 4 neuroni (ma forse anche meno) che ho... ed ho cercato di capire da dove venivano questi Volt che innescavano il conteggio ed ho scoperto, col tester, che alimentando il timer, pur senza avviarlo, veniva fuori la tensione :roll_eyes: :roll_eyes:... al che ho pensato "vuoi vedere che avendo generato il segnale a 5V con un partitore di tensione con due semplici resistenze (poichè in origine sono 12V) e le GND (tra Arduino e Timer) sono separate la tensione scorre liberamente?" ...EUREKA (concedetemelo.. per me sono piccole soddisfazioni :smiley: ).
Alla prova del nove infatti collegando le due GND... il tutto funziona meravigliosamente .. :star_struck: :star_struck: :star_struck:.
Grazie a tutti... ma se avete osservazioni sarò ben lieto di leggerle.

Se le masse non sono collegate le tensioni non hanno più un riferimento comune, diciamo che il nuovo riferimento diventano gli accoppiamenti capacitivi all'interno degli alimentatori, il che vuol dire potenzialmente centinaia di volt di differenza (al lavoro avevamo morie di porte seriali di PC per questo motivo).

Per il resto, buono aver usato la variabile 'stato' per rilevare il fronte di pressione. La scrittura sul display la metterei dentro il primo if, se non serve scrivere altro ad ogni giro di loop. Il delay finale si può ridurre a 30..50ms, in genere i rimbalzi dei pulsanti si risolvono entro pochi millisecondi, se si leggono solo segnali puliti senza rimbalzi allora il delay si può togliere del tutto (a meno di non avere motivo di voler rallentare il ciclo di loop).

1 Like

Ciao, enantio.

Per una migliore comprensibilità del codice (anche da parte tua fra qualche anno), ti consiglio di usare un nome più significativo per la variabile stato, ad esempio "puls_a_riposo" o "stato_in_prec" (cioè stato precedente dell'ingresso, che sarebbe lo stato opposto). Anche un commento più esplicativo di "variabile di comodo" (???...) sarebbe MOLTO utile! :slight_smile:

Grazie Claudio ..per la spiegazione tecnica :pray: ..in effetti i due hardware devono "congiungersi" sulle masse per avere una lettura univoca della tensione :+1: :+1:
Ho seguito i tuoi consigli e messo lcd.print nel primo if ..anche se per visualizzare lo zero (0) iniziale faccio scrivere la variabile (i) la prima volta nel "void setup()". Il "delay" l'ho lasciato a 200 perchè ininfluente con i tempi lunghi del ciclo del timer che è di circa 10 secondi, ma mette abbondantemente al riparo da eventuali rimbalzi del relè n.1 (quello master).
Per correttezza allego il listato finale, laddove qualcuno volesse utilizzarlo o semplicemente studiarlo.

/* Questo conta cicli è stato pensato per visualizzare il numero di Cicli Timer su un temporizzatore
per fotografie in Time Lapse e quindi per capire quanti scatti sono stati fatti, realmente dalla fotocamera!
Il segnale di partenza di ogni ciclo preso a 12V sul canale 1 del relè master (quello che inizia ogni ciclo) 
è stato convertito in 5V con un partitore di tensione (due semplici resistenze da 1500 Ohm e 1000 Ohm, dove quella da 1500 Ohm 
è sul lato del positivo 12v+ del Timer e l'altra su GND del Timer) e inviato al PIN 3 di Arduino (dichiarato in INPUT).
Fondamentale affinchè il sistema funzioni correttamente è la connessione tra di loro delle 2 GND, quella del Timer e quella di Arduino,
altrimenti avremo sempre un tensione, non prevedibile, sul filo che porta al PIN 3 e il conteggio avanzerà anche a Timer non avviato!
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define led 2 // dichiaro che il led è sul pin 2
#define impulso 3 // dichiaro che l'impulso è sul pin 3

int i; // variabile del conteggio

bool stato; // variabile di comodo

LiquidCrystal_I2C lcd(0x27, 20, 4);


void setup() {
  
  pinMode (impulso, INPUT_PULLUP); // il pin 3 è un ingresso
  
  
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(8, 1);  
  lcd.print(i);  
    
  
}

void loop () {
  if (digitalRead(impulso) == true && stato == true){ // se arriva l'impulso incremento "i"  di 1 e la variabile "stato" diventa "falsa" 
    i ++; // contatore, i++ è un abbreviazione di i= i + 1;
    
    lcd.setCursor(8, 1);   
    lcd.print(i);
    
    stato = false; // si commuta la variabile in falsa per uscire da questo if 
  }

  else if (digitalRead(impulso) == false) { // se non arriva l'impulso la variabile "stato" diventa "vera"
    stato = true; // si commuta la variabile in attesa del nuovo impulso
    
  } 
         
  delay(200); // pausa di 200 millisecondi

}

Nell'immagine considerate il Rele (tra l'altro a 12V non a 5V come segnato) come se fosse il timer. Perdonatemi ma non sono riuscito a fare di meglio.

1 Like