Hallo Jungs ertsmal möchte ich euch alle schöne Weinachtstage wünschen. zu meinem Problem, Ich habe ein STK500 mit einem Atmega88, nun möchte ich mich mit den Analogen digitalen Wandler vertraut machen.Dazu habe ich am Eingang am Pin C0/ADC0 eine 0,4 V soannung angeschlossen, nun möchte ich gerne testen ob diese Spannung gewandlet wurde dazu habe ich das folgende Code geschrieben. Ich möchte einfach, dass die LEDS 0 bis 5 eingeschaltet werden falls die Spannung kleiner 1 V ist.Bei meinem Test bleiben die LEDs leider immer an erst wenn ich die Bedinung von 1 auf 1000 dann gehen Sie ert aus. vielleicht kann mir jemand sagen was ich hier falsch mache , oder ein typ geben wie ich das am besten testen kann besten Dank im voraus #include <avr/io.h> /* ADC initialisieren */ void ADC_Init(void) { uint16_t result; ADMUX = (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen // 1,1 V ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler ADCSRA |= (1<<ADEN); // ADC aktivieren /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */ ADCSRA |= (1<<ADSC); // eine ADC-Wandlung while (ADCSRA & (1<<ADSC) ); // auf Abschluss der Konvertierung warten /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen. */ result = ADCW; } /* ADC Einzelmessung */ uint16_t ADC_Read( uint8_t channel ) { // Kanal waehlen, ohne andere Bits zu beeinflußen ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F); ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" while (ADCSRA & (1<<ADSC) ) // auf Abschluss der Konvertierung warten ; return ADCW; // ADC auslesen und zurückgeben } /* Beispielaufrufe: */ int main (void) { uint16_t adcval; uint16_t voltage; ADC_Init(); while(1) { adcval = ADC_Read(0); // Kanal 0 //Hier möchte ich den umwandlenden Wert in Spannung Umrechnen voltage = adcval*4.883; if (voltage <1 ) { DDRB |= 0xFF; PORTB |= (1<<PORTB6) | (1<<PORTB7); } } }
1. Wie kommst du auf die magische Zahl (4.883)? Im Tutorial zu ADC steht eine andere Formel mit Referenzspannung und Auflösung des ADC in Bits. 2. Wenn du mit Ganzzahlen statt mit Fliesskomma rechnest, wird dein Programm kürzer. Es bietet sich an, in mV statt in V zu rechnen:
1 | DDRB |= ...; // Ausgänge LED 0-5 |
2 | while(1) |
3 | {
|
4 | uint16_t millivoltage; |
5 | adcval = ADC_Read(0); // Kanal 0, interne Referenzspannung 1,1 V |
6 | millivoltage = (adcval * 1100UL) / 1024UL; |
7 | if ( millivoltage < 1000 ) |
8 | PORTB |= ...; // LED 0-5 Status hüh |
9 | else
|
10 | PORTB &= ~(...); // LED 0-5 Status hott |
11 | }
|
NB: C-Code kann man hier im Forum formatieren. Das erhöht IMHO die Lesbarkeit.
Hab ich es überlesen, oder wurde der PinC0 nicht als Analog-In definiert?
Hi >Hab ich es überlesen, oder wurde der PinC0 nicht als >Analog-In definiert? Wozu? MfG Spess
Hi Danke erstmal für die schnelle Antwort, ich habe es hingekriegt, jetzt funktioniert, es war ein variablen Fehler Der Variable voltage war als unit16_t deklariert, jetzt habe ich als double deklariert und siehe passt. aber es hat sich einnen andern Problem herrausentwickelt. wenn ich den STK500 einschalte un die analoge gemessene Spannung ist unter der "if" wert,dann bleiben alle LEDs aus, soweit sogut, erhöhe ich dis Spannung über den Schwellwert dann gehen die LED 0 bis 5 an, nun sinke ich die Spannung wider unter den Schwellwert bleiben Sie trotzdem an!!! wo liegt den das Problem, ich hoffe ich langweile euch nicht mit meinen Anfängerfragen int main (void) { uint16_t adcval; double voltage; double led; // Variable zum vormerken des Zustand der LED ADC_Init(); led=0; while(1) { adcval = ADC_Read(0); // Kanal 0 //Hier möchte ich den umwandlenden Wert in Spannung Umrechnen voltage = adcval* 1.1 / 1024.0; if (voltage >0.29 ) { DDRB |= 0xFF; PORTB |= (1<<PORTB6) | (1<<PORTB7); led=1; } else { if (led==1 ) PORTB &= ~( (1<<PB6) | (1<<PB7) ); led=0; } } }
1 | #define LEDS_0_5 ((1<<PB5)|(1<<PB4)|(1<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0))
|
2 | DDRB |= LEDS_0_5; |
3 | |
4 | ...
|
5 | |
6 | if ( voltage > 0.29 ) |
7 | {
|
8 | PORTB &= ~LEDS_0_5; // active low: LEDs AN |
9 | led = 1; |
10 | }
|
11 | else
|
12 | {
|
13 | if ( led == 1 ) |
14 | PORTB |= LEDS_0_5; // active low: LEDs AUS |
15 | led = 0; |
16 | }
|
Hi Stefan Habe mein Code umgeschrieben, nach deinem Vorschlag, leider sind die LEDs jetzt immer an. Die gehen gar nicht aus. ich komm leider nicht weiter, ich schmeiss mich gleich vom fahrenden Zug:-) int main (void) { while(1) { #define LEDS_0_5 ((1<<PB5)|(1<<PB4)|(1<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0)) uint16_t adcval; double voltage; double led; ADC_Init(); led=0; DDRB |= LEDS_0_5; adcval = ADC_Read(0); // Kanal 0 //Hier möchte ich den umwandlenden Wert in Spannung Umrechnen voltage = adcval* 1.1 / 1024.0; if ( voltage > 0.29 ) { PORTB &= ~LEDS_0_5; // active low: LEDs AN led = 1; } else { if ( led == 1 ) PORTB |= LEDS_0_5; // active low: LEDs AUS led = 0; } } }
Du musst halt besser aufpassen, wo du Definitionen und Initialisierungen machst. Der AVR ist stur. Der macht was du programmierst, selbst wenn das Quatsch ist.
1 | #define LEDS_0_5 ((1<<PB5)|(1<<PB4)|(1<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0))
|
2 | |
3 | int main (void) |
4 | {
|
5 | uint8_t led = 0; |
6 | |
7 | DDRB |= LEDS_0_5; |
8 | |
9 | while(1) |
10 | {
|
11 | uint16_t adcval; |
12 | double voltage; |
13 | |
14 | ADC_Init(); |
15 | adcval = ADC_Read(0); // Kanal 0 |
16 | |
17 | voltage = adcval * 1.1 / 1024.0; |
18 | |
19 | if ( voltage > 0.29 ) |
20 | {
|
21 | PORTB &= ~LEDS_0_5; // active low: LEDs AN |
22 | led = 1; |
23 | }
|
24 | else
|
25 | {
|
26 | if ( led == 1 ) |
27 | PORTB |= LEDS_0_5; // active low: LEDs AUS |
28 | led = 0; |
29 | }
|
30 | }
|
31 | }
|
Hi >Habe mein Code umgeschrieben, nach deinem Vorschlag, leider sind die >LEDs jetzt immer an. Die gehen gar nicht aus. Du setzt mit 'led=0;' in der Mainloop dein Flag nach jeder Messung auf Null. Nimm den Code um ADC-Init aus der Schleife heraus. Das macht man nur ein mal. MfG Spess
Hi Stefan bestrn Dank Stefan es hat funktioniert, nun bin ich ein stückschen weiter mit meinem Grundlagen. Meine Letzte Frage, zumindst für Heute:-) wenn das eingestellte anlog-wert unter dem Schwellwert ist dann sind die LEDs aus, so soll es auch sein,nun schalte ich das STK aus und wider ein ohne die analogequelle abzuschalten ,gehen die LEds an obwohl der Wert unter den Schwellwert liegt. hast du vielleicht Ahnung was das sein kann!!!! Danke nochmal für euer Mühe
Die LED auf dem STK500 sind active low geschaltet, d.h. wenn der PORT-Pin LOW hat, ist die LED an. Der Portpin ist LOW nach der Einstellung der Datenrichtung auf Ausgang in dieser Zeile: DDRB |= LEDS_0_5; Wenn du vor dem Einstellen der Datenrichtung die Portpins HIGH setzt, sind die LEDs zu Anfang aus: Statt DDRB |= LEDS_0_5; dann PORTB |= LEDS_0_5; // Pullups ein DDRB |= LEDS_0_5; // Datenrichtung Ausgang => active low LEDs AUS
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.