Ich habe vor kurzem damit angefangen mich mit der Programmierung des ATmega32 zu beschäftigen. Ich wollte nun mein erstes "richtiges Projekt" starten und habe mir vorgenommen meinen Strom- und Gaszähler zu überwachen. Die Überwachung des Stromzählers funktioniert soweit. Es ist ein elektronischer Stromzähler, bei dem eine LED 1000 mal pro KWh blinkt. Ich überwache das Blinken mit einer Fotodiode - das funktioniert einwandfrei. Das Problem ist mein Gaszähler. Es handelt sich um folgenden: http://www.cd-k.de/2012/11/installation-nf-impulsnehmer-ni-3-fur-metrik-gaszahler/ Von meinem Gasversorger habe ich den passenden Reedkontakt bekommen. Eigentlich dachte ich, das wird einfach, aber der Reedkontakt macht mich wahnsinnig. Ich weiss nicht genau woran es liegt. (Prellen ?) Der Reedkontakt schließt, wenn die letzte Stelle am Gaszähler in etwa bei der 8 ist und öffnet ca. bei der 2 (das dauer ca. 5 Sekunden). Eine ganze Umdrehung dauert ca. 13 Sekunden. Ich habe folgendes bisher versucht: 1. interner Pullup: mein Programm erhöht den Zählerstand um 0,003 pro Umdrehung der letzten Ziffer des Gaszähler 2. externer Pullup mit 100KOhm: +0.002 pro Umdrehung 3. externer Pullup mit 400kOhm: +0.001 pro Umdrehung. Ich dachte mit schon, dass es nun passen würde, ABER mein Zähler hat sich um 0.020 in 1 Stunde erhöht, obwohl die Gastherme ausgeschaltet war ?!?!? 4. ich habe Versuche mit RC- Gliedern gemacht (100KOhm + 100nF, 10KOhm + 100nF): meine Anzeige steigt ca. 0.010 pro Umdrehung. Da mir das Equipmet fehlt, habe ich versucht mit dem Eingag meiner Soundkarte das Ein- und Ausschaltsignal des Reedkontaktes zu analysieren um etwaiges Prellen zu erkennen (siehe Anhang). Keine Ahnung ob dies geeignet ist, aber ich kann kein Prellen erkennen. Jedenfalls bin ich mit meinem Latein jetzt am Ende. Vielleicht kann mir von euch jemand weiter helfen. Vielen Dank. PS: ich weiß es gibt fertige Sachen wie zB den volkszaehler, aber ich wollte ja etwas lernen.
Bei mir hat ein C mit 100n parallel zum Reedschalter Wunder bewirkt. Oder Du versuchst es mit Softwaredebouncing.
Der Reedkontakt ist in der richtigen Lage zum Magnetfeld ausgerichtet? Hast du den Kontakt im Programm entprellt? Kannst du mit einem DSO die steigende und fallende Flanke des Reedkontaktes ansehen, um ein längeres Prellen auszuschließen?
Also ein C parallel hat es eigentlich verschlechtert. Der Reedkontakt ist in der dafür vorgesehenen Einkerbung und es ist auch der, welcher für den Gaszähler vorgesehen ist. DSO? Da ich nicht weiss was das ist, denke ich nicht, dass ich das habe. Wenn es das Prellen ist, warum wird dann in einer Stunde ca. 20mal gezählt ohne das sich der Gaszähler auch nur einen Millimeter gedreht hat?
Das sollte der Reedkontakt sein: http://www.mysmartshop.de/smart-metering/installation/metrix-impulsnehmer-ni-3-fuer-metrix-gaszaehler.html
Wenn du + 0.001etwas schreibst, rechnest Du mit floats? Gibt es da eventuell Rundungsfehler? Zahl einfach mal die Impulse in Int und Entprellen (hard oder Software). Am besten zeige mal den source-code.
Sorry, hatte den angehängten code nicht gesehen...
Mögliche Ursachen: - Prellen des Reed-Kontakts - Einstreuung von Störsignalen in die Leitung des Reed-Kontakts - Zählen bzw. Rechnen mit ungeeigneten Datentypen Was fehlt: - Eingangsschaltung am ATmega - Leitungslänge zum Reed-Kontakt
:
Bearbeitet durch User
Michael L. schrieb: > Mögliche Ursachen: > - Einstreuung von Störsignalen in die Leitung des Reed-Kontakts Das wird wohl der springende Punkt sein. Schau nach einer Minimallänge des Signals und schmeiss alles andere als Störung weg.
Liegt wohl am anstrengenden Tag, aber irgendwie verstehe ich überhaupt nicht, was du mit dem Code bezwecken willst. if (PIND & (1<<PD3)) PORTD |= (1<<PD5); if (!(PIND & (1<<PD3))) PORTD &= ~(1<<PD5); => Ich weiß nicht welche Zeiten da wirken, aber das sollte man mit einem 'else' lösen. Wer weiß (gerade bei Blitzen), wie lange sie dauern und nachher beide Bedingungen hintereinander erfüllt sind. ISR(INT0_vect){ //INT0 Interrup Stromzähler PD2 - Fotodiode i_start = i_ende; i_ende = (sekunde * 1000) + ms; kwh_gesamt = kwh_gesamt + 0.001; } => Verstehe ich auch nicht. Und um vom verschwenderischen float wegzukommen, kann man ja z.B. erstmal bis 1.000 zählen. Generell ist einfaches Zählen der Blitze wohl sinnvoll(er). ISR(INT1_vect){ //INT1 Interrupt Gaszähler PD3 - Reedkontakt gasstand = gasstand + 0.01; } => Wenn du so ungefähr deine elend lahme "Drehgeschwindigkeit" kennst... Interrupt wird ausgelöst. Die ISR ist wohl extrem flott abgearbeitet. Rückkehr zum Hauptprogramm. Was passiert wohl dann (immer noch)? Datenblatt des Impulsnehmers: • Impulsdauer min.: 0,3s Ich glaube nicht, daß das was mit der externen Beschaltung zu tun hat. Zumal der ja extra dafür gemacht ist.
H.Joachim Seifert schrieb: > Michael L. schrieb: >> Mögliche Ursachen: > >> - Einstreuung von Störsignalen in die Leitung des Reed-Kontakts > > Das wird wohl der springende Punkt sein. Einer von mehreren, ich hab grad noch den Code "entdeckt" ... Tatsächlich wird mit float Variablen gezählt. Es wird in der ISR nicht entprellt.
:
Bearbeitet durch User
Micha schrieb: > Wenn du + 0.001etwas schreibst, rechnest Du mit floats? Gibt es da > eventuell Rundungsfehler? Zahl einfach mal die Impulse in Int und > Entprellen (hard oder Software). Am besten zeige mal den source-code. Dachte ich Anfangs auch. Ich habe zur Überwachung schon mal eine Int-Variable mitzählen lassen. Diese wird genauso oft hochgezählt wie um 0,001 erhöht wird. Also kein Rundungsfehler. Michael L. schrieb: > Was fehlt: > - Eingangsschaltung am ATmega > - Leitungslänge zum Reed-Kontakt Zur Eingangsschaltung gibts nicht viel zu sagen. Bei internem Pullup ein Kontakt auf PD3 und einer auf Masse. Bei externem Pullup habe ich einen Kontakt auf PD3 und einen auf Masse wobei eben noch ein Widerstand gegen 5V hängt. Leitungslänge sind ca. 2 Meter. Vom Gaszähler durch die Aussenwand direkt zum AVR. Dort sind keine anderen elektrischen Leitungen. Lutz schrieb: > Liegt wohl am anstrengenden Tag, aber irgendwie verstehe ich überhaupt > nicht, was du mit dem Code bezwecken willst. > > if (PIND & (1<<PD3)) PORTD |= (1<<PD5); > if (!(PIND & (1<<PD3))) PORTD &= ~(1<<PD5); > => Ich weiß nicht welche Zeiten da wirken, aber das sollte man mit einem > 'else' lösen. Wer weiß (gerade bei Blitzen), wie lange sie dauern und > nachher beide Bedingungen hintereinander erfüllt sind. Es hängt nur eine LED an PD5. Sollte nur eine optische Anzeige zum Test sein, ob der Reedkontakt offen oder geschlossen ist. Lutz schrieb: > ISR(INT0_vect){ //INT0 Interrup Stromzähler PD2 - Fotodiode > i_start = i_ende; > i_ende = (sekunde * 1000) + ms; > kwh_gesamt = kwh_gesamt + 0.001; > } > => Verstehe ich auch nicht. > Und um vom verschwenderischen float wegzukommen, kann man ja z.B. > erstmal bis 1.000 zählen. Generell ist einfaches Zählen der Blitze wohl > sinnvoll(er). Hat nichts mit dem Gaszähler zu tun, sondern mit dem Stromzähler. Ich zähle die Zeit zwischen 2 Impulsen der LED am Stromzähler und berechne damit den momentanen KWh Verbrauch. Das funktioniert eigentlich. Es stimmt, dass der Reed nicht entprellt wird. Was ich aber trotzdem nicht verstehe ist: Wenn der Gaszähler ein paar Stunden still steht, dann wird trotzdem ein paar mal hochgezählt. Und warum verschlechtert sich das Ganze noch, wenn ich parallel einen Kondensator anschliesse. Ich habe heute nochmals ein wenig getestet und werde einfach nicht schlau daraus.
prinzmi schrieb: > Hat nichts mit dem Gaszähler zu tun, sondern mit dem Stromzähler. Weiß ich, war auch nur ein Hinweis. prinzmi schrieb: > Ich > zähle die Zeit zwischen 2 Impulsen der LED am Stromzähler und berechne > damit den momentanen KWh Verbrauch. Das funktioniert eigentlich. Nö. Oder ich habe es falsch verstanden. 1.000 Blitze entsprechen 1 kWh. Wenn du also Blitze zählst, zählst du Arbeit. Also, wieviel Arbeit du verbraucht hast. Ob jetzt die 1.000 Blitze in einer Minute oder in einer Stunde gezählt wurden, ist egal: Du hast 1 kWh verbraucht. Wenn du die Zeit zwischen 2 Blitzen zählst, dann mißt du die momentane Leistung ("den momentanen Stromverbrauch in Watt"). prinzmi schrieb: > Es stimmt, dass der Reed nicht entprellt wird. Ich glaube, daß er wegen des konkret bestimmten Anwendungsfalls schon von Haus aus entprellt ist. Du kannst ja spaßeshalber mal die Zeit zwischen den Flanken messen. Laut deinem Link muß sie > 0,3 s sein. prinzmi schrieb: > Wenn der Gaszähler ein paar Stunden still steht, dann wird trotzdem ein > paar mal hochgezählt. Das ist in der Tat merkwürdig. Stromversorgung o.k? Leider funktioniert dein Link zum Gaszähler nicht. Was ich aber (schon wieder) gar nicht verstehe: ISR(INT1_vect){ //INT1 Interrupt Gaszähler PD3 - Reedkontakt gasstand = gasstand + 0.01; } Wie können da Steigerungen von 0.001 und 0.002 entstehen???
Lutz schrieb: > Wenn du die Zeit zwischen 2 Blitzen zählst, dann mißt du die momentane > Leistung ("den momentanen Stromverbrauch in Watt"). Stimmt natürlich - mein Fehler. Ich messe damit die Watt. Lutz schrieb: > Du kannst ja spaßeshalber mal die Zeit zwischen den Flanken messen. Laut > deinem Link muß sie > 0,3 s sein. Wenn du mit Flanken die Zeit zwischen dem Schließen und dem wieder Öffnen des Reedkontaktes meinst, dann beträgt diese im "Rauchfangkehrbetrieb" (ich glaube das heisst so. Die Therme läuft dabei mit voller Leistung.) meiner Gastherme ca. 5 Sekunden. Die offene Zeit beträgt ca. 8 Sekunden, dh eine Umdrehung der letzten Stelle des Gaszähler dauert ca. 13 Sekunden. Im "normalen" Betrieb kann das auch länger dauern, da die Therme nicht immer mit voller Leistung läuft. Lutz schrieb: > Das ist in der Tat merkwürdig. Stromversorgung o.k? Ich habe das Ganze auf einem Pollin Evaluationsboard laufen. Netzteil hat 8V mit 1.2A. Lutz schrieb: > Wie können da Steigerungen von 0.001 und 0.002 entstehen??? Wieder mein Fehler. Ich habe mich verschrieben. Natürlich meinte ich 0.01.
Lutz schrieb: > Leider funktioniert dein Link zum Gaszähler nicht. Der Gaszähler ist ein Metrix 6G4L: http://www.apator.com/de/produkte/gas-messung/haushaltsgaszaehler/6g4l-einstutzen Das Datenblatt des Reedkontakts: http://heathungary.hu/doc/text/metrix_impulzusado.pdf
In der main: DDRD = 0b1110000; DDRA = 0b0000000; Wohl hier egal, aber sind das absichtlich jeweils nur 7 statt 8 bit? Das Entprellen (obwohl ich das hier nicht als Problem erwarte) kannst du auch quick&dirty so machen: Wenn Vollgas (im wahrsten Sinne des Wortes) 13 Sekunden sind (schneller geht nicht), kannst du in der ISR den Interrupt ja die nächsten z.B. 11 Sekunden sperren. Sollte in der Zeit ein Impuls kommen, muß er falsch sein und kann nichts anrichten. Das ändert aber nichts an dem Problem, daß er zählt, wenn der Gaszähler steht. Und da vermute ich auch das Problem. Wie hast du den Sensor denn angeschlossen? Er hat ja 2 Kontakte. Wenn du beide gleichzeitig überwachst (ist ja der Sinn), hast du eine höhere Sicherheit: Wenn der eine geschlossen ist, muß der andere offen sein. Und umgekehrt. Nur dann ist es ein gültiger Impuls. Kann ja auch in der ISR überprüft werden.
prinzmi schrieb: > Es stimmt, dass der Reed nicht entprellt wird. Was ich aber trotzdem > nicht verstehe ist: > Wenn der Gaszähler ein paar Stunden still steht, dann wird trotzdem ein > paar mal hochgezählt. Und warum verschlechtert sich das Ganze noch, wenn > ich parallel einen Kondensator anschliesse. Ein Kondensator allein ist kein Tiefpass. Es kann eher sein, dass du in Verbindung mit der Leitungslänge (Induktivität) einen Empfänger für Störsignale gebastelt hast. > Ich habe heute nochmals ein wenig getestet und werde einfach nicht > schlau daraus. Blindes Probieren bringt dich nicht weiter. Was hilft, ist eine vernünftige Entprellung in Software. Aber nicht den Vorschlag (quick&dirty) 11 Sekunden die ISR sperren. Statt dessen solltest du nur dann einen Impuls zählen, wenn der Reed-Kontakt mindestens 0,5 Sekunden geschlossen war. Öffnet er vor Ablauf der Zeit, ist der Impuls zu ignorieren. Das sollte alle beschriebenen Problemfälle abdecken.
Lutz schrieb: > In der main: > DDRD = 0b1110000; > DDRA = 0b0000000; > Wohl hier egal, aber sind das absichtlich jeweils nur 7 statt 8 bit? Keine Absicht. Ist ein Fehler. Danke. Lutz schrieb: > Wie hast du den Sensor denn angeschlossen? Er hat ja 2 Kontakte. Ich habe nur braun/grün angeschlossen. Weiss/geld dachte ich eigentlich, dass ich nicht brauche (Sabotagekontakte). Michael L. schrieb: > Ein Kondensator allein ist kein Tiefpass. Hatte ich immer in Verbindung mit einem Widerstand als RC Glied. Michael L. schrieb: > Statt dessen solltest du nur > dann einen Impuls zählen, wenn der Reed-Kontakt mindestens 0,5 Sekunden > geschlossen war. An sowas in der Art habe ich auch schon gedacht und habe darum vorhin den Code etwas verändert. Ich dachte mir folgendes. Ich frage einfach im Sekundentakt den Zustand des Reedkontaktes ab, und speichere den Zustand der letzten 5 Sekunden in einem Array reed_ist. Steht in dem Array dann 0,0,1,1,1 (0=Reed geschlossen, 1=Reed offen), dann zähle ich meinen Zähler um 0,01 hoch. Beim einschalten des AVR wird ebenfals einmal der Zustand des Reedkontaktes überprüft. Wenn dieser geschlossen ist wird reed_ist mit {0,0,0,0,0} und wenn er offen ist mit {1,1,1,1,1} befüllt. Das ist die ISR Routine, die im Sekundentakt den Zustand überprüft. Was meint ihr dazu? Mit einem Taster funktioniert das Ganze gut. Ich werde es morgen oder übermorgen mit dem Reedkontakt testen.
1 | ISR(TIMER1_OVF_vect) { //TIMER1 Overflow einmal pro s Eingang PD3 abfragen |
2 | TCNT1 = 49911; //Zählregister mit Vorladewert |
3 | |
4 | for (i=0; i<5; i++) reed_ist[i] = reed_ist[i+1]; //Werte des Array nach links verschieben |
5 | |
6 | if (PIND & (1<<PD3)) reed_ist[4] = 1; //aktuellen Status in die letzte Stelle des Array schreiben |
7 | else reed_ist[4] = 0; |
8 | |
9 | if (memcmp(reed_ist, reed_soll, 5) == 0) gasstand = gasstand + 0.01; //Arrays vergleichen |
10 | }
|
Ehe du weiter irgendwelche Experimente zusammenbastelst, schau doch mal hier in den Artikel: http://www.mikrocontroller.net/articles/Entprellung Unten bei "Timer-Verfahren (nach Peter Dannegger)" findest du ein gutes Beispiel in ASM und C.
Ich wollte nur noch einmal kurz Bescheid geben, dass es mit der Methode den Eingang im Sekundentakt zu überprüfen seit ein paar Tagen ohne Probleme funktioniert. Vielen Dank für eure Hilfe! Jetzt fehlt mir eigentlich nur mehr der Wasserzähler ;-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.