Forum: Mikrocontroller und Digitale Elektronik ATmega ADC, 2 Kanäle wandeln


von Florian (Gast)


Lesenswert?

Hallo zusammen,
ich möchte einen analogen Joystick mit 2 Achsen auswerten. Dazu benutze 
ich
bei meinem ATmega8 den AD Wandler.
Da ich eine konstante Durchlaufzeit des Programms will (für spätere 
Regelung), nutze ich keine Interrupts. Ich will also meine analogen 
Werte nur "updaten", wenn der AD Wandler fertig ist mit seiner Wandlung, 
ansonsten möchte ich die alten Werte benutzen:
1
void GetJoystick(uint8_t* JoyStick)
2
{
3
4
5
6
7
  old_Kanal = Kanal;
8
  Kanal = (((~(ADCSRA & (1<<ADSC))>>ADSC) & ~Kanal)) & 1; // Kanal ändern, wenn 
9
                              // Wandlung abgeschlossen
10
11
12
  
13
  if (Kanal != old_Kanal)  // Wenn Wandlung abgeschlossen
14
  {
15
      JoyStick[old_Kanal] = ADCH;      
16
      ADMUX = (ADMUX & ~(0x1F)) | (Kanal & 0x1f);  
17
      ADCSRA |= (1<<ADSC);  
18
  }
19
20
}
Im Hauptprogramm nutze ich dann die beiden Felder von JoyStick, daher 
als Pointer übergeben. Kanal ist entweder 0 oder 1.
Bisher ist die Durchlaufszeit von alle Codepfaden noch nicht konstant, 
aber das werde ich versuchen zu realisieren, wenn der Code funktioniert.
Mein Problem nun an dieser Stelle, das Wandeln funktioniert, wenn ich 
ein größeres Delay drin habe (z. B. so etwas wie uart_puts() ) oder 
sonstiges Delay.
Ich habe jetzt zum Testen 2 Potis an den ADCs und 2 LEDS die ich dann 
mit dem gewandelten analogen Signal über PWM dimme.
Wenn das Programm nun mit voller Geschwindigkeit ohne jegliches Delay 
und mit voller Optimierung (Os3) läuft, dann wird nur auf ein Poti 
(ADC1) reagiert, welches dann aber beide LEDs dimmt. Beim Drehen an dem 
2ten Poti passiert nichts mehr.
Was mich verwirrt ist nun diese Geschwindigkeitsabhängigkeit.
Hat vielleicht jemand einen Tipp, oder gar die Lösung? Irgendwie trete 
ich nämlich gerade ziemlich auf der Stelle.
gruß Florian

von Karl H. (kbuchegg)


Lesenswert?

Florian schrieb:
> Hallo zusammen,
> ich möchte einen analogen Joystick mit 2 Achsen auswerten. Dazu benutze
> ich
> bei meinem ATmega8 den AD Wandler.
> Da ich eine konstante Durchlaufzeit des Programms will (für spätere
> Regelung), nutze ich keine Interrupts.

gerade für den Teil, der eine gleichbleibende Aufrufsequenz benötigt, 
solltest du dann Interrupts nehmen. Einen Timer der regelmässig eine ISR 
aufruft und schon hast du deinen gleichbleibenden Takt, in den du die 
Regelschleife packst. Das bischen Jitter, das du in den ISR Aufrufen 
hast, wird wohl die Regelung nicht ausser Tritt bringen.

> Werte nur "updaten", wenn der AD Wandler fertig ist mit seiner Wandlung,
> ansonsten möchte ich die alten Werte benutzen:

um ehrlich zu sein:
Das hier

>
>   old_Kanal = Kanal;
>   Kanal = (((~(ADCSRA & (1<<ADSC))>>ADSC) & ~Kanal)) & 1; // Kanal
> ändern, wenn
>                               // Wandlung abgeschlossen


hab ich nicht wirklich verstanden. (Habs aber auch nicht großartig 
analysiert)
Kommt mir ehrlich gesagt auch übermässig kompliziert vor:
1
void GetJoystick(uint8_t* JoyStick)
2
{
3
  static uint8_t kanal = 0;
4
5
  if( ADCSRA & ( 1 << ADSC ) )    // Wandlung läuft noch?
6
    return;                       // yep: das wars
7
8
  Joystick[kanal] = ADC;          // Nö Wandlung ist fertig. Ergebnis abholen
9
10
  kanal = 1 - kanal;              // der andere Kanal ist drann
11
 
12
                                  // Neue Wandlung starten. Das Ergebnis
13
                                  // wird im nächsten Aufruf abgeholt, wenn es 
14
                                  // dann schon fertig ist.
15
  ADMUX = (ADMUX & ~(0x1F)) | (kanal & 0x1f);    
16
  ADCSRA |= (1<<ADSC);
17
}

so würde ich das machen.
Und da ich den Teil, der ein exaktes Timing benötigt, in eine ISR 
verbannt habe, macht es mir auch nichts aus, wenn die Durchlaufzeit 
durch die ADC Funktion nicht in allen Fällen gleich ist.

von Florian (Gast)


Lesenswert?

Ich danke dir!
ich schau mir morgen alles mal in Ruhe an.

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.