www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Attiny85/45/25 Soft-PWM mit Timer 1 - 12bit


Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend,

ich möchte mit einem Attiny85 eine 12bit RGB-Steuerung realisieren.

Allgemeine Problematik von RGB Steuerungen:
Um möglichst weiche Farbübergänge zu erzeugen sollte die RGB-Steuerung 
mit einer möglichst hohen Auflösung arbeiten. Dabei muss aber 
gleichzeitig auf die Frequenz des PWM-Signals geachtet werden, dass 
diese nicht flimmert.
Außerdem soll die nicht lineare Kennlinie des menschlichen Auges 
berücksichtigt werden um so einen linearen Helligkeitsverlauf der Farben 
zu erzeugen.

Kurz zu meiem Programm:
Ich möchte den Timer 1 des Attiny85 im asynchronen Modus mit 64Mhz 
betreiben um eine möglichst hohe PWM Frequenz zu erreichen. Rechnerisch 
ergäbe sich meines Verständnisses nach in meinem Programm eine 
PWM-Frequenz von ca. 61Hz (siehe Kommentar). Leider sehe ich ein starkes 
Flackern, sodass ich sagen kann die Frequenz liegt bei vllt 10 Hz 
(geschätzt). Leider habe ich kein Oszilloskop oder Ähnliches um mir das 
erzeugte PWM-Signal anzeigen zu lassen.

Meine Frage:
Wo liegt also mein Fehler? Warum beträgt die PWM-Frequenz nicht meine 
errechneten 61Hz?
#ifndef F_CPU
#define F_CPU 8000000UL 
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define rot_an    PORTB |= (1 << PB1)
#define rot_aus    PORTB &= ~(1 << PB1)

#define gruen_an    PORTB |= (1 << PB3)
#define gruen_aus    PORTB &= ~(1 << PB3)

#define blau_an    PORTB |= (1 << PB4)
#define blau_aus    PORTB &= ~(1 << PB4)

// Variablen definieren
volatile uint8_t rot;
volatile uint8_t gruen;
volatile uint8_t blau;
volatile uint16_t timer; 

uint16_t Helligkeit[99]   = {
  0,    1,    1,    1,    1,    1,    2,    2,    2,    2,
  2,    3,    3,    3,    3,    4,    4,    4,    5,    5,
  5,    6,    6,    7,    8,    8,    9,    10,    11,    12,
  13,    14,    15,    16,    18,    20,    21,    23,    25,    27,
  30,    32,    35,    38,    42,    46,    50,    54,    59,    64,  
  70,    76,    83,    90,    98,    106,  116,  126,  137,  150,
  163,  177,    193,  210,  229,  249,  271,  295,  321,  349,  
  380,  414,  451,  491,  534,  581,  633,  689,  750,  816,
  889,  967,  1053,  1146,  1248,  1359,  1479,  1610,  1752,  1908,
  2077,  2261,  2461,  2679,  2916,  3174,  3456,  3762,  4095
};

// ***** Timer1-Overflow-Interrupt ****** --> PWM Frequenz = 64MHz/256(Oerflows pro Sek)/4096(Timer)/1(Prescaler) = 61 Hz
ISR (TIMER1_OVF_vect){ 

if (timer < 4095) {timer++;}
else {timer = 0;}

if (timer < Helligkeit[rot]) {rot_an;}
else {rot_aus;}
if (timer < Helligkeit[gruen]) {gruen_an;}
else {gruen_aus;}
if (timer < Helligkeit[blau]) {blau_an;}
else {blau_aus;}
}

// ***** Hauptprogramm *****
int main(void){
// Variablen setzen
rot = 0; 
gruen = 0;
blau = 0;
timer = 0;

// PortB 345 zu Ausgängen und auf 0
DDRB |= (1<<DDB3)|(1<<DDB4)|(1<<DDB1);
PORTB &= ~(1<<PB3)|(1<<PB4)|(1<<PB1);
                
//asynchronen Modus aktivieren (64Mhz) - dazu laut Datenblatt: 1) PLL aktivieren 2) Warten bis PLL eingerastet 3) PCKE setzen
PLLCSR |= (1<<PLLE);
_delay_us(100); 
while(!(PLLCSR & (1<<PLOCK)));
PLLCSR |= (1<<PCKE);

// Timer 1 konfigurieren: Clock = PCK 
TCCR1 |= (1<<CS10); 

//Overflow Interrupt Timer 1 aktivieren
TIMSK |= (1<<TOIE1);

// Global Interrupts aktivieren
sei();

// ***** Endlosschleife *****
while(1){

while (rot<98) {rot++; _delay_ms(1);}
while (rot>0) {rot--; _delay_ms(1);}

} //eof while
} //eof main


Vielen Dank für eure Hilfe!

Freundliche Grüße,
Sven

Autor: Mark Leyer (m2k10) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir fallen da mehrere Sachen auf. Zum einen, ich persönlich sehe sogar 
bei 150Hz noch Flackern, hab aber gelesen, dass ab 100-120Hz die meisten 
Menschen kein Flackern mehr wahrnehmen. Vielleicht sind die 61Hz 
insgesamt schon etwas zu wenig.

Aber egal, bei Software von dir passiert folgendes:
Du lässt zwar den Timer mit 64MHz laufen, aber der AVR arbeitet dennoch 
mit 8MHz seine Befehle ab. Du hast daher alle 32 Takte einen Overflow 
vom Timer und dein AVR kommt da nicht mehr mit die ISR abzuarbeiten und 
verschluckt daher entsprechend viele (bei ca. 10Hz würde er eine 
abarbeiten und 5 überspringen). Selbst in reinem Assembler würde das 
knapp. Der Compiler sichert schlimmstenfalls alle Register und benötigt 
dafür alleine 132 Takte.

Die 64MHz bringen nichts, wenn man nur den Timeroverflow ohne die PWM 
verwendet. Ist das gleiche, als wenn du den Timer normal bis 31 laufen 
lässt (außer, dass es eher auffällt, dass es so nicht geht).

Mark

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank!

Jetzt habe ich meinen Denkfehler(nach einigen Tagen nahe der 
Verzweifelung) verstanden!

Also kann ich wohl eine höhere Auflösung mit diesem AVR (bei gleichem 
Takt) und Soft-PWM nicht erreichen.

Schönen Abend noch!

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Soft-PWM. Allerdings ist bei ~10 Bit Auflösung Feierabend. 
Reicht aber meist, siehe LED-Fading.

MFG
Falk

Autor: Frank Buss (foobar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann den PWM-Ausgang direkt rausschalten, sodaß du also nicht per 
Interrupt die LEDs manuell an- und ausschalten musst, was bei der hohen 
Frequenz wegen dem Jitter sowieso zu starken Ungenauigkeiten bei der 
Helligkeit führen würde. Ich weiss allerdings nicht, wieviel 
PWM-Ausgänge der Chip hat, also RGB wird damit dann ggf. nicht gehen, 
aber du kannst es ja mal für eine LED ausprobieren. Sollte dann nicht 
flackern. Die 100 Hz kannst du per Soundkarte aufnehmen und mit einen 
der vielen verfügbaren Soundkarten Oszilloskope analysieren.

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.