PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ADC-Ergebnis in Variable weiter benutzen



Cvecko
28.09.2005, 22:19
Hallo alle zusammen!
Ich bin dabei, etwas mit dem Atmega8 zu experimentieren, die grundlegendsten Schrittte hab ich hinter mir.
Aktuell programmiere ich etwas mit einer Software-PWM (Hardware-PWM lasse ich also erst mal außen vor). Als Programmierbeispiel
fahre ich einfach ein paar LEDs in der Helligkeit hoch und runter. Die Geschwindigkeit dieses Hoch- und Runterfahrens
würde ich nun gerne über ein Poti steuern, also über den ADC. Funktion und Ansprechen des ADCs ist auch kein Problem, ABER:
ich habe Schwierigkeiten, den Wert aus der ADC weiter zu verwenden.
Das Programm "stürzt" meistens einfach ab, sobald der über den ADC ermittelte Wert zum Einsatz kommen soll. Nur ab und zu wird der ADC-Wert (nach einem Reset) richtig interpretiert.
Hier dazu mal die Dimmfunktion, in der die neue Geschwindigkeit aus der AD-Wandlung übernommen werden soll:


void hochdimmen (int ausgabe_pin)
{
while (t_aus>0)
{
while (v>0)
{
pwm_hoch(ausgabe_pin); //verschachtelte Schleife, in der die PWM-Funtion ausgeführt wird
v=v-4;
}
t_aus--;
t_ein++;
v=v_set; // <------ hierum gehts: in v_set steht das ADC-Ergebnis drin, mit dem jetzt eine neue Geschwindigkeit erreicht werden soll.
}
t_aus=t_aus_set;
t_ein=t_ein_set;
}


Wenn ich eine "Überprüfung" des Wertebereiches (z.B. grob zwischen 100 und 1000) der ADC-Wandlung mache, scheint acuh der richtige Zahlenbereich herauszukommen (LED zeigts an):

if (ad_result>100 && ad_result<1000)
outp(0x01, PORTB);

Hab schon allerhand ausprobiert, aber es klappt einfach nicht, das ADC-Ergebnis weiter zu verwenden....
Könnte es evtl. an einem speziellen Format des ADC-Ergebnisses im ADC-Ergebnisregister liegen?
Ich wäre für einen Lösungsansatz sehr dankbar, hab mir echt schon Stunden damit vertrieben....

Danke schon mal, Stefan!

SprinterSB
29.09.2005, 10:35
Was heisst 'abstürzen'?
Wie sind die Variablen deklariert/definiert?
Wie bekommst du den ADC-Wert?

Cvecko
29.09.2005, 14:20
Abstürzen heißt, dass das Hoch- und Runterdimmen der LEDs solange funktioniert, bis ein Wert aus der AD-Wandlung in die Geschwindigkeitsvariable "v_set" kommt. Dann bleibt die LED einfach auf der aktuellen Helligkeit stehen und nix passiert mehr. Dann hilft nur noch ein Reset.

Die Variablen sind als unsigned int deklariert.

Den ADC lasse ich frei laufen und hole mir den ADC-Wert mittels
ad_result = ADCL;
aus dem Ergebnisregister. (Ich weiß, dass das ADCL-Reg nur die unteren 8 bit enthält; hab auch schon versucht, mit diesem kleineren Wertebereich bis 255 (statt bis 1023) zurecht zu kommen, gibt aber das gleiche Problem.)

Danke schon mal für dein Interesse!

m.a.r.v.i.n
29.09.2005, 15:15
Hallo Cvecko,

die Variable v sollte als 'signed int' deklariert werden.
Weil der Vergleich

while (v>0)
mit 'unsigned int' Variablen hier zu einer Endlosschleife führt, wenn v nicht durch 4 teilbar ist, wegen

v=v-4
am Ende der Schleife

Gruß Peter

Cvecko
29.09.2005, 18:53
Moin Peter!
JAU! Das war das Problem, es funktioniert jetzt so wie es soll!!
Is mir ja fast peinlich, dass die Lösung so relativ "einfach" war und ich da so lange dran rumgehühnert hab...
Naja, ganz großen Dank auf jeden Fall!!! =D>
MfG, Cvecko!

Cvecko
29.09.2005, 22:00
Da ist mir noch eine kleine Frage eingefallen: Wie "verschwenderisch" kann ich generell mit der Zuweisung von Variablentypen umgehen (char/int etc)? Also welcher Typ schmeckt dem Atmega am besten?
MfG, Cvecko!

SprinterSB
30.09.2005, 11:26
Als 8-Bit-µC munden den AVRs am besten 8b, am besten char oder besser unsigned char (bzw utint8_t aus <inttypes.h>), weil sich da nich um das Vorzeichen gekümmert werden muss.
8b sind natürlich recht wenig, und nicht immer ausreichend.
Falls es weniger als 8b sein sollen lohnt sich das packen in Bitfelder nur dann, wenn es viele Daten sind und immer der gleiche Code verwendet wird (zB Array of bitfields oder so).

Die grösseren AVRs können auch mit 16b umgehen.
Bei Zugriff auf Arrays wird der Offset nach 16b umgerechnet, ebenso werden Argumente/Rückgabewert von Funktionen von 8b auf 16b erweitert (promotet). Pointer sind auch 16b breit.

Falls du Klarheit darüber haben willst, wie viel Code erzeugt wird, sind avr-size und avr-nm dein Freund:
avr-size --help
avr -nm --help

avr-size -x foo1.o foo2.o ...
avr-size -x -A foo.elf
avr-nm -A -S --size-sort foo.elf foo1.o foo2.o ...

Oder als phony target im Makefile:
size: $(PRG).elf $(OBJ)
avr-size -x $(OBJ)
avr-size -x -A $(PRG).elf

Um den Code selbst zu optimieren hilft oft nur ein Blick in den generierten asm-Code, den man beim compilieren oder beim assemblieren mit ausgeben kann. Danach kann man dann gcc Hilfestellung leisten. So ist es günstig, nichtlokale Variablen temporär in lokalen Variablen abzulegen.