Aiuto modifica sketch playground su EEM12L-32A

Ho collegato ad un Arduino Mega questo contatore monofase http://www.energiasolare100.it/contatore-monofase-a-due-cavi-guida-din-con-uscita-impulsi-p-670.html

Ho usato lo sketch preso dal playground Arduino Playground - EEM12L-32AKWhMonitoring utilizzando una resistenza come consigliato nell'articolo ma da 330 ohm.

Da quello che ho visto mi rileva la potenza attuale in step di 0,50 w alla volta e non ha mezze misure. Accendendo il microonde per alcuni minuti a 750W mi segnala potenze variabili da 0.0010 a 0.0015 mentre in situazioni "stabili" mi segnala sempre da 0.0000 a 0.0050 ed inoltre il contatore mi si incrementa ovviamente di 0.0050 alla volta.

Come devo modificare il codice per conoscere l'esatta potenza istantanea in uso da utilizzare magari come stato di allerta in per evitare il distacco del contatore per superamento della soglia?

Grazie mille.

devi misurare il tempo tra un impulso e l' altro.
Ciao Uwe

Buon giorno uwe e grazie per la risposta.
In effetti non lo avevo scritto ma sul fatto che dovessi calcolare il tempo tra T0 e T1 ci ero già arrivato. :wink: Quello che non so è che usando il playground gli interrupt non so come fare a riconoscere in quel codice il mutamento di stato da low ad high. :blush:

Nel codice che hai linkato agganciano un interrupt al passaggio del pin da alto a basso:

attachInterrupt(0, Kirq, FALLING);

Se il tuo problema è misurare lo stato inverso, passaggio da basso ad alto, metti RISING

Documentazione base degli interrupt hardware dell'Arduino:
http://arduino.cc/en/Reference/AttachInterrupt

Il dispositivo fornisce un impulso di 50 ms ogni 0,5 Wh (e non W come erroneamente indicato).

Quindi il programma non fa che sommare gli impulsi che arrivano, azzerandoli nel caso siano superiori al miliardo (500 kWh).

Il programma indicato è probabilmente un prototipo in cui ci sono delle variabili non utilizzate (ad esempio SUM).

Se collego una stufetta da 1kW, leggerò dopo 60 minuti un incremento del contatore (variabile rpk) di 2000 impulsi.

Riceverò, cioè, circa 2000 imp /3600 sec = 0.55 impulsi al secondo.

Grazie a tutti per l'aiuto.
Ho fatto uno sketch di prova mandando usando questo codice

int IRQ = 4; //Utilizzo il pin D19 della Mega
volatile int state = LOW;

long tempo_trascorso;
long durata;


void setup()
{
  Serial.begin(9600);
  pinMode(IRQ, OUTPUT);
  attachInterrupt(4, blink, CHANGE);
}

void loop()
{
  if (!state || (durata == 0))
  {
    // Serial.println ("Nessun evento");
  }
  else
  {
    digitalWrite(IRQ, state);
    Serial.print ("stato dell'irq ");
    Serial.print (IRQ);
    Serial.print (" e'= ");
    Serial.print (state);
    Serial.print (" e sono passati ");
    Serial.print (durata/1000);
    Serial.println (" secondi");
    durata = 0;
  }
}

void blink()
{
  state = !state;
  durata = millis()-tempo_trascorso;
  tempo_trascorso = millis();
}

Secondo voi può andar bene?

Accendendo il solito microonde a 750w per qualche minuto questo è il risultato che mi tira fuori il serial monitor

stato dell'irq 4 e'= 1 e sono passati 9 secondi
stato dell'irq 4 e'= 1 e sono passati 9 secondi
stato dell'irq 4 e'= 1 e sono passati 2 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 3 secondi
stato dell'irq 4 e'= 1 e sono passati 3 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 0 e sono passati 0 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi
stato dell'irq 4 e'= 1 e sono passati 1 secondi

Come mostro ora la potenza istantanea da tenere sotto controllo per evitare il distacco enel in caso di superamento della soglia dei 3Kwh?

Inoltre a cosa è dovuto il quart'utlimo risultato (0 secondi)?

Grazie

"Gli è tutto da rifare..." :smiley:

1 - Il millis() non funziona in una interrupt service routine.
2 - L'attach non può essere su CHANGE poiché la routine viene eesguita due volte.
3 - Il pin sotto interrupt deve essere un input.

da ciò penso si sia capito che sono agli inizi.
Ho usato il change perché con gli altri mi diceva quanto tempo durava quello stato mentre a me serve sapere quanto tempo tempo passa tra due stati high.
È possibile avere un aiuto concreto e meno teorico?
Grazie! :blush:

@cyberhs:
vorrei correggere, o per meglio dire spiegare meglio, un paio di tue affermazioni, per dare informazioni corrette:

cyberhs:
1 - Il millis() non funziona in una interrupt service routine.

Questo è vero solo se si usa il millis per gestire un'attesa perché la routine di gestione dell'interrupt agganciato all'overflow del timer 0 che viene usata per aggiornare il valore del contatore di millisecondi non può funzionare, e quindi millis dà una lettura sempre uguale. La funzione delay, difatti, che si basa sull'incremento di millis, è una funzione il cui uso è senz'altro da evitare in una routine di interrupt. Nel suo caso, però, lui salva il valore di millis in una variabile, non lo usa per creare un'attesa, per cui l'uso che ne fa è del tutto lecito.

3 - Il pin sotto interrupt deve essere un input.

Anche questo non è del tutto corretto perché l'interrupt può essere rilevato indipendentemente dallo stato del pin. Il pin, cioè, può anche essere in stato di output: l'interrupt rileverà lo stesso il cambiamento di stato. Anzi, la tecnica di "scrivere" su un pin agganciato ad un interrupt è spesso usata per simulare degli interrupt software.
Cito dal datasheet (cap 13):

Observe that, if
enabled, the interrupts will trigger even if the INT0 and INT1 or PCINT23...0 pins are configured as outputs. This
feature provides a way of generating a software interrupt.

ziopippo:
...
È possibile avere un aiuto concreto e meno teorico?
Grazie! :blush:

up... :stuck_out_tongue:

Per Leo:
grazie per il completamento delle mie affermazioni, ma confesso che non sapevo della possibilità di lasciare in output un pin e di poter rilevare le variazione sotto interrupt. Si impara sempre...

Per Ziopippo:
non puoi pretendere che si risponda subito alle tue richieste: c'è un tempo tecnico per elaborarle.
Ad esempio, sto approntando uno sketch proprio per te ma devo risolvere ancora qualche punto.

@cyberhs: con il mio up non intendevo mettere fretta a nessuno :wink: ho pensato però che essendo già stato trattato diverse volte sul forum (ma solo a livello teorico) qualcuno avesse già trovato una soluzione :blush:

Come promesso, anche se non l'ho potuto provare!

/*
 KwH
 for Arduino UNO/MEGA R3 & IDE 1.0.1
 by Ettore Massimo Albani 13/02/2013
 www.cyberhs.it
 info@cyberhs.it
 */

const float ImpulsiWh = 0.5;                  // 1 impulso = 0.5 Wh
const long T = 30000;                         // 30 secondi
unsigned long Timer = 0;                      // timer

volatile unsigned int Impulsi = 0;            // impulsi contati
volatile unsigned int ImpulsiMemo = 0;        // memoria impulsi
volatile unsigned long kWh = 0;               // totale energia (kWh)

float W = 0;                                  // potenza istantanea (W)

void setup() {
  Serial.begin(9600);
  attachInterrupt(0, Contatore, FALLING);
}

void loop() {
  if (millis() - Timer > T) {                // timer scaduto 
    if (Impulsi > ImpulsiMemo) {             // lettura valida 
      W = (Impulsi - ImpulsiMemo) * 3600000 / T * ImpulsiWh;
    }
    ImpulsiMemo = Impulsi;
    Timer = millis();                      // timer partito 
  }
  Serial.print("kWh: ");    
  Serial.println(kWh);
  Serial.print("W: ");    
  Serial.println(W, 1);
}

void Contatore() {
  Impulsi ++;                    // incrementa contatore
  if (Impulsi > 1999) {          // raggiunto il kWh 
    kWh ++;                      // incrementa kWh
    Impulsi = 0;                 // azzera contatore
  }
}

Grazie mille! Dopo pranzo la carico e poi ti faccio sapere :wink:
Saluti, Ettore.

Ciao ETTORE! Che bello trovare di rado un omonimo! :smiley:

Rieccomi con i dati rilevati, ma prima volevo innanzitutto ringraziarti :wink: poi dirti che se puoi modificare il tuo post, nel caso questo threed sarà utile a qualcuno, dovresti sostituire questa riga Volatile unsigned long kWh = 0; in volatile unsigned long kWh = 0; :wink: :sweat_smile:

Volevo poi chiederti se secondo il tuo codice al superamento di 1999 W la variabile kWh dovrebbe incrementarsi esatto? Se è così qualcosa non mi torna e ti trascrivo i dati rilevati prima con il solito microonde a 750w questa volta tenuto acceso per 1.30 minuti ma che mi pare abbia fatto segnare la variabile W massimo a W: 4260.0 con l'appunto che nel frattempo i bimbi si stavano lavando le mani aprendo e chiudendo l'acqua azionando quindi la caldaia diverse volte. Non avrebbe dovuto segnare la W a 750.0? Ed inoltre la variabile kWh: non si sarebbe dovuta incrementare?

Ultima cosa, ho notato che il serial monitor prima di visualizzare l'aumento dei valori rilevati impieghi diversi secondi (non so quanti perchè non li ho contati per ho visto che inizia a mostrare valori diversi da zero dopo 1.808 Serial.println(W, 1); ovvero dopo 3.616 righe stampate) è normale?

Ecco i dati stampati dai quali ovviamente per limidi di caratteri posstabili ammessi dal forum ho omesso i doppioni
Allego però un file con tutti i dati rilevati durante il minuto e mezzo.

Contatore KwH for Arduino UNO/MEGA R3 & IDE 1.0.1  by Ettore Massimo Albani 13/02/2013
kWh: 0
W: 0.0
kWh: 0
W: 180.0
kWh: 0
W: 1620.0
kWh: 0
W: 300.0
kWh: 0
W: 1200.0
kWh: 0
W: 4260.0
kWh: 0
W: 480.0
kWh: 0
W: 2040.0

Grazie ancora Ettore. :grin:

Contatore KwH.htm (10.2 KB)

Il contatore emette 2000 impulsi per kWh (0,5Wh/imp).

Questo vuol dire che se ho un carico di 1000W (resistivi) e lo lascio inserito per un ora, il contatore totalizzerà 2000 impulsi.

Accendendo il microonde da 750W per 1.30 minuti (90 secondi) non può totalizzare i 2000 impulsi per apprezzare il kWh: bisognerebbe tenerlo acceso per più di un'ora, per l'esattezza 75 minuti!
Inoltre, il carico, in questo caso, non è puramente resistivo, ma induttivo (cosfi < 1) e quindi P = V x I x cosfi < V x I.

Quindi per calcolare la potenza istantanea devo attendere almeno 30 secondi (variabile T) per beccare almeno qualche impulso.
Comunque se provi ad aumentare il valore della variabile T portandolo a 60000 (60 secondi) il calcolo dovrebbe essere più preciso, ma ovviamente dovrai attendere 60 secondi prima di conoscere la potenza.

A proposito, la costante numerica 36000000 mettila nella forma 36000000.0 altrimenti il calcolo non tiene conto dei decimali.
Metti anche alla fine del loop un delay(1000); per evitare inutili righe.

Tieni presente che lo sketch si dovrebbe migliorare perché è solo un buon punto di partenza.