PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bin wieder mal ein "Blind-Bummie" ;)



oderlachs
19.05.2013, 21:00
Für eine Spannungsauswertung, habe ich mich mal mit den ADC Funktionen eines ATMega8 befasst und habe anhand der ATmega8 Beschreibung mir ein Gcc Prog "zusammengebaut" mit opt. Auswertung auf dem STK500.
Was ich aber nicht recht begriffen habe, ist der ADC-Wert in Bezug auf die am ADC0 Eingang anliegende Spannung zu konkretisieren. ich habe zwar zwei Zustände der beiden LED.
Vieleicht habe ich mich auch ganz hinten angestellt und nur einen "Schmitt-Trigger" gebastelt ;) , mir ging es aber darum einen Wert zu erhalten, der mir Aufschluss auf den gemessenen Wert gibt.
Hier ist mal der Code:
/* ================================================== ======================== */
/* */
/* adc_atm8_1.c */
/* (c) 2013 Gerhard Hinze */
/* */
/* Description */
/* ADC Test mit ATmega8 auf STK500 */
/* ================================================== ======================== */
#ifndef F_CPU
#define F_CPU 3686400UL
#endif
#include <avr/io.h>
#include <util/delay.h>
//#include <avr/interrupt.h>

void adc_init();


int main (void)
{

adc_init();

while(1)
{

ADCSRA |= (1<<ADSC); // starte conversion
while(ADCSRA & (1<<ADSC)); //Warte bis fertig
if (ADC <= 128) // Welcher Wert entsprechend dem Eingangswert , Messspannungsauswertung
{

PORTD |= (1<<PD4); // ADC-Wert nicht überschritten LED 4
PORTD &= ~(1<<PD5);
}
else
{
PORTD |= (1<<PD5); // ADC-Wert überschritten LED 5
PORTD &= ~(1<<PD4);
}
}

}

// Init ADC

void adc_init()
{
DDRD = 0x30; //DDRD Pin 4,5 Ausgang
ADCSRA |= (1 << ADEN); // Enable ADC
ADMUX |= (1 << REFS0); // Set ADC reference to AVCC
ADCSRA |= (1 << ADPS2) | ( 1 << ADPS0); // Prescaler 32 = ~115kHz ADC sample rate
ADMUX |= (1 << ADLAR); // Left shift ADC result

}



Vielleicht kann mir ja jemand helfen, der Source ist wie gesagt aus dem ATmega8-PDF und Recherchen im Web und meinen Büchern entstanden.

Ich danke mal schon für jede Hilfe.

Gruss Gerhard

PS. der Messwert soll später mal auf einem LCD oder LED Balken angezeigt werden

Hubert.G
19.05.2013, 21:24
Dein Programm funktioniert bis auf einen kleinen Fehler.
Hier "if (ADC <=128"
muss es heißen "if (ADCH <=128"
Dann schalten deine LED bei der halben Spannung um.

oderlachs
20.05.2013, 09:06
Hallo Hubert,
habe vielen Dank für die Antwort. Ich bin aber auch noch nicht so richtig mir klar geworden, wie ich da vorgehen soll. Manche Beispiele nehmen den wert ADC, andere ADCW, Du schreibst ADCH , ich denke das soll das HByte von ADC sein ??...
Was ich noch nicht richtig kapiert habe ist wie rechne ich das in einen Masseinhei bezogenen Wert um , in diesem Falle Volt ?
Ein Beispiel habe ich aus der Arduino-Welt, da heisst es , so verstehe ich es, Ausgabe in Volt = ADC * Vref(5v)* 1024, gilt das auch hier ??
da tut sich die nächste Frage auf bei mir , wie muss der Wert VRef sein , kann/muss er kleiner, (grösser) oder gleich gegenüber der Betriebsspannung sein ??

Ich sage mal was das Projekt werden soll, es soll zur Kontrolle eines Akkus sein , ich brauche als so 2 Kontrollwerte, Laden ein, Laden aus...es wird zwar eine getaktete Lade-/Prüfeinrichtung , aber erst mal muss ich ja die Funktion des ADC kapiert haben , um mich dann weiter damit zu befassen was noch so drum herrum ist. Das sollte mit einem ATmega8 besser noch mit dem ATTiny2313 machbar sein, letzterer hat aber keinen ADC soviel ich weiss, bzw.besser gesagt, verstanden habe.

Na vieleicht hat wer noch ne Info für mich,wo ich sehr dankbar für sein würde.

Mein English ist leider nicht so gut, als das ich alles aus den datenblättern alles 100% verstehe, d.h. ich arbeite mit PC-Translatorprogramm "PT-20" und Wörterbuch

Gruss und Danke !!

Gerhard

radbruch
20.05.2013, 09:39
Hallo

Durch

ADMUX |= (1 << ADLAR); // Left shift ADC result

wird bestimmt, dass das 10-bitige Ergebnis der Wandlung linksbündig im 16-Bit ADC-Register gespeichert wird. Deshalb findet man die MSB (=most significant bites -> http://de.wikipedia.org/wiki/Bitwertigkeit) im Highbyte ADCH. Und da dies nur 8 Bit besitzt, geht der Bereich von 0 bis 255. Die Formel zur Berechnung der Spannung lautet

Referenzspannung / Auflösung des ADC * Messwert

Wenn du linksbündig wandelst und nur ADCH auswertest ist die Auflösung 255. Die gemessene Spannung muss immer kleiner als die Referenzspannung sein. Wenn die Akkuspannung ohne Spannungsregler den AVR versorgt ist sie als Referenz nicht geeignet.

Gruß

mic

Hubert.G
20.05.2013, 09:40
Hallo und einen schönen Feiertag Vormittag
Ob du ADC oder ADCW nimmst ist egal, solange es der Compiler versteht. Es werden in dem Fall beide Byte ausgelesen. Ich habe ADCH genommen, das höherwertige Byte, da du ja linksbündig ausgibst. Überleg mal wann der Wert <128 ist wenn das Ergebnis, 10bit, linksbündig ausgegeben wird.
Ganz stimmt deine Rechnung nicht. Ausgabe in Volt= (ADC*Vref)/1024.
Vref darf max. VCC sein, min. laut Datenblatt.

021aet04
20.05.2013, 09:56
Beim ADC hast du mehrere Möglichkeiten wie du ihn auslesen kannst. Du musst immer ADCH auslesen, ansonsten wird der Zugriff auf den ADC blockiert (der ADC liest keine neuen Daten ein). Steht im DB auf S190 letzter Absatz. Das ist der Grund warum es das ADLAR Bit gibt.

Wenn du 8Bit Auflösung benötigst setzt du das ADLAR Bit im ADMUX Register und liest es dann mit
Variable = ADCH;aus

Wenn du die vollen 10Bit benötigst gibt es 2 Möglichkeiten. Entweder du liest es mit ADCL und ADCH aus oder du liest es direkt mit ADCW aus (ADLAR Bit bleibt 0).

Variante 1 (ADCH immer als letztes auslesen):
Variable1 = ADCL; //0-255
Variable2 = ADCH; //0-3

Variante 2:
Variable = ADCW; //0-1023

Die Referenzspannung muss zwischen 0V und VCC sein. Welche Spannung genau gewählt wird ist egal. Zusätzlich gibt es interne Referenzen (meist 1,1V und/oder 2,56V, beim Atmega8 hast du nur 2,56V).

Beim Atmega8 hast du als Referenz eine externe Spannung an AREF Eingang (zwischen 0V und VCC), AVCC mit externen Kondensator an AREF (Achtung die Spannung liegt an AREF an, nur mit Kondensator) oder die interne Referenz (gilt das gleiche wie bei AVCC als Referenz).
Die Einstellmöglichkeiten findest du auf S199.
Bei AVCC als Referenz hast du die gleichen Störungen am ADC wie am AVCC Eingang (deswegen wird die Schaltung mit Induktivität und Kondensator am AVCC empfohlen (S196)

Die Formel wie man den ADC Wert berechnet steht auf S199. Die Formel musst du noch umformen. Wenn du 8Bit verwendest musst du statt 1024 mit 256 rechnen.

Der Attiny2313 hat, so wie du schon geschrieben hast keinen ADC. Eventuell könntest du mit dem Komparator arbeiten. Dieser löst einen Int aus.

http://www.atmel.com/Images/Atmel-2486-8-bit-AVR-microcontroller-ATmega8_L_datasheet.pdf

MfG Hannes

oderlachs
20.05.2013, 10:02
Erstmal Euch Beiden ein Dankeschön für schnelle Antwort...
@Hubert :wie war das mit dem "Blindbummie" bei mir? :

Ausgabe in Volt = ADC * Vref(5v)* 1024, natürlich sollte es Ausgabe in Volt = ADC * Vref(5v) / 1024heissen
so stehts ja auch in meinem Souce..

@Radbruch
Dir auch Danke für die detailierte Erklärung der Register, da bin ich noch ein wenig wacklich auf den Beinen in der Hinsicht. Nicht das ich das nicht verstehe, nein ich weiss einfach noch nicht alles so genau.
Die Ref.Spannung wird über eine Stabilisatorschaltung im Ladegerät bereitgestellt, nicht vom Akku.. trotzdem Danke für den Hinweis.

+++++++++++++++++++++++++++++++++++

Hier mal ein Blockschaltbild (http://robot.oderlachs.de/garten/) (nicht das beste) was ich mir vorstelle, es ist die zentrale Stromversorgung für alle Gartensteuerungen...

Gruss Gerhard

PS.: Bei meinem STK500 habe ich 5,1V Vcc und 3,3V Vref eingestellt.

@Hannes : Auch Dir vielen Dank, besonders für die Ausführlichkeit, wir müssen uns beim Posting lesen/Schreiben überschnitten haben, das ich Dich nicht gleich gelesen habe