Se sei già registrato           oppure    

Orario: 28/03/2024 13:02:49  

 

Energia Alternativa ed Energia Fai Da Te > Elettrodomestici

VISUALIZZA L'ALBUM

Pagine: (12)   1   2   3   4   5   6   7   8   9   [10]   11   12    (Ultimo Msg)


Frigorifero da incasso Rex ENN 2853 COW, Possiamo Migliorarne le prestazioni ???
FinePagina

Riccardo

Avatar
GigaWatt


Gruppo:Utente
Messaggi:2906

Stato:



Inviato il: 30/06/2017 19:30:57

BellaEli,non capisco perchè vuoi amplificare il segnale del sensore di corrente. Per il 712 1A corrispondono ad una variazione di 185 mV
Sono già molto precisi.Ho utilizzato anche i sensori da +- 200A dove 1A corrisponde a 10 mV,ho messo un condensatore al tantalio da 10 microF per stabilizzare le variazioni di tensione e i risultati di precisione sono stati ottimi,alcune piccole variazioni le ho modificate tramite il software.
Nel tuo schema hai già previsto una alimentazione separata per i sensori e dovresti essere ok cosi



---------------
Q.CELLS Q.PEAK 4575W sud-est
Solar Frontier CIS 850W sud-ovest
Inverter PIP5048MST
Batterie:LifePo4 Seplos MASON-48280-DIY EVE280AK 28,6 kWh
Scaldabagno Ferroli 30l 1500w
Scaldabagno Ariston 80l 1200w

 

calcola
GigaWatt


Gruppo:Utente
Messaggi:4435

Stato:



Inviato il: 30/06/2017 19:43:53

Non so, probabilmente parliamo di due cose diverse. La corrente alternata la si può misurare sia con l'unidirezionale che con il bidirezionale.

L'acs712 non é molto preciso, prova e vedrai, specialmente misurando corrente alternata. In passato ho provato più volte confrontando i valori ottenuti con quelli letti dal tester, lo scarto sempre elevato. Ho provato vari algoritmi di calcolo e librerie diverse, il risultato sempre scadente. Per tale motivo nella mia centralina del fv non ho un sensore che mi calcola la corrente 220 ottenuta. Ho un contatore a valle dell'inverter, non nella centralina.

Non ci sono riuscito, ma non é detto che tu non riesca, anzi...



---------------
Impara l'arte e mettila da parte
14 pannelli da 100w, inverter kemapower 3kw, regolatore morningstar tristar ts60, banco batterie n.1 di 12 elementi 2v 480Ah C5 corazzate per trazione pesante, banco batterie n.2 di 400Ah in C5 formato da 24 elementi 2V 200Ah corazzate al gel per fotovoltaico in due serie da 12 elementi, centralina di gestione impianto autoprodotta.

 

calcola
GigaWatt


Gruppo:Utente
Messaggi:4435

Stato:



Inviato il: 30/06/2017 19:47:33


CITAZIONE

Ho utilizzato anche i sensori da +- 200A dove 1A corrisponde a 10 mV,ho messo un condensatore al tantalio da 10 microF per stabilizzare le variazioni di tensione e i risultati di precisione sono stati ottimi,alcune piccole variazioni le ho modificate tramite il software.


In alternata?



---------------
Impara l'arte e mettila da parte
14 pannelli da 100w, inverter kemapower 3kw, regolatore morningstar tristar ts60, banco batterie n.1 di 12 elementi 2v 480Ah C5 corazzate per trazione pesante, banco batterie n.2 di 400Ah in C5 formato da 24 elementi 2V 200Ah corazzate al gel per fotovoltaico in due serie da 12 elementi, centralina di gestione impianto autoprodotta.

 

Riccardo

Avatar
GigaWatt


Gruppo:Utente
Messaggi:2906

Stato:



Inviato il: 30/06/2017 19:59:26

No in C.C.
@ BellaEli Rileggendo il post ho capito come mai vuole usare l'operazionale per aumentare la sensibilità per arrivare sui 10 mA



---------------
Q.CELLS Q.PEAK 4575W sud-est
Solar Frontier CIS 850W sud-ovest
Inverter PIP5048MST
Batterie:LifePo4 Seplos MASON-48280-DIY EVE280AK 28,6 kWh
Scaldabagno Ferroli 30l 1500w
Scaldabagno Ariston 80l 1200w

 

BellaEli

Avatar
GigaWatt


Gruppo:MODERATORE
Messaggi:3286

Stato:



Inviato il: 30/06/2017 20:35:52

Forse parliamo di 2 cose diverse e non riusciamo a comprenderci...
Vediamo di sbrogliare la matassa!

Io non devo misurare la produzione di un pannello fotovoltaico, ma qualcosa di più complesso, osserviamo questa immagine:

http://www.energialternativa.info/public/newforum/ForumEA/R/instvi.png



La curva rossa è la tensione, quella blu la corrente.

Io dovrò misurare, istante per istante, le due curve (circa 50 campioni per sinusoide) per poter calcolare Tensione RMS, Corrente RMS, Potenza Attiva, Reattiva e Apparente, kWh, etc.

Per far ciò devo essere capace di leggere sia tensioni positive che negative, da qui la necessità di spostare l'offset della lettua su 1/2 Vcc.

Ora per poter calcolare con sufficiente precisione ogni valore dovrò utilizzare un'hardware che sia sufficientemente preciso e stabile, da qui la scelta di alcune soluzioni tecniche circuitali.

Non posso fare medie o filtrare i segnali, altrimenti le letture saranno falsate !

Infatti i vari filtri che ho e sto inserendo lavorano tutti a frequenze comprese tra i 500 e i 1.000 Hz (l'idea è di campionare a 2,5 kHz ogni segnale) proprio per non perdermi informazioni utili come picchi di assorbimento.


CITAZIONE (Riccardo, 30/06/2017 19:30:57 ) Discussione.php?214604&10#MSG136
...Ho utilizzato anche i sensori da +- 200A dove 1A corrisponde a 10 mV,ho messo un condensatore al tantalio da 10 microF per stabilizzare le variazioni di tensione e i risultati di precisione sono stati ottimi...

Come spiegato sopra non posso permettermi il lusso di stabilizzare la lettura con un condensatore di capacità elevata, perderei importani informazioni e falserei completamente la lettura.

CITAZIONE (Riccardo, 30/06/2017 19:30:57 ) Discussione.php?214604&10#MSG136
Nel tuo schema hai già previsto una alimentazione separata per i sensori e dovresti essere ok cosi

Non del tutto... Se, ad esempio, l'uscita del 7805 passa da 4.97 a 4,95 Volt per qualsiasi motivo (termico, disturbi, etc.) tramite tutta la catena di componenti arduino considerebbe tale variazione come un assorbimento di 20 mA in meno, ovvero circa 4,4 Watt in meno !
Quindi debbo adottare soluzioni che annullino tale errore, da qui l'idea di campionare anche l'offset.
Ovviamente è tutto da verificare, è solo un'idea.


CITAZIONE (calcola, 30/06/2017 19:43:53 ) Discussione.php?214604&10#MSG137
Non so, probabilmente parliamo di due cose diverse. La corrente alternata la si può misurare sia con l'unidirezionale che con il bidirezionale.

Mi fai capire come ?

CITAZIONE (calcola, 30/06/2017 19:43:53 ) Discussione.php?214604&10#MSG137
L'acs712 non é molto preciso, prova e vedrai, specialmente misurando corrente alternata.

Si, ho visto di tante brutte esperienze con l'ACS ma ancora non ci sbatto la testa per desistere !

Scherzi a parte credo che se hanno fatto quel sensore che misura correnti con considerevole precisione ci sarà un modo di farlo funzionare... basta solo trovarlo !!!

CITAZIONE (calcola, 30/06/2017 19:43:53 ) Discussione.php?214604&10#MSG137
In passato ho provato più volte confrontando i valori ottenuti con quelli letti dal tester, lo scarto sempre elevato....

La speranza è di riuscire a trovare un metodo che permette di utilizzare correttamente il sensore, per questo l'ho contornato di qualche componente accessorio...


CITAZIONE
@ BellaEli Rileggendo il post ho capito come mai vuole usare l'operazionale per aumentare la sensibilità per arrivare sui 10 mA

Esatto !



---------------
C'è un limite al fai da te ???
Si, ma lo stabiliamo noi !!!

 

Riccardo

Avatar
GigaWatt


Gruppo:Utente
Messaggi:2906

Stato:



Inviato il: 30/06/2017 20:47:30

CITAZIONE (BellaEli, 30/06/2017 20:35:52 ) Discussione.php?214604&10#MSG140



CITAZIONE (Riccardo, 30/06/2017 19:30:57 ) Discussione.php?214604&10#MSG136
...Ho utilizzato anche i sensori da +- 200A dove 1A corrisponde a 10 mV,ho messo un condensatore al tantalio da 10 microF per stabilizzare le variazioni di tensione e i risultati di precisione sono stati ottimi...

Come spiegato sopra non posso permettermi il lusso di stabilizzare la lettura con un condensatore di capacità elevata, perderei importani informazioni e falserei completamente la lettura.


Non mi sono spiegato,il condensatore è sull'alimentazione(+5v/massa)vicino al sensore non sul valore di tensione rilevato,questo per ovviare alla distanza del sensore da Arduino circa 3-4 metri



---------------
Q.CELLS Q.PEAK 4575W sud-est
Solar Frontier CIS 850W sud-ovest
Inverter PIP5048MST
Batterie:LifePo4 Seplos MASON-48280-DIY EVE280AK 28,6 kWh
Scaldabagno Ferroli 30l 1500w
Scaldabagno Ariston 80l 1200w

 

BellaEli

Avatar
GigaWatt


Gruppo:MODERATORE
Messaggi:3286

Stato:



Inviato il: 02/07/2017 16:08:38

Allora, dopo aver studiato un po' di cosette inizio ad aver le idee un po' più chiare sul da farsi, vediamo di capire come vorrei procedere:

Nel setup andrà configurato uno dei tre timer per richiamare una funzione di interrupt ad intervalli prestabiliti.
Questo vuol dire che mentre il codice della funzione loop gira ad un certo punto, ad intervalli precisissimi, basati sul quarzo, il codice si interrompe e parte la funzione di interrupt richiamata, in automatico, dal timer.
Il codice presente nella funzione interrupt dovrà essere molto veloce e privo di funzioni bloccanti (delay, etc.) per evitare che la stessa funzione possa essere richiamata prima che la precedente chiamata abbia completato di eseguire il codice in essa contenuto (mi sono capito ???).
Basando il ragionamento su Arduino, poiché il suo clock è di 16 MHz vuol dire che viene eseguita una istruzione ogni: 1 s / 16.000.000 Hz = 0,000.000.0625 s, ovvero una istruzione ogni 62,5 nS, quindi la configurazione del timer richiamerà la funzione di interrupt ad intervalli multipli di tale valore.
Dopo una serie di valutazioni ritengo di lanciare la funzione di interrupt ad intervalli di 125 uS.
La prima lettura sarà la tensione, la seconda la corrente, la terza l'offset per poi ripartire dalla tensione.
Quindi nella sinusoide di rete a 50 Hz, in cui ogni onda completa ha una durata di 1 s / 50 Hz = 0,02 s, ovvero 20 mS, viene campionata: 20 mS / (3 x 125 uS) = 53,3 volte.
Quindi su ogni sinusoide ci saranno 53 campioni per la tensione, 53 per la corrente e 53 per l'offset.
I singoli campioni di tensione e corrente verranno elaborati matematicamente per ottenere tutti i valori desiderati di tensione RMS, corrente RMS, potenza, etc.

Sembra tutto facile ma, ovviamente, non lo è: un problema importante è capire se l'ADC sia in grado di essere così veloce a campionare i segnali.
Di quanti "sample" stiamo parlando ? Semplice: 1 s / 0,000.125 s = 8.000 SPS !
Per capire se possiamo essere così veloci dobbiamo capire i tempi dell'ADC, quindi provo a descrivere come funziona.
Si parte sempre dal clock di 16 MHz, il quale viene "rallentato" dal prescaler (immaginatelo come un divisore di frequenza dove entrano 16 MHz ed escono 16 MHz diviso un numero a nostro piacimento multiplo di 2). Di default il prescaler dell'ADC di arduino è settato a 128, quindi alla sua uscita avremo un clock di 16 MHz / 128 = 125 kHz.
Secondo le specifiche dell'atmega 328P il clock dell'ADC deve essere compreso tra 50 e 200 kHz per garantire la precisione dichiarata di 1 LSB (non è una allucinogeno !!!).
Se si superano i 200 kHz l'ADC continuerà a funzionare perdendo precisione.
Sul datasheet viene specificato che se ci si accontenta di una risoluzione inferiore è possibile far funzionare l'ADC fino a 1 MHz, oltre tale valore il datasheet non non si pronuncia, non negandone il funzionamento.
Ok, quindi l'ADC lavora con un clock di 125 kHz, ovvero un colpo di clock ogni: 1 s / 125.000 Hz = 0,000.008 s, ovvero 8 uS.
Bene, ma quanti cicli di clock servono all'ADC per effettuare una lettura su una porta analogica ?
Purtroppo questo dato non è costante, ma dipende dal valore letto, in ogni caso il datasheet dichiara che mediamente una lettura dura 13 colpi di clock: quindi 8 uS x 13 = 104 uS.
Azz... Basta che una lettura duri 16 cicli di clock e avremo: 16 x 8 uS = 128 uS !!!
Quindi c'è il risciò che una singola lettura sia più lenta dell'intervallo con cui viene chiamata la funzione di interrupt !!!
Da prove pratiche una lettura dura mediamente 15 cicli, 120 uS, in ogni caso troppo vicini al limite, quindi le soluzioni sono 2: o si diminuiscono il numero di campioni per sinusoide, ovvero anziché 53 se ne fanno 33, ad esempio, portando l'intervallo di campionamento a circa 200 uS oppure si aumenta il clock dell'ADC, riducendo il tempo necessario all'adc per leggere un campione.
Mi piace questa seconda opzione, così ipotizzando di settare il prescaler dell'ADC a 64 avrei un clock per l'ADC di: 16.000.000 MHz / 64 = 250 kHz, leggermente fuori specifica ma si può provare.
Con questa frequenza ogni colpo di clock durerà 1 s / 250.000 Hz = 0,000.004 s, ovvero 4 uS.
Quindi, se mediamente una lettura impiega 15 cicli di clock, l'ADC impiegherà 15 x 4 uS = 60 uS, meno della metà del tempo che intercorre tra una chiamata e l'altra della funzione interrupt, perfetto !

Allora abbiamo risolto ogni problema ??? No, ovviamente...

Un altro ostacolo da superare è il fatto che la funzione analogRead di Arduino è una funzione bloccante, ovvero una volta lanciata il codice si interromperà per circa 60 uS in attesa della lettura del dato!!!
Ma come, abbiamo un hardware che potrebbe lavorare comodamente in parallelo al codice senza bloccarlo e non lo sfrutto ???
Certo che lo sfrutto !!! Come ?: o si interagisce direttamente con i registri del micro oppure si usa una libreria che ci permette di leggere l'ADC senza bloccare il codice.
Ovviamente questa seconda opzione va benissimo al mio caso, non ho necessità di spingermi oltre...
Tale libreria (al momento non ricordo il nome), tra le altre cose, ha 3 funzioni:
1) Avvia lettura da porta x
2) È pronto il dato ?
3) Leggi dato.

Quindi ricapitolando il tutto, nel setup setterò:
1) Uno dei 3 timer per richiamare la funzione di interrupt ogni 125 uS;
2) Prescaler dell'ADC a 64;
3) Nella funzione di interrupt leggerò il valore, avvierò la lettura successiva ed effettuerò i vari calcoli matematici per I, V e P;
4) Nel loop, invece, saranno gestire le 7 sonde di temperatura e l'invio in rete delle letture.

Tutto chiaro ? Dubbi ? Errori ? Suggerimenti ?

Elix



Modificato da BellaEli - 03/07/2017, 12:55:07


---------------
C'è un limite al fai da te ???
Si, ma lo stabiliamo noi !!!

 

calcola
GigaWatt


Gruppo:Utente
Messaggi:4435

Stato:



Inviato il: 02/07/2017 17:41:45

Se non ricordo male la libreria del dallas inserisce un delay ad ogni lettura.



---------------
Impara l'arte e mettila da parte
14 pannelli da 100w, inverter kemapower 3kw, regolatore morningstar tristar ts60, banco batterie n.1 di 12 elementi 2v 480Ah C5 corazzate per trazione pesante, banco batterie n.2 di 400Ah in C5 formato da 24 elementi 2V 200Ah corazzate al gel per fotovoltaico in due serie da 12 elementi, centralina di gestione impianto autoprodotta.

 

BellaEli

Avatar
GigaWatt


Gruppo:MODERATORE
Messaggi:3286

Stato:



Inviato il: 04/07/2017 03:32:48

CITAZIONE (calcola, 02/07/2017 17:41:45 ) Discussione.php?214604&10#MSG144

Se non ricordo male la libreria del dallas inserisce un delay ad ogni lettura.

E' un problema che affronterò a tempo debito ma credo che la funzione interrupt abbia priorità sul delay.
Spero solo che ciò non crei problemi sulla comunicazione con le sonde dallas...
In ongi caso la funzione di interrupt dovrebbe essere eseguita in tempi davvero piccoli, probabilmente nell'ordine di microsecondi.

Chiacchierando con Bolle è venuta fuori una questione interessante:
avevo già accennato al problema dell'offset delle sonde ACS712 da 5A, ovvero che loro tirano fuori una tensione di Vcc/2 per correnti pari a 0 e salgono o scendono rispetto a tale valore di 185 mV per Amper.
La questione era che se Vcc, per qualsiasi motivo, non risulta stabile il software considererebbe tale variazione come una variazione di corrente circolante nell'ACS.
Per eliminare tale problema avevo ipotizzato di adottare 2 tecniche:
1) Utilizzare un 78L05 per stabilizzare e alimentare solamente l'ACS;
2) Campionare Vcc/2 in modo che una qualsiasi variazione di tensione fosse compensata a livello software (differenziale software).

Tale meccanismo, almeno sulla carta, dovrebbe essere efficace tuttavia ha un grosso aspetto negativo: mi costringe a "sprecare" un campione dell'ADC solo per compensare un errore di lettura...

C'è un metodo semplice per ovviare a ciò ? Ovvero compensare in hardware, senza sprecare un campione dell'ADC ?
In effetti la soluzione è molto semplice (ed è anche quella che in realtà permette all'ADC di funzionare abbastanza bene anche con tensioni ballerine): collegare il pin AREF dell'ADC direttamente all'uscita del 78L05 che alimenta l'ACS !
In questo modo una eventuale variazione della Vcc/2 viene compensata in ardware dall'ADC stesso poichè si vede i riferimenti cambiati !

Quindi si rende necessaria la prima delle revisioni (ma quante saranno ???) dello schema elettrico, ecco la versione 1.1:

http://www.energialternativa.info/public/newforum/ForumEA/R/schema1.png



Quindi ho tolto il collegamento di Vcc/2 sul pin dell'ADC e l'ho collegato ad AREF, ho risistemato le etichette dei componenti, ritoccato qualche valore e ho ridisegnato l'ACS, aggiungendo delle note.
Leggendo con attenzione il datasheet dell'ACS ho approfondito la questione del pin 6, ovvero un pin predisposto per inserire una capacità di filtro (passa basso) sul segnale in uscita.
Ora, poichè io campiono a frequenza limitata (per il momento sto a 2,5 kSPS), non mi interessano spike o disturbi vari e non voglio incorrere in problemi di aliasing, preferisco limitare la banda passante dell'ACS, per cui ho previsto di parallelare al C2 dell'ACS una capacità di 100 nF per introdurre un primo polo a circa 900 Hz, il secondo, a circa 600 Hz, sta sull'operazionale IC1/B.
Inoltre ho previsto l'inserimento di una capacità da 10 uF (sarebbe preferibile al tantalio per le eccellenti caratteristiche) in parallelo al C1 dell'ACS, per stabilizzare ulteriormente eventuali piccole variazioni introdotte dai collegamenti.

A questo punto il precedente ragionamento sui tempi di campionamento dovrà essere conseguentemente rivisto...
Visto che ora devo campionare solo 2 valori, volendo mantenere inalterati il numero di campioni (circa 50) potrei lasciare il prescaler dell'ADC a 128 per mantenere la frequenza di clock dell'ADC a 125 kHz (come da specifiche) e campionare ogni circa 187,5 uS.
In questo modo dovrei ampiamente starci coi tempi mantenendo un'altra precisione dei campioni.

Ho ritrovato la libreria per la lettura dell'ADC senza bloccare il codice, si tratta della libreria pollingAnalogRead (prelevabile anche qui).

I lavori continuano in mezzo a tanti altri... ma vi terrò aggiornati.

Elix



Modificato da BellaEli - 04/07/2017, 03:37:11


---------------
C'è un limite al fai da te ???
Si, ma lo stabiliamo noi !!!

 

BellaEli

Avatar
GigaWatt


Gruppo:MODERATORE
Messaggi:3286

Stato:



Inviato il: 05/07/2017 13:08:30

Ho iniziato a fare qualche prova col codice e, come immaginavo, è abbastanza complicato far funzionare tutto alla perfezione...

Descrivo per sommi capi l'impostazione di base per poterci ragionare su:

*****************************************
#include...
#define...
int...

void setup() {
Impostazioni Timer1 e ISR
Impostazioni DisplayLCD
Impostazioni varie...
}

void loop() {
Visualizza Dati su LCD
Se i dati sono pronti richiama la funzione di calcolo
}

void CalcoloValori() {
Calcolo TensioneRMS
Calcolo CorrenteRMS
Calcolo PotenzaAttiva
Calcolo PotenzaReattiva
Calcolo PotenzaApparente
Calcolo Cosfi
Calcolo Frequenza
}

void ISR() {
Se la chiamata è "pari" leggi campione Tensione
Se la chiamata è "dispari" leggi campione Corrente

Se è iniziata una nuova sinusoide (passaggio per zero, in salita)
salva i dati locali in variabili globali e setta la variabile di "dati pronti"
}
*****************************************


Ok, questa l'impostazione di base, ora i problemi :

1) Come faccio a sapere quando è iniziata una nuova sinusoide ?

Attualmente ho utilizzato un sistema molto semplice, più o meno questo:

Se (sono trascorsi 18 mS) e (il precedente campione era < 0) e (il campione attuale >= 0)
vuol dire che è iniziata una nuova sinusoide.

Almeno in teoria dovrebbe funzionare, a meno di non avere una sinusoide talmente disturbata da non riuscire a capire cosa succede, tuttavia il fatto che devono essere trascorsi 18 mS mi mette al riparo da situazioni assurde.

Ci potrebbero essere soluzioni migliori ?


2) Essendo la ISR richiamata con cadenza di 200 uS, di fatto la prima chiamata potrebbe ricadere sullo "0" oppure più avanti, inoltre la ISR non è sincronizzata con l'onda Enel, quindi i campioni, in ogni sinusoide letta, potrebbero essere traslati leggermente in avanti o indietro.
Ciò implica qualche tipo di problema ?


3) Da test effettuati, con 50 campionamenti per sinusoide, la ISR (richiamata ogni 200 uS) così scritta impiega circa 40 uS per eseguire tutto il codice in essa contenuto, le letture dell'ADC (che avvengono contemporaneamente all'esecuzione del codice) impiegano circa 120 uS.
Quindi ho:
- Campionamenti per sinusoide 50
- ISR chiamata ogni 200 uS
- Codice eseguito in circa 20-40 uS
- Letture ADC eseguite in circa 120 uS

Potrebbe essere vantaggioso raddoppiare i campionamenti ?
Ovvero dovrei raddoppiare la frequenza di clock dell'ADC (andando fuori specifiche, ma comunque dovrebbe funzionare bene, anche per via degli operazionali a bassa impedenza prima dell'ADC) e lanciare la ISR ogni 100 uS.

Quindi avrei:
- Campionamenti per sinusoide 100
- ISR chiamata ogni 100 uS
- Codice eseguito in circa 20-40 uS
- Letture ADC eseguite in circa 60 uS


4) E' corretto l'approccio di effettuare i calcoli alla fine di ogni sinusoide o potrebbe essere più vantaggioso rimandare i calcoli ogni, che so, 10, 20 o più sinusoidi ?


5) E' corretto l'approccio di usare l'ISR o potrebbe essere più conveniente un approccio diverso (già fatto da qualcun altro) del tipo:

- Aspetto il passaggio per lo zero;
- Effettuo i campionamenti stabiliti (50, 100, etc.);
- Effettuo tutti i calcoli

In questo modo vengono analizzate solo le sinusoidi pari (o dispari), poichè in quelle pari viene effettuata la lettura, in quelle dispari i calcoli e poi si attende un nuovo passaggio per lo zero per riniziare le letture.


6) Il calcolo della frequenza lo effettuo contando quanti campioni da 200 uS sono serviti per trovare un nuovo passaggio per lo zero, ciò implica una risoluzione di circa 1 Hz.
Per avere una lettura precisa dovrei cambiare totalmente approccio, ma... ha senso farlo ? Ossia serve conoscere con precisione la frequenza di rete ?



Elix



Modificato da BellaEli - 05/07/2017, 13:26:05


---------------
C'è un limite al fai da te ???
Si, ma lo stabiliamo noi !!!

 

BellaEli

Avatar
GigaWatt


Gruppo:MODERATORE
Messaggi:3286

Stato:



Inviato il: 05/07/2017 16:55:56

Altro dubbio...

7) Ma serve davvero sapere quando sto passando per lo 0 ???
Cioè potrei campinare a 200 uS senza sapere in quale punto della sinusoide sono e fare i calcoli dopo 20 mS, tanto i valori di Tensione, Corrente e Potenza non sono legati al punto in cui si avvia e finisce la misurazione, l'importante è che nell'intervallo di 20 mS ci sia tutta la sinusoide (e anche su questo aspetto dovrei essere tranquillo).

Elix



---------------
C'è un limite al fai da te ???
Si, ma lo stabiliamo noi !!!

 

BellaEli

Avatar
GigaWatt


Gruppo:MODERATORE
Messaggi:3286

Stato:



Inviato il: 14/07/2017 18:53:46

Qualche aggiornamento...

I lavori sono andati avanti con una marea di difficoltà da risolvere...

Una grossa difficoltà che ho dovuto gestire è stata la difficoltà nel debbuggare la funzione di interrupt (ISR).
Questa viene lanciata in automatico, dal micro, ogni 200 uS bloccando qualsiasi altro codice in esecuzione e, una volta terminata, il codice normale riprende.

A differenza del normale codice nel loop, dove se qualcosa non va ce ne accorgiamo con dei Serial.print, etc., la ISR è una funzione asincrona, ovvero parte in qualsiasi momento, fa quello che deve fare (se ci riesce), si chiude e il codice del loop riprende.

Nella ISR non posso inserire istruzioni lente (Serial.print) o delay per fare delle verifiche, per cui l'unico modo che ho trovato per verificare se il codice funzionasse correttamente è stato quello di modificare lo stato di un pin digitale al verificarsi di una determinata condizione e visualizzare tale variazione con l'oscilloscopio !

Metodo complicato ma che alla fine ha funzionato.

Altro strano problema l'ho avuto sul sensore ACS712 da 5 A: secondo il datasheet dovrebbe tirare fuori una tensione di +/- 185 mV per Amper rispetto a Vcc/2, in realtà il mio ne tira fuori solo 135 !
Ovvero collegando Vcc, GND e un tester sull'uscita, facendo scorrere 1 Amper ho una variazione di 135 mV, 2 A 270 mV, etc.
Ho dovuto modificare lo schema inserendo un trimmer di regolazione del guadagno...

Inoltre se la corrente assorbita supera un certo valore (ad esempio se collego un trapano come carico) il sensore va in blocco, la tensione in uscita si piazza a circa Vcc/2 e l'unico modo per farlo ripartire è staccare l'alimentazione: è capitato anche a voi ?

Attualmente mi ritrovo con uno strumento di misura che va tarato prima di utilizzarlo, ma come lo taro ? Ovvero mi fido del Tester ? O ci potrebbero essere altri metodi più convenienti ?


In ogni caso, la difficoltà più grande che ho dovuto superare è stata la misura dei valori Tensione, Corrente e Potenze: lavorando in regime sinusoidale le difficoltà sono molto più grandi di quello che si possa immaginare...

Credo che il grosso sia fatto, attualmente riesco ad ottenere letture molto stabili e precise di Tensione RMS, Corrente RMS, Potenza Attiva, Reattiva, Apparente e CosFi oltre i valori di campionamento della Tensione e della Corrente rilevati.

Ah, quasi dimenticavo, un gigantesco problema in cui mi sono imbattuto è il seguente: Una sinusoide dei 50 Hz dura 20 mS, infatti 1 S / 50 Hz = 0,02 S, ovvero 20 mS.

Campionando a 200 uS, ovvero a 0,2 S, mi occorrono 100 campioni per completare tutta la sinusoide.

Ingenuamente ho impostato 200 uS ed eseguito il codice.

Tuttavia mi ritrovavo con una Tensione RMS che oscillava, con forma perfettamente sinusoidale, di circa 5 Volt.

Dopo non so quante prove mi sono accorto che l'onda sinusoidale della 220 Volt non durava 20 mS ma solo 19,6 mS (51,02 Hz), quindi campionando a 200 uS andavo a leggere un pezzettino della sinusoide successiva...

Abbassando il tempo di campionamento a 196 uS il problema si è risolto rendendo stabilissima la lettura della Tensione RMS.

Tuttavia si presenta un nuovo problema: se la frequenza varia lo strumento inizierà a mostrare valori ballerini ??? Devo gestire il problema in automatico...
Ma poi, davvero la rete enel sta a 51 Hz ??? E perchè ???

Ogni osservazione, contestazione, suggerimento è graditissimo, rendere la scheda stabile si è rilevato molto più difficile del previsto !

Elix


Questo il cocice scritto fin'ora, ci sono ancora molte cose da aggiungere ma la lettura dei valori funziona correttamente.


#include <pollingAnalogRead.h>                                                // Inclusione Librerie

// #define Soglia 3199                                                           // Soglia ICR1 per Tempo di Campionamento: 200,0 µS con 16 MHz e Prescaler a 1

#define N_Elem 15.0                                                           // Numero di Elementi per la media dei valori calcolati
// #define CoeffV 152.0                                                          // Costante di Conversione per Tensione
#define CoeffV 348.0                                                          // Costante di Conversione per Tensione
#define CoeffI 2.119767                                                       // Costante di Conversione per Corrente

volatile bool  DatiPronti, Let_V = true;                                      // Dichiarazioni Variabili
volatile int   Rig, Col, Offset_V = 511, Offset_I = 511;
volatile long  Dato_ADC, Somma_V_2, Somma_I_2, Somma_P_W;
volatile float NumCampioni, SommaV2, SommaI2, SommaPW;

volatile int   VI[50][4];                                                     // Vettore dei singoli campioni della Tensione e della Corrente

float TensioneRMS, CorrenteRMS, PotenzaAttiva, PotenzaReattiva, PotenzaApparente, FattorePotenza, kV, kI, kP;
float V_Media, I_Media, P_Media, VA_Media, VAR_Media, Cosfi_Media;


// Variabili Temporanee per Debug
volatile int Max_Campioni, Campioni_Tot, contatore;
volatile unsigned long Letture_Ok;
volatile unsigned long Start_Time, Middle_Time, Stop_Time, Tempo_Parz, Tempo_Tot, Start;
volatile int Uscita, Colon, V1, V2, V3, V4;

int Soglia = 3136;





void setup() {
  int i;
  float Temp;
  
  pinMode (2, INPUT_PULLUP);                                                  // Impostazione Pin
  pinMode (3, INPUT_PULLUP);
  pinMode (4, INPUT_PULLUP);
  pinMode (13, OUTPUT);

  pollingAnalogReference(EXTERNAL);                                           // Imposto l'ADC per usare AREF

  if (digitalRead(2) == LOW) {                                                // Se all'accensione è premuto il pin per il "Service Mode"
    for (i = 0; i < 100; i++) {                                               // Calcolo l'offset della Tensione (Occorre prima mettere a massa l'ingresso dell'operazionale)
      Temp += (float)analogRead(A0);
      delay(10);      
    }
    Offset_V = ((int)(Temp / 100.0)) + 1;

    Temp = 0.0;
    for (i = 0; i < 100; i++) {                                               // Calcolo l'offset della Corrente (Occorre prima scollegare qualsiasi carico dall'ACS)
      Temp += (float)analogRead(A1);
      delay(10);      
    }
    Offset_I = ((int)(Temp / 100.0)) + 2;

    for (i = 0; i < 10; i++) {                                                // Faccio lampeggiare 10 volte il Led sulla Board di Arduino collegato al pin 13 per l'Ok
      digitalWrite(13, HIGH);
      delay(100);      
      digitalWrite(13, LOW);
      delay(100);      
    }
  }

  triggerAnalogRead(A0);                                                      // Effettuo una lettura per inizializzare l'ADC e preparare il dato per l'ISR

  TCCR1A = 0;                                                                 // Azzeramento registri TCCR1A e TCCR1B
  TCCR1B = 0;                                                                 // per annullamento impostazioni "Init" di Arduino

  TCCR1A |= (1 << WGM11);                                                     // Modalità Fast PWM a che conta da 0 fino a ICR1
  TCCR1B |= (1 << WGM12) | (1 << WGM13);

  TCCR1B |= (1 << CS10);                                                      // Prescaler a 1

  ICR1 = Soglia;                                                              // Impostazione Soglia a 200,0 µS (con Fck 16,0 Mhz e Prescaler 1)

  TIMSK1 |= (1 << TOIE1);                                                     // Abilitazione ISR su OverFlow

  sei();                                                                      // Avvio gli interrupt

  kV = CoeffV * 5.0 / 1023.0;                                                 // Calcolo i coefficienti di conversione per Tensione, Corrente e Potenza
  kI = CoeffI * 5.0 / 1023.0;
  kP = (CoeffV * CoeffI * 5.0 * 5.0) / (1023.0 * 1023.0);

  Serial.begin(115200);                                                       // *** Debug: abilitazione interfaccia Seriale
}





void loop() {

  if (DatiPronti) CalcolaValori();
  
/*
  int i, indice = 0;
  if (Col == 0) indice = 2;

    Serial.print   (VI[0][0]);
    Serial.print   ("\t");
    
    Serial.print   (VI[0][1]);
    Serial.print   ("\t");
*/

  if (millis() - Start > 250) {
    Start = millis();

    Serial.print   ("Vrms: ");
    Serial.print   (TensioneRMS, 1);                                           // V-RMS
    Serial.print   ("\t");

    Serial.print   ("Irms: ");
    Serial.print   (CorrenteRMS, 2);                                           // I-RMS
    Serial.print   ("\t");

    Serial.print   ("P Watt: ");
    Serial.print   (PotenzaAttiva, 1);                                         // P-Watt
    Serial.print   ("\t");

    Serial.print   ("P VA: ");
    Serial.print   (PotenzaApparente, 1);                                      // P-VA
    Serial.print   ("\t");

    Serial.print   ("P VAR: ");
    Serial.print   (PotenzaReattiva, 1);                                       // P-VAR
    Serial.print   ("\t");
    
    Serial.print   ("CosFi: ");
    Serial.println (FattorePotenza, 2);                                        // CosFi
  }
}





// Funzione per il calcolo dei valori letti. La presenza di calcoli matematici complessi (lenti) costringe lo spostamento di tale codice al di fuori della ISR
// Per stabilizzare le letture, sui valori letti viene fatta una pseudo-media degli ultimi N_Elem

void CalcolaValori() {
  float V, I, P, VA, VAR, Cosfi;

  V = kV * sqrt(SommaV2 / NumCampioni);                                        // Calcolo la Tensione RMS, kV = 5 * Coeff. Tens. / 1023
  V_Media -= V_Media / N_Elem;
  V_Media += V;
  TensioneRMS = V_Media / N_Elem;                                              // Il valore di TensioneRMS sarà circa la media degli ultimi N_Elem

  I = kI * sqrt(SommaI2 / NumCampioni);                                        // Calcolo la Corrente RMS, kI = 5 * Coeff. Corr. / 1023
  I_Media -= (I_Media / N_Elem);
  I_Media += I;
  CorrenteRMS = I_Media / N_Elem;
  if (CorrenteRMS < 0.1) CorrenteRMS = 0.0;                                    // Se il valore letto è inferiore a 10 mA (risoluzione strumento) lo metto a 0

  P = kP * SommaPW / NumCampioni;                                              // Calcolo la Potenza Attiva in Watt, kP = (Coeff. Tens. * Coeff. Corr. * 5 * 5) / (1023 * 1023);
  P_Media -= P_Media / N_Elem;
  P_Media += P;
  PotenzaAttiva = P_Media / N_Elem;
  if (CorrenteRMS == 0.0) PotenzaAttiva = 0.0;                                 // Se la corrente è inferiore a 10 mA azzero la Potenza Attiva

  VA = V * I;                                                                  // Calcolo la Potenza Apparente in VA (Volt-Amper)
  VA_Media -= VA_Media / N_Elem;
  VA_Media += VA;
  PotenzaApparente = VA_Media / N_Elem;
  if (CorrenteRMS == 0.0) PotenzaApparente = 0.0;                              // Se la corrente è inferiore a 10 mA azzero la Potenza Apparente

  if (VA > 0) Cosfi = P / VA;                                                  // Calcolo il Cosfi
  else Cosfi = 1.0;
  Cosfi_Media -= Cosfi_Media / N_Elem;
  Cosfi_Media += Cosfi;
  FattorePotenza = Cosfi_Media / N_Elem;
  if (CorrenteRMS == 0.0) FattorePotenza = 1.0;                                // Se la corrente è inferiore a 10 mA Setto CosFi = 1

  VAR = TensioneRMS * CorrenteRMS * sin(acos(Cosfi));                          // Calcolo la Potenza Reattiva in VAR (Volt-Amper Reattivi)
  VAR_Media -= VAR_Media / N_Elem;
  VAR_Media += VAR;
  PotenzaReattiva = VAR_Media / N_Elem;

  DatiPronti = false;                                                          // Resetto il Flag per una nuovo calcolo
}





// Funzione Interrupt lanciata dal timer ogni 200 uS: il codice è stato ottimizzato per essere eseguito entro i 200 uS con ampio margine.
// Il codice viene eseguito in circa 20-40 uS, le letture dell'ADC (che avvengono contemporaneamente all'esecuzione del codice) vengono eseguite mediamente in 120 uS
// La funzione si occupa di campionare Tensione e Corrente con una frequenza di 2,5 kHz per ogni ingresso, ovvero con 50 campioni per sinusoide (50 V + 50 I).
// Per rendere veloce il codice i calcoli più complessi e in virgola mobile sono effettuati all'esterno della ISR.
// La funzione memorizza i tutti valori in variabili e, alternativamente, in 2 vettori da passare al resto del codice

ISR (TIMER1_OVF_vect) {

  if (isAnalogReadingAvailable()) {                                            // Se il dato dell'ADC è pronto, procedo

    Dato_ADC = getAnalogReading();                                             // Leggo il dato dell'ADC

    if (Let_V) {                                                               // Se il dato letto dall'ADC è un campione della Tensione
      triggerAnalogRead(A1);                                                   // Avvio la Lettura della Corrente, che sarà disponibile alla prossima chiamata dell'ISR
      Let_V = false;                                                           // Setto la prossima lettura come Corrente
      Dato_ADC -= Offset_V;                                                    // Sottraggo l'Offset della tensione
      Somma_V_2 += sq(Dato_ADC);                                               // Preparo calcolo per Tensione RMS

      VI[Rig][Col] = (int)Dato_ADC;                                            // Salvo la lettura nella matrice (colonna 0 o 2)
    }
    else {                                                                     // Se il dato letto dall'ADC è un campione della Corrente
      triggerAnalogRead(A0);                                                   // Avvio la Lettura della Tensione, che sarà disponibile alla prossima chiamata dell'ISR
      Let_V = true;                                                            // Setto la prossima lettura come Tensione
      Dato_ADC -= Offset_I;                                                    // Sottraggo l'Offset della Corrente
      Somma_I_2 += sq(Dato_ADC);                                               // Preparo calcolo per Corrente RMS
      Somma_P_W += Dato_ADC * (long)VI[Rig][Col];                              // Preparo calcolo Potenza Istantanea (Watt)
  
      VI[Rig][Col + 1] = (int)Dato_ADC;                                        // Salvo la lettura nella matrice (colonna 1 o 3)
      Rig++;                                                                   // Incremento l'indice di Riga della Matrice
    }
  }

  if (Rig > 49) {                                                              // Se ho letto 50 campioni (con la coppia tensione-corrente)
    NumCampioni = (float)(Rig - 1);                                            // Memorizzo ogni valore in variabili float da passare al resto del codice per le dovute elaborazioni
    SommaV2 = (float)Somma_V_2;
    SommaI2 = (float)Somma_I_2;
    SommaPW = (float)Somma_P_W;
    DatiPronti = true;
    Rig = 0;                                                                   // Resetto l'indice di campionamento
    Somma_V_2 = 0;                                                             // Resetto le somme per i calcoli dei valori 
    Somma_I_2 = 0;
    Somma_P_W = 0;    
    Col ^= 2;                                                                  // Sposto il salvataggio di V e I dalle colonne 0-1 alle colonne 2-3 (o viceversa)
  }
}



Modificato da BellaEli - 14/07/2017, 21:15:17


---------------
C'è un limite al fai da te ???
Si, ma lo stabiliamo noi !!!

 

calcola
GigaWatt


Gruppo:Utente
Messaggi:4435

Stato:



Inviato il: 14/07/2017 22:03:21


CITAZIONE

Altro strano problema l'ho avuto sul sensore ACS712 da 5 A: secondo il datasheet dovrebbe tirare fuori una tensione di +/- 185 mV per Amper rispetto a Vcc/2, in realtà il mio ne tira fuori solo 135 !


accade anche con quelli da 20 e 30A, non tutti e non con lo stesso errore. Ho il sospetto che molti dei sensori in vendita su ebay siano delle seconde scelte, poco male, si risolve modificando la sensibilità da inserire nell'algoritmo di calcolo.
In genere li taro con un alimentatore da banco regolabile e facendo passare una corrente nota oppure, se non posso usare l'alimentatore da banco, più semplicemente mettendo in serie un tester e poi modifico la sensibilità fino ad ottenere una misura accettabile, ci vuole più a scriverlo che a farlo.

CITAZIONE
Inoltre se la corrente assorbita supera un certo valore (ad esempio se collego un trapano come carico) il sensore va in blocco, la tensione in uscita si piazza a circa Vcc/2 e l'unico modo per farlo ripartire è staccare l'alimentazione: è capitato anche a voi ?


forse dipende dallo spunto e dal fatto che è solo da 5A, con quelli da 20 o 30A non mi è mai successo, fusi si, bloccati mai.Faccine/blowup.gif

CITAZIONE
Dopo non so quante prove mi sono accorto che l'onda sinusoidale della 220 Volt non durava 20 mS ma solo 19,6 mS (51,02 Hz), quindi campionando a 200 uS andavo a leggere un pezzettino della sinusoide successiva...


oscilla e per misurare il tempo usano dei fattori di correzione, vi è un sito della società elettrica svizzera dove si vede in tempo reale la variazione della frequenza e se oscilla quella svizzera ...



---------------
Impara l'arte e mettila da parte
14 pannelli da 100w, inverter kemapower 3kw, regolatore morningstar tristar ts60, banco batterie n.1 di 12 elementi 2v 480Ah C5 corazzate per trazione pesante, banco batterie n.2 di 400Ah in C5 formato da 24 elementi 2V 200Ah corazzate al gel per fotovoltaico in due serie da 12 elementi, centralina di gestione impianto autoprodotta.

 

dani9191

Avatar
GigaWatt


Gruppo:Utente
Messaggi:780

Stato:



Inviato il: 19/07/2017 11:05:50

In questi giorni ho fatto una prova stupida,ma che potrebbe portare dei piccoli risparmi energetici. Praticamente ho svuotato il frigo e messo 10 bottiglie di acqua a temp ambiente la prima prova lo fatta di pomeriggio(la temperatura ambiente era molto calda),il compressore ha lavorato per 75minuti,la stessa prova lo rifatta alle 11 di sera e il compressore è stato acceso solo 50minuti. Certamente è una prova blanda, per capire se realmente c'e un risparmio energetico sarebbe da fare altre prove con i sensori di temp,ecc...pero teoricamente il risparmio dovrebbe esserci,in particolar modo per chi ha la tariffa a fascie orarie.
Quindi per abbattere la temp degli alimenti sarebbe meglio caricare il frigo di sera cosi durante le ore piu calde del giorno lavorerebbe solo per mantenere la temperatura? Cosa ne pensate?



Modificato da dani9191 - 19/07/2017, 11:09:52


---------------
Non è impossibile se è fattibile!

 

Luca450Mhz

Avatar
GigaWatt


Gruppo:Utente
Messaggi:3204

Stato:



Inviato il: 19/07/2017 11:58:37

Che se ho sete e voglio l'acqua fresca, non posso aspettare la sera! Se faccio la spesa al pomeriggio, non posso aspettare la sera per riporre gli articoli acquistati dentro il frigo.
Probabilmente qualche watt potresti risparmiare, ma non è un metodo applicabile (e comunque la tecnica che hai utilizzato per fare questo test è troppo approssimativa)



Modificato da Luca450Mhz - 19/07/2017, 13:26:21


---------------
Pannelli: 6975 Wp (poli e mono). Inverter UPS PSW7 6kW 48V toroidale con switch comandato dal mio sistema di domotica (RaspberryPi + vari Wemos D1 Mini - ESP8266). Regolatore di carica: Mpp Solar PCM8048.
Batterie: 24 elementi trazione pesante 315Ah C5 48V.

 
 InizioPagina
 

Pagine: (12)   1   2   3   4   5   6   7   8   9   [10]   11   12    (Ultimo Msg)

Versione Mobile!

Home page       TOP100-SOLAR      Home page forum