Forum: Mikrocontroller und Digitale Elektronik Bit Angle Modulation Probleme


von Max T. (charmquark)


Lesenswert?

Hey zusammen,

ich habe ein paar Schwierigkeiten Bit Angle Modulation zu 
implementieren. Erstens ist die niedrigste Helligkeitsstufe schon recht 
hell, viel heller als erwartet. Zweitens ist z.B. bei vier Bit BAM die 
LED mit Wert 0100 dunkler als wenn ich sie auf 0011 einstelle, und 
Helligkeitsstufen 0100, 0010 und 0001 sind vergleichbar. Dieses 
Verhalten zeigt sich jedenfalls bei höheren Stufen immer weniger. Ich 
vermute, dass wenn ich den Timer mit dem neuen Wert "counts = 
(0x00000200 << iteration)" lade, wird der Interrupt erst nach "counts' = 
counts + x" aufgerufen, wobei x ein konstanter Wert ist. Dadurch könnte 
ich das Verhalten erklären.
Ich arbeite mit einem Stellaris Launchpad (LF4M120) und mein Timer ISR 
enhält folgendes:
1
void Timer0IntHandler(void)
2
{
3
  static unsigned char iteration = 0;
4
  ...
5
  ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT );
6
  ROM_TimerLoadSet( TIMER0_BASE, TIMER_A, (0x00000200 << iteration));
7
  ROM_TimerEnable(  TIMER0_BASE, TIMER_A );
8
  
9
  iteration++;                      // schematisch...
10
  if (iteration > 7) iteration = 0; // ...
11
  ...
12
  AlteLEDsAusschalten();
13
  NeueLEDsEinschalten();
14
  ...
15
}
und der Timer wird konfiguriert mit
1
  TimerConfigure( TIMER0_BASE, TIMER_CFG_ONE_SHOT );
2
  TimerLoadSet(   TIMER0_BASE, TIMER_A, 0x00000400 ); // Wert egal
3
  
4
  IntEnable( INT_TIMER0A );
5
  
6
  TimerIntEnable( TIMER0_BASE, TIMER_TIMA_TIMEOUT );
7
  TimerEnable(    TIMER0_BASE, TIMER_A);
Der interrupt braucht deutlich weniger als die ~500 Zyklen für die 
kürzeste Dauer.
Kann es sein, dass, obwohl ich den Timer direkt am Anfang des Interrupts 
wieder einschalte, er erst nach beenden des Interrupts wieder anfängt zu 
Zählen? Ich konnte jedenfalls durch einfaches abziehen einer konstante x 
im TimerLoadSet für ein paar verschiedene Werte von x nicht das 
gewünschte Verhalten erzielen.

Hat jemand eine Ahnung woran es liegen könnte bzw. was ich falsch 
gemacht habe?

Schöne Grüße,
Max

von danke (Gast)


Lesenswert?

Servus,
Wozu
1
(0x00000200 << iteration))
 wenn du
1
static unsigned char iteration = 0;
 setzt? Also
1
(0x00000200 << 0))
 bewirkt jetzt was?

1
 iteration++;                      // schematisch...
2
  if (iteration > 7) iteration = 0; // ...

Folgt 0+1 = 1 und 1 ist nicht größer als 7 und kann nicht größer werden 
als wozu ein if, wenn es eh nimals wahr werden kann?

Warum nimmst du nicht einfach eine fertige Implementierung?

von Max T. (charmquark)


Lesenswert?

Hi danke,
1
  static unsigned char iteration = 0;

Variablen die mit "static" deklariert werden behalten ihren Wert bei 
erneutem Aufruf der Funktion.

von maveric00 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

zur ersten Feststellung: Die Helligkeit von LEDs wird nichtlinear 
wahrgenommen: Wenn Du eine BAM mit nur 4 Bit implementierst, wird die 
erste Stufe nicht wie 1/16, sondern eher wie 1/4 der Maximalhelligkeit 
wahrgenommen. Abhilfe schafft eine wesentlich höhere Auflösung der BAM 
mit einer Logarithmierung der Eingangswerte (z.B. 
Eingangs-Helligkeitswert mit 8 Bit auf 14 Bit BAM durch eine 
entsprechende Look-Up-Table).

Zur 2. Frage: für höherwertige Bits muss man länger warten. Also LSB: 1 
Zeiteinheit, 2. Bit 2 Zeiteinheiten, 3. Bit 4 Zeiteinheiten etc.). Für 
hohe Auflösungen bedeutet das in der Regel, dass man bei der ersten Bits 
auf jeden einzelnen Prozessortakt achten muss, weswegen die BAM häufig 
in Assembler implementiert wird. Eine 14-Bit BAM mit 480 Hz 
Grundfrequenz für AVR hab' ich 'mal angehängt, eventuell wirst Du daraus 
ja schlau.

Dein Code sieht so ählich aus, als ob er die unterschiedlichen Zeiten 
berücksichtigen wollte; da ich allerdings den LF4M120 und die 
dazugehörende Entwicklungsumgebung nicht kenne, kann ich nur raten: Zum 
einen verwendest Du in der Main andere Routinen als in der ISR (einmal 
mit ROM_ einmal ohne). Zum Zweiten: bist Du sicher, dass die ISR weniger 
als 500 Zyklen braucht? Aufgelaufene Interrupts könnten dazu führen, 
dass die Routine immer in gleichen Abständen aufgerufen wird. Ähnliches 
könnte passieren, wenn die Interrupts im Hauptprogramm für >500 Takte 
disabled werden.

Schöne Grüße,
Martin

von danke (Gast)


Lesenswert?

Servus,

cool das ergib dann natürlich sinn. Wieder was dazu gelernt.

Warum sollte der Interrupt eine gewisse zeit brauchen also ~500Zyklen? 
Wartest du etwa im Interupt irgend wo?

Ich verstehe allerdings immer noch nicht ganz was du dir von dem 
Interupt erwartest. Ich muss zu geben ich kenne mich mit BAM jetzt auch 
nicht wirklich aus. Du startes den Timer neu mit werten zwischen 0 und 7 
sozusagen. Machst aber nur 4bit BAM?

Was hat es mit den funktionen für die LEDs auf sich?

von Max T. (charmquark)


Lesenswert?

Hi Martin,
vielen Dank für die Antwort! Ich muss die Zyklen mal genau abzählen, 
denke aber dass es maximal 300 sind. Vielleicht kann ich ja irgendwie 
testen ob die Interrupts aufeinander laufen. Dann werde ich wohl mit den 
hellen dunklen LEDs leben müssen ;)
Die Tabelle ist jedenfalls ein super Tip, den ich auf jeden Fall 
einbauen werde.

@danke,
das mit den vier und acht bit Modulation war unglücklich gewählt. Es 
läuft momentan mit 6 Bit Auflösung.
Ich warte im Interrupt nicht, sondern speise ein paar Shift Register mit 
Werten, die beim nächsten Aufruf die LEDs an- bzw. ausschalten sollen. 
So weit wie möglich am Anfang des Interrupts werden die Shift Register 
dann beim nächsten Interrupt in die Storage register geladen. Falls es 
dich interessiert warum man die timer so laufen lässt dann lies dir am 
besten mal einen Artikel über BAM durch.

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.