PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Aufgaben zur Elektronik --> Batterieprüfung (A/D-Wandler)



jawo3
02.09.2007, 13:14
Hi,
ich habe das erste Begleitbuch zum ASURO und hinten bei den Elektronik-Aufgaben steht unter Punkt 5.2 "Batterieprüfung", dass man im Handbuch [5] zu dem eingesetzen Prozessor das Kapitel über den A/D Wandler durchlesen soll.

Ich habe bisher zwar soviel mitbekommen, dass ein A/D Wandler dazu da ist, analoge in digitale Signale umzuwandeln, aber daraus werde ich noch nicht so ganz schlau, wozu das Teil eigentlich nötig ist, geschweige denn wie man mit Hilfe dessen die Batterie prüfen kann.

Ich habe mir das Handbuch zum AtMega8 von der CD angeguckt aber da steht alles auf Englisch und ich konnte nichts über den A/D Wandler finden, dass mir irgendwie weitergeholfen hätte.

Es wäre schön, wenn ihr mir detailliert für Anfänger erklären könntet, wozu das Ding da ist und wie man damit die Spannung auslesen kann oder wenn ihr mich zu einer guten Erklärung verweisen könntet. [-o<


Vielen Dank
jawo3

Reeper
02.09.2007, 14:17
Du kannst die Spannung mit einem Spannungsteiler (zB. wie dem vom RN-Board) ermitteln:

init:

void adc_init(void)
{
ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Teilungsfaktor 73.728 <= X <= 294,912 ---> X=128
/* ADMUX &=~ ((1<<REFS1) | (1<<REFS0)); // Referenzspannung off */
}

//-----------------------------------------------------

float adc_Kanal_messen(uint8_t mux)
{
adc_result = 0;
ADMUX = mux; // Kanal waehlen
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC) ) {;} // auf Abschluss der Konvertierung warten
adc_result = ADCW; // ADCW muss einmal gelesen werden
adc_result = 0; // Dummy
for( adc=0; adc<4; adc++ )
{
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) ) {;} // auf Abschluss der Konvertierung warten
adc_result += ADCW; // Wandlungsergebnisse aufaddieren
}
adc_result /= 4; // Summe durch vier teilen = arithm. Mittelwert
adc_result = adc_result*(5.00/1023);
return adc_result;
}

auslesen:

adc_Kanal_messen(1);
adc_result=adc_result*5.00736;
dtostrf(adc_result,2,2,puffer_tostr);
lcd_gotoxy(0,1);
lcd_puts("Spannung: ");
lcd_puts(puffer_tostr);
lcd_puts(" Volt \n\r");

Die Code-Schnipsel findest du hier im Forum (sowie die Spannungsteiler-Berechnung) und hier: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#ADC_.28Analog_Digital_Converter.29

Gruß
Stefan

damaltor
02.09.2007, 14:37
der adc nimmt eine analoge spannung (also eine spannung zwischen 0V und 5V) und berechnet daraus einen wert zwischen 0 (0V) und 1023 (5V).

damit kann man zB die liniensensoren nutzen:

der sensor selbst ist ein lichtabhängiger widerstand. je mehr licht drauf fällt (bzw vom boden reflektiert wird, was halt bei weisser fläche besser ist als bei schwarzem strich), desto kleiner ist der widerstand. desto höher ist also die spannung die am adc ankommt.

sagen wir mal, der sensor hat einen ausreichenden widerstand um nur 2,5 v ankommen zu lassen, wir sprechen also von einer recht grauen fläche bzw. ungefähr dem zustand wenn der sensor genau auf der kante der linie ist.

der adc berechnet dann ungefähr 500. mit diesem wert kann man arbeiten und rechnen, im gegensatz zur analogen spannung von 2,5 v.

ganz grob gesehen kann man also sagen, dass der adc eine spannung misst und das ergebnis ausgibt.

jawo3
02.09.2007, 15:32
Okay, dann weiß ich jetzt schon mal ein bisschen mehr.

@Reeper
In dem Code stehen ganz viele Befehle drin, von denen ich noch nie etwas gehört habe. Was sind das für Dinger mit dem "lcd"? Dient das zur Ausgabe auf einem Display? Wie kann man das dann umschreiben, sodass es als SerWrite gesendet wird?

In dem von dir geposteten Link stand etwas von 8Bit und 10Bit A/D-Wandlern. Formen die dann aus der Spannung nur einen Wert von 0 bis 8 statt von 0 bis 1024? Wie viel Bit hat denn ASUROs A/D Wandler?


@damaltor

der adc nimmt eine analoge spannung (also eine spannung zwischen 0V und 5V) und berechnet daraus einen wert zwischen 0 (0V) und 1023 (5V).

Also würde er dann die Batteriespannung auslesen und daraus dann einen Wert zwischen 0 und 1024 machen?
Aber wie kann ich die Auslesung starten bzw. welche Funktion muss ich dafür aufrufen und wie kann ich dann auf den ermittelten Wert zugreiffen und mit ihm rechnen.

Und wenn er aus einer Spannung zwischen 0V und 5V einen Wert errechnet, wie macht er das dann mit vollen Batterien, die dann ja so um die 6V haben dürften?


Und dann hätte ich noch eine kleine Frage für die ich nicht extra einen neuen Thread aufmachen möchte:
Wie greifft man auf einem BESTIMMTEN Taster zu. Mit PollSwitch() fragt man ja ab, ob IRGENDEINE Taste gedrückt wurde, aber wie ist das, wenn man eine BESTIMMTE Taste haben möchte? Sind die einfach durchnummeriert?
Ich habe irgendwo schonmal was von unterschiedlichen Wiederständen gehört. In welcher Weise spielen die dabei eine Rolle?


Es tut mir wahnsinnig Leid, dass ich euch mit so vielen Fragen überrumpeln muss, aber ich freue mich immer sehr, wenn ich etwas sinnvolles dazulernen kann.

Schon mal vielen Dank im Voraus
jawo3

damaltor
02.09.2007, 16:04
der adc hat nicht festgelegt, dass 1023 = 5V sind. dies kann man mithilfe einer extern anzulegenden vergleichsspannung einstellen, ausserdem kann der prozessor selbst eine exakte spanung von 2,56V intern generieren. dieser zählt dann glaube ich als "256".

due batteriespannung ist ausserdim etwa 6V, aber wird durch die große diode um etwa 0,7V heruntergeregelt.

mit pollswitch fragt man nicht alle taster ab. sondern man startet den analog-digital-wandler =)

jeder taster ist mit einem widerstand verbunden. dabei ist der wert, den pollswitch zurückgibt, die SUMME aller taster. die taster haben folgende werte:

Taster1: 1
Taster2: 2
Taster3: 4
Taster4: 8
Taster5: 16
Taster6: 32

Wenn Pollswitch also "16" zurückgibt, dann ist taster 5 gedrückt. wenn pollswitch "44" zueück gibt, dann sind die taster 6,4,3 gedrückt.

für jede zurückgegebene zahl gib es ur eine mögliche tasterkombination.


die asuro adcs haben 10 bit, man kann aber auch nur 8 bit auslesen wenn man will. dann ist der wert nicht so genau, er geht nur von 0 bis 255. das reicht oftmal aus.

jawo3
02.09.2007, 16:26
der adc hat nicht festgelegt, dass 1023 = 5V
Schade eigentlich...


dies kann man mithilfe einer extern anzulegenden vergleichsspannung einstellen, ausserdem kann der prozessor selbst eine exakte spanung von 2,56V intern generieren. dieser zählt dann glaube ich als "256".
Sorry, aber den Satz verstehe ich inhaltlich nicht so ganz. Was ist das für Vergleichsspannung und wo kommt die her? Und wozu kann der Prozessor 2,56V generieren?


due batteriespannung ist ausserdim etwa 6V, aber wird durch die große diode um etwa 0,7V heruntergeregelt.
Achso, okay!


mit pollswitch fragt man nicht alle taster ab. sondern man startet den analog-digital-wandler =)

jeder taster ist mit einem widerstand verbunden. dabei ist der wert, den pollswitch zurückgibt, die SUMME aller taster. die taster haben folgende werte:

Taster1: 1
Taster2: 2
Taster3: 4
Taster4: 8
Taster5: 16
Taster6: 32

Wenn Pollswitch also "16" zurückgibt, dann ist taster 5 gedrückt. wenn pollswitch "44" zueück gibt, dann sind die taster 6,4,3 gedrückt.

für jede zurückgegebene zahl gib es ur eine mögliche tasterkombination.
Juhu, das habe ich verstanden.
Allerdings macht mir trotzdem eines meiner Übungsprogramme Probleme.
Was ist hier dran falsch:


#include "asuro.h"

int main(void)
{
Init();

while(1)
{
if (PollSwitch()==1)
{
StatusLED(YELLOW);
BackLED(OFF,OFF);
FrontLED(OFF);
}
else if (PollSwitch()==2)
{
StatusLED(RED);
BackLED(OFF,OFF);
FrontLED(OFF);
}
else if (PollSwitch()==4)
{
BackLED(ON,OFF);
FrontLED(OFF);
}
else if (PollSwitch()==8)
{
BackLED(OFF,ON);
FrontLED(OFF);
}
else if (PollSwitch()==16)
{
BackLED(ON,ON);
FrontLED(OFF);
}
else if (PollSwitch()==32)
{
BackLED(OFF,OFF);
FrontLED(ON);
}
else StatusLED(GREEN);
}
return 0;
}

Hier soll bei einem bestimmten Tastendruck eine bestimmte LED leuchten, aber da gibt´s zwischendurch immer Probleme. Die StatusLED Anweisungen laufen sauber, aber wenn ich zB Taster3 drücke und danach Taster4 verändert sich gar nichts. Es wäre nett, wenn ihr da mal kurz drüber gucken könntet.


die asuro adcs haben 10 bit, man kann aber auch nur 8 bit auslesen wenn man will. dann ist der wert nicht so genau, er geht nur von 0 bis 255. das reicht oftmal aus.
Habe, ich glaube ich auch verstanden.

Aber jetzt muss ich noch mal kurz genauer nachfragen:
Also wenn dem ADC zum Beispiel über die Taster eine Spannung zugeführt wird, was macht er dann damit? Wandelt er dass dann in einen Wert zwischen 0 und 1023 um, oder läuft die Sache anders.



Vielen Dank
jawo3

PS: Ich komme mir irgendwie so unwissend vor, aber jeder wird ja hoffentlich mal so angefangen haben, oder O:)

Werner++
02.09.2007, 17:43
Allerdings macht mir trotzdem eines meiner Übungsprogramme Probleme.
Was ist hier dran falsch:
Wenn Du gleichzeitig Taster 3 und 4 drückst, so liefert Pollswithc() die Summe von 4 (für Taster 3) und 8 (für Taster 4) zurück - also 12. In Deinem Programm wird nie auf 12 abgefragt, also bleibt die StatusLED grün - der letzte else-Fall.

Um das gleichzeitige Drücken der Tastern feststellen zu können, kannst Du den Returnwert von Pollswitch binär undieren. Also etwa so:
unsigned char taster = Pollswitch();
if( taster & 4 ) /* Taster 3 */
{
/* zeige LED für Taster 3 */
}
else
{
/* LED für Taster 3 OFF */
}
if( taster & 8 ) /* Taster 4 */
{
/* zeige LED für Taster 4 */
}
else
{
/* LED für Taster 4 OFF */
}
/* usw. */


Ich komme mir irgendwie so unwissend vor, aber jeder wird ja hoffentlich mal so angefangen haben, oder O:) na ja - Du bist ja noch jung - oder?

Gruß
Werner

Reeper
02.09.2007, 18:37
Hallo jawo3,

der Code soll stellvertretend sein (merke gerade, dass nicht der rp6, sondern der Asuro gemeint war, deshalb müssten evtl. die Register-Einstellungen geändert werden).

Ersteinmal die Spannungsteiler - Berechnunge (ohne Spannungsteiler darf höchstens bis zur Referenzspannung gemessen werden):
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=1483&highlight=spannungsteiler+berechnung

Variable:

uint8_t bPortd,adc;
float adc_result;
char puffer_tostr[20];

init (Register setzen):

void adc_init(void)
{
ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Teilungsfaktor 73.728 <= X <= 294,912 ---> X=128
/* ADMUX &=~ ((1<<REFS1) | (1<<REFS0)); // ---> Referenzspannung off */
}

messen:

float adc_Kanal_messen(uint8_t mux)
{
adc_result = 0;
ADMUX = mux; // Kanal waehlen und VCC=Referenzspannung
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung starten
while ( ADCSRA & (1<<ADSC) ) {;} // auf Abschluss der Konvertierung warten
adc_result = ADCW; // ADCW muss einmal gelesen werden
adc_result = 0; // Dummy -> adc_result nullen
for( adc=0; adc<4; adc++ ) // 4x eine ADC-Wandlung durchführen
{
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) ) {;} // auf Abschluss der Konvertierung warten
adc_result += ADCW; // Wandlungsergebnisse aufaddieren
}
adc_result /= 4; // Summe durch vier teilen = arithm. Mittelwert
adc_result = adc_result*(5.00/1023); // 5,00 Volt nach Spannungswanlder gemessen -> wenn kein Spannungsteiler verwendet = Endergebnis
return adc_result;
}


auslesen (zB. im main-Teil):

adc_Kanal_messen(1); // PORTA1 auswählen
adc_result=adc_result*5.00736; // 5,00736 = bei den gewählten Widerständen bester Wert (vom Spannungsteiler)
dtostrf(adc_result,2,2,puffer_tostr); // float to string umwandlung -> LCD und UART Ausgabe (verständlich Zeichen)
/*
lcd_gotoxy(0,1);
lcd_puts("Spannung: ");
lcd_puts(puffer_tostr);
lcd_puts(" Volt \n\r");
*/

Habe den Code nochmal besser kommentiert (am besten in einen Editor wie Programmers Notepad kopieren -> besser lesbar).
Die LCD Kommandos wurden ausgeklammert.

Der Code oben ist für einen Atmega32 (Register könnten andere sein).
Wie o.g. ist es hier recht gut erklärt:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#ADC_.28Analog_Digital_Converter.29

Gruß
Stefan

damaltor
02.09.2007, 21:15
ja, so sieht das ganze auf registerebene aus... =)

über die taster wird immer eine spannung an den adc gelegt. dieser wird durch die funktion pollswitch nur dazu aufgefordert, den wert umzuwandeln.

um eine spannung zu messen braucht man immer eine vergleichspannung. diese vergleichspannung wird i.a. als 1023 festgelegt. die hälfte dieser spannung wäre dann z.b.511 und ein viertel dieser spannung wäre 255. ein tausendstel der spannung wäre theoretisch der wert 1.

wenn man jedoch die batteriespannung messen will braucht man eine vergleichsspannung - es macht ja wenig sinn die batteriespannung mit sich selbst zu vergleichen. dazu hat der prozessor eine interne schaltung, die jederzeit exakt 2,56V generiert. diese kann man als vergleichsspannung nutzen.


zurück zu pollswitch: das interessante an ebendiesen werten ist die binäre darstellung.
1 = 00000001
2 = 00000010
4 = 00000100
8 = 00001000
16 = 00010000
32 = 00100000

dadurch kann man ganz gut herausfinden, welche taster nun gedrückt sind. dazu solltest du dich mal mit LOGISCHEN OPERATOREN beschäftigen, das sind & (und) sowie | (oder).

jawo3
03.09.2007, 14:22
ja, so sieht das ganze auf registerebene aus... =)
Gibt es zu der Darstellung auf Registerebene hilfreiche Tutorials/Anleitungen/Erklärungen/Lehrtexte. Das würde mir das Verständnis wohl um einiges erleichtern.



über die taster wird immer eine spannung an den adc gelegt. dieser wird durch die funktion pollswitch nur dazu aufgefordert, den wert umzuwandeln.
Läuft das auch so zum Beispiel bei den Fototransistoren, dass je nach Helligkeit eine unterschiedlich große Spannung erzeugt un an den ADC gelegt wird und je nachdem wie groß die Spannung ist die ihn erreicht ein Wert ermittelt wird, indem er die erhaltene Spannung mit einer vom Prozessor generierten Vergleichsspannung vergleicht?
(Bitte sagt mir, dass das richtig war 8-[ )


zurück zu pollswitch: das interessante an ebendiesen werten ist die binäre darstellung.
1 = 00000001
2 = 00000010
4 = 00000100
8 = 00001000
16 = 00010000
32 = 00100000

dadurch kann man ganz gut herausfinden, welche taster nun gedrückt sind. dazu solltest du dich mal mit LOGISCHEN OPERATOREN beschäftigen, das sind & (und) sowie | (oder).
Okay, danke. Das habe ich soweit jetzt alles verstanden. Mit logischen Operatoren habe ich mich während des Lernens der C Grundlagen schon beschäftigt und das Binär-System habe ich mittlerweile ziemlich gut drauf.


Aber wie gesagt, es wäre schön, wenn ihr mir mit dem Programmieren auf Registerebene helfen könntet.


Vielen Dank
jawo3

damaltor
03.09.2007, 21:06
die register sind im datenblatt des atmega erklärt. lade das datenblatt bei atmel runtre oder schau auf der cd nach, und blättere zu analog-digital-converter. zuerst kommt ein erklärung, dann eine exakte veschreibung welche register wie gesetzt werden müssen (register lassen sich wie normale unsigned-char-variablen beschreiben) und dann ein programmierbeispiel.

jawo3
03.09.2007, 21:49
Okay, danke.

Ich guck mir das morgen mal in aller Ruhe an.

Sternthaler
10.09.2007, 00:06
Hallo jawo3,
wenn du wegen der Taster und deren Spannungswerte mal genauer nachlesen möchtest, dann sieh mal ab hier (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=273400#273400) nach. (P.S.: Ist sehr persönlich geschrieben. Bitte nicht auf dich beziehen jawo3.)
@damaltor: Bitte nicht lachen, aber es scheint sich zu lohnen mal ausführlich zu schreiben.

Mit der 2,56Volt Referenzspannung ist es ein bisschen anders.
Der AD-Wandlerkanal 5 (Batterie) ist über einen Spannungsteiler mit der Betriebspannung vom Asuro verbunden. Im Schaltplan sind da angegeben:

VCC --- R12/12k ---+--- R13/10k --- Masse
|
AD-Kanal 5Somit misst ADC-5 immer VCC * R13 / (R12 + R13) Volt. Also VCC * 0,4545..
Damit ist die Spannung bei VCC=5 Volt dann 2,27.. Volt am ADC.
Ist der Jumper auch bei Batterien gesteckt, hätten wir VCC=6 Volt und dann 2,72.. Volt. Hier knallt uns aber der AVR-Prozessor um die Ohren und sollte somit tunlichst nur ohne Jumper betrieben werden.
Dann sind VCC=6 Volt - 0,6 Volt und somit 2,45..Volt am ADC.

Diese Spannung ist immer kleiner als die Referenzspannung von 2.56 Volt. Höhere Spannungen können hier auch nicht gemessen werden, da der maximale Wert von 1023 schon bei eben diesen 2,56 Volt ermittelt wird.

Hier wird die Referenzspannung in 1023 Teilstücke zerlegt und somit ist jeder ermittelte ADC-Wert ein vielfaches von 1 / 1023 * 2,56 Volt.

Wenn der ADC-Wert nun z.B. 909 liefert, ergibt dies somit:
909 * ( 1 / 1023 * 2,56 Volt ) = 2,2747.. Volt am Pin ADC5.
Mit dem Spannungsteiler an diesem Eingang, berechnet sich VCC dann
zu 2,2747.. / 0,4545.. = 5 Volt.
Das ganze kann sehr gut im Band I zum Asuro nachgeschlagen werden.

P.S.: Die Genauigkeit des Ergebnis ist recht eingeschränkt.
Die im Asuro erzeugte Referenzspannung ist relativ schlecht, und natürlich sind auch die beiden Widerstände R12 und R13 noch mit einer hohen Tolerant behaftet.
Im Asuro Band I wird eine Beispiel-Rechnung für einen Messwert von 720 durchgeführt. Dort werden Schwankungen dann von 3,74 Volt bis hoch zu 4,40 Volt berechnet.

jawo3
10.09.2007, 13:54
Danke,
theoretisch habe ich es jetzt verstanden.
Ich gucke mir das im ASURO Buch 1 nochmal genauer an, zumal ich mich in den letzten Tagen mit Registern und so beschäftigt habe. Bestimmt verstehe ich das dann mehr.

damaltor
14.09.2007, 12:13
ichdachte immer die 2,56 volt sind sehr exakt...

dasmit 2,56v = 1023hab ichauch getstern geleen, sorry nohmal..

Sternthaler
14.09.2007, 18:13
ichdachte immer die 2,56 volt sind sehr exakt...
Was ist den exakt?
Haarspalter Sternthaler nöhlt ja schon bei 1% Toleranz ;-)
Wie genau das Ding aber nun tatsächlich ist müsste ich nun auch mal nachschlagen. Ich 'meine' aber gelesen zu haben, dass die Genauigkeit aber tatsächlich recht schlecht wäre. Im Verhältniss zu den Widerstandstoleranzen aber bestimmt vernachlässigbar.

Sternthaler
15.09.2007, 23:32
Hier wieder der Haarspalter.
Nachgelesen in der Asuro-Bibel Band I, Seite 72:
- Toleranz der Widerstände: popelige 1%
- Toleranz der Spannungsreferenz: 2,45 bis 2,8 Volt.
Da also weht der Wind her, und ist doch recht böhig.

damaltor
16.09.2007, 16:00
oha, das ist wirkich nicht schön. na gut...

wovon hängt das ab? allgemeine toleranz? versorgungsspannung? takt?

Sternthaler
16.09.2007, 22:27
Hallo zusammen.
Lesestoff in der AVR-Doku:
Im AVR ist eine Bandgap-Reference, die mit typischen 1,23 Volt angegeben wird. Von der werden irgendwie die 2,56 Volt abgeleitet.
Das Bandgap-Ding wird schon mit Min 1,15 und Max 1,35 Volt angegeben auf Seite 40 der AVR-Doku.
Hochgerechnet müssten das dann Min 2,39 bis Max 2,81 Volt für die 2,56V-Referenz geben.
Auf Seite 243 in der AVR-Doku werden dann aber 2,3 bis 2,7 Volt angegegeben.
Welches Papier auch immer am geduldigsten ist, jedenfalls ist das Teil eine windige Angelegenheit.
Warum? Wieso? Scheint nicht das Lieblingsbauteil bei den AVR-Herstellern zu sein.
Ich gehe mal davon aus, dass die angegeben Werte nur Streuungen innerhalb der produzierten AVR's sind, und nicht innerhalb eines einzelnen Chips je nach Wetterlage so schwanken.
Somit sollte es für uns Asurorianer ausreichen, 2 Messpaare zu machen.
Volle Akkus mit Multimeter und ADC-Wandler
Leere Akkus dito.
Aus diesen Werten den 'persönlichen' Umrechenwert berechnen und fertig.

damaltor
17.09.2007, 13:14
hmmm das klingt vernünftig..