Contatore elettromeccanico

Buongiorno a tutti,
scrivo nella speranza di avere qualche suggerimento...avrei la necessità di rilevare gli scatti di un contatore elettromeccanico (così da poterli poi contare/memorizzare e gestire). Il contatore è collegato a una scheda di controllo a sua volta collegata alla scheda madre di un PC.
Con quale logica potrei rilevare gli scatti?
Ogni consiglio o idea sarebbe di grande aiuto!
Grazie

Se non sei sicuro e vuoi mantenere tutto isolato galvanicamente, un'opto con il led (e relativa resistenza in serie) in parallelo alla bobina del contatore elettromeccanico dovrebbe risolvere il problema senza troppe difficolta'.

Grazie mille @Etemenanki !
Ok, e poi dovrei usare una fotoresistenza per contare i lampeggi del led?

No, l'optoisolatore esce con un transistor (fototransistor) che va in conduzione quando il led interno si accende, per cui puoi usare direttamente lui (un banale 4N25 o qualsiasi altro simile trovi dovrebbe andare bene, ovviamente se il contatore e' alimentato in DC).

Colleghi l'emettitore a GND, il collettore con una resistenza in serie a VCC (GND e VCC della logica tua, ovviamente), e sul collettore hai un'impulso verso massa ogni volta che il contatore scatta.

Grazie mille!

Buonasera,
Ho seguito le indicazioni di @Etemenanki, tuttavia non riesco a ottenere il risultato voluto. Il contatore è a 12v. Ho fatto questi collegamenti: l'anodo al + del contatore con resistenza da 1k; il catodo al - del contatore; l'emettitore al gnd di Arduino e il collettore con resistenza 10k al vin + segnale Pin.

Ho provato il 4n25 con il tester: quando scatta il contatore ho misurato da 0.3 a 5.5v tra anodo e catodo ma sempre 0 tra emettitore e collettore.

Cosa sto sbagliando?

Grazie mille

5,5V tra A e K???... Dovrebbero esserci 1,2V! Mi sa che non sono i piedini giusti, oppure il LED interno è interrotto.

mi devo correggere, tra emettitore e collettore non ho 0 ma circa 5v. Tra anodo e catodo il tester misura valori sempre diversi ma compresi nel range 0.3 - 5.5v.
Ho collegato il pin 1 al + e il pin 2 al -
ps. condivido la foto del contatore

Puoi collegarlo in due modi diversi secondo il tipo di uscita che vuoi.

Nel primo modo, l'uscita e' sempre ad 1 e va a 0 quando il contatore e' alimentato, nel secondo l'uscita e' sempre a 0 e va ad 1 quando il contatore e' alimentato, il led in serie all'opto ti permette di vedere se gli impulsi arrivano correttamente (si puo metterne uno anche sull'uscita se vuoi, basta collegarlo, ovviamente con una sua resistenza da 470 ohm in serie al led, in parallelo alla R da 4k7), il diodo 1N4148 lo metto perche' il contatore elettromeccanico ha all'interno una bobina che potrebbe generare picchi in apertura, che potrebbero bruciare l'opto.

Fra i pin 1 e 2 del 4N25 deve esserci o 0 (circa 0, quando il contatore non e' alimentato), oppure circa 1.3 / 1.5 V (quando il contatore e' alimentato) ... per provare il circuito prima di collegarlo al contatore, puoi semplicemente dargli i 12V all'ingresso con un qualsiasi alimentatorino a 12V esterno.

Essendo impulsi poi nel programma dovrai leggerli in modo corretto (interrupt con rising o falling), ma questo e' un problema software, risolviamo prima quello hardware.

grazie @Etemenanki per il dettaglio nella risposta, è fondamentale per me per riuscire a venirne a capo. Ho seguito il secondo schema (impulsi +): fra 1 e 2 c'è 0.5 quando non alimentato (come suggerito ho utilizzato un alimentatore a 12 v), 1.2 quando alimentato.
L'uscita (pin2) è semrpe 0 e va a 4.4v quando alimentato.

Ho testato un codice di base per inviare ad un server la lettura e sembra funzionare! Condivido la parte del loop, potresti darmi qualche dritta in merito a quello che mi hai scritto su interrupt con rising o falling?

GRAZIE!!!

int notificaAcceso = 0;
int notificaSpento = 1;
int conta = 0;
int invia = 0;
long int pausa = 0;
long int pausa1 = 0;

void loop() {  

  // ARRIVA IMPULSO A CONTATORE --> LED OPTO ACCESO //
  if (digitalRead(4) == HIGH && notificaSpento == 1 ) {

    notificaAcceso = 1;
    notificaSpento = 0;
    conta++;
  }
  
  // TERMINA IMPULSO A CONTATORE --> LED OPTO SPENTO //
  if (digitalRead(4) == LOW && notificaAcceso == 1 ) {

      Serial.println("LED SPENTO!");  
        
    notificaAcceso = 0;
    notificaSpento = 1;
    pausa = millis();
  }
  
  // SE LED RIMANE SPENTO PER PIU DI 4 SEC E VARIABILE CONTA > 0 ALLORA INVIA DATI
  if( notificaAcceso == 0 && notificaSpento == 1 && conta > 0 ){
    
    pausa1 = millis();

          Serial.println("LED SPENTO ATTENDI ACCENSIONE!");  
    
    if( pausa1 - pausa > 4000 ){

          Serial.println("LED SPENTO PER PIU DI 4 SEC!");  

          //INVIA DATI
        if (ArduinoClient.connect(server, 80))
              {
                
          Serial.println("INVIA DATI!");  

              Serial.println("connected");
              ArduinoClient.print( "HEAD /xxxx/save.php?m=nome|g|");
              ArduinoClient.print(conta);
              ArduinoClient.print("|");
              ArduinoClient.println(" HTTP/1.1"); 
              ArduinoClient.println("Host: 192.168.1.180");
              ArduinoClient.println("User-Agent:Arduino");
              ArduinoClient.println("Accept: text/html");
              ArduinoClient.println("Connection: close");
              ArduinoClient.println();
              ArduinoClient.stop();
              } else {
              // VEDERE SE SI PUÒ SALVARE DATI  IN FILE CSV //
              }
    // RESETTA VARIABILI // 
    pausa = 0;
    pausa1 = 0;
    conta = 0; 
    }
  }
}

A grandi linee, perche' non sono un programmatore (e qui di gente piu esperta di me nell'uso degli interrupt ce n'e' tanta), diciamo che usare un'interrupt (come rising, nel tuo caso), ti risolverebbe alcuni problemi ... cerco di fare un'esempio o due al volo.

Mettiamo che l'impulso che fa scattare il contatore meccanico sia molto breve, meno della durata del tuo loop() (difficile, ma non impossibile), se non capita nel momento in cui stai leggendo un'ingresso con digitalread() viene ignorato e quindi non contato ... esempio opposto, mettiamo invece che l'impulso del contatore sia piu lungo del loop, magari lungo come 5 o 10 cicli di loop (possibile se nel loop fai poche cose), allora servirebbe usare una funzione che setti una flag alla prima lettura, in modo che il loop non legga lo stato alto come se fossero 5 o 10 impulsi, uno per ogni giro del loop.

Un'interrupt invece viene azionato in qualsiasi punto del loop, indifferentemente da quello che il loop sta facendo in quel momento (in parole povere si ferma, entra nella ISR, routine interrupt, fa quello che c'e' scritto dentro, esce e ricomincia da dove si era fermato), in questo modo l'impulso viene sempre letto, inoltre impostandolo come "rising", legge solo il passaggio del segnale da 0 ad 1 e non il tempo in cui il segnale rimane alto, per cui sei sicuro che per ogni salita del segnale verra' conteggiato solo un impulso.

Dentro la ISR bisogna fare il meno possibile, per fare in modo che il loop riprenda il piu in fretta possibile, quindi se ad esempio dovessi solo incrementare un contatore, potresti farlo, tipo contatore++ o simile, mentre se ci devi fare altre cose, e' meglio limitarsi a settare una variabile e poi usarla in un'altro punto del loop, ad esempio, dichiara una variabile qualsiasi, chiamala impulso, a 0 nel setup, nella ISR la metti ad 1 (il che vuol dire che e' stato letto un'impulso), poi nel loop la controlli, se la trovi ad 1, fai tutto quello che serve fare quando viene letto un'impulso e la rimetti a 0 per il prossimo.

Grazie @Datman...in effetti quel 4n25 era saltato

Grazie @Etemenanki, approfondirò sicuramente l'argomento per capire se sia il caso di utilizzarlo. Nel frattempo lo sto testando con il codice già condiviso e funziona alla perfezione...non ha perso nemmeno un impulso fino ad ora (condivido i dati inviati al server)

Grazie!!!