Forum: Mikrocontroller und Digitale Elektronik Spannungswächter - ADC Anfängerfrage


von IceCap (Gast)


Angehängte Dateien:

Lesenswert?

Hallo, möchte einen Elektrozaun darauf überprüfen, ob Spannung anliegt.
Dies wollte ich eigentlich über einen Spannunsteiler und evtl. 
Optokoppler realisieren.
Falls der gemessene ADC Wert 5s lang unter 2000V fällt, soll eine 
Signalleuchte über ein Relais eingeschalten werden. Optional ist im 
Betrieb eine Spannungsanzeige auf LCD vorgesehen, vorerst aber nicht so 
wichtig.
Mir geht es vor allem um die Benutzung des ADC im geplanten ATMega8.
Bin blutiger AVR Anfänger, hab mir bisher aber einiges angelesen.

Wie kann ich denn in der for-Zählschleife eine Messung von 5s 
realisieren, also wieviele Messungen muss ich entsprechend dem CPU Takt 
ausführen lassen ?

von Armin (Gast)


Lesenswert?

der ansatz ist gut. Bedenke aber, dass dein Spannugsteiler ziemlich 
hochohmig sein muss, damit die Spule im Gerät nicht zu schnell leer 
wird.

du kannst auch einen interrupt werfen lassen, wenn die spannung unter 
2kV fällt und nur dann 5sek lang messen, ob die spannung wieder 
ansteigt. Könnte vielleicht Strom sparen? Kenn mich aber nicht gut genug 
aus.


Vereinfachen kannst du das Ganze natürlich, indem du ohne uC arbeitest 
und das Licht einfach immer dann anmachst, wenn die Spannung zu niedrig 
ist. Über die Schwelle stellst du dann ein, dass die Leuchte nicht 
ständig blinkt beim be- und entladen. Müsste man mal versuchen (oder 
rechnen, falls genügend Daten übers Gerät vorhanden sind).

von IceCap (Gast)


Lesenswert?

Danke für die Antwort Armin, du hast natürlich Recht, dass dies auch mit 
Analogtechnik möglich ist. Erste Testschaltungen in MultiSim sind auch 
gelaufen, allerdings reizt mich die Herausforderung, das mit einem uC 
umzusetzen ... zumal man damit wesentlich flexibler ist und die 
Zaunspannung bei Bedarf auch über ein LCD anzeigen lassen kann.

von IceCap (Gast)


Lesenswert?

Kann sich evtl. mal jemand in den Code reinschaun, ob ich da gröbere 
Fehler gemacht habe ... wie gesagt, bin Anfänger.

von AVRuser (Gast)


Lesenswert?

Hallo,

ich habe mal kurz den Code überflogen. Dabei fand ich die folgende 
Zeile:

>  while(ADCSRA & (1<<ADIF));

Das ADIF abzufragen, ist falsch. Das wird nach der ersten Wandlung 
gesetzt und BLEIBT GESETZT, bis die ISR aufgerufen wird oder man es von 
Hand löscht.
Stattdessen nimmt man dafür folgenden Code:

while (ADCSRA & (1<<ADSC));

(siehe dazu auch AVR GCC Tutorial: ADC)

Weiterhin wird bei jedem Aufruf von "messung()" der ADC eingeschaltet, 
eine Dummy-Wandlung durchgeführt, dann 1000 Werte genommen und vor 
Verlassen der Funktion der ADC wieder abgeschaltet.
Normalerweise wird der ADC nicht abgeschaltet. Dann wird auch die 
Dummy-Wandlung überflüssig, und der ADC ist sofort bereit für 
Wandlungen.

Der ADC steht auf "externe Referenzspannung an AREF". Ist das korrekt? 
Hängt an AREF tatsächlich eine passende Referenzspannung?

Der ADC im Mega8 hat 10bit Auflösung; er liefert also Werte zwischen 0 
und 1023. Daher solltest du die zugewiesenen Werte der Variablen 
"maximum" und "minimum" überprüfen; diese sind grösser als der maximal 
mögliche Ausgabewert des ADC.

Es ist ungeschickt, in einer Funktion eine (lokale) Variable zu 
verwenden, die mit gleichem Namen ("maximum") auch im Hauptprogramm 
deklariert ist. Obwohl es verschiedene Variablen sind, führt der 
identische Name schnell zu Verwirrung.

Und zum Schluss noch einen Hinweis: wenn du in definierten Zeitabständen 
A/D-Wandlungen durchführen willst, kann man dazu gut einen Timer 
verwenden, der die Wandlung alle x ms startet. Aber dazu sollte man sich 
mit Interrupts und deren Routinen auskennen ...
Oder du verwendest einen Mega88 (ein "neuerer" Mega8); dieser kann den 
ADC hardwaremässig von einem Timer triggern lassen, ohne eine ISR zu 
brauchen.

von Peter R. (gelb)


Lesenswert?

IceCap schrieb:

> Hallo, möchte einen Elektrozaun darauf überprüfen, ob Spannung anliegt.

> Falls der gemessene ADC Wert 5s lang unter 2000V fällt, soll ...

Ich kenne jetzt nicht den genauen Typ deines Zauns, aber an einem 
Weidezaun liegt doch nicht ständig Hochspannung an, sondern alle paar 
Sekunden kommt mal ein kurzer Impuls, den du mit einem langsamen ADC 
womöglich nicht einmal messen kannst.

Nur so als Hinweis.

Grüße, Peter

von IceCap (Gast)


Lesenswert?

Danke für die vielen Hinweise, ich werde den Code nochmal überarbeiten 
und mich auch an Interrupten versuchen.

Frage an Peter: Ich weiß jetzt nicht wie schnell der ADC des ATMega8 
ist, aber sollte die Geschwindigkeit nicht ausreichen, den Spitzenwert 
eines kurzen Stromimpulses zu erfassen ?

Natürlich weiß ich, dass an einem Weidezaungerät nicht ständig Spannung 
anliegt, deswegen sollen ja auch immer 5s lang gemessen werden.
Falls in dieser Zeit kein Messwert >2000V zustande kommt, soll der Alarm 
auslösen. Dann soll erneut geprüft werden ob ein neuer Stromimpuls 
kommt, der den Alarm dann wieder abschaltet.

von Peter R. (gelb)


Lesenswert?

@ IceCap (Gast)

der ADC kann mit 1MHZ getaktet werden, wenn du nur 8 der 10 Bit benützt.
Dann liefert der etwa alle 15µs einen Messwert. Sonst (10 Bit) halt 
maximal
100kHz ADC-Takt.

Laut Wikipedia liefert ein Zaun für etwa 5ms Strom. Da würde ich zur 
Sicherheit jede Milisekunde messen.

Grüße, Peter

von spess53 (Gast)


Lesenswert?

Hi

>Sonst (10 Bit) halt maximal 100kHz ADC-Takt.

Nein. Für 10Bit 50...200kHz ADC-Takt.

MfG Spess

von IceCap (Gast)


Angehängte Dateien:

Lesenswert?

Wollte nochmal Rückmeldung über den Fortschritt des Projektes geben.
Habe mich nochmal hingesetzt, den Code überarbeitet und mit meinem MyAVR 
Board getestet. Die ADC Messung habe ich nochmal weggelassen, da ich 
erst mal mit ein paar grundliegenderen Sachen zu kämpfen hatte.

Die LCD Ausgabe habe ich auf einem 16x2 Display mit implementiert.
Natürlich wurde das LCD im ursprünglichen Code viel zu schnell 
angesteuert, so dass man kaum etwas erkennen konnte.
Hilfsweise habe ich nun in der LCD Ausgabe eine for-Schleife eingebaut 
um nur jeden 20.000ten Messwert auszugeben. Kann man das auch etwas 
eleganter lösen ? Habe evtl. an einen Timer gedacht, der alle 2-3s einen 
Wert ausgibt, ist das zu machen und kann mir jemand evtl. Hinweise 
geben, wie ich das verwirkliche ?  Beschäftige mich wie gesagt erst 
wieder seit Kurzem mit C-Programmierung und AVR.

von Karl H. (kbuchegg)


Lesenswert?

IceCap schrieb:

> Die LCD Ausgabe habe ich auf einem 16x2 Display mit implementiert.
> Natürlich wurde das LCD im ursprünglichen Code viel zu schnell
> angesteuert, so dass man kaum etwas erkennen konnte.
> Hilfsweise habe ich nun in der LCD Ausgabe eine for-Schleife eingebaut
> um nur jeden 20.000ten Messwert auszugeben. Kann man das auch etwas
> eleganter lösen ? Habe evtl. an einen Timer gedacht, der alle 2-3s einen
> Wert ausgibt, ist das zu machen und kann mir jemand evtl. Hinweise
> geben, wie ich das verwirkliche ?  Beschäftige mich wie gesagt erst
> wieder seit Kurzem mit C-Programmierung und AVR.

Dein Ansatz ist falsch.
Dein Problem ist das ständige lcd_clear.
Das braucht kein Mensch.

Du musst deine Sichtweise ändern: Du willst nicht das Display ständig 
löschen und neu beschreiben, sondern du willst auf der Anzeige nur die 
Dinge überschreiben, die sich geändert haben. Dann bist du das 
Flackern los und hast trotzdem eine schnelle Reaktion.

Edit: Aber aufpassen. Eventuell musst du manche Dinge mit Leerzeichen 
überschreiben. Sonst hast du den Fall, dass der Text "ZAUN FEHLER" wenn 
er durch "ZAUN EIN" überschrieben wird, auf der Anzeige ein "ZAUN 
EINLER" ergibt :-)

von IceCap (Gast)


Lesenswert?

Vielen Dank für den Hinweis.
Eigentlich sehr einfach :)

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
Noch kein Account? Hier anmelden.