Hallo an alle!
Ich versuche mich gerade neu am Microcontroller programmieren.
Mein Ziel ist es, eine Spannung, abgegriffen über ein Potentiometer
(o-5V), in ein digitales Signal umzuwandeln, und je nach dem, wie hoch
die Spannung ist, möchte ich, dasss erst keine, dann eine, dann zwei und
schließlich 3 LEDs leuchten.
Ich habe ein Atmega8 (myAVR Board USB2.0), dabei habe ich das
Potentiometer an PortC.0 angeschlossen, dies entspricht dem Channel0 im
A/D-Wandler. Als Ausgabe dienen normal die Ports B.0 bis B.2.
Hier mein kleines Programm:
#define F_CPU 3686400
#include <avr\io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
ISR (ADC_vect)
{
int wert;
wert = ADC; //Konvertierte Zahl wird in
ADC gechrieben
if (0b0000000000 < wert <= 0b0100000000)//0V - 1,25V
PORTB = 0b00000000;
if (0b0100000000 < wert <= 0b1000000000)//1,25V - 2,5V
PORTB = 0b00000001;
if (0b1000000000 < wert <= 0b1100000000)//2,5V - 3,75V
PORTB = 0b00000011;
if (0b1100000000 < wert <= 0b1111111111)//3,75V - 5V
PORTB = 0b00000111;
sbi (ADCSRA,6);
}
void initADC()
{
ADMUX = 0; // Kanal 0
ADCSRA = 0xDD; //enable, free run,
intterrupt, runtergetaktet(da adu langsamer als CPU)
}
int main (void)
{
DDRB = 0xFF; // Port B = Ausgang
PORTB= 0xFF;
initADC();
sei (); // Interupts erlauben
do { } while(true);
}
Ich habe die 5V in 4 Bereiche eingeteilt und diese dann in etwa ins
binäre 10Bit umgerechnet, da laut Datenblatt 0V 0000000000b entsprechen
und 5V 1111111111b. Wie man sieht ist ein 10bit AD-Umwandler vorhanden.
Mein Problem ist nun, dass immer alle 3 LED leuchten, egal wie ich das
Potentiometer drehe. Könnte es vllt. Probleme mit der 10bit gewandelten
Zahl geben?
Vielen Dank für eure Hilfe
Viele Grüße
Michael M. schrieb:
> da nimmt er die boardspannung, müsste ich denke ich nicht extra> anschließen, laut datenblatt;
nö, du stellst doch auf AREF, und wenn da nix anliegt, ist dein Wandler
doch immer auf Maximalwert...
Michael M. schrieb:
> also ich hab gerade noch mal geschaut, aref ist mit dem potentiometer> verbunden
AREF geht über einen Kondensator an GND laut Schaltplan...
Michael M. schrieb:
> ( wenn ich die leiteruüge an der> boarunterseite weiter verfolge, komme ich zum potentiometer :()
ein Blick in den Schaltplan wäre sinnvoller...
und wenn ich mal davon ausgehe, dass du einen Poti auf dem Board
benutzt, bei denen eh schon VCC anliegt, wäre es irgendwie praktisch,
die Spannung auch als Referenz zu wählen...
übrigens wäre es auch nett von dir, wenn du Schaltpläne etc und was du
wie angeschlossen hast von Anfang an preisgibst und dir nicht alles aus
der Nase ziehen lässt...irgendwie geht jeder zweite Fragesteller hier
davon aus, dass alle anderen Kristallkugeln zu Hause haben...
Es tut mir leid, dass ich mich hier noch nicht so auskenne. Ich versuche
mich gerade in die Thematik tiefer einzusteigen.
Verbunden ist es, keine Änderung. Ich denke, dass es am Programm liegt.
Michael M. schrieb:
> also ich hab gerade noch mal geschaut, aref ist mit dem potentiometer> verbunden
Und? Hängt da sonst noch was an AREF?
So wie du ADMUX programmiert hast, musst du eine externe Spannung an
AREF anschliessen.
Man kann über ADMUX den AREF Pin auch so programmieren, dass sich der µC
selbst eine Referenzspannung erzeugt.
> ADCSRA = 0xDD; //enable, free run,
Mach das nicht.
Kein Mensch hat Lust dazu, 0xDD im Kopf in eine binäre Darstellung
umzuwandeln um mit dem Datenblatt zu recherchieren, welche Bits du da
gesetzt hast.
0xDD = 0b11011101
Das ist ADEN, ADSC, ADIF, ADIE, ADPS2, ADPS0 gesetzt.
Schreib das auch im Code so!
ADCSRA = ( 1 << ADEN ) | ( 1 << ADSC ) |
( 1 << ADIF ) | ( 1 << ADIE ) |
( 1 << ADPS2 ) | ( 1 << ADPS0 );
Damit sieht man auch im Code zumindest mal, welche Bits im Control
Register gesetzt werden und muss nicht mühsam eine Hex-Zahl
auseinanderpfriemeln.
Ich seh nirgends, wo du ADATE setzt um den Free Running Mode zu
aktivieren.
Das hier
1
if(0b0000000000<wert<=0b0100000000)//0V - 1,25V
2
PORTB=0b00000000;
3
if(0b0100000000<wert<=0b1000000000)//1,25V - 2,5V
4
PORTB=0b00000001;
5
if(0b1000000000<wert<=0b1100000000)//2,5V - 3,75V
6
PORTB=0b00000011;
7
if(0b1100000000<wert<=0b1111111111)//3,75V - 5V
8
PORTB=0b00000111;
ist falsch. Du kannst Vergleiche nicht so kaskadieren, wie du dir das
vorstellst. Ein Vergleichsoperator hat im Regelfall immer links von sich
einen Wert und rechts von sich einen Wert. Mehrere Vergleiche werden mit
&& bzw. || miteinander verknüpft. Das was du da geschrieben hast, ist
zwar nach den C-Regeln durchaus erlaubt und syntaktisch korrekt, macht
aber ganz was Anderes als du vermutest. Auch gibt es nun wirklich keinen
Grund da Binärzahlen für die Werte zu verwenden. Dein ADC liefert Werte
von 0 bis 1023. Die Binärdarstellung interessiert normalerweise
niemanden. Interessant ist praktisch immer das Verhältnis des ADC Wertes
zu 1023, da es eine Aussage darüber erlaubt in welchem Verhältnis die
gemessene Spannung zu AREF steht. AREF kennt man und daher kann man
zurückrechnen, welche Spannung am Messeingang anliegt. Das sind aber
alles Berechnungen. Da interessieren Zahlen und keine einzelnen Bits.
Wenn du zum setzen der Portbits für die Anzeige Binärdarstellung
benutzt, dann geht das in Ordnung (auch wenn es da eine bessere
Schreibweise gibt): Dort ist jedes einzelne Bit wichtig, weil jedes Bit
für eine LED steht. Und in einer Binärdarstellung sieht man wiederrum
besser welches Bit gesetzt wird und welches nicht - vulgo: welche LED
eingeschaltet wird und welche nicht. Die Wahl der Darstellung einer
Zahl, dezimal hex oder binär, passt man dem Verwendungszweck an und
welcher Aspekt davon wichtig ist.
besser so:
1
unsignedintwert;// wert kann per Definition nicht negativ sein
2
wert=ADCW;// Konvertierte Zahl wird in
3
4
if(wert<=256)// 0V - 1,25V
5
PORTB=0b00000000;
6
7
elseif(wert<=512)// 1,25V - 2,5V
8
PORTB=0b00000001;
9
10
elseif(wert<=768)// 2,5V - 3,75V
11
PORTB=0b00000011;
12
13
else
14
PORTB=0b00000111;
PS: Warum verwendest du für deine ersten Versuche nicht die
funktionierende ADC Routine aus dem Tutorial?
Hab vielen Dank, jetzt funktioniert es, super ;). Mir war nich bewusst,
dass mein Vergleich mit dem Wert so nicht geht. Ich dachte, dass meine
Syntax funktioniert.
Hab auch vielen Dank für deine konstruktive Kritik, ich wusste auch
nicht, dass ich ADCSRA auf deinem Weg initialisieren kann. So erscheint
es natürlich logischer und nachvollziehbarer.
Ich werde bei meinem nächsten Problem versuchen, es verständlicher zu
machen. Ich dachte eben, dass ich solche Kniffe von Profis hier lerne
und nicht schon wissen muss und nicht als Neuling (auch im Forum) gleich
angeraunt werde.
Vielen Grüße