Hallo zusammen, ich versuche auf meinem Demoboard von PicKit eine ganz einfache SoftPWM zu Programmieren. Es hat eigentlich ganz gut geklapt, nur die LED beginnt zu flackern sobald man unter ca. 80% ist. Hier mein Code: #pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF // CONFIG1H #pragma config PWRT = OFF, BOREN = SBORDIS, BORV = 30 // CONFIG2L #pragma config WDTEN = OFF, WDTPS = 32768 // CONFIG2H #pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC // CONFIG3H #pragma config STVREN = ON, LVP = OFF, XINST = OFF // CONFIG4L #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF // CONFIG5L #pragma config CPB = OFF, CPD = OFF // CONFIG5H #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF // CONFIG6L #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF // CONFIG6H #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF // CONFIG7L #pragma config EBTRB = OFF // CONFIG7H /** I N C L U D E S **************************************************/ #include "p18f45k20.h" #include "delays.h" /** D E C L A R A T I O N S ******************************************/ unsigned char TIME; //LED1 als 8-Bit void LED (unsigned char ADWERT) { TIME++; if (TIME<ADWERT) {LATD = 0b11111111;} else {LATD =0b00000000;} } int main(void) { TIME=0; TRISD = 0x00; TRISA = 0xFF; ANSELH = 0b00000000; //AN0 ist nun ein Analoger Eingang ADCON0= 0b00000001; //Teiler von 2 einstellen, und den ADC einschalten ADCON1= 0b10000000; //Rechtsbündig, Vcc und Vdd verwenden ADCON2= 0b00111000; CM1CON0 = 0b00000000; // Komperator 1 aus CM2CON0 = 0b00000000; // Komperator 2 aus while (1) { ADCON0bits.GO = 1; while(ADCON0bits.GO ==1); LED(ADRESH); } return 0; } Woran könnte das liegen, was kann ich verbessern oder schneller machen?
Fahr doch mal einem Passat mit LED-Rücklichtern hinterher und frag den Fahrer :-) Spaß beiseite. LEDs sind unglaublich schnell. Was Du mit einer Glühbirne und 50Hz flackerfrei hinbekommst, klappt mit einer LED überhaupt nicht. Hier kommt es darauf an, was der Betrachter (Mensch) noch störend empfindet. Die LED wirst Du nie so schnell angesteuert bekommen, dass sich eine mittlere Helligkeit direkt an der LED einstellt.
sdfg2qz2 schrieb: > Hier kommt es darauf an, was der Betrachter (Mensch) noch > störend empfindet. Die LED wirst Du nie so schnell angesteuert > bekommen, dass sich eine mittlere Helligkeit direkt an der > LED einstellt. Was genau meinst du damit? Eine 8-Bit PWM mit der man auf eine Zykluszeit jenseits von 100Hz kommt, schafft jeder Nasenpopel-AVR-Tiny. Und ausser für ganz empfindsame Gemüter IST die für 99% der Menschheit flackerfrei und eine in der Helligkeit stellbare LED. Zu seinem Code kann ich nicht viel sagen, da ich mit diesem µC keine Erfahrung habe. Die PWM durch die Hauptschleife ist jetzt sicher nicht so der Bringer, aber abhängig vom CPU-Takt sollte sich damit selbst bei kleinen Taktfrequenzen schon eine flackerfreie PWM einstellen.
sdfg2qz2 schrieb: > Hier kommt es darauf an, was der Betrachter (Mensch) noch > > störend empfindet. Die LED wirst Du nie so schnell angesteuert > > bekommen, dass sich eine mittlere Helligkeit direkt an der > > LED einstellt. Ich habe das Programm umgestellt das der Pic nur einmal Initialisieren muss. Jetzt sieht das ganze sehr viel angenemer aus. Der neue Code: void main(void) { TIME=0; TRISD = 0x00; TRISA = 0xFF; ADCON0= 0b00000001; //Teiler von 2 einstellen, und den ADC einschalten ADCON1= 0b10000000; //Rechtsbündig, Vcc und Vdd verwenden CM1CON0 = 0b00000000; // Komperator 1 aus CM2CON0 = 0b00000000; // Komperator 2 aus while (1) { TIME++; ANSELH = 0b00000000; //AN0 ist nun ein Analoger Eingang ADCON0bits.GO = 1; while(ADCON0bits.GO ==1); ADWERT=(ADRESH); if (TIME<ADWERT) {LATD = 0b11111111;} else {LATD =0b00000000;} } } Wenn jemand verbesserungs Vorschläge hat, ich bin offen für alles. Bin ein Mikrocontrollerneuling und lerne gerne dazu.
Ja, kann man erheblich verbessern um die PWM schneller zu machen. Ein Problem ist die while() Schleife die auf den ADC wartet. Wenn Du das ganze wirklich unbedingt ohne Interrupt machen willst, hier mal ein Beispiel (ohne den ganzen Init-Kram):
1 | unsigned char pwm_count; |
2 | unsigned char led_value; |
3 | |
4 | void do_pwm(void) |
5 | {
|
6 | pwm_count++; |
7 | |
8 | if(pwm_count < led_value) |
9 | {
|
10 | LATD = 0xFF; |
11 | }
|
12 | else
|
13 | {
|
14 | LATD = 0x00; |
15 | }
|
16 | }
|
17 | |
18 | void main(void) |
19 | {
|
20 | // Hier PIC und ADC init, etc.
|
21 | // ...
|
22 | |
23 | ADCON0bits.GO = 1 |
24 | |
25 | pwm_count = 0; |
26 | led_value = 0; |
27 | |
28 | while(1) |
29 | {
|
30 | if(ADCON0bits.GO == 0) |
31 | {
|
32 | led_value = ADRESH; |
33 | ADCON0bits.GO = 1; |
34 | }
|
35 | |
36 | do_pwm(); |
37 | }
|
38 | }
|
So wird die PWM Routine permanent ausgeführt, und nicht erst wenn der neue ADC Wert eingelesen ist. Das Problem bei deiner Methode: Ohne sehr saubere Vref für den ADC, sowie ohne sehr saubere (= gefilterte) Eingangsspannung zum ADC werden da immer irgendwelche unteren Bits im Ergebnis "wackeln". Nehmen wir mal an dein PWM Zähler steht auf 10, dein vorheriger ADC Wert war 11, somit ist PORTD jetzt an. Jetzt liest Du den ADC aus, wartest dabei aber bis der Wert da ist. Der ausgelesene Wert ist jetzt aber 10. Nun vergleichst Du wieder, und der Port wird abgeschaltet, da der Zähler jetzt 11 ist. Beim nächsten mall kann es dann sein das der ADC 12 ist, und somit wieder den Port wieder einschaltet. Normalerweise ist das kein Problem, da eine PWM eigentlich mit fester und schneller Frequenz läuft. Durch die lange Verzögerung des ADC-Auslesens aber kann das zu sichtbarem flimmern kommen, je nach ADC Konfiguration. Um das ganze noch besser als im Beispiel von mir zu machen: Entweder direkt das PWM Modul des PIC benutzen (wenn er eines hat). Oder einen Timer benutzen und das, was oben do_pwm() ist in die IRQ Routine stecken (plus das IRQ Flag des Timers dort löschen). Somit hast Du dann eine feste PWM Frequenz. Achja, mit dem Code kann man den Augang übrigens nie komplett abschalten, weil ein Zählerwert von 0 nicht kleiner ist als ein ADC Wert von 0. Somit wird der Ausgang immer für einen Tick aktiviert sein. Grüße, Chris
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.