Forum: Mikrocontroller und Digitale Elektronik ADC Wandlung 6 Bit verschieben ?


von Philipp L. (viech)


Lesenswert?

Hallo zusammen,

nachdem ihr mir bisher immer so gut helfen konntet, hier mal wieder ein 
Verständnisproblem :-)
Ich benutze einen Atmega8

Der ADC hat 10Bit, das Ergebnis einer Wandlung wird in 2 Byte (16Bit) 
gespeichert.

In meinem Buch steht, dass ich das Ergebnis nach der Wandlung also um 6 
Stellen nach rechts verschieben muss, um einen korrekten Wert zu 
erhalten (klingt logisch).
Ich glaube in meinem Fall stimmt das aber nicht.

#include <avr/io.h>
#include <util/sbit.h>

int Dimmstufe =0;

int main(void)
{
  DDRB |= (1<<PB1);
  DDRD &= ~(1<<PD0);

  ICR1 = 1024;
  OCR1A = 0;
  TCCR1A = (1<<WGM11)+(1<<COM1A1);
  TCCR1B = (1<<WGM12)+(1<<WGM13)+(1<<CS10);

  ADMUX |=  (1<<REFS0);
  ADCSRA |= (1<<ADEN)+(1<<ADPS0)+(1<<ADPS1)+(1<<ADPS2);

  while (1)
    {
  ADCSRA |= (1<<ADSC);

  while(ADCSRA &(1<<ADSC));
  {
  Dimmstufe = ADC;
  //Dimmstufe = Dimmstufe >> 6;
  OCR1A = Dimmstufe;
  }

  }
}


Zum Test wird eine PWM mit TOP(ICR1)=1024 verwendet.
Da der ADC mit 10bit (ebenfalls 1024) wandelt, ergibt sich dadurch eine 
Dimmung zwischen 0-100%.

Der Ausgang wird aber nur zwischen 0-100% (1024) gedimmt, wenn ich die 
Zeile mit dem Rechtsverschub nicht einbinde.
Wobei ich auch nicht ganz auf 0 herunterkomme, etwas leuchtet die Lamape 
auch bei 0V auf dem ADC-Eingang..

von Sebastian H. (technik_freak)


Lesenswert?

Hallo Philipp L.,

das verschieben um 6 Bits scheint nur notwendig zu sein, wenn das Bit 
ADLAR gesetzt ist (vgl. [1], Seite 201). Da diese Bit mit 0 
initialisiert wird, wird das Verschieben nicht benötigt.

[1]: 
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2486-8-bit-AVR-microcontroller-ATmega8_L_datasheet.pdf

von Philipp L. (viech)


Lesenswert?

Ja, das ADLAR hatte ich auch schon gelesen.
Wenn ich ADLAR aber einschalte und am Ende alles um 6 Bit verschiebe, 
bekomme ich nicht die gleiche Charakteristik wie ohne ADLAR und ohne 
verschieben.
Mit ADLAR gibt ab einer Dimmstufe (evtl. so 50%??) einen Sprung in der 
Kennlinie zu 100%.
Die untere Häfte sieht damit auch "komisch" aus.

Sorry, kann den Verlauf schlecht erklären.

von P. W. (deneriel)


Lesenswert?

Das ADLAR Register (AD Left Adjust) steuert wie dein ADC-Messwert (10bit 
breit) im Ergebnisregister (16bit breit) abgelegt wird.

ADLAR = 0
xxxx xx11 1111 1111

ADLAR = 1
1111 1111 11xx xxxx

Das entspricht einem Shift von 6 bit.
Du hast ADLAR nicht gesetzt und Timer 1 nutzt ebenfalls ein 16bit 
Register, also schreibst du Werte bis maximal 1024. Alles Shiny.
bei gesetztem Bit müsstest du hingegen 6 Bits nach rechts shiften.

Praktisch ist das Register, wenn du nach der Messung eh nur 8 bit weiter 
verarbeitest, denn dann kannst du deinen Messwert direkt aus dem 
höherwertigen Byte auslesen.
Würdest du Timer0 benutzen, wäre das der Fall.



Dass deine Lampe immer schwach leuchtet, liegt an der Konfiguration des 
Timers.
Der Timer läuft über, setzt den Ausgang, resettet das Zählregister und 
wartet dann auf den Compare Match um wieder abzuschalten. Bei OCR1A = 0 
passiert das beim nächsten Timertakt, aber der Ausgang wird immer zuerst 
mal eingeschaltet. Und das siehst du halt.
Schau dir die Timer-Modi im Datenblatt nochmal genau an. Genau wegen 
solcher Probleme gibt es so viele unterschiedliche 
Ansteuerungsmöglichkeiten.


Nachtrag:
Dein Helligkeitssprung bei aktiviertem ADLAR wird daran liegen dass 
"int" als Datentyp erstmal 16bit signed ist.
Da das Vorzeichen im MSB abgelegt wird, tritt der Fehler nur auf wenn du 
einen Wert von mehr als 50% am ADC-Eingang hast und das Ergebnis 
linksbündig ausgerichtet ist. Dann ist das MSB plötzlich 1 was eben 
nicht einen höheren Wert sondern ein invertiertes Vorzeichen zur Folge 
hat.
Benutze die dafür vorgesehenen Datentypen, hier z.b. einen uint16_t.
Damit sollte das Problem verschwinden.

von Philipp L. (viech)


Lesenswert?

Danke, das war eine sehr gute Erklärung !

Habe auf deine Empfehlung nochmals gelesen und auf einen anderen Modus 
(Phasenkorrekte-PWM) umgestellt, kann nun auch bis 0 runterdimmen.

Ich habe zwar die Grundfunktion mit Hoch/Runterzählen verstanden.
aber hier gibt es doch den Zeitpunkt, in dem der Zähler bei 0 ist und 
wieder anfängt hochzuzählen.
Warum schaltet er in diesem Moment nicht den Ausgang auf 1, da Zähler 
und OCR1A identisch sind.

Ist es also richtig, dass ich mit Fast-PWM in keiner Einstellung bis 0 
runterdimmen kann?

von Stefan F. (Gast)


Lesenswert?

Philipp L. schrieb:
> Ist es also richtig, dass ich mit Fast-PWM in keiner Einstellung bis 0
> runterdimmen kann?

Ja. Steht im Datenblatt:

"The extreme values for the OCR1x Register represents special cases when 
generating a PWM waveform output in the fast PWM mode. If the OCR1x is 
set equal to BOTTOM (0x0000) the out- put will be a narrow spike for 
each TOP+1 timer clock cycle."

von Philipp L. (viech)


Lesenswert?

Danke.

Ich habe für das Anschlussproblem (Flackern) einen neuen Thread 
aufgemacht.

von Axel S. (a-za-z0-9)


Lesenswert?

Philipp L. schrieb:
> Wenn ich ADLAR aber einschalte und am Ende alles um 6 Bit verschiebe,
> bekomme ich nicht die gleiche Charakteristik wie ohne ADLAR und ohne
> verschieben.

Das liegt daran, daß du für die Variable "Dimmstufe" den Typ int 
genommen hast. Es sollte aber ein unsigned int sein. Diese Typen 
verhalten sich unterschiedlich beim Rechsschieben. Stichwort: 
Vorzeichen.

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.