AVR Hardware PWM - ich raffs nicht

OP #1426140
Hallo!
Ja, das Thema gabs schon öfter ;-)
Ich hab diverse Threads durch und auch das LED-Dimmen laut Artikel läuft 
auf dem dort auch verwendeten Mega8.

Ich habe mittlerweile aus dem Vorhaben, einen RGB-LED Controller zu 
bauen, eins gemacht, erstmal nur eine LED irgendwie zu faden und die PWM 
zum laufen zu bringen. Quasi ein Minimal-Programm:
1
#include <avr/io.h>
2
#include <util/delay.h>
3

4
int main(void)
5
{
6
  PORTB=(1<<PB0);
7
  TCCR0A=(1<<COM0A1)|(1<<WGM01)|(1<<WGM00); //fast-pwm, non inverted OC0A
8
  TCCR0B=(1<<CS02)|(1<<CS00); //Prescaler 1/1024
9
  OCR0A=0;
10
  //Hauptschleife
11
  while(1)
12
  {
13
    OCR0A=OCR0A+1;
14
    if(OCR0A==255)OCR0A=0;
15
    _delay_ms(100);
16
    
17
  }
18
}

Das programm soll auf einem ATTiny25 laufen, die Fuses stehen auf 
Standard (8Mhz interner Oszillator, CKDIV/8 programmiert, also 1Mhz 
Takt).

Keine logarithmische Kurve/Tabelle, nichts, die LED sollte einfach nur 
irgendwie heller werden und dann von vorne anfangen.

Was habe ich vergessen??? Das Ding macht mich seit wochen bescheuert...

EDIT: Mit diesem Programm leuchtet die LED ganz schwach mit einer 
Helligkeit durch. Kein Flackern, nichts. Oszilloskop habe ich leider 
nicht, um zu gucken, was wirklich rauskommt.

Danke für die hilfe im Voraus!
LG, Björn
OP
Scheisse wie peinlich...hab PORTB anstatt DDRB geschrieben...wird sofort 
getestet...
In den Programmen vorher war dann viellciht was anderes falsch, also 
nicht dass einer denkt ich verzweifel seit wochen an den 3 zeilen wegen 
dem ddr...

Danke schonmal!
LG, Björn
Gast
Hi

>Was habe ich vergessen??? Das Ding macht mich seit wochen bescheuert...

Timer0 des ATMega8 hat keine Hardware-PWM! Wenn schon 8-Bit, dann 
musst du Timer2 nehmen.

>Vielleicht das Datadirection-Register?

Quatsch. Die Funktion des OCR-Pins wird mit den COM-Bits
Gast
Hi

Dummerweise auf Absenden gedrückt.

>Quatsch. Die Funktion des OCR-Pins wird mit den COM-Bits

im TCC-Register eingestellt. Wenn das PIN mit der Compareeinhet 
verbunden ist kannst du in DDR einstellen, was du willst.

MfG Spess
OP
Es ging um den Tiny25, nicht um den Mega8!
Und, Zitat aus dem Datenblatt:

>>The COM0A1:0 and COM0B1:0 bits control the behaviour of Output Compare >>pins 
OC0A and
>>OC0B, respectively. If any of the COM0A1:0 bits are set, the OC0A output 
>>overrides the normal
>>port functionality of the I/O pin it is connected to. Similarly, if any of >>the 
COM0B1:0 bits are set,
>>the OC0B output overrides the normal port functionality of the I/O pin it >>is 
connected to. How-
>>ever, note that the Data Direction Register (DDR) bit corresponding to the 
>>OC0A and OC0B pins
>>must be set in order to enable the output driver.

Das DDR war der Fehler. Außerdem war die PWM-Frequenz wesentlich zu 
niedrig.
So funktioniert es jetzt:
1
#include <avr/io.h>
2
#include <util/delay.h>
3

4
int main(void)
5
{
6
  DDRB=(1<<PB0);
7
  TCCR0A=(1<<COM0A1)|(1<<WGM01)|(1<<WGM00); //fast-pwm, non inverted OC0A
8
  TCCR0B=(1<<CS01)|(1<<CS00); //Prescaler 1/64
9
  OCR0A=0;
10
  //Hauptschleife
11
  while(1)
12
  {
13
    OCR0A=OCR0A+1;
14
    if(OCR0A==255)OCR0A=0;
15
    _delay_ms(20);
16
    
17
  }
18
}
nur für die, die es interessiert.

Jetzt kann ich die logarithmische Tabelle einbauen und dann das ganze 
verdreifachen....

Danke nochmals für die Hilfe!
LG, Björn
Gast
Hi

Kommando zurück. Soll ja ATTiny25 sein.

Trotzdem musst du in TCCR0A mit COM0A1 und COM0A0 dem Timer sagen, was 
er mit dem Pin machen soll. Wie gesagt, DDR ist egal.

MfG Spess
Gast
>Timer0 des ATMega8 hat keine Hardware-PWM! Wenn schon 8-Bit, dann
>musst du Timer2 nehmen.

Den Mega8 habe ich überlesen. Der Tiny25 hat allerdings die gewünschte 
Funktion.

>Wenn das PIN mit der Compareeinhet
>verbunden ist kannst du in DDR einstellen, was du willst.

Ist beim Tiny45 nicht der Fall. (Figure 11-6; Text nicht gelesen, nur 
Bild beguckt...).
OP
spess53 schrieb:
> Trotzdem musst du in TCCR0A mit COM0A1 und COM0A0 dem Timer sagen, was
> er mit dem Pin machen soll.
Hatte ich bereits von Anfang an..
>Wie gesagt, DDR ist egal.
Eben nicht...siehe mein Zitat aus dem Datenblatt oben.

Trotzdem danke für die Hilfe!
LG, Björn
OP
Ich mach mal hier weiter ;-)

Das nächste absolut unerklärliche Problem für mich:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/pgmspace.h>
4

5

6
uint8_t pwmtable[32] PROGMEM= {0, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 11,
7
                                    13, 16, 19, 23, 27, 32, 38, 45, 54, 64, 76,
8
                                    91, 108, 128, 152, 181, 215, 255};
9

10

11
int main(void)
12
{
13
  DDRB=(1<<PB0);
14
  TCCR0A=(1<<COM0A1)|(1<<WGM01)|(1<<WGM00); //fast-pwm, non inverted OC0A
15
  TCCR0B=(1<<CS01)|(1<<CS00); //Prescaler 1/64
16
  OCR0A=0;
17
  uint8_t i =0;
18
  //Hauptschleife
19
  while(1)
20
  {
21
    
22
    for(i=0;i<32;i++)
23
    {
24
      OCR0A=pgm_read_byte(&pwmtable[i]);
25
      _delay_ms(100);
26
    }
27
    for(i=31;i>=0;i--)
28
    {
29
      OCR0A=pgm_read_byte(&pwmtable[i]);
30
      _delay_ms(100);
31
    }
32
    
33
    
34
  }
35
}

Die LED fadet jetzt einmal hoch und einmal runter wie sie soll, was dank 
der Wertetabelle echt gut aussieht. Danach scheint das Programm aber den 
Programmspeicher zu lesen anstelle der Tabelle. Die LED blinkt wild 
herum, irgendwann fadet sie wieder von ganz hell nach dunkel, dann 
wiederholt sich das Spiel. Irgendwas scheint also mit i nicht zu stimmen 
bzw. mit meinen for-Schleifen...

LG, Björn
@  Björn R. (sushi)

>wiederholt sich das Spiel. Irgendwas scheint also mit i nicht zu stimmen

Stimmt genau! ;-)
Mach mal aus deinem i mal ein int8_t ohne u und staune ;-)

>bzw. mit meinen for-Schleifen...

Schau dir mal die zweite Schleife an.

MFG
Falk
OP
Danke, Falk! Da wäre ich so schnell nicht drauf gekommen. Auch nachdem 
ich es ausprobiert hatte und es auf einmal funktionierte, hat es die 
Zahnräder im Hirn etwas drehen müssen, bis der Groschen gefallen ist...

Spitze!
LG, Björn
OP
So, das RGB-faden funktioniert jetzt auch. Allerdings hat es mit der 
exponentiellen Kennlinie nicht so gut funktioniert, da waren dann 
hauptsächlich die grundfarben zu sehen und die Mischfarben nur sehr 
kurz. Ich habe dann mit mehreren anderen Kennlinien experimentiert, 
wobei sich herausstellte, dass es mit einer linearen doch am Besten 
klappt. Ich vermute, die Kennlinie meiner RGB-LED ist dahingehend 
angepasst, dass man mit einer linearen PWM da schön faden kann. Leider 
habe ich dafür keine Beweise, da ich kein Datenblatt dazu habe. 
Überhaupt habe ich da wohl am falschen Ende gespart, die 3 Chips 
strahlen nicht in die gleiche Richtung. man hat also immer Ränder in den 
beteiligten Grundfarben mit dabei. Im Anhang die kennlinien, die ich 
ausprobiert habe(naja die braune nicht mehr, da war es schon klar), 
bevor ich das feature rausgenommen und einfach von 0 bis 255 
durchgelaufen bin. Das Programm sieht jetzt so aus:
1
#include <avr/io.h>
2
#include <util/delay.h>
3

4
int main(void)
5
{
6
  DDRB=(1<<PB0)|(1<<PB1)|(1<<PB4);
7
  //Timer 0(R,G)
8
  TCCR0A=(1<<COM0A1)|(1<<COM0B1)|(1<<WGM01)|(1<<WGM00); //fast-pwm, non inverted, OC0A, OC0B
9
  TCCR0B=(1<<CS01)|(1<<CS00); //Prescaler 1/64
10
  //Timer 1(B)
11
  TCCR1=(1<<CS10)|(1<<CS11)|(1<<CS12);//Prescaler 1/64
12
  GTCCR=(1<<PWM1B)|(1<<COM1B1);//PWM, non-inverted, OC1B
13
  //Timer 1 TOP
14
  OCR1C=255;
15
  
16
  OCR0A=0;
17
  OCR0B=0;
18
  OCR1B=0;
19
  uint8_t r =0;
20
  uint8_t g =31;
21
  uint8_t b =31;
22
  uint8_t phase = 0;
23
  //Hauptschleife
24
  while(1)
25
  {
26
    
27
    OCR0A=r;
28
    OCR0B=g;
29
    OCR1B=b;
30
    
31
    switch(phase)
32
    {
33
      case 0:
34
        b--;
35
        if(b==0) phase++;
36
        break;
37
      case 1:
38
        r++;
39
        if(r==255) phase++;
40
        break;
41
      case 2:
42
        g--;
43
        if(g==0) phase++;
44
        break;
45
      case 3:
46
        b++;
47
        if(b==255) phase++;
48
        break;
49
      case 4:
50
        r--;
51
        if(r==0) phase++;
52
        break;
53
      case 5:
54
        g++;
55
        if(g==255) phase++;
56
        break;
57
        
58
      case 6: phase=0;
59
        
60
    }
61
      
62
    _delay_ms(10);
63
    
64
  }
65
}

LG, Björn
Angehängte Dateien:
Gast
Das sind nicht zufällig die Flux-LEDs ausm Ebay-Shop "shop4leds" oder? 
Da ist mir das mit den Farbrändern auch schon unangenehm aufgefallen. 
Wenn du besseren Ersatz findest (schön hell sind sie a schon), oder 
jemand bessere helle RGB-LEDs kennt, teilt das mal bitte mit.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.