Forum: Mikrocontroller und Digitale Elektronik ATMEGA8: <<<Analog Comperator>>>


von Chillxx (Gast)


Lesenswert?

Hallo!

Ich will folgendes tun:
Kurz gesagt hab ich einen Taster, mit dem ich einen Verbraucher 
einschalte, bei erneuter Betätigung schalte ich den Verbraucher wieder 
ab.

Für diese Anwendung verwende ich einen Lithium-Ionen Akku mit 7,4V.
Bei Unterschreitung einer Spannung von 6,8V (ist momentan nicht so 
wichtig), soll meine Anwengung nicht mehr starten können.

Deswegen will ich mit dem Analog Comperator die Akku-Spannung mit der 
Ausgangsspannung des Spannungsreglers (5V als Referenzspannung) 
vergleichen und ins Programm als "Einschaltvoraussetzung" einbinden.
- Akkuspannung >6,8 --> Anwendung wird fortgesetzt
- Akkuspannung <6,8 --> Anwendung darf nicht mehr Starten

??? Welche Bits am ACSR-Port muss ich setzen bzw. brauche ich den 
Interrupt?
??? Wie kann ich den Wert des Vergleichs (0 oder 1) auslesen bzw. wo 
steht dieser drin?

Wer kann mir helfen?
MFG

von nicht gast (Gast)


Lesenswert?

>Wer kann mir helfen?
Datenblatt. Besonders der Teil "Absolute Maximum Ratings" (o.ä.)...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Chillxx schrieb:
> des Spannungsreglers
Welcher Spannungsregler?
> (5V als Referenzspannung)
Ein "normaler" 7805 hat da gern mal +-5% Toleranz...

nicht gast schrieb:
> Besonders der Teil "Absolute Maximum Ratings"
Und den Abschnitt "Common Mode Range".
Du solltest besser deine 5V Referenz auf 2,5V teilen und deine 6,8V über 
einen Spannungsteiler ebenfalls auf diese 2,5V bringen...

BTW: es ist ein Comparator mit kleinem 'a'

von Chillxx (Gast)


Lesenswert?

...werd ich mir mal anschaun, der Vorgang ist hier aber nicht 
beschrieben.
Muss ich für diesen Vergleich den Comperator oder den AD-Wandler nehmen?

mfg

von Timmo H. (masterfx)


Lesenswert?

Chillxx schrieb:
> Muss ich für diesen Vergleich den Comperator oder den AD-Wandler nehmen?
Kannst du beides machen. Bei Comparator hast du halt nur gut oder nicht 
gut (ACI = 1 oder 0), mit dem ADC kannst du die exakte Spannung 
bestimmen und per Software quasi deine Grenzen festlegen.

von Bernd (Gast)


Lesenswert?

Chillxx schrieb:
> Muss ich für diesen Vergleich den Comperator oder den AD-Wandler nehmen?

RTFM

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Chillxx schrieb:
> Muss ich für diesen Vergleich den Comperator oder den AD-Wandler nehmen?
Comp-A-rator... :-/

Seis drum:
Der Comparator könnte dir bei unterschreiten der Spannung einen 
Interrupt auslösen, das kann der ADC nicht. Aber wenn du sowieso erst 
beim Tastendruck nachschaust, ob die Spannung noch passt, kannst du auch 
den Comparator nehmen...
Ich würde die Sache allerdings mit dem ADC machen, denn dann kannst du 
messen, ob da eher 7,3V oder 6,9V da sind...

von Chillxx (Gast)


Lesenswert?

OK, sowas würde ich gerne machen 6,7V wäre ja meine Grenze.

Wenn die anliegende Spannung am Spannungsteiler der Referenzspannung und 
der zu messenden Spannung (also Grenze 6,7V) gleich ist, könnte ich 
damit auch einen Vergleich durchführen, oder?

Und welche Variante zieht mehr Strom oder ist das vernachlässigbar?
mfg

von Timmo H. (masterfx)


Lesenswert?

Am Li-Ion wohl eher vernachlässigbar, das liegt im µA-Bereich.
Wenn du richtig Strom sparen willst solltest du dir das Power Management 
und Sleep-Modes ansehen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Chillxx schrieb:
> Wenn die anliegende Spannung am Spannungsteiler der Referenzspannung und
> der zu messenden Spannung (also Grenze 6,7V) gleich ist, könnte ich
> damit auch einen Vergleich durchführen, oder?
Wie meinst du das?

Wenn du den AD-Wandler nimmst, dann mußt du nur noch gegen einen 
Zahlenwert vergleichen, denn den Vergleich (die Wandlung) gegen eine 
Referenzspannung macht ja schon der AD-Wandler...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

1. Du darfst die Akkuspannung nicht direkt auf den AVR geben.
   Beitrag "Re: ATMEGA8: <<<Analog Comperator>>>"
   Du kannst aber einen Spannungsteiler benutzen.

2. ADC hat den Charme, dass du den Ist-Wert messen kannst.

3. AC hat den Charme, dass du Interrupts bekommen kannst.
   Und den Nachteil, dass du nur digital > oder < Referenzspannung
   messen kannst.

4. Mit 2. und 3. kannst du auch während der Verbraucher läuft den Akku
   vor dem Leersuckeln schützen. 2. kanppst dabei mehr Rechenzeit ab und
   wechselwirkt u.U. mit anderen Programmteilen insbesondere anderen ADC
   Messungen

5. Wenn nach 4. der Akkustand bei laufendem Verbraucher unter die
   kritische Grenze fällt und du den Verbraucher abschaltest, rechne
   damit, dass sich der Akku sofort erholt. Du könntest in die AUS-AN-
   AUS... Falle tappen. Thema Hysterese nachlesen. Überlege wie deine
   Schaltung das Einsetzen voll geladener Akkus handhabt.

6. Wenn der 7805 aus dem Akku versorgt wird:
   Arbeitet der 7805 mit 7,4-6,8V Eingangsspannung oder muss da ein
   Low-Drop-Regler verwendet werden? Kann die Eingangsspannung so
   abgesenkt werden, dass der 7805 automatisch die komplette Schaltung
   inkl. AVR (=> Brownout) ausschaltet z.B. durch Diode(n) (-0,7V).

von Chillxx (Gast)


Lesenswert?

@lkmiller
also zuert-als Spannungsregler nehme ich den MCP1703

Lothar Miller schrieb:
> Wie meinst du das?
Damit meinte ich die Spannungteiler für den Analog Converter (falls ich 
den nehmen würde)

Nehm aber wahrscheinlich doch den AD-Wandler, nach deiner Empfehlung :).
Aber wie gehe ich dabei vor?
1.Analogeingan im ADMUX-Register festlegen
2.ADSCR-Register initialisieren
3.ADCW-Wert herausnehmen
4.diesen Wert mit dem gewünschten Wert vergleichen

-->ist das ansatzweise richtig??

MFG und DANKE schon mal für eure Antworten

von Chillxx (Gast)


Lesenswert?

@Stefan
also ich verwende einen MCP1703, der mindestens mit 6,5V betrieben 
werden muss...da der LithiumIonen-Akku (lt.meinen recherchen)erst kurz 
vor der totalen Entladung an Spannung verliert, hab ich 6,7V als 
minimale Spannung angenommen, wobei noch alles funktionieren sollte.

Eigentlich will ich einfach nur verhindern, dass mein Verbraucher 
betätigt werden kann, wenn der akku "leer" ist. Außerdem will ich, dass 
der Verbraucher automatisch abschaltet, wenn die Akkuspannung nicht mehr 
ausreicht.

MFG

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Chillxx schrieb:
> @Stefan
> also ich verwende einen MCP1703, der mindestens mit 6,5V betrieben
> werden muss...

Hmm, Laut Datenblatt geht der sogar tiefer: Vin typ. >5,330V max. 
>5,650V.

Deine Aufgabe kannst du mit dem AC oder dem ADC lösen. Ich würde den AC 
benutzen. Damit bist du nicht auf einen AVR angewiesen, der eine ADC 
Einheit hat (OK, der Atmega8 hat eine).

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Tutorials zu Benutzung von ADC und AC gibt es in der Artikelsammlung.
Es gibt auch Beispiele für Atmega8 auf dem Pollin Board:

Messung der Vcc
http://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#Die_Versorgung_muss_stimmen

Analog Comparator
http://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#Analog_Comparator

von Chillxx (Gast)


Lesenswert?

Ich hab eine kurze Zwischenfrage (bin grad am programmieren):
Wenn ich nur den PC0 als Analogeingang verwende, sind dann alle anderen 
Pins am PORT C als normale I/O`s verfügbar?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Jawoll, das ist (zum Glück) möglich.

von Chillxx (Gast)


Angehängte Dateien:

Lesenswert?

Hab hier einen kleinen Programmausschnitt...
Würde das so funktionieren??

MFG

von reviewer (Gast)


Lesenswert?

> int Referenz=2.5;

Nein.

Compiliert das überhaupt?

von Chillxx (Gast)


Lesenswert?

ich hab einfach mal was reingeschrieben....ist ja wegen dem 
Spannungsteiler kleiner 5V.
Oder kann ich die 5V vom Spannungsregler bzw an AVCC direkt als 
Referenzspannung hernehmen?

Code compiliert ohne Fehler...

von Karl H. (kbuchegg)


Lesenswert?

Chillxx schrieb:
> Hab hier einen kleinen Programmausschnitt...
> Würde das so funktionieren??

Nein.

Du kriegst vom ADC keinen direkten Spannungswert.

Der ADC liefert dir das Verhältnis von gemessener Spannung zur 
Referenzspannung.

(Ich vereinfache jetzt hier bewusst):
Der ADC liefert Werte zwischen 0 und 1023. Wenn dir der ADC 1023 als 
Antwort liefert, dann ist die gemessene Spannung genauso groß wie die 
Referenzspannung. Liefert er 512, dann ist sie genau die Hälfte der 
Referenzspannung usw. usw.

Das heißt jetzt aber NICHT, dass du zuerst die Spannung ausrechnen 
musst, auch wenn das ganz leicht geht

               Messwert * Referenzspannung
    Spannung = ----------------------------
                          1024

Tus trotzdem nicht. Rechne dir aus welchem Messwert deine Schaltschwelle 
entspricht und vergleich dann auf der Basis der ADC Einheiten. Das spart 
zum einen Rechenzeit, zum anderen erspart es dir das Kopfzerbrechen, wo 
denn eigentlich die ganzen Nachkommastellen bei der Umrechnung bleiben.

von Chillxx (Gast)


Lesenswert?

Ok, dann muss ich mir diesen Wert ausrechnen.
Aber vom Programmaufbau/Logik würds so funktionieren?

von Karl H. (kbuchegg)


Lesenswert?

Mal abgesehen davon, dass es ziemlich sinnlos ist, den ADC in jeder 
Runde in der Hauptschleife erneut zu intialisieren und das hier

      while (ADCSRA&(1<<ADSC))

ein ; fehlt

Ja, so würde das funktionieren. Wobei allerdings eine Mittelung über 
mehrere Messwerte der Sache sicherlich nicht abträglich sein würde.

Aber warum in die Ferne schweifen, wenn das Gute im AVR-GCC-Tutorial so 
nahe liegt :-) Dort gibt es fertige ADC Routinen. Du musst nur noch 
deine Referenzspannung wie gewünscht einstellen.

von Walter (Gast)


Lesenswert?

reviewer schrieb:
>> int Referenz=2.5;

Chillxx schrieb:
> Code compiliert ohne Fehler...


das glaube ich dir nicht
(oder du hast einen kaputten Compiler)

von Chillxx (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Mal abgesehen davon, dass es ziemlich sinnlos ist, den ADC in jeder
> Runde in der Hauptschleife erneut zu intialisieren und das hier

Dann schieb ich die Initialisierung einfach an den Anfang?
Diese Merfachmessung hat aber nichts mit dem Free-running Modus zu tun?

Karl heinz Buchegger schrieb:
> while (ADCSRA&(1<<ADSC))
> ein ; fehlt
...steht glau ich in der 5.Zeile in der while-Schleife

Übrigens hab ich dabei mich eh ans AVR-GCC-Turotial gehalten :), sonst 
wär wahrscheinlich garnichts rausgekommen...
Allerdings hab ich noch nicht verstanden, was es mit diesem "uint_t" auf 
sich hat...ist das einfach eine Funktion bzw. wie ein Nebenprogramm?

MFG :)

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Walter schrieb:

>>> int Referenz=2.5;
> das glaube ich dir nicht
> (oder du hast einen kaputten Compiler)

Mein Compiler (Tiny C Compiler) schluckt das ohne murren. Referenz wird 
halt mit 2 initialisiert und nicht wie vielleicht erwartet mit 2.5

@ Chillxx

Statt mit der Fließkommazahl 2.5 könntest du mit dem 1000 fachen Wert 
als Ganzzahl rechnen, also in mV statt in V. Das gibt keine Probleme bei 
der Zuweisung in ein int. Und statt int als Ganzzahl mit Vorzeichen 
bietet sich eine Ganzzahl ohne Vorzeichen an, also unsigned int.

von Karl H. (kbuchegg)


Lesenswert?

Chillxx schrieb:
> Karl heinz Buchegger schrieb:
>> Mal abgesehen davon, dass es ziemlich sinnlos ist, den ADC in jeder
>> Runde in der Hauptschleife erneut zu intialisieren und das hier
>
> Dann schieb ich die Initialisierung einfach an den Anfang?
> Diese Merfachmessung hat aber nichts mit dem Free-running Modus zu tun?

Nein, hat nichts mit dem Freerunning Mode zu tun.
Aber du stellst ja einen Ausgabeport auch nicht ständig auf Ausgabe. Du 
machst das einmal und dann passt das.
Mit dem ADC ist das genauso

>
> Karl heinz Buchegger schrieb:
>> while (ADCSRA&(1<<ADSC))
>> ein ; fehlt
> ...steht glau ich in der 5.Zeile in der while-Schleife

Red dich nicht raus.
Da ist kein ; wo einer hingehört.
Du hast ihn vergessen und dabei die Semantik des Programms verändert.
Rein logisch gesehen macht

         while (ADCSRA&(1<<ADSC))
           Messwert = ADCW;

das genau Gegenteil von

         while (ADCSRA&(1<<ADSC))
           ;
         Messwert = ADCW;

und damit hast du dein Programm durch einen einzigen vergessenen ';' 
zerstört (wenn alles andere stimmen würde). Dein Pech, dass sich durch 
den vergessenen ';' wieder etwas ergeben hat, was gültiges C ist.

>
> Übrigens hab ich dabei mich eh ans AVR-GCC-Turotial gehalten :), sonst
> wär wahrscheinlich garnichts rausgekommen...
> Allerdings hab ich noch nicht verstanden, was es mit diesem "uint_t" auf
> sich hat...

Mehr Sorgfalt!
Das Teil heist nicht uint_t sonder uint16_t und ist ein Datentyp!
u     wie unsigned, also ohne Vorzeichen
int   wie INteger, also Ganzzahl
16    wie 16, und das ist die Anzhahl der Bits
_t    wie underscore T, und das ist ein Anhängsel, damit der geneigte
      Leser schnell erkennen kann, dass er es mit einem Datentyp zu
      tun hat

uint16_t
Ein Datentyp: unsigned Integer mit 16 Bit

> ist das einfach eine Funktion bzw. wie ein Nebenprogramm?
Nebenprogramm gibt es nicht.

Ja, im Tutorial sind fix fertige Funktionen. Du musst sie nur benutzen.
Und wie das geht, ist dort ebenfalls angegeben. Wir haben da ja nicht 
zum Spass ein Beispielprogramm abgedruckt
1
/* Beispielaufrufe: */
2
 
3
int main()
4
{
5
  uint16_t adcval;
6
  ADC_Init();
7
 
8
  while( 1 ) {
9
    adcval = ADC_Read(0);  // Kanal 0
10
    // mach was mit adcval
11
 
12
    adcval = ADC_Read_Avg(2, 4);  // Kanal 2, Mittelwert aus 4 Messungen
13
    // mach was mit adcval
14
  }
15
}

so verwendet man die Funktionen.
Ganz einfach und ganz simpel.

Vor der Hauptschleife wird die Funktion ADC_Init aufgerufen, die, oh 
Wunder, den ADC initilisiert (also seine Parameter einstellt wie zb 
Referenzspannung).
In der Hauptschleife ruft man entweder die Funktion ADC_Read oder die 
Funktion ADC_Read_Avg (Avg steht für Average, engl. Durchschnitt) auf 
und die liefert den aktuellen Messwert, der dann in der Variablen adcval 
abgelegt wird. Und mit dem Wert kannst du dann tun was immer du damit 
tun willst.

Vielleicht wäre ein Blick in ein C-Buch mal angebracht, wenn dir 
Funktionen nichts sagen.

von Chillxx (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Red dich nicht raus.

....ahh....sorry :)

alles andere les ich mir mal sorgfältig durch!!
Danke für die schnelle Antwort!

von Chillxx (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> adcval = ADC_Read_Avg(2, 4);  // Kanal 2, Mittelwert aus 4 Messungen

Kanal 2:
ist damit der Pin am Mikrocontroller gemeint?

von Karl H. (kbuchegg)


Lesenswert?

Ja

ADC0, ADC1, ADC2, ADC3, ADC4, ....

soviele Eingänge wie dein µC für den ADC eben hat. Findet sich im 
Datenblatt, dort aufgeschlüsselt als die MUX Bits.

von Chillxx (Gast)


Lesenswert?

Kurze Vertändnissfrage:

Ist der average ADC Wert im ganzen Programm aktuell (also läuft die 
Messung im Hintergrund und schreibt fortlaufend den neuen Mittelwert in 
adcval) oder muss ich jedes mal, wenn ich was mit dem Wert machen will, 
die Funtkion/Messung neu starten??

mfg

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.