3fach Software PWM reizt Tiny44 voll aus.

OP #2072237
Lesenswert?

...joar... ich habe ein kleines Problem...

Ich habe einen Tiny44 welcher einfach eine Software PWM für 3 LED (RGB) 
zur Verfügung stellt. Leider jedoch muß ich meinen 8Bit Timer ohne 
Prescaler laufen lassen, welches den Tiny dann doch recht hart in die 
Knie zwingt.

Mit dem Oszi und dem Multimeter nachgemessen, ergaben sich ohne 
Prescaler gerade mal ~122Hz an den Pins, bei 8Mhz internem Takt.

Ich finde das schon recht wenig. Könnte jemand kurz über den Code 
schauen und sagen ob ich eventuell versuche dem falschen Lösungsansatz 
zu folgen?!
1
// Tiny44 - 8Mhz int. - MicroC - EasyAVR6
2
 
3
#define RedLED PortA.B2
4
#define GreLED PortA.B1
5
#define BluLED PortA.B0
6

7
volatile unsigned short Red, Blue, Green;
8
volatile unsigned short Runner;
9
unsigned short rRed, rGreen, rBlue;
10

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

15
void Timer0Overflow_ISR() org IVT_ADDR_TIM0_OVF                   //PWM OVF
16
 {
17
      Runner++;                                                      //Runner läuft über
18
      
19
      if(Runner >= Red)   RedLED = 0; else RedLED = 1;
20
      if(Runner >= Green) GreLED = 0; else GreLED = 1;
21
      if(Runner >= Blue)  BluLED = 0; else BluLED = 1;
22
 }
23

24
void GenRandom()
25
 {
26
          rRed = pwmtable[runner*32/255];delay_ms(11);
27
          rBlue = pwmtable[runner*32/255];delay_ms(97);
28
          rGreen = pwmtable[runner*32/255];
29
 }
30

31

32

33
void main() {
34
   unsigned short Runner2;
35

36
   SREG_I_bit = 1;                                     //Interrupt einschalten
37
   TIMSK0 = (1<<TOIE0);                                //Timer 0 Timer Overflow Interrupt
38
   TCCR0B = (1<<CS00);                                 //Prescaler 0 Timer 0
39

40
   DDRA   = 0xFF;                                      //PortB auf Ausgang
41
   PORTA  = 0;                                         //PortB aus
42
   delay_ms(1000);                                     //Einschaltverzögerung
43

44
   while(1)
45
   {
46
       Runner2++;                         //Runner2 läuft über
47
       
48
       if(Runner2==1) {                   //Farben per "Zufall" wählen
49
         GenRandom();
50
       }
51
       
52
           if(rRed > Red) {               //durch Farben faden
53
             Red = Red +1;
54
           } else if(rRed < Red) {
55
             Red = Red -1;
56
           }
57

58
           if(rBlue > Blue) {
59
             Blue = Blue +1;
60
           } else if(rBlue < Blue) {
61
             Blue = Blue -1;
62
           }
63

64
           if(rGreen > Green) {
65
             Green = Green +1;
66
           } else if(rGreen < Green) {
67
             Green = Green -1;
68
           }
69

70
         delay_ms(20);
71
   }
72
}
Gast #2072332
Lesenswert?

In der GenRandom Funktion sind auch nochmal 2 Delays drinne. Für was 
sind die denn gut?

Ich hab ein 32fach PWM mit je 32 Schritten auf dem ATTiny88 (8MHz) 
laufen und bekomm pro Ausgang 500Hz PWM Frequenz.

Genug Power hat der µC also.

Gruß Joachim
Gast #2072387
Lesenswert?

wenns dann nochmal schneller werden muss eignet sich an der stelle auch 
ein wenig asm...

Gerade wenn man mehr als einen PWM Kanal hat kann man das folgendermaßen 
machen:


cp counter, pwm1 //carry wird gesetzt wenn counter > pwm1
rol r_tmp //bit0 ist gesetzt wenn counter > pwm1

cp counter, pwm2
rol r_tmp
...
out PORTX, r_tmp //bit0 wenn counter > pwm2, bit1 wenn counter > pwm1


Man braucht also pro Kanal nur noch 1x cp, 1x rol und vermutlich 
irgendwo ein paar lds. Dazu kommt noch ein out. Macht 3 + Kanalanzahl*4 
Takte

Damit schafft man dann doch einiges.
OP #2072427
Lesenswert?

Ich habe nun ein Comparematch eingefügt, den Vorteiler auf 8 und somit 
noch einige Resourcen offen.

yx<bcx schrieb:
> 20ms Delay sollten doch eigentlich nur noch 50 Hz ergeben?
>
> yx<bcx

Ist für die PWM Erzeugung relativ uninteressant. Da die Frequenz 
ausschließlich in der Interruptroutine generiert wird.

Joachim schrieb:
> In der GenRandom Funktion sind auch nochmal 2 Delays drinne. Für was
> sind die denn gut?

Eigentlich nur um einen relativ unaufwendigen Randomizer zu bekommen. Er 
übernimmt einfach nur die Werte vom Runner der interruptroutine. 
Funktioniert eigentlich ganz gut, im ferigen Code wird dies natürlich 
nicht vorkommen, da der Tiny durch einen anderen µC gesteuert wird.

Joachim schrieb:
> Ich hab ein 32fach PWM mit je 32 Schritten auf dem ATTiny88 (8MHz)
> laufen und bekomm pro Ausgang 500Hz PWM Frequenz.
>
> Genug Power hat der µC also.

Jaja, das ist mir durchaus bewußt, das solch ein µC dies eigentlich 
links aus der Hüfte schaffen sollte.

sven schrieb:
> wenns dann nochmal schneller werden muss eignet sich an der stelle auch
> ein wenig asm...
>
> Gerade wenn man mehr als einen PWM Kanal hat kann man das folgendermaßen
> machen:
>
>
> cp counter, pwm1 //carry wird gesetzt wenn counter > pwm1
> rol r_tmp //bit0 ist gesetzt wenn counter > pwm1
>
> cp counter, pwm2
> rol r_tmp
> ...
> out PORTX, r_tmp //bit0 wenn counter > pwm2, bit1 wenn counter > pwm1
>
>
> Man braucht also pro Kanal nur noch 1x cp, 1x rol und vermutlich
> irgendwo ein paar lds. Dazu kommt noch ein out. Macht 3 + Kanalanzahl*4
> Takte
>
> Damit schafft man dann doch einiges.

Wirklich ein sehr sehr guter Ansatz! Damit werde ich mich mal 
auseinandersetzen!

Peter Dannegger schrieb:
> Dein Compiler macht "unsigned short" wirklich als 8Bit?
> Sehr ungewöhnlich.
>
> Laut C-Standard muß "unsigned short" mindestens 16-bittig sein.
> Nur "unsigned char" darf 8-bittig sein.
> Besser ist aber "uint8_t" zu verwenden.
>
>
> Peter

Jep, bei meinem Compiler (MicroC PRO AVR) ist short 8bit / 1Byte groß. 
Hier mal die übersicht, float und double haben 4byte:


bit                    1–bit          0 or 1
sbit                   1–bit          0 or 1
(unsigned) char        1              0 .. 255
signed char            1              -128 .. 127
(signed) short (int)   1              -128 .. 127
unsigned short (int)   1              0 .. 255
(signed) int           2              -32768 .. 32767
unsigned (int)         2              0 .. 65535
(signed) long (int)    4              -2147483648 .. 2147483647
unsigned long (int)    4              0 .. 4294967295

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