Datum:
Ich habe nach einer Anleitung im Netz versucht Hardware-PWM auf meinem Atmega 168 zu implementieren. Im groben funktioniert es auch, es tritt nur folgendes Problem auf: Bei "OCR0A = 0" ist die LED nicht aus, sondern leuchtet trotzdem sehr schwach. Was mache ich falsch?
#include <avr/io.h> #include <util/delay.h> #include <avr/pgmspace.h> uint16_t pwmtable[32] PROGMEM = {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}; int main(void) { DDRD = 1 << PD6; OCR0A = 0; TCCR0A = 1 << COM0A1 | 1 << WGM01 | 1 << WGM00; TCCR0B = 1 << CS02; while (1) { uint16_t i; for (i = 0; i < 32; i++) { OCR0A = pgm_read_word(pwmtable + i); _delay_ms(200); } } } |
Datum:
Marcel Holle schrieb: > # Bei "OCR0A = 0" ist die LED nicht aus, sondern leuchtet trotzdem sehr > schwach. Yep. Das ist normal. Die Hardware PWM funktioniert so, dass bei einem Timerwert von 0 auf jeden Fall der Ausgang ein geschaltet wird. Danach kommt der Compare Match bei 0 und schaltet gleich wieder aus. Aber eine gewisse kurze Zeit ist eingeschaltet. > > # Wenn ich die pwmtable einmal vernünftig durchlaufen haben, fängt die > LED ab dem 2. Durchlauf an wilkürlich zu blinken. > > Was mache ich falsch? > uint16_t pwmtable[32] PROGMEM = {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}; > for (i = 0; i < 256; i++) { > OCR0A = pgm_read_word(pwmtable + i); Oha. Dein Array ist 32 Einträge groß und nicht 256
Datum:
> Dein Array ist 32 Einträge groß und nicht 256 Das habe ich selber auch gerade gemerkt. ^^ > Die Hardware PWM funktioniert so, dass bei einem Timerwert von 0 auf > jeden Fall der Ausgang ein geschaltet wird. Danach kommt der Compare > Match bei 0 und schaltet gleich wieder aus. Aber eine gewisse kurze Zeit > ist eingeschaltet. Das heißt, ich schreibe eine Funktion "set_pwm(unit16_t value)", welche bei "value == 0" den timer deaktiviert und ansonsten den Wert des Registers ändert? Oder geht es eleganter?
Datum:
Marcel Holle schrieb: >> Dein Array ist 32 Einträge groß und nicht 256 > Das habe ich selber auch gerade gemerkt. ^^ > >> Die Hardware PWM funktioniert so, dass bei einem Timerwert von 0 auf >> jeden Fall der Ausgang ein geschaltet wird. Danach kommt der Compare >> Match bei 0 und schaltet gleich wieder aus. Aber eine gewisse kurze Zeit >> ist eingeschaltet. > Das heißt, ich schreibe eine Funktion "set_pwm(unit16_t value)", welche > bei "value == 0" den timer deaktiviert und ansonsten den Wert des > Registers ändert? Oder geht es eleganter? Es reicht, wenn du den Ausgansgpin vom Timer wegkoppelst (COM0A1 wieder löschen) und den Pin auf 0 setzt. den Timer kannst du ja weiter laufen lassen. (Und natürlich umgekehrt, wenn dann wieder ein PWM Wert ungleich 0 kommt)
Datum:
Hi >Bei "OCR0A = 0" ist die LED nicht aus, sondern leuchtet trotzdem sehr >schwach. Was mache ich falsch? Eigentlich nichts. Aber die PWM erzeugt kurze Spikes. Also entweder bei OCR0A = 0 die PWM abschalten oder invertierte PWM benutzen. MfG Spess
Datum:
OK, das bekomme ich hin. Wenn 3 PWM-Kanäle brauche, kann ich maximal eine Auflösung von 8 Bit verwenden, da nur Timer 1 eine Auflösung von 10 Bit verwendet. Oder gibt es noch eine andere Möglichkeit auf 10 Bit zu kommen?