Forum: Mikrocontroller und Digitale Elektronik IRMP mit 16bit PWM kombinierbar?


von Julian T. (Firma: Stuttgart) (livingevil)


Lesenswert?

Hallo Leute,

folgendes Problem: Ich habe ein LED-Blinklicht mit 16bit Rampe basierend 
auf folgendem Code (Autor: Kersten Decker) realisiert:
1
TCCR1A |= _BV(COM1A1) | _BV(COM1B1); // Eigenschaften der Portpins
2
3
TCCR1A |= _BV(WGM11); // 16 Bit Fast PWM, TOP ist ICR1:
4
TCCR1B |= _BV(WGM12);
5
TCCR1B |= _BV(WGM13);
6
7
ICR1H = 0xFF; //Top = 0xFFFF;
8
ICR1L = 0xFF; //Normalerweise über ein TEMP-Register schreiben, aber da
9
der Timer noch nicht läuft sollte das nicht nötig sein
10
11
TCCR1B |= _BV(CS10); // kein Prescaler und Timer starten
12
13
OCR1A = 0xFFFF; //5V
14
OCR1B = 0x7FFF; //die Hälfte

Ich wollte diesen 16bit Blinker nun in dem berühmten IRMP Programm 
einbauen, dass wenn ich eine Taste (Fernbedienung) drücke, eine 
Blinklichtschleife läuft und bei erneutem Drücken dieser Taste, die 
Schleife beendet wird und neue "Tastendrücke" erkannt werden können.

Versucht habe ich das ganze über eine void blinker (); aber selbst wenn 
ich, keine Schleife einbaue, sondern nur "einmal blinken und fertig" 
anordne, bleibt er in der void hängen (so scheint es) und findet nicht 
mehr ins Hauptprogramm:
1
 for (;;)
2
    {
3
        if (irmp_get_data (&irmp_data))
4
        {
5
            if (irmp_data.protocol == IRMP_NEC_PROTOCOL) 
6
            { usw...

Nun nehme ich an, dass das mit den Timern usw zusammenhängt, aber da 
steig ich leider nicht genug durch, um zu durchschauen, was ich tun 
muss, dass es wieder in die "main" zurückfindet und dort auch seine 
ursprünglichen Timer wieder findet...

Meine Idee war, in die void Blinker diese irmp_get_data Abfrage 
einzubauen, aber das habe ich nicht hinbekommen.

Was wäre denn da die klügste Vorgehensweise? Vielen Dank schonmal :)

: Verschoben durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Julian T. schrieb:
> Was wäre denn da die klügste Vorgehensweise?

Du musst lediglich dafür sorgen, dass irmp_ISR() 15.000 mal pro Sekunde 
aufgerufen wird. Wie, das ist egal.

Das Beispielprogramm main.c bedient sich dafür des Timers1. Genauso 
kannst Du aber auch einen 8-Bit-Timer dafür verwenden. Dann hast Du den 
Timer1 für Deine LEDs frei. Du kommst dann zwar nicht exakt auf 15000 
Interrupts pro Sekunde, aber den Wert kannst Du ja anpassen.

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Unter

  https://www.mikrocontroller.net/articles/IRMP#Einstellungen_in_irmpconfig.h

findest Du den entscheidenden Hinweis, wie Du den Timer2 für IRMP nutzen 
kannst.

Zitat:

Auf AVR-Prozessoren wird in der Beispielroutine in main.c der Timer1 mit 
16-Bit-Genauigkeit verwendet. Sollte der Timer1 aus irgendwelchen 
Gründen nicht verfügbar sein, kann man alternativ auch den Timer2 mit 
8-Bit-Genauigkeit verwenden.

In diesem Fall wird dieser dann konfiguriert über:
1
OCR2   =  (uint8_t) ((F_CPU / F_INTERRUPTS) / 8) - 1 + 0.5);   // Compare Register OCR2
2
TCCR2  = (1 << WGM21) | (1 << CS21);                           // CTC Mode, prescaler = 8
3
TIMSK  = 1 << OCIE2;                                           // enable timer2 interrupt

Das obige Beispiel gilt für ATmega88/ATmega168/ATmega328. Bei anderen 
AVR-µCs empfiehlt sich ein Blick ins Datenblatt.

Man sollte in diesem Fall nicht vergessen, auch die Interrupt-Routine an 
den Timer2 anzupassen:

ISR(TIMER2_COMP_vect)
{
  (void) irmp_ISR();
}

von Julian T. (Firma: Stuttgart) (livingevil)


Lesenswert?

Urlaub für morgen ist eingereicht; werde mich dann daran versuchen :) 
Danke!

von Julian T. (Firma: Stuttgart) (livingevil)


Lesenswert?

Hi Frank, das hat super geklappt! Wie ist das mit dem Timer der für IRMP 
belegt ist, kann ich den noch anderweitig verwenden (parallel), z.B. um 
mir einen 50% duty cycle an einem beliebigen Pin ausgeben zu lassen ? 
Wenn ich z.B. eine LED nur dimmen und nicht faden will, ist 8bit ja 
vollkommen ausreichend..Dann hätte ich nach wie vor 3 Timer bei meinem 
Atmega8.

Beste Grüße!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Julian T. schrieb:
> Hi Frank, das hat super geklappt! Wie ist das mit dem Timer der für IRMP
> belegt ist, kann ich den noch anderweitig verwenden (parallel), z.B. um
> mir einen 50% duty cycle an einem beliebigen Pin ausgeben zu lassen ?

Da sehe ich keinen Hinderungsgrund. Mit welchem Takt läuft denn Dein µC?

von Julian T. (Firma: Stuttgart) (livingevil)


Lesenswert?

8Mhz. Beeinflusst das meine "Bildwiederholungsrate in [Hz]" für PWM? 
Oder spielt das nur dafür eine Rolle, wie oft ich pro Zeit auf den Timer 
zugreifen kann?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Julian T. schrieb:
> 8Mhz. Beeinflusst das meine "Bildwiederholungsrate in [Hz]" für PWM?

Beeinflussen nicht direkt. Aber bei 16MHz ist die Prozessorauslastung 
natürlich entsprechend geringer, da er alles doppelt so schnell 
abarbeiten kann.

von Julian T. (Firma: Stuttgart) (livingevil)


Lesenswert?

Hi,
ich habe beim Atmega8 drei 8bit Timer, wobei ich die ersten zwei zu 
einem 16bit Timer kombiniert habe. Jetzt habe ich den dritten 8bit Timer 
für IRMP benutzt - kann ich trotzdem noch SoftPWM realisieren, oder komm 
ich mir da irgendwie in die Quere? Ich überschau nicht ganz, in wie weit 
hier "multi-tasking" möglich ist (auch wenn die Prozesse hintereinander 
ablaufen).

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Julian T. schrieb:
> ich habe beim Atmega8 drei 8bit Timer, [...]

Der Atmega8 hat 2 8Bit-Timer und 1 16Bit-Timer.

> wobei ich die ersten zwei zu einem 16bit Timer kombiniert habe.

Warum? Was machst Du denn mit den Timern außer IRMP?

> Jetzt habe ich den dritten 8bit Timer für IRMP benutzt - [...]

Welchen? Timer2?

> kann ich trotzdem noch SoftPWM realisieren, oder komm ich mir da
> irgendwie in die Quere?

Kommt drauf an, wie effizient die SoftPWM programmiert ist. Warum keine 
HW-PWM? Übrigens halte ich 16Bit-PWMs für eine LED-Ansteuerung für 
Oversized. Bei 12 Bit hast Du 4096 Stufen. Das reicht dicke. Die 12 Bit 
kann man mit einem 8Bit-Timer in HW machen. Die restlichen 4 Bit macht 
man in Software.

Aber vielleicht erklärst Du Deine Anwendung mal genauer bzw. zeigst mal 
zumindest Auszüge des Codes?

Ansonsten gilt: Probieren geht über Studieren. Probiers einfach aus.

von Julian T. (Firma: Stuttgart) (livingevil)


Lesenswert?

Hi,

im Moment habe ich meinen Code nicht zur Hand - wird nachgeliefert ;)

Ich hatte das so verstanden, dass der Atmega8a drei 8bit Timer hat. Im 
Moment habe ich Timer2 für IRMP und die anderne beiden Timer (dachte ich 
zumindest) für den 16bit kombiniert. Ich habe doch auch nur OC1A und B 
und kann somit einen dritten Timer nicht als Hardware PWM ausgeben 
(bestimmt falsch diese Annahme, aber mein Durchblick ist bei µCs sehr 
begrenzt). Ich habe festgestellt, dass wenn ich an OC1A 16bit fading 
ausgebe, ich an OC1B nur die geklonten Werte ausgeben kann - oder eben 
nichts.

Zusammengefasst: Wenn ich 16bit PWM, 8bit PWM parallel und IRMP 
gleichzeitig nutzen will, komm ich um SoftPWM nicht drumherum - korrekt?

Wenn du eine Glühlampe als Blinker mit 150ms Rampe simulieren willst, 
ist 16bit PWM meines Erachtens sehr realistisch - allerdings habe ich 
bisher nur 8bit und 16bit hinbekommen (Anfänger ;) ) und somit keinen 
12bit zum Vergleich.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hi Julian,

Julian T. schrieb:
> Ich hatte das so verstanden, dass der Atmega8a drei 8bit Timer hat.

Timer0: 8 Bit
Timer1: 16 Bit
Timer2: 8 Bit

> Im
> Moment habe ich Timer2 für IRMP und die anderne beiden Timer (dachte ich
> zumindest) für den 16bit kombiniert.

Das ist nicht nötig. Timer1 ist bereits ein 16Bit-Timer. Damit hast Du 
noch Timer0 frei.

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


Lesenswert?

Julian T. schrieb:
> Ich habe doch auch nur OC1A und B
> und kann somit einen dritten Timer nicht als Hardware PWM ausgeben

OC1A und OC1B sind auf dem gleichen Timer. Es sind zwei verschiedene 
Compare-Kanäle. Und ja, für Hardware-PWM brauchst du einen Compare-Kanal 
pro PWM-Output. Software-PWM kann verschieden implementiert werden. Die 
geringsten Anforderungen den den Timer hast du mit binär gewichteter PWM 
(aka Bit Angle Modulation - BAM). Meine Software-PWM braucht einen 
Compare-Kanal auf einem 16-Bit Timer und kann dann ca. 10 Bit Auflösung 
(um die 200 Helligkeitsstufen nach Gammakorrektur) für bis zu 8 Kanäle.

Mit etwas Suchen findest du hier im Forum und auch nebenan im Wiki genug 
Erklärungen und Beispielcode für Software-PWM.

Ganz spezifisch läuft meine Software-PWM für 3 LED zusammen mit IRMP auf 
einem ATmega8: Beitrag "noch ein AVR Moodlight"

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Axel S. schrieb:
> Ganz spezifisch läuft meine Software-PWM für 3 LED zusammen mit IRMP auf
> einem ATmega8: Beitrag "noch ein AVR Moodlight"

Stimmt, darauf hätte ich Julian direkt hinweisen können - komplett 
vergessen :)

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.