Hallo,
Ich habe ein kleines Problem mit meinem ADC und hoffe ihr könnt mir
weiterhelfen.
Ich besitze ein STK 500 Board und möchte per AD-Wandler mit dem ATMEGA8
über den PC0 Eingang einen Analogwert messen und auf Port D für jeder
Wert ein Led einschalt.
Dafür habe ich etwa so den Schleifer auf dem PC0 Eingang verbindet (Wie
im AVR GCC tutorial erklärt):
VCC-----+
|
|
Sensor
|
+--------PC0
|
---
| |
| |
---
|
+----------GND
Der code:
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <stdlib.h>
void init(void)
{
DDRB = 0xff;
DDRC = 0xff;
DDRD = 0xff;
ADCSRA = (1<<ADEN);
}
uint16_t readADC(uint8_t Mux_channel)
{
uint8_t i;
uint16_t result = 0;
ADMUX = Mux_channel; // Kanal des Multiplexers waehlen
ADMUX = (1<<REFS0) | (1<<REFS1); //int. REF Versorgungsspannung
auswählen
ADMUX &= ~(1<<ADLAR); //ergebnis rechtsbündig ausrichten
//ADCSRA = (1<<ADEN); // Den ADC aktivieren
ADCSRA = (1<<ADPS0) | (1<<ADPS2); // Teilungsfaktor zwischen der
Taktfrequenz und dem Eingangstakt des ADC auf 32 setzen Tmin = 20 , Tmax
= 80
ADCSRA |= (1<<ADSC); // Den ADC initialisieren und einen sog.
Dummyreadout machen
_delay_us(40);
while(ADCSRA & (1<<ADSC));
result = ADCW; // ADCW muss einmal gelesen werden,
result = 0; // sonst wird Ergebnis der nächsten Wandlung
// nicht übernommen.
// Jetzt 4x die analoge Spannung and Kanal channel auslesen
// und dann Durchschnittswert ausrechnen.
for(i=0; i<4; i++)
{
ADCSRA |= (1<<ADSC); // Eine Single conversionWandlung
while(ADCSRA & (1<<ADSC)); // Auf Abschluss der Konventierung
abwarten
result += ADCW;
}
//ADCSRA = (0<<ADEN); // ADC wieder deaktivieren
result /= 4;
return result;
}
int main(void)
{
init();
while(1)
{
uint16_t result = readADC(0); //Auslesen der analogen Spannungen an
Pin 0,
// also ADC0. In result steht das Ergebnis.
while(1)
{
PORTB = (result / 50) + 1;
}
}
}
Die Referenzspannung des Stk 500 Boards habe ich auf 11V gesetzt und den
Jumper auf AREF(Board) gejumpert. Mit dem Multimeter kann ich am Eingang
dann auch die Spannung wie gewünscht messen, nur mit meinem Programm
gibt
leuchtet sofort nur die led 1 bis 5 und es ist alles. Ich habe schon
alles ausprobiert aber finde den Fehler einfach nicht!
Zur Kontrolle habe ich mir mittlerweile auch schon die Zustände der
Register ADC anzeigen lassen, scheint dass es kein wert im ADC ist.
Die Frequenz des Board ist auf 3,686 MHZ gesetzt!
Ich danke Ihnen im Voraus.
Bitte nutze die Code-Formatierung des Forums!
Und das hier
> ADMUX = Mux_channel; // Kanal des Multiplexers waehlen
> ADMUX = (1<<REFS0) | (1<<REFS1); //int. REF Versorgungsspannung
ist schon mal Blödsinn. Überlege, was die Anweisung in der zweiten Zeile
mit dem macht, was Du in der ersten Zeile in ADMUX geschrieben hast.
> Die Referenzspannung des Stk 500 Boards habe ich auf 11V gesetzt
Eine Referenzspannung von 11 V gibt es nicht, der AVR kann maximal
(A)VCC, und wie hoch das sein darf, steht im Datenblatt. Jedenfalls
nicht 11 V.
zweimal while(1) macht wenig sinn..
> Die Referenzspannung des Stk 500 Boards habe ich auf 11V gesetzt
> und den Jumper auf AREF(Board) gejumpert.
Autsch!
Dir ist anscheinend nicht klar, dass es eine Obergrenze für die
Referenzspannung gibt. Wenn du extern eine Referenzspannung anlegst,
dann darf die nicht.
Wenn du extern eine Referenzspannung anlegst, warum aktivierst du dann
per MUX Register die interne Referenzspannung? Jetzt arbeiten 2
Referenzspannungen gegeneinander
Karl heinz Buchegger wrote:
>> Die Referenzspannung des Stk 500 Boards habe ich auf 11V gesetzt
>> und den Jumper auf AREF(Board) gejumpert.
>
> Autsch!
>
> Dir ist anscheinend nicht klar, dass es eine Obergrenze für die
> Referenzspannung gibt. Wenn du extern eine Referenzspannung anlegst,
> dann darf die nicht.
Ich vermute mal, dass das nur ein Tippfehler ist und 1,1 V heißen
soll... Aber das wollte ich gern vom OP selber hören (bzw. lesen).
Und das hier
> ADMUX = Mux_channel; // Kanal des Multiplexers waehlen
> ADMUX = (1<<REFS0) | (1<<REFS1); //int. REF Versorgungsspannung
ist schon mal Blödsinn. Überlege, was die Anweisung in der zweiten Zeile
mit dem macht, was Du in der ersten Zeile in ADMUX geschrieben hast.
> Die Referenzspannung des Stk 500 Boards habe ich auf 11V gesetzt
Eine Referenzspannung von 11 V gibt es nicht, der AVR kann maximal
(A)VCC, und wie hoch das sein darf, steht im Datenblatt. Jedenfalls
nicht 11 V.
ADMUX = Mux_channel;
mit dem Zeile wird mein messende Kanal bestimmt, hier hole ich die
entsprechende pinnummer
ADMUX = (1<<REFS0) | (1<<REFS1);
hier wähle ich die spannung reference für die ADC.
Ok 11 v war nicht gedacht sondern 5,5 v meinte ich.
Und wenn ich euch richtig verstehe sogar diese 5;5 v brauchte ich nicht
mehr weil ich interne spannung benutze!
Aber trotz dies geht immer nicht.
zweimal while(1) macht wenig sinn..
wie meinst du!?!?
Penie Lydos wrote:
> ADMUX = (1<<REFS0) | (1<<REFS1);
> hier wähle ich die spannung reference für die ADC.
...und löscht gleichzeitig die Kanalauswahl wieder!
>> zweimal while(1) macht wenig sinn..
> wie meinst du!?!?
Zeichne Dir bitte ein Ablaufdiagramm Deines Programms auf! Wenn Du so
etwas nicht selber siehst, musst Du Dir erstmal über die
Programmstruktur klar werden!
Ich habe fast den Eindruck, dass Du nicht weißt, dass eine
"while(1)"-Schleife (zumindest ohne break) niemals wieder verlassen
wird...
oh ye!!!
so dumm von mir.
jetzt sehe ich:
ADMUX |= (1<<REFS1) | (1<<REFS0);
und auch
>> zweimal while(1) macht wenig sinn..
ja fehler beseitig.
leider funktionniert immer nicht.
wenn ich debugge bleibt der cursor auf
<c>
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <stdlib.h>
void init(void)
{
DDRB = 0xff;
DDRC = 0xff;
DDRD = 0xff;
ADCSRA = (1<<ADEN);
}
uint16_t readADC(uint8_t Mux_channel)
{
uint8_t i;
uint16_t result = 0;
ADMUX = Mux_channel; // Kanal des Multiplexers waehlen
ADMUX |= (1<<REFS0) | (1<<REFS1); //int. REF
Versorgungsspannung auswählen
ADMUX &= ~(1<<ADLAR); //ergebnis rechtsbündig ausrichten
ADCSRA = (1<<ADEN); // Den ADC aktivieren
ADCSRA |= (1<<ADPS1) | (1<<ADPS0); // Teilungsfaktor zwischen
der Taktfrequenz und dem Eingangstakt des ADC auf 32 setzen Tmin = 20 ,
Tmax = 80
ADCSRA |= (1<<ADSC); // Den ADC initialisieren und einen
sog. Dummyreadout machen
_delay_us(40);
while(ADCSRA & (1<<ADSC))
{;}
result = ADCW; // ADCW muss einmal gelesen werden,
result = 0; // sonst wird Ergebnis der
nächsten Wandlung
// nicht übernommen.
// Jetzt 4x die analoge Spannung and Kanal channel auslesen
// und dann Durchschnittswert ausrechnen.
for(i=0; i<4; i++)
{
ADCSRA |= (1<<ADSC); // Eine Single conversionWandlung
while(ADCSRA & (1<<ADSC)); // Auf Abschluss der
Konventierung abwarten
result += ADCW;
}
ADCSRA = (0<<ADEN); // ADC wieder deaktivieren
result /= 4;
return result;
}
int main(void)
{
init();
while(1)
{
uint16_t result = readADC(0); //Auslesen der analogen Spannungen an
Pin 0,
// also ADC0. In result steht das Ergebnis.
PORTB = (result / 50) + 1;
}
}
</c>
leider bekomme ich immer gar nichst mit dem code!!!!
bitte wie kann ich dann mein code formatieren?
Penie Lydos wrote:
> bitte wie kann ich dann mein code formatieren?
Indem Du zunächst mal das liest, was über dem Editierfenster unter den
"Wichtigen Regeln" steht! Das ist doch nicht zu übersehen!
> ADCSRA = (0<<ADEN); // ADC wieder deaktivieren
Das schaltet den ADC zwar aus, macht aber auch sonst noch so einiges
(zumindest nicht das was du willst)
Warum benutzt du nicht einfach mal die readADC aus dem Tutorial so wie
sie ist? Dann funktioniert sie nämlich. Und erst dann fängst du an sie
zu verändern, wobei du nach jeder Änderung überprüfst, obs noch geht
oder nicht.
1 | #include <avr/io.h>
| 2 | #include <inttypes.h>
| 3 | #include <util/delay.h>
| 4 | #include <stdlib.h>
| 5 |
| 6 |
| 7 |
| 8 | void init(void)
| 9 | {
| 10 | DDRB = 0xff;
| 11 | DDRC = 0xff;
| 12 | DDRD = 0xff;
| 13 | }
| 14 |
| 15 |
| 16 | uint16_t readADC(uint8_t Mux_channel)
| 17 | {
| 18 | uint8_t i;
| 19 | uint16_t result = 0;
| 20 |
| 21 |
| 22 |
| 23 | ADMUX = Mux_channel; // Kanal des Multiplexers waehlen
| 24 | ADMUX |= (1<<REFS0) | (1<<REFS1); //int. REF Versorgungsspannung auswählen
| 25 | //ADMUX |= ~(1<<ADLAR); //ergebnis rechtsbündig ausrichten
| 26 |
| 27 |
| 28 | ADCSRA = (1<<ADEN); // Den ADC aktivieren
| 29 | ADCSRA |= (1<<ADPS1) | (1<<ADPS0); // Teilungsfaktor zwischen der Taktfrequenz und dem Eingangstakt des ADC auf 8 setzen Tmin = 20 , Tmax = 80
| 30 | ADCSRA |= (1<<ADSC); // Den ADC initialisieren und einen sog. Dummyreadout machen
| 31 |
| 32 | // _delay_us(40);
| 33 |
| 34 |
| 35 | while(ADCSRA & (1<<ADSC));
| 36 |
| 37 | result = ADCW; // ADCW muss einmal gelesen werden,
| 38 | result = 0; // sonst wird Ergebnis der nächsten Wandlung
| 39 | // nicht übernommen.
| 40 |
| 41 |
| 42 |
| 43 | // Jetzt 4x die analoge Spannung and Kanal channel auslesen
| 44 | // und dann Durchschnittswert ausrechnen.
| 45 | for(i=0; i<4; i++)
| 46 | {
| 47 | ADCSRA |= (1<<ADSC); // Eine Single conversionWandlung
| 48 |
| 49 | while(ADCSRA & (1<<ADSC)); // Auf Abschluss der Konventierung abwarten
| 50 |
| 51 | result += ADCW;
| 52 | }
| 53 |
| 54 | ADCSRA &= ~(1<<ADEN); // ADC wieder deaktivieren
| 55 |
| 56 | result /= 4;
| 57 |
| 58 | return result;
| 59 | }
| 60 |
| 61 | int main(void)
| 62 | {
| 63 |
| 64 | init();
| 65 |
| 66 | while(1)
| 67 | {
| 68 | uint16_t result = readADC(0); //Auslesen der analogen Spannungen an Pin 0,
| 69 | // also ADC0. In result steht das Ergebnis.
| 70 | PORTB = (result / 50) + 1;
| 71 | }
| 72 |
| 73 | }
|
Jetzt habe ich mir dieser code vom AVR GCC tutorial eins zu eins
kopiert. Leider ist immer mein ADC value beim debuggen 0x0000
mit was debuggst du denn? Also welche Hardware/Software?
Penie Lydos wrote:
> mit avr studio 4
Und woher soll das AVRStudio Informationen über Deine Hardware haben?
Das AVRStudio kann keine analoge Peripherie simulieren! Du kannst bei
der Simulation höchstens von Hand Werte in ADCH/ADCL schreiben, die dann
verarbeitet werden.
Dass da in der Simulation immer 0 rauskommt, ist völlig normal.
zuerst vielen dank für alle die Tipp
ok,
habe ich es getan, per hand die werte einzugeben.
für ADCL (50)--> 23 ----> portB 0x01
ADCL (100)--> 46 ----> portB 0x02
ADCL (150)--> 96 ----> portB 0x03
ADCL (200)--> 8C ----> portB 0x03
ADCL (255)--> FF ----> portB 0x06
weiss jemand warum es keine unterschied am portb Ausgang für die beiden
werte gibt?
DCL (150)--> 96 ----> portB 0x03
ADCL (200)--> 8C ----> portB 0x03
Und es ist immer mir noch nicht klar warum es auf den Hardware AVR mit
prozessor atmega nicht lauft.
> ok,
> habe ich es getan, per hand die werte einzugeben.
>
> für ADCL (50)--> 23 ----> portB 0x01
> ADCL (100)--> 46 ----> portB 0x02
> ADCL (150)--> 96 ----> portB 0x03
> ADCL (200)--> 8C ----> portB 0x03
> ADCL (255)--> FF ----> portB 0x06
Das passt aber immer noch nicht mit deiner Formel zusammen
PORTB = (result / 50) + 1;
50 / 50 macht 1, dann noch 1 dazu macht 2
100 / 50 macht 2, dann noch 1 dazu macht 3
Hast du dir schon mal direkt die Werte für result angesehen?
> Und es ist immer mir noch nicht klar warum es auf den Hardware AVR mit
> prozessor atmega nicht lauft.
Könnte auch ein Hardware-Problem sein.
Speist du deine Spannung am richtigen Pin ein?
Wie ist der ARef Aufgang beschaltet?
> und auf Port D für jeder Wert ein Led einschalt.
vielleicht nur ein Tippfehler, aber: du gibst am Port B aus
1 | Wie ist der ARef Aufgang beschaltet?
|
AREF-Jumper ist gesetzt
1 | Speist du deine Spannung am richtigen Pin ein?
|
und mein mein Analog spanung lese ich am pin pc0
1 | vielleicht nur ein Tippfehler, aber: du gibst am Port B aus
|
ja tippfehler, ich meine portB
Penie Lydos wrote:
> 1 | Wie ist der ARef Aufgang beschaltet?
|
>
> AREF-Jumper ist gesetzt
Verzeih meine Unwissenheit: Das bedeutet jetzt was?
> 1 | Speist du deine Spannung am richtigen Pin ein?
|
>
> und mein mein Analog spanung lese ich am pin pc0
Von PC0 liest dein Program. Aber hängt deine zu messende Spannung auch
am physischen Pin PC0? (Ist mir auch schon passiert, dass ich mich bei
den Pins verzählt habe)
>Von PC0 liest dein Program. Aber hängt deine zu messende Spannung auch
>am physischen Pin PC0? (Ist mir auch schon passiert, dass ich mich bei
>den Pins verzählt habe)
ja meine zu messende spannung ist am PC0 angeschlossen.
>AREF-Jumper ist gesetzt
>Verzeih meine Unwissenheit: Das bedeutet jetzt was?
ich habe so gelassen wie gekauft (fängt gerade mit AVR). Weil ich im
Dadenblatt dass gelesen habe:
1 | Die analoge Spannung AREF liefert die Referenzspannung für den on-chip A/D-Konverter des AVR. Wenn der AREF-Jumper gesetzt ist, ist die On-Board analog Referenzspannung mit dem AREF-Pin des AVR ver-bunden. Die On-Board Referenzspannung kann über AVR Studio von 0V bis 6V eingestellt werden, jedoch nicht über VTARGET.
| 2 | Wenn der AREF-Jumper nicht gesetzt ist, muß dem AVR die Referenz-spannung von einer externen Spannungsquelle über die PORTE/AUX-Leiste zugeführt werden (siehe Abbildung 3.6). Abbildung 3.25 zeigt die AREF-Jumper Einstellungsmöglichkeiten.
|
danke
Wenn ich das jetzt richtig verstehe, dann hast du gleichzeitig
* von extern eine Referenzspannung zugeführt
(weil der Jumper gesteckt ist).
* per Programm die interne Referenzspannung ausgewählt.
-> also bekriegen sich 2 Referenzspannungserzeuger.
(Nur so aus Neugier: Auf welche Referenzspannung hast du den das STK500
mithilfe des AVR-Studio programmiert?)
Zieh mal den Jumper ab.
Ich denke mal, dass hier 1 | Wenn der AREF-Jumper nicht gesetzt ist, muß dem AVR die
| 2 | Referenz-spannung von einer externen Spannungsquelle über die
| 3 | PORTE/AUX-Leiste zugeführt werden (siehe Abbildung 3.6). Abbildung 3.25
| 4 | zeigt die AREF-Jumper Einstellungsmöglichkeiten.
|
ist etwas unglücklich formuliert.
Dein Mega8 hat grundsätzlich 2 Möglichkeiten für die Referenzspannung.
Die interne: hier erzeugt sich der Chip selber die Referenzspannung. Das
hat aber nichts mit besagtem Jumper zu tun. ARef ist ein Ausgang, an dem
die benutzte Referenzspannung herausgeführt wird (zb um sie zu
stabilisieren)
Die externe: hier benutzt der Chip die Referenzspannung, die ihm am ARef
Pin angeboten wird. Dafür muss dann der Jumper gesetzt sein, da dein
STK500 diese Referenzspannung erzeugen muss oder aber die
Referenzspannung wird über PORTE/AUX eingespeist. Auf jeden Fall aber
muss das Programm in so einem Fall den Mega8 auf externe
Referenzspannung umschalten.
Wenn auf dem STK500 der AREF-Jumper nicht gesetzt ist, muss also
entweder dem AVR die Referenzspannung von einer externen Spannungsquelle
zugeführt werden, oder aber der Chip erzeugt sich die Referenzspannung
chipintern selber. Dein Programm stellt letztere Variante ein (interne
Generierung der Referenzspannung), also darfst du auf keinen Fall an
ARef eine von aussen zugeführte Spannung anschliessen -> Jumper bleibt
offen
>(Nur so aus Neugier: Auf welche Referenzspannung hast du den das STK500
>mithilfe des AVR-Studio programmiert?)
2,56 volt.
Wenn ich richtig verstehe muss ich mein AREF-Jumper nicht setzen.
ok und danke für alle die Erklärungen,
leider funktioniert troztdem noch nicht
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|