PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Projekt: Stromzähler optisch auslesen mit Leistungsmessung



thoweiss
13.01.2010, 08:58
Hallo zusammen,
aktuell erfasse ich die Umdrehungen meines Stromzählers mit einem CNY 70 und einem 1-wire Zähler. Die Signalaufbereitung erolgt über einen OPV.

Die Auswertung der Daten erfolgt über meinen Misterhouse-Server http://misterhouse.wikispaces.com/Thorsten%27s+HA+Webinterface

Leider macht mein Zähler nur 75U/kWh, somit ist die Auflösung der Leistungsmessung begrenzt. (Ich zähle die Impulse in 5 Minuten intervallen)


Jetzt möchte ich einen anderen Ansatz versuchen. Anstatt die Impulse über einen festen Zeitraum zu erfassen, möchte ich die Messung der Leistung über die Zeit die die Zählerscheibe für eine Umdrehung benötigt, berechen.

dadurch habe ich für jede Umdrehung einen aktuellen Messwert, und nicht wie im moment nur alle 5 Minuten.

Die Berechnung geht über die Zählerkonstante mit der folgenden Formel:

P=n*3600/t*Cz also vereinfacht 3600/t*Cz

Beispiel:
Zähler braucht für eine Umdrehung 40sek. Cz= 75 u/kWh

3600/40*75= 1,2kW

Damit habe ich die aktuelle Leistung berechnet, zusätzlich kann man den Zählerstand weiterzählen. Bei Jeder umdreheung kommen 0,013333 kWh hinzu.


Das ganze soll über einen Atmel AVR gemacht werde, der sich um die Auswertung und die Übertragung der Daten (Funk, USB, LAN, etc.) zum PC kümmern soll.

Jetzt muss ich nur noch rauskriegen wie ich die Impulslänge bei relativ langen impulsen mit Bascom ermittle...

Ambesten über einen Timer mit Interrupt? Oder mit dem pulsein-Befehl, wobei der eher für kurze Impulse geeignet ist - oder?

Deteils gibt es später, ich wollte erstmal das Projekt Vorstellen.


Gruß,

Thorsten


[/code]

uwegw
13.01.2010, 09:09
Wie lang ist der Impuls bei maximaler Drehgeschwindigkeit (Maximalstrom des Zählers erreicht)? Ein Ansatz wäre, im Timer-Interrupt mit einem kürzeren Zeitabstand (etwa doppelt bis viermal so schnell) zu pollen, dabei eine der Flanken zu erkennen und dazwischen die Interrupts zu zählen. Man bräuchte für niedrige Leistungen natürlich ne recht große Variable und ein timeout für den Fall, dass der Zähler komplett stehenbleibt.

thoweiss
13.01.2010, 11:58
Naja, besonders schnell drehen die Scheiben sich ja nicht...

Es kommt ja auf die Zählerkonstante an - bei mir ist die relativ niedrig mit 75.

Es gibt aber auch Zähler mit höherer Konstante.

Ich würde sagen der messbereich liegt irgenwo ziwschen 5sekunden und 2-3 minuten (wenn ganz wenig last drin ist...)

Das mit dem timeout ist auch keine schlechte idee....

Ich gehe mal davon aus das eine Auflösung von 1 Sekunde ausreichend ist

Haben die AVR's nicht auch einen Timer der als RTC arbeitet?

Jetzt habe ich ja das Signal von der Scheibe. Da muss ich mit einer Flankenerkennung arbeiten um die Länge des 0-Pegels (silber) zu messen.

Ich glaube ich muss mir mal ein paar BASCOM codeschnipsel zusammensuchen und mal was zusammenfrickeln.

uwegw
13.01.2010, 14:38
5 Sekunden für eine volle Umdrehung?
Interessanter ist eigentlich die Länge des Impulses, denn daraus ergibt sich die nötige Abtastrate.

Alternativ könnte man auch einen externen Interrupt benutzen. Dafür ist es aber wichtig, dass das Signal prellfrei ist. Wenn kein Umgebungslicht im Spiel ist, dürfte es wahrscheinlich ausreichen, den OP als Schmitt-Trigger mit Hysterese zu schalten.

Besserwessi
13.01.2010, 17:11
Soweit ich weiss ist die Pulsein Funktion nur für kurze Zeiten geeigent, denn der µC wartet die ganze Zeit, macht also nichts zwischendurch.

Die AVRs haben Timer, aber die gehen oft nicht so langsam. Ein Vorteiler von 1024 ist oft da Maximum. Die Methode der Wahl wäre damit wohl ein Software Timer der in einem Interrupt (vom Timer) alle etwa 10 ms hochgezählt wird und dabei den Eingang Testet.
Wenn nötig kann man da auch Störungen noch abfangen, ggf. auch die Lichtschranke per AD Wandler einlesen, um von der Einstellung der Empfindlicheit los zu kommen.

thoweiss
13.01.2010, 17:38
Ich erfasse ja die Zeit die die Scheibe für eine Umdrehung benötigt.

Dazu möchte ich auf die flanke beim Übergang von Rot -> Silber triggern und die zeit bis zum nächsten Übergang Rot->SIlber messen.

Als Sensor habe ich mir diese Schaltung von ELV ausgewählt http://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=8353&flv=1&bereich=&marke= die hat den vorteil der unempfindlichkeit gegen Fremdlicht und man kann Empfindlichkeit und Impulsdauer am Ashang einstellen.

Mit meiner jetzigen schaltung bin ich nicht 100% zufrieden...

Ursprünglich hatte ich vor die Funktionalität dieser PLL-Schaltung in Software nachzubauen, aber das schein zu kompliziert zu sein.


Zur Auswertung schwebt mir sowas wie dieses Programm von Roland Walter vor (listing ganz unten):
http://www.rowalt.de/mc/index.htm


'0014.BAS: InputCapture mit Timer1 (2) (Frequenzzähler)
'Hardware: MAX232 an PD0/PD1
' Nullmodemkabel zum PC
' Pin ICP/PD6 an RTS
'--------------------------------------
$Regfile = "2313def.dat"
$Crystal = 3686400 '3,6864MHz-Quarz
$Baud = 115200 'Hohe Baudrate

Dim lCount As Word At &H60
Dim wCountLo As Word At &H60 Overlay
Dim wCountHi As Word At &H62 Overlay

On ICP1 OnCapture 'Interrupt-Routine
On OVF1 OnOverflow 'Interrupt-Routine

Config Timer1=Timer,Prescale=1,Capture Edge=Rising

Enable ICP1 'Capture-Interrupt
Enable OVF1 'Overflow-Interrupt
Enable Interrupts 'Interrupts global

Main: 'Hauptschleife
Goto Main
'--------------------------------------
OnCapture: 'Timer1-Capture
wCountLo = Timer1 'Erst Wert sichern
Timer1 = 0 'Sofort Timer-Reset
Print lCount;" ";
wCountHi = 0
Return
'--------------------------------------
OnOverflow:
Incr wCountHi 'lCount=lCount+65536
Return


Dann müssten noch zwei Zähler für den Gas- und Wasserverbrauvh eingebaut werden.


Zur Datenübertragung werde ich vermutlich einen X-port auf LAN einsetzen, oder ein Datenfunkmodul (wenn ich ein Preiswertes finde...)


Ich fang das Basteln mal an, habe mein STK500 schon angewärmt.
O:)

Besserwessi
13.01.2010, 18:11
Die Modulation der Lichtschranke durch den µC zu machen ist eigentlich keine Schlechte Idee, und auch nicht so kompliziert. Einen PLL in Software braucht man dazu auch gar nicht. Es genügt eine Modulation der LED und ein einlesen des Signals vom Fototransistor über den AD wandler.
Jeweils Abwechslend für 1 oder 2 Wandlungen die LED einschalten und dann die Differenz der werte des AD wandlers messen. Für mehr unterdrückung ggf. noch die hauptsächliche Störfrequenz von 100 Hzachten.

thoweiss
13.01.2010, 18:35
@Besserwessi:

Mhhh, das hört sich interressant an... Leider sind meine µC-kenntnisse etwas eingerostet, habe seit meinem Techniker-Projekt 2006 nichts mehr mit AVR's gemacht..

Also ich lasse einen Timer laufen der die LED mit ich sag mal 1-2 kHz pulst.
Und wenn led = an mache ich eine Messung mit dem ADC? Oder wie muss ich mir das Vorstellen?

Ich möchte ja verhindern das der Empfänger von Fremdlicht beeinflusst wird.

Den ADC-Wert dann vergleichen mit einem Schwellwert und dann mit der Stoppuhr die Pulslänge messen.

Mann kann doch den Analogkomperator auch auf den Interrupt schalten wenn mich nicht alles täuscht... fragt sich nur wie.

Mhhh langsam habe ich wieder blut geleckt O:)

thoweiss
14.01.2010, 08:52
So - ich habe mal ein Blockschaltbild erstellt wie es mal werden soll.

Beim Stromzähler werde ich wohl die Signalaufbereitung extern machen, ich habe noch keine Zündende Idee das in Software umzusetzen.

Die Beiden anderen Eingänge sind einfache Reedkontakte angeschlossen, bzw. OC-Ausgänge (evtl. beim Wasserzähler)

Das LCD soll die Zählerstände und die momentane Leistungsaufnahme beim Strom anzeigen.

Aber erstmal werde ich mich mit der Zeitmessung beschäftigen.

Die Zähler für die anderen eingänge sind ja eher einfach zu machen. Die Laufen in der Hauptschleife dafür möchte ich keine Timer opfern, das sollte ausreichen.

Ein erster test mit dem STK500 war vielversprechend - ich muss erstmal den Code für die Zeitmessung "entwickeln".

Mein thread wurde anscheinend Verschobe, sorry für das falsche Unterforum.

Sauerbruch
14.01.2010, 10:20
Beim Stromzähler werde ich wohl die Signalaufbereitung extern machen, ich habe noch keine Zündende Idee das in Software umzusetzen.

Eine Lösungsmöglichkeit wäre der Einsatz eines zweiten CNY 70, der neben den anderen montiert wird. Wenn Du die Differenz zwischen beiden Ausgangsspannungen verwertest, könntest Du den Farbenwechsel auch bei sehr unterschiedlich hellem Fremdlicht detektieren.

Dazu würde sich z.B. der Analog-Komparator anbieten, der die Spannungen zweier Eingangspins vergleicht und bei einem entsprechenden Unterschied einen Interrupt (!!!) auslösen kann.

Oder Du verwendest das Signal des "hinteren" CNY70 als externe Referenzspannung für den AD-Wandler. Dann hättest Du bei Silber/Silber einen stabilen Wert von 1023, bei Rot/Silber aber einen definitiv niedrigeren Wert.

thoweiss
16.01.2010, 16:48
So, ich habe die Hardware soweit am laufen...

Zwei CNY70 auf den ADC gelegt. Bei silberner Scheibe habe ich einen Wert zwischen 0 - 7, bei der roten markierung habe ich einen wert >15 .


'Emon.bas
'Energiemonitor für Strom, Gas und Wasser
'Sensor für Strom: 2 CNY70 am AD-Wandler
'Sensor für Gas und Wasser Kontakte an Portpins

'v0.1 16.01.2010 - Test der Analogen Eingänge, Debug über RS232


$regfile = "m8def.dat"
$crystal = 8000000
$baud = 9600


Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.5 , Rs = Portb.4
Config Lcdbus = 4

Config Timer1 = Timer , Prescale = 256 'Konfiguriere Timer1
Enable Timer1 'schalte den Timer1 ein
On Timer1 Isr_von_timer1 'verzweige bei Timer1 überlauf zu Isr_von_Timer1
Enable Interrupts
Timer1 = 34285 'Timer1 soll schon von 34285 wegzählen


Config Adc = Single , Prescaler = Auto
Start Adc


Dim W1 As Word , W2 As Word , Diff As Word , Channel As Byte , Mark As Bit , Time As Word , Count As Word , Count2 As Word,
Dim Flanke1 As Bit , Flanke2 As Bit , Flanke3 As Bit
Dim Sek As Word , Sek_alt As Word , Sek_delta As Word



Channel = 0 'Startkanal für ADC

Do
W1 = Getadc(0)
W2 = Getadc(1)
Diff = W2 - W1
Print "Kanal1: " ; W1 ; "Kanal2: " ; W2 ; "Differenz: " ; Diff
Cls
Locate 1 , 1
Lcd "Diff.:" ; Diff

If Diff > 15 Then
Mark = 1
Locate 2 , 1
Lcd "---OOO---"
Else
Mark = 0
End If

If Mark = 0 Then

Sek = Count
Elseif Mark = 1 Then
Sek_alt = Count
Sek_delta = Sek - Sek_alt
End If

Locate 2 , 10
Lcd "sek: " ; Sek_delta


Waitms 100
Loop
End


Isr_von_timer1: 'ISR von Timer1
Timer1 = 34285 'Timer1 soll wieder von 34285 wegzählen
Incr Count
Toggle Flanke1
Return

Hier mal der Code bis jetzt. Was ich nicht ganz verstehe ist wie ich die Zeit messe zwischen dem Erscheinen der roten Markierung.

Ich müsste wenn die Markierung kommt den Zählerstand speichern, und wenn die Markierung erneut erscheint die Differenz zum Aktuellen Zählerstand ermitteln und Wieder neu starten...

Aber ich weiss nicht wie?

Irgenwas mit flankenerkennung, hat jemand einen Tip?

Sauerbruch
16.01.2010, 22:35
Irgenwas mit flankenerkennung, hat jemand einen Tip?

Geradezu prädestiniert hierfür wäre der Analog-Komparator anstelle des Analog-Digital-Konverters. Dieser Komparator hat zwei Eingänge: AIN0 und AIN1. Je nachdem an welchem Eingang die angelegte Spannung größer ist, ist sein Ausgang 1 oder 0. Im Laufe einer kompletten Umdrehung hättest Du also eine HL- und eine LH-Flanke. Und das beste daran ist, dass Du einen Interrupt von der steigenden, der fallenden oder von beiden Flanken auslösen lassen kannst. In Deinem Fall wäre natürlich nur eine von beiden sinnvoll, wobei es egal sein dürfte ob steigend oder fallend.

Das drumherum würde ich ganz ähnlich machen wie in Deinem Ansatz:

1. Alle 1 Sek. wird eine Variable in der Timer1-ISR hochgezählt.
2. In der ISR vom AD-Komparator wird einfach nur ein Flag gesetzt.
3. In der Hauptschleife wird das Flag abgefragt. Ist es 1, wird aus der Variablen (= vergangene Zeit) nach Deiner Formel die momentan entnommene Leistung errechnet, zur Gesamtenergie 0,0133 kWh addiert, und die Variable sowie das Flag auf 0 gesetzt.

Alle Infos zum Analog-Komparator gibt´s ab Seite 193 im Datenblatt des Mega8!

Besserwessi
16.01.2010, 23:14
Mit dem Analogkomperator könnte man es ganz gut machen, wenn es um schnelle Signale geht. Bei so langsamen Sachen geht der AD wandler besser. Da kann man wenn nötig noch ein entprellen in Software machen.

Statt 2 Lichtschranken, wäre ein mit einer schaltbaren LED besser gewesen. Die Differenz wäre dann ziwschen LED an und LED aus. So sollte es aber auch gehen.

Die Flankenerkennung in Software geht etwa so:
1) neuen Wert von der Lichtschranke einlesen
2) Testen ob man als neuen Wert rot, und als alten Silber hat,
dann hat man eine Flanke. Entsprenchend die Differenz bilden und Zeit für die nächste Flanke merken.
3) den Wert als alten Wert speichern

Wenn man im Programm noch was anderes zu tun hat, könnte man den AD wandler theoretisch in der timer ISR starten und dann in der AD-Wandler ISR auswerten. Allerdings muß man dann den AD-Wandler Direkt über die Register auslesen. Die Auswertung könnte so aber komplett in ISRs verschoben werden, ohne das man da warten muß. Das einzig schwere (weil etwas unübersichtlich) wird eventuell sein die verschiedenen AD Messungen auseinander zu halten.

Beim Timer sollte man besser die Hardware zum Einstellen der Periode nutzen. Das wird etwas genauer, ist aber hier nicht unbedingt nötig.

thoweiss
17.01.2010, 10:09
So - nachdem ich das Brett vor meinem Kopf demontiert habe, klappt auch die Flankenauswertung.

Jetzt muss ich noch die Zeitmessung machen, aber das sollte das kleinere problem sein.


Danke euch für die Hilfe... Ich komme bestimmt nochmal darauf zurück wenn es an das Feintuning gehrt... 8-[ 8-[ 8-[ 8-[




'Emon.bas
'Energiemonitor für Strom, Gas und Wasser
'Sensor für Strom: 2 CNY70 am AD-Wandler
'Sensor für Gas und Wasser Kontakte an Portpins

'v0.1 16.01.2010 - Test der Analogen Eingänge, Debug über RS232


$regfile = "m8def.dat"
$crystal = 8000000
$baud = 9600

'LCD Display konfigurieren
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.5 , Rs = Portb.4
Config Lcdbus = 4


'Timer 1 konfigurieren
'Wert für Timervorgabe
'Timer läuft bei 34286 alle 1 sek über
Const Timervorgabe = 34286
Config Timer1 = Timer , Prescale = 64
Enable Timer1
On Timer1 Isr_von_timer1
Enable Interrupts
'Timer1 Startwert
Timer1 = 34286

'AD-Wandler konfigurieren
Config Adc = Single , Prescaler = Auto
Start Adc


'Variablen deklarieren
Dim W1 As Word , W2 As Word , Diff As Word , Mark As Bit , Count As Word , Count2 As Word , Schwelle As Word
Dim Flanke As Bit , Flanke_old As Bit
Dim Sekunden As Word , Sekunden_alt As Word , Sekunden_delta As Word


'Schwellwert zur Erkennung der Markierung
'Bei Silber ist die Differenz 0...8
'Bei Rot (Markierung) ist die Differenz < 15
Schwelle = 15



'Init für Flankenerkennung und Zeitmessung
Flanke_old = 0
Sekunden_alt = 0

'Hauptschleife
Do
'ADC-Messwerte holen
W1 = Getadc(0)
W2 = Getadc(1)
'Differenzwert bilden
Diff = W2 - W1

'Durchlauf der roten Markierung erkennen
If Diff > Schwelle Then
Mark = 1
Elseif Diff < Schwelle Then
Mark = 0
End If

'Flankenauswertung
Flanke = Mark
If Flanke <> Flanke_old Then
Flanke_old = Flanke
If Flanke = 1 Then
Incr Count2

'Messung der Umdrehungszeit
Sekunden = Count - Sekunden_alt
Sekunden_alt = Count

End If
End If

'DEBUG-Ausgabe über RS232
Print ";Kanal1:" ; W1 ; ";Kanal2:" ; W2 ; ";Differenz:" ; Diff ; ";Flanke:" ; Count2 ; ; ";Count" ; Count ; ";Time:" ; Sekunden

'DEBUG-Ausgabe über LCD
Cls
Locate 1 , 1
Lcd "Diff.:" ; Diff
Locate 2 , 1
Lcd "Count.:" ; Count2
Locate 2 , 12
Lcd "s" ; Sekunden
Waitms 250
Loop
End


Isr_von_timer1: 'ISR von Timer1
Timer1 = 34286 'Timer1 soll wieder von 34285 wegzählen
Incr Count
Return

Richard
17.01.2010, 13:01
Hmm, ich habe gerade mal meinen Stromzähler angeschaut.
der hat na ner sich drehenden Scheibe sehr viele kleine Rillen
welche auch noch Schwarz eingefärbt sind. Möglich das eine
Lasermouse darauf reagiert? Dann hätte mann einige 100
Pulse/Umdrehung. :-)

Gruß Richard

thoweiss
19.01.2010, 06:27
Ich habe das Programm jetzt mal einige Tage getestet.

Läuft soweit sehr gut, nur den Überlauf der count variable muss ich noch abfangen - das gibt sonst komische messwerte.

Die Auflösung werde ich noch auf 10'tel Sekunden erhöhen, und die Messwerterfassung evtl. in die ADC-ISR verlegen.

Dann noch die Hardware in ein passendes Hutschienengehäuse reinfrickeln und an den Rechner anbinden.

Dann noch ein Menü für die Einstellungen von Schwellwert und Zählerkonstante - dann kann ich es schon bald verkaufen :cheesy:


Achja - Dokumentation muss auch noch gemacht werden...

Eisbaeeer
04.06.2010, 06:16
@thoweis
Bei den Energieversorgern gibt es verschiedene Abrechnungsmodelle, welche bei den Privathaushalten aber keine Rolle spielen. Trotzdem hat sich auf dem Markt ein gewisser Standard, welches die Leistungsermittlung betrifft, festgesetzt.

Dabei wird nicht die Zeit zwischen den Impulsen zur Leistungsermittlung hergezogen, also nicht mit jeder Umdrehung, sondern über einen Zeitraum von 15 Minuten. Hierdurch wird das ganze einfacher zu handhaben. Die Messperiode beginnt immer mit der vollen Stunde. Auf das kann man aber zuhause auch verzichten :-)

War nur eine Info als Anregung. Ich werde das Thema demnächst auch angehen. Bei mir wird dann der Zählerstand und die Leistung noch mit einem RFM12 an die Zentrale gefunkt.

Gruß Eisbaeeer