mikrocontroller.net

Forum: Compiler & IDEs LED Helligkeit festlegen mit Soft-PWM ( ATMEGA8 )


Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Aus freude an der Sache habe ich mir ein Entwicklungsboard MySmartUSB 
(mit ATMEGA8 Prozessor) zugelegt und wage die ersten Schritte im 
Programmieren. Dazu habe ich mir eine LED-Platine zusammengelötet um zu 
experimentieren.

Die Idee sieht wie folgt aus: Wenn PINC0 aktiv ist sollen die LEDS an 
PINB1 und PINB2 mit reduzierter Helligkeit leuchten (case 0xc1). Wenn 
PINC1 zugeschaltet wird soll die LED an PINB1 mit voller Helligkeit 
leuchten, d.h. ohne Soft-PWM und PINB2 weiterhin mit reduzierter 
Helligkeit (case 0xc3).

Hier ist mein bestehender C-Code:
#include <avr/io.h>
#include <util/delay.h>

  int main(void)
  {
  
  DDRC = 0x00;     // Port C ist Eingang
  PORTC = 0xff;    // Port C ist auf "high" gelegt
  
  DDRB = 0xff;     // Port B ist Ausgang
  PORTB = 0x00;    // Port B ist auf "low" gelegt
  
  DDRD = 0xff;     // Port D ist Ausgang
  PORTD = 0x00;    // Port D ist auf "low" gelegt
  
  volatile unsigned char input;
  
  while(1)
  {
  
  input =~ PINC;  // LEDs an Anode (+5V) und Kathode an GRD; also invertiert
 
  switch (input)
   
  {
    case 0xc1:                          // Schalter 1 zu, Schalter 2 offen
    PORTB = ((1<<PINB1) | (1<<PINB2));  // LED1 & LED2 Helligkeit reduziert
    break;
    
    case 0xc3:                          // Schalter 1 & 2 zu
    PORTB = ((1<<PINB1) | (1<<PINB2));  // LED1 volle Helligkeit und LED2 reduziert 
    break;
    
    default:                 // Zeigt das keine Inputs aktiv sind
    PORTB = (1<<PINB3);      // LED3 an PINB3 
  }
  _delay_ms(1000);           // Verzögerung um CPU Last zu reduzieren
  }
  }

Ich habe mir die Soft-PWM im Tutorial zu gemüte geführt. Leider fehlt 
mir das Verständnis um meine Idee zu realisieren. Das Beispiel für 
PWM-Modi unter 
http://www.rn-wissen.de/index.php/Timer/Counter_(A... 
scheint mir im Prinzip naheliegend (?). Hier kann man den PWM-Wert 
festlegen, wobei ich die Output-Pins selber bestimmen möchte.

Vielleicht kann mir jemand helfen die Lösung zu erarbeiten.

Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In der Zwischenzeit bin ich ein paar Schritte vorwärts gekommen. Ich 
habe under "case 0xc1" eine Bibliotek pwmLed1() eingefügt. Das sieht so 
aus:
#include <avr/io.h>

int pwmLed1 (void)
  {  
  int pwm_phase=0, pwm_soll=90;    // Dimmerwert definieren
  
  while(1)
  {
    if(pwm_soll==pwm_phase)
    {
      PORTB = ((1<<PINB1) | (1<<PINB2));    //  LED1 & LED2 Helligkeit reduziert
    }
    pwm_phase++;
    if(pwm_phase==100)
    {
      pwm_phase=0;
      PORTB = 0x00;
    }
    }
  return(0);
  }

Die LEDs werden gedimmt, wie gewünscht. Aber, wenn das Programm einmal 
in pwmLed1() ist bleibt es dort hängen.

Was habe ich übersehen?

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>while(1)

bildet nun mal eine Endlosschleife. Da gibt es kein Entrinnen. Und 
pwmLed1() ist eine Funktion, keine Bibliothek.

Oliver

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
>>while(1)
>
> bildet nun mal eine Endlosschleife. Da gibt es kein Entrinnen

Gibt es schon, nennt sich "break" und "return" (und noch ein paar 
weniger gebräuchliche, wie "goto" oder "longjump()").

Sind im Code aber nicht vorhanden, also Endlosschleife = Endstation.

Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke euch beiden für die Hinweise. Jetzt werde ich wohl einen anderen 
Lösungsansatz suchen müssen. Habt ihr eventuell einen Tipp?

Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, ich habe mir mal die 8-kanalige PWM mit intelligenter Lösungsansatz 
probiert. Es funktioniert mit den angegebenen Test Values.

Als Anfänger komme ich jetzt leider nicht mehr weiter und bitte um 
Starthilfe. Wie kann ich jetzt z.B. 8 LEDs mit unterschiedlicher 
Helligkeit unten einbinden?
int main(void)
{
    // PWM Port einstellen
    
    PWM_DDR = 0xFF;         // Port als Ausgang
    
    // Timer 1 OCRA1, als variablem Timer nutzen
 
    TCCR1B = 2;             // Timer läuft mit Prescaler 8
    TIMSK |= (1<<OCIE1A);   // Interrupt freischalten
 
   sei();                   // Interrupts gloabl einschalten
 
volatile unsigned char input;

????????????
  
  while(1)
    {
    input = ~PINC;         // LEDs an Anode (+5V) und Kathode an GRD; also invertiert
   
    switch (input)
    {
      case 0xc1:           // Schalter 1 zu, Schalter 2 offen
        ????;
      break;
   
      case 0xc3:           // Schalter 1 & 2 zu
        ????;
      break;
   
      default:             // Zeigt das keine Inputs aktiv sind
        PORTB |= 0x10;     // LED5 an PINB4
    }  
    }
  return 0;
} 

Besten Dank

Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt hab ich's fast. Die LED Helligkeiten kann ich problemlos 
bestimmen, aber sie blinken unregelmässig, als ob sie unter 
"Wackelkontakt" leiden. Waran könnte das liegen?
volatile unsigned char input;

const uint8_t t1[8] = {150, 150, 150, 150, 0, 150, 0, 0};
const uint8_t t2[8] = {0, 200, 200, 200, 0, 50, 0, 0};
const uint8_t d[8] = {0, 0, 0, 0, 0, 0, 0, 0};

  while(1)
    {
    input = ~PINC;    // LEDs an Anode (+5V) und Kathode an GRD; also invertiert
    
   
    switch (input)
    {
      case 0xc1:        // Schalter 1 zu, Schalter 2 offen
        memcpy(pwm_setting, t1, 8);
        pwm_update();  
      break;

      case 0xc3:               // Schalter 1 & 2 zu
        memcpy(pwm_setting, t2, 8);
        pwm_update();
      break;

      default:       // Zeigt das keine Inputs aktiv sind
        memcpy(pwm_setting, d, 8);  // LEDs off
        pwm_update();  
    }
    }
  return 0;
}

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Firebird (Gast)

>Jetzt hab ich's fast. Die LED Helligkeiten kann ich problemlos
>bestimmen, aber sie blinken unregelmässig, als ob sie unter
>"Wackelkontakt" leiden. Waran könnte das liegen?

Deine Tastenabfrage ist komisch. Mach es lieber einfach per

  if(input & (1<<PC0)) {}    /// Taste an PC0 gedrückt

MFG
Falk

Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Falk

Danke für den Hinweis. Ich habe es wie folgt ausprobiert:
  while(1)
  {
    input = ~PINC;    // LEDs an Anode (+5V) und Kathode an GRD; also invertiert
    if (input & (1<<PINC0))         // Schalter 1 zu, Schalter 2 offen
    {
      memcpy(pwm_setting, t1, 8);
      pwm_update();
    }
    if (input & (1<<PINC1))         // Schalter 1 offen, Schalter 2 zu
    {
      memcpy(pwm_setting, t2, 8);
      pwm_update();
    }
    if (input & ((1<<PINC0)|(1<<PINC1)))  // Schalter 1 und 2 zu
    {
      memcpy(pwm_setting, t3, 8);
      pwm_update();
    }
    else
    {
      memcpy(pwm_setting, d, 8);    // LEDs off
      pwm_update();
    }
  }
  return 0;

Es funktioniert besser wobei dazu kommt, dass die einzelnen Fälle nicht 
sauber erfasst werden:
Für (1<<PINC0) flackern die LEDs
Für (1<<PINC1) flackern sie ein bischen weniger
Für ((1<<PINC0)|(1<<PINC1)) leuchten die LEDs analog wie für (1<<PINC0)
Die else Anweisung wird nicht erkannt ausser wenn INPUT =~PINC

In meiner Switch Anweisung habe ich "0xc1" und "0xc3" verwendet um alle 
PINC Zustände zu erfassen. Sobald ich dort mit einzelnen PINC Zustände 
(analog oben) gearbeitet habe gab es die gleichen Probleme.

An meinem ATMEGA8 wird PINC6 für Reset verwendet und PINC7 ist gar nicht 
vorhanden, deswegen die "c" in "0xC1".

Mit freundlichem Gruss
Firebird

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.