2 contatore impulsi contemporanei

slave a tutti, sto cercando di leggere 2 contatori di energia con uscita S0 con arduino nano per poi inviarli a emoncms su raspberry per controllo consumi e produzione.
sto usando questo sketch ma ho molte false letture. qualcuno puo aiutarmi a risolvere?

#include <SoftwareSerial.h>
 
const byte rxPin = 5; // Arduino RX = D5
const byte txPin = 6; // Arduino TX = D6
SoftwareSerial mySerial (rxPin, txPin); 

volatile long contatore_rete = 0;
volatile long contatore_pv = 0;
volatile unsigned long pv_pulse_now = 0;
volatile unsigned long pv_pulse_last = 0;
volatile unsigned long rete_pulse_now = 0;
volatile unsigned long rete_pulse_last = 0;
volatile int pv_watt = 0;
volatile int rete_watt =0;
int debounce = 50;
unsigned long ultimo_invio = 0;
unsigned long adesso = 0;

void setup() {
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  attachInterrupt(0, rete, LOW);
  attachInterrupt(1, pv, LOW);
  mySerial.begin(9600); 
}
 
void loop() {
  if (mySerial.available() != 0){
     char carattere = mySerial.read();
     //Serial.println(carattere);
    if(carattere=='@'){
      mySerial.println(String(contatore_rete));
      mySerial.println(String(rete_watt));
      mySerial.println(String(contatore_pv));
      mySerial.println(String(pv_watt));
      mySerial.println('/');
    }
  }
}


void rete(){
  rete_pulse_now = millis();
  if ((rete_pulse_now - rete_pulse_last)> debounce){
    contatore_rete = contatore_rete + 1;
    rete_watt = (3600000/(rete_pulse_now - rete_pulse_last));
    rete_pulse_last = rete_pulse_now;
    
    
  }
}

void pv(){
  pv_pulse_now = millis();
  if ((pv_pulse_now - pv_pulse_last)> debounce){
    contatore_pv = contatore_pv + 1;
    pv_watt = (3600000/(pv_pulse_now - pv_pulse_last));
    pv_pulse_last = pv_pulse_now;
  }
  
}
 

Cosa significa di preciso?

attachInterrupt(0, rete, LOW);

Sei sicuro che "LOW" sia quello che ti serve? Se devi leggere un impulso dovrebbe essere piĂą adeguato "FALLING".

Ciao, Ale.

Cosa significa di preciso?

Come programma è un po' povero:

  1. fai troppa roba nelle ISR
  2. come ti hanno fatto notare usi gli interrupt sbagliati
  3. usi, oltretutto inutilmente, oggetti String
  4. debounce? perché? non sono contatti

dai uno sguardo a
"aiutateci ad aiutarvi"
"la pappa è fatta"
"aiutati che il ciel"

avendo delle false letture credevo che l'utilizzo di low fosse migliore di di falling. lo cambio

come faccio a ridurre le operazioni nelle isr? se voglio la potenza istantanea quello è l'unico punto in cui posso calcolarla...
se c'è un'altro modo si accettano suggerimenti...

Quindi un impulso vale 1joule?

Direi 1 Wh :roll_eyes: … o se proprio ci tieni 3600 J …

Non saprei, non capisco il calcolo che fa
Vediamo se scrivere mi chiarisce le idee
Lui calcola 3megae600mila diviso il tempo tra due impulsi

Quindi se il tempo tra due impulsi, in millisecondi, fosse 3e6centomila avrebbe 1 come risultato

Ovvero un impulso ogni 3600 secondi equivale alla potenza di un vatt
E in 3600 secondi hai ragione 3k6joule

Quindi andiamo avanti
Alla potenza di 3kW avremmo circa un impulso al secondo, facendo il CdS (conto della serva)

C'è tutto il tempo per fare tutti i conti che vogliamo, senza bisogno di intasare la ISR...

A me onestamente non pare che nell'ISR accada questo granchè da sprecare tempo, considerando che il debounce dovrebbe anche essere inutile ed eliminabile.
Poi ci sono tutta una serie di cose strane, dalle inutili String usate nel print, all'uso di Software Serial per comunicare con Raspberry. Passa sicuramente piĂą tempo a scrivere i dati su seriale che non ad eseguire l'ISR.

Ciao, Ale.

Non c’e’ nessun problema a fare quello che fai nelle isr.
Metti gli interrupt su FALLING come ti hanno detto e aumenta il tempo di antirimbalzo in modo da coprire tutta la durata dell’impulso se no rischi che il fronte di salita svaccato generi delle conte spurie. Presumo che tu stia usando una configurazione open collector. Confermi?

Le string le posso anche togliere, per quanto riguarda software serial ho usato quello perchè i pin rx/tx sono gia occupati...

Aldilà del codice, migliorabile, ma se funziona può andare bene anche così, le false letture possono semplicemente provenire da un hardware mal cablato, io ad esempio non ho ancora capito cosa pilota i pin degli interrupt : un relè? Un'uscita open collector? Altro?
A seconda dei casi ad esempio potresti avere miglioramenti usando un pullup esterno, tipo 4.7 o 3.3 Kohm, che ti aumenta senz'altro l'immunitĂ  dai disturbi. Ma bisognerebbe prima sapere cosa ci sta collegato...

Ciao, Ale.

Elimina anche il debounce poiché l'uscita S0 è optoisolata, in breve due terminali C e E del optoisolatore, e quindi non c'è rischio di rimbalzi dei contatti elettromeccanici. C'è anche da vedere che tensione usi, e che resistenza.
Quanto sono lunghi i fili S0+ e S0-?
L'impulso dovrebbe essere all'incirca lungo 30ms.

Sul pin puoi anche provare a mettere un condensatore da 10nF o piĂą specie se i fili sono lunghi.

Ciao.

Sono open collector

i cavi da aurduino ai contatori sono lunghi circa 20cm.
la tensione che uso è 5v.
prima avevo provato a leggerli con raspberry con cavi lunghi circa 10mt ed avevo questo problema, cosi ho provato a mettere un arduino vicino ai contatori ma vedo che il problema continua.
Ho modificato lo sketch cambiando low con falling ed allungando il tempo di debounce a 100ms ma poco fa ho avuto una lettura da 32000watt...

A mio parere pv_watt, rete_watt e debounce devono essere unsigned long.

Inoltre, prima di mandare i dati su seriale, bisogna disabilitare gli interrupt, copiare i valori da stampare in delle variabili di appoggio e riabilitare gli interrupt.

Se disabilita rischia di perdere impulsi

Occorre velocizzare la isr e le routine di stampa

Se limpulso è lungo 30 fare un debounce a 100...

I flags di interrupt rimangono memorizzati e gli interrupt eventualmente avvenuti quando erano disabilitati vengono serviti quando si riabilitano.
Velocizzare riduce solo la probabilita’ che ci siano degli errori dovuti all’incongruenza di variabili composte da piu’ bytes, ma non l’annulla.

L’ impulso non dura 30mS.
30 mS e’ il minimo garantito.

Non lo nego

Ma questo non cambia la questione debounce