AVR Hardware PWM - ich raffs nicht

#1426140
Lesenswert?

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
#1426161
Lesenswert?

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 #1426167
Lesenswert?

>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...).
#1426213
Lesenswert?

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
#1427046
Lesenswert?

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:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren