mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 3fach Software PWM reizt Tiny44 voll aus.


Autor: Rene K. (draconix)
Datum:

Bewertung
0 lesenswert
nicht 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?!

// Tiny44 - 8Mhz int. - MicroC - EasyAVR6
 
#define RedLED PortA.B2
#define GreLED PortA.B1
#define BluLED PortA.B0

volatile unsigned short Red, Blue, Green;
volatile unsigned short Runner;
unsigned short rRed, rGreen, rBlue;

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

void Timer0Overflow_ISR() org IVT_ADDR_TIM0_OVF                   //PWM OVF
 {
      Runner++;                                                      //Runner läuft über
      
      if(Runner >= Red)   RedLED = 0; else RedLED = 1;
      if(Runner >= Green) GreLED = 0; else GreLED = 1;
      if(Runner >= Blue)  BluLED = 0; else BluLED = 1;
 }

void GenRandom()
 {
          rRed = pwmtable[runner*32/255];delay_ms(11);
          rBlue = pwmtable[runner*32/255];delay_ms(97);
          rGreen = pwmtable[runner*32/255];
 }



void main() {
   unsigned short Runner2;

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

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

   while(1)
   {
       Runner2++;                         //Runner2 läuft über
       
       if(Runner2==1) {                   //Farben per "Zufall" wählen
         GenRandom();
       }
       
           if(rRed > Red) {               //durch Farben faden
             Red = Red +1;
           } else if(rRed < Red) {
             Red = Red -1;
           }

           if(rBlue > Blue) {
             Blue = Blue +1;
           } else if(rBlue < Blue) {
             Blue = Blue -1;
           }

           if(rGreen > Green) {
             Green = Green +1;
           } else if(rGreen < Green) {
             Green = Green -1;
           }

         delay_ms(20);
   }
}

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rene K. schrieb:
> Mit dem Oszi und dem Multimeter nachgemessen, ergaben sich ohne
> Prescaler gerade mal ~122Hz an den Pins, bei 8Mhz internem Takt.

Das klingt jetzt nicht unbedingt falsch - kannst ja mal einen 
Taschenrechner nehmen und das durchrechnen =)

Autor: Rene K. (draconix)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
8.000.000Hz / 2 = 4.000.000Hz / 256 Timer Stufen = 15.625Hz... ohne 
Code... Aber der Code zieht doch den Tiny nicht von 15Khz auf 122Hz 
runter?!

Autor: Rene K. (draconix)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahhh..... Geistesblitz komme -.-

Ich lasse ja den Timer bis 256 überlaufen UND Runner als PWM Signal bis 
256 laufen....

Man man, manchmal sieht man echt den Wald vor lauter Bäumen net mehr -.-

Autor: yx<bcx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
20ms Delay sollten doch eigentlich nur noch 50 Hz ergeben?

yx<bcx

Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Rene K. (draconix)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Soft-PWM

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:

Ging mir ums Prinzip, hatte garnich auf die Datentypen geschaut.

Und mit 16Bit isses dann auch nur 1 cpc pro Kanal mehr :)

Gruß,
Sven

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.