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_tmillivoltage;
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.
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;
}
}
}
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.
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