kramann.info
© Guido Kramann

Login: Passwort:










kramann.info
© Guido Kramann

Login: Passwort:




Ansteuerung aller LEDs der Licht-Klangkugel (RGB - Rot, Grün, Blau)

(EN google-translate)

(PL google-translate)

In dem vorangegangenen Kapitel wurden versciedene Techniken angesprochen, die erste der in die Licht-Klangkugel einzubauenden LEDs anzusprechen.

Im folgenden wird besprochen, wie alle sechs LEDs benutzt und auch in ihrer Helligkeit über Mikrocontrollerprogramme beeinflußt werden können.

Zur besseren Orientierung werden die LEDs zunächst mit festen Bezeichnungen versehen, die denen des Elaktronik-Layouts entspricht (s. nachfolgendes Schaubild).

Bezeichnungen der 6 LEDs der Licht-Klangkugel.

Bild 0-1: Bezeichnungen der 6 LEDs der Licht-Klangkugel.

Die folgende Tabelle stellt dar, wie die LEDs mit dem Mikrocontroller und ggf. der Spannungsversorgung verbunden sind:

  • Die LEDs blau2 und rot2 können über PWM-Signale angesteuert werden.
  • Die Anode von blau2 ist mit dem PWM-Ausgang von Timer2 verbunden: OC2.
  • Die Kathode von rot2 ist mit dem PWM-Ausgang von Timer0 verbunden: OC0.
  • Hinweis: Timer1 hat zwei PWM-Ausgänge OC1A und OC1B.
  • Diese werden bei der Licht-Klangkugel jeweils mit einer Anode einer Infrarot-Sende-LED verbunden.
  • Deren Kathoden liegen gemeinsam bei PD1/TXD an.
  • Dies erlaubt es sowohl das Infrarot-Signal zu takten und zum anderen auf diese eine niederfrequentere Modulation darüberzulegen, um damit serielle Daten zu übertragen.
LED-Bezeichnung Anode + Kathode -
rot1 PC4 GND
gruen1 PA1 PA0
blau1 PA7 PA6
rot2 PB4 PB3/OC0
gruen2 PC6 PC7
blau2 PD7/OC2 PC1

Tabelle 0-1: Verbindungen der LEDs mit dem Mikrocontroller.

Das nachfolgende Programm 005_rgb12.c erlaubt es, auf komfortable Weise alle LEDs anzusprechen. Der Funktion rgb(..) wird eine unsigned char-Variable übergeben. Jedem der unteren 6 Bits dieser Variablen ist eine LED zugeordnet. Durch setzen der Bits auf 1 wird die korrespondierende LED ein durch Setzen auf 0 ausgeschaltet. Die Zuordnung ist die folgende:

LED-Bezeichnung Bit-Nummer
rot1 0
gruen1 1
blau1 2
rot2 3
gruen2 4
blau2 5

Tabelle 0-2: Bitzuordnung zum Ansprechen der LEDs.

Indem im Hauptprogramm die Variable ZEIT der Funktion rgb(..) übergeben wird, werden ständig alle Kombinationsmöglichkeiten der LEDs durchgspielt. Die Bits oberhalb des Bits Nr. 5 (6. Bit) werden von der Funktion nicht beachtet.

#include <avr/io.h>  
#include<avr/interrupt.h>

volatile unsigned int ZEIT = 0;

SIGNAL(SIG_OUTPUT_COMPARE1A) //Interruptfunktion
{
    ZEIT++;
    ZEIT%=10000;    
}


void init()
{
   DDRA = 0;DDRB = 0;DDRC = 0;DDRD = 0;
   PORTA = 0;PORTB = 0;PORTC = 0;PORTD = 0;   

   //rot1: Pin26
   DDRC |= 0b00010000;  //PC4 als Ausgang konfigurieren.                           
   //grün1: Pin39,40
   DDRA |= 0b00000011;  //PA0 und PA1 als Ausgang konfigurieren.          
   //blau1: Pin33,34
   DDRA |= 0b11000000;  //PA6 und PA7 als Ausgang konfigurieren.

   //rot2: Pin4,5
   DDRB |= 0b00011000;
   //grün2: Pin28,29
   DDRC |= 0b11000000;
   //blau2: Pin21,23
   DDRC |= 0b00000010; //PC1
   DDRD |= 0b10000000; //PD7

   //ZEIT-Geber:
   TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<FOC1A) | (0<<FOC1B) | (0<<WGM11) | (0<<WGM10);
   TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10);
   TIMSK |= (1<<OCIE1A); 
   OCR1A = 97; //97=> ungefähr im 0,1 Sekunden-Takt wird Interrupt ausgelöst.
              //genauer sind es 10,067654639Hz, also 0,099328Sekunden pro Zählschritt.

    sei(); //Interrupts zulassen
}

void rgb(unsigned char farbe)
{
    //rot1==bit0
    if( (farbe & 0b00000001)>0 )
        PORTC |= 0b00010000;
    else
        PORTC &= 0b11101111;

    //grün1==bit1
    if( (farbe & 0b00000010)>0 )
        PORTA |= 0b00000010;
    else
        PORTA &= 0b11111101;

    //blau1==bit2
    if( (farbe & 0b00000100)>0 )
        PORTA |= 0b10000000;
    else
        PORTA &= 0b01111111;

    //rot2==bit3
    if( (farbe & 0b00001000)>0 )
        PORTB |= 0b00010000;
    else
        PORTB &= 0b11101111;

    //grün2==bit4
    if( (farbe & 0b00010000)>0 )
        PORTC |= 0b01000000;
    else
        PORTC &= 0b10111111;

    //blau2==bit5
    if( (farbe & 0b00100000)>0 )
        PORTD |= 0b10000000;
    else
        PORTD &= 0b01111111;

}

             
int main(void)                    
{      
   unsigned int zaehler = 0;

   init();
   while(1)                       
   {             
       rgb(ZEIT);
   }                              
}

Code 0-1: Quelltext von 005_rgb12.c

Verwendung von PWM-Signalen

Im nun folgenden Programm wird ein PWM-Signal eingesetzt, um die rote LED zu dimmen. Da diese am PWM-Ausgang des Timers0 angeschlossen ist, muß dieser entsprechend konfiguriert werden.

Der Timer0 wird als PWM-Geber mit Phasen-korrektem Signal realisiert. Die notwendigen Bitkonfigurationen des Registers TCCR0 (Timer/Counter Control Register) können der Tabelle 38 im Datenblatt auf Seite 78 entnommen werden. Es handelt sich um den Modus 1. Die entsprechende Befehlszeile zur Konfiguration lautet entsprechend:

   TCCR0 = (0<<FOC0) | (1<<WGM00) | (1<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (1<<CS00);

Code 0-2: Timer0 als Phasen korrekten PWM-Geber konfigurieren.

//Blinken grüne LED

#include <avr/io.h>  
#include<avr/interrupt.h>

volatile unsigned int ZEIT = 0;

SIGNAL(SIG_OUTPUT_COMPARE1A) //Interruptfunktion
{
    ZEIT++;
    ZEIT%=10000;    
}


void init()
{     
   DDRA = 0;DDRB = 0;DDRC = 0;DDRD = 0;
   PORTA = 0;PORTB = 0;PORTC = 0;PORTD = 0;   

   //rot1: Pin26
   DDRC |= 0b00010000;  //PC4 als Ausgang konfigurieren.                           
   //grün1: Pin39,40
   DDRA |= 0b00000011;  //PA0 und PA1 als Ausgang konfigurieren.          
   //blau1: Pin33,34
   DDRA |= 0b11000000;  //PA6 und PA7 als Ausgang konfigurieren.

   //rot2: Pin4,5
   DDRB |= 0b00011000;
   //grün2: Pin28,29
   DDRC |= 0b11000000;
   //blau2: Pin21,23
   DDRC |= 0b00000010; //PC1
   DDRD |= 0b10000000; //PD7

   //Timer0 kann ein PWM-Signal erzeugen und damit LED rot2 
   //durch Variation der Pulsbreite dimmen.
   //Dies wird hier konfiguriert:
   TCCR0 = (0<<FOC0) | (1<<WGM00) | (1<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (1<<CS00);
   OCR0 = 0; //Pulsbreite 0..255, 0==dunkel, 255==maximale Helligkeit.
   //Damit Strom fließen kann, muß PB4 auf High-Potential gelegt werden:
   PORTB |= 0b00010000;

   //ZEIT-Geber:
   TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<FOC1A) | (0<<FOC1B) | (0<<WGM11) | (0<<WGM10);
   TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10);
   TIMSK |= (1<<OCIE1A); 
//   OCR1A = 97; //97=> ungefähr im 0,1 Sekunden-Takt wird Interrupt ausgelöst.
              //genauer sind es 10,067654639Hz, also 0,099328Sekunden pro Zählschritt.

//Kleiner setzen, sonst ist das Dimmen zu langsam:
   OCR1A = 10;

    sei(); //Interrupts zulassen
}
             
int main(void)                    
{      
   unsigned int wert = 0;

   init();
   while(1)                       
   {             
       wert = ZEIT%511;
       if(wert>255)
           wert = 511-wert;
       OCR0 = wert;
   }                              
}

Code 0-3: Quelltext von 006_rot2_gedimmt.c

Übung
  • Welche Vorteilung wird für Timer0 in 006_rot2_gedimmt.c verwendet?
  • Wie lange dauert ein kompletter Dimm-Vorgang (rote LED wird ganz hell und dann wieder ganz dunkel)?
  • Versuchen Sie die gleiche Funktionalität für die blaue LED zu programmieren. Bitte versuchen Sie es erst nur mit Hilfe des Datenblattes und schauen Sie sich erst anschließend eine mögliche Lösung an: 007_blau2_gedimmt.c