Forum: Mikrocontroller und Digitale Elektronik STK 500 Atmega88 ADC WAndler


von Aron (Gast)


Lesenswert?

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);

  }

 }


}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von AVR-Fan (Gast)


Lesenswert?

Hab ich es überlesen, oder wurde der PinC0 nicht als
Analog-In definiert?

von Spess53 (Gast)


Lesenswert?

Hi

>Hab ich es überlesen, oder wurde der PinC0 nicht als
>Analog-In definiert?

Wozu?

MfG Spess

von Aron (Gast)


Lesenswert?

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

 }


}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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
  }

von Aron (Gast)


Lesenswert?

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

}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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
}

von Spess53 (Gast)


Lesenswert?

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

von Aron (Gast)


Lesenswert?

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

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.