Liebes Forum,
ich versuche für die Ansteuerung von RGB-LEDs einen Tiny dazu zu
bewegen, mir 3 16bit PWMs bereitzustellen. Mit den beiden PWMs vom
Timer1 ist das kein Problem.
Den dritten wollte ich aus dem Timer0 basteln. Dazu wird der im
Fast-PWM-Modus gestartet und ruft sich in einer Interrupt-Routine immer
wieder selbst auf, bis der 16bit-Wert erreicht ist und schaltet sich
dann ab, bis der Timer1 eine neue Runde einlaeutet.
Das funktioniert auch einigermaßen. Leider gibt es immer wieder
"Ruckler" im Fading. Ich kann die Ursache nicht finden. Vielleicht hat
ja jemand eine Idee dazu, oder sowas schon mal selbst gemacht....
lg,
arne
Hier der Code:
1 | '3 Kanal 16bit PWM
| 2 | '
| 3 | 'Laesst drei LEDs an OC0A, OC1A und OC1B mit 16 bit ein- und ausfaden
| 4 | 'Der dritte 16-bit Kanal wird durch mehrfaches Aneinanderhaengen
| 5 | 'von Timer0 (8bit) nachgebildet
| 6 | '
| 7 | 'Arne Groh
| 8 | '2011-06-20
| 9 | '
| 10 | 'Fusebits
| 11 | '1111 1111
| 12 | '1111 1111
| 13 | '1101 1111
| 14 | '1110 0100
| 15 |
| 16 | $regfile = "attiny2313.dat"
| 17 | $crystal = 8e6
| 18 |
| 19 |
| 20 | Dim I As Byte
| 21 | Dim J As Integer
| 22 | Dim Ocr_0a As Word
| 23 | Dim Ocr0ah As Byte
| 24 | Dim Ocr0al As Byte
| 25 | Dim Ocr1a As Word
| 26 | Dim Ocr1b As Word
| 27 | Dim Flags As Byte
| 28 | Lastrun Alias Flags.0
| 29 |
| 30 |
| 31 | '------------ Timer konfigurieren --------
| 32 | '-- Timer1 --
| 33 | 'Fast PWM-Mode 14 einstellen (TOP in ICR1)
| 34 | Set Tccr1a.wgm11
| 35 | Set Tccr1b.wgm12
| 36 | Set Tccr1b.wgm13
| 37 |
| 38 | 'Ausgaenge bei Compare Match low schalten
| 39 | Set Tccr1a.com1a1
| 40 | Set Tccr1a.com1b1
| 41 |
| 42 | 'Overflow-Interrupt einschalten
| 43 | Set Timsk.toie1
| 44 |
| 45 | 'niedrigste Frequenz einstellen (damit man das PWM voll ausreizen kann)
| 46 | Icr1h = &HFF : Icr1l = &HFF
| 47 |
| 48 | '-- Timer0 --
| 49 | 'Fast PWM-Mode 3 einstellen
| 50 | Set Tccr0a.wgm00
| 51 | Set Tccr0a.wgm01
| 52 |
| 53 | 'Ausgang bei Compare-Match low schalten
| 54 | Set Tccr0a.com0a1
| 55 |
| 56 | 'Compare-Match-Interrupt einscalten
| 57 | Set Timsk.ocie0a
| 58 |
| 59 | 'OC0A OC1A und OC1B als Output (PB2 PB3 PB4)
| 60 | Set Ddrb.2
| 61 | Set Ddrb.3
| 62 | Set Ddrb.4
| 63 |
| 64 | 'Globale Interrupts einschalten
| 65 | Set Sreg.7
| 66 |
| 67 | 'Timer1 einschalten (kein Prescale)
| 68 | Set Tccr1b.cs10
| 69 | 'Timer0 einschalten (kein Prescale)
| 70 | Set Tccr0b.cs00
| 71 |
| 72 | '--------------------------------------
| 73 |
| 74 | On Ovf1 T1ovf
| 75 | On Oc0a T0cm
| 76 |
| 77 |
| 78 | Do
| 79 |
| 80 | 'Einatmen
| 81 | For I = 0 To 255 Step 1
| 82 | J = I - 255
| 83 | J = J * -1
| 84 | Ocr1a = Lookup(j , Fade256)
| 85 | Ocr1b = Lookup(i , Fade256)
| 86 | Ocr_0a = Ocr1a
| 87 | 'Tastverhaeltniss einstellen
| 88 | Ocr1ah = High(ocr1a) : Ocr1al = Ocr1a
| 89 | Ocr1bh = High(ocr1b) : Ocr1bl = Ocr1b
| 90 | Waitms 7
| 91 | Next I
| 92 |
| 93 | 'Verharren
| 94 | Waitms 150
| 95 |
| 96 | 'Ausatmen
| 97 | For I = 255 To 0 Step -1
| 98 | J = I - 255
| 99 | J = J * -1
| 100 | Ocr1a = Lookup(j , Fade256)
| 101 | Ocr1b = Lookup(i , Fade256)
| 102 | Ocr_0a = Ocr1a
| 103 | 'Tastverhaeltniss einstellen
| 104 | Ocr1ah = High(ocr1a) : Ocr1al = Ocr1a
| 105 | Ocr1bh = High(ocr1b) : Ocr1bl = Ocr1b
| 106 | Waitms 14
| 107 | Next I
| 108 |
| 109 | 'Verharren
| 110 | Waitms 400
| 111 |
| 112 | Loop
| 113 |
| 114 |
| 115 | '--------------------PWM DATA----------------------------
| 116 |
| 117 | Fade256:
| 118 | Data 0% , 1% , 1% , 1% , 1% , 1% , 1% , 1% , 1% , 1% , 2% , 2% , 2% , 2% , 2% , 2%
| 119 | Data 2% , 2% , 2% , 2% , 2% , 2% , 3% , 3% , 3% , 3% , 3% , 3% , 3% , 4% , 4% , 4%
| 120 | Data 4% , 4% , 4% , 5% , 5% , 5% , 5% , 5% , 6% , 6% , 6% , 6% , 7% , 7% , 7% , 8%
| 121 | Data 8% , 8% , 9% , 9% , 10% , 10% , 10% , 11% , 11% , 12% , 12% , 13% , 14% , 14% , 15% , 15%
| 122 | Data 16% , 17% , 18% , 18% , 19% , 20% , 21% , 22% , 23% , 24% , 25% , 26% , 27% , 28% , 30% , 31%
| 123 | Data 32% , 34% , 35% , 37% , 39% , 40% , 42% , 44% , 46% , 48% , 50% , 52% , 55% , 57% , 60% , 62%
| 124 | Data 65% , 68% , 71% , 74% , 77% , 81% , 84% , 88% , 92% , 96% , 100% , 105% , 110% , 115% , 120% , 125%
| 125 | Data 130% , 136% , 142% , 149% , 155% , 162% , 169% , 177% , 185% , 193% , 202% , 210% , 220% , 230% , 240% , 250%
| 126 | Data 262% , 273% , 285% , 298% , 311% , 325% , 340% , 355% , 371% , 387% , 404% , 422% , 441% , 461% , 481% , 502%
| 127 | Data 525% , 548% , 572% , 598% , 624% , 652% , 681% , 711% , 743% , 776% , 811% , 847% , 884% , 924% , 965% , 1007%
| 128 | Data 1052% , 1099% , 1148% , 1199% , 1252% , 1308% , 1366% , 1427% , 1490% , 1556% , 1625% , 1698% , 1773% , 1852% , 1934% , 2020%
| 129 | Data 2110% , 2204% , 2302% , 2404% , 2511% , 2623% , 2739% , 2861% , 2988% , 3121% , 3260% , 3405% , 3556% , 3714% , 3879% , 4052%
| 130 | Data 4232% , 4420% , 4616% , 4822% , 5036% , 5260% , 5494% , 5738% , 5993% , 6259% , 6537% , 6828% , 7132% , 7449% , 7780% , 8125%
| 131 | Data 8487% , 8864% , 9258% , 9669% , 10099% , 10548% , 11017% , 11507% , 12018% , 12552% , 13110% , 13693% , 14302% , 14938% , 15602% , 16295%
| 132 | Data 17020% , 17776% , 18566% , 19392% , 20253% , 21154% , 22094% , 23076% , 24102% , 25173% , 26292% , 27461% , 28682% , 29957% , 31288% , 32679%
| 133 | Data 34132% , 35649% , 37234% , 38889% , 40617% , 42423% , 44308% , 46278% , 48335% , 50484% , 52728% , 55072% , 57520% , 60076% , 62747% , 65535%
| 134 |
| 135 |
| 136 | '------------ Interrupt-Routinen -----------------------
| 137 |
| 138 | T1ovf:
| 139 | Reset Lastrun
| 140 | Ocr0ah = High(ocr_0a) : Ocr0al = Ocr_0a
| 141 | Set Tccr0a.wgm01
| 142 | Set Ddrb.2
| 143 |
| 144 | Return
| 145 |
| 146 | T0cm:
| 147 | Ocr0a = 0
| 148 | 'wenn die letzte Runde gelaufen ist, Timer0 aus, bis Timer1 neu startet
| 149 | If Lastrun = 1 Then
| 150 | Reset Tccr0a.wgm01
| 151 | Goto Raus
| 152 | End If
| 153 |
| 154 | 'solange Timer0 auf High, bis Highbytes alle sind
| 155 | If Ocr0ah > 0 Then
| 156 | Ocr0a = &HFF
| 157 | Decr Ocr0ah
| 158 |
| 159 | 'dann noch den Lowbyte-Rest High und danach Low durch Abschalten
| 160 | Else
| 161 | Ocr0a = Ocr0al
| 162 | Set Lastrun
| 163 | End If
| 164 |
| 165 | Raus:
| 166 | Return
|
Arne Groh schrieb:
> 'Verharren
> Waitms 150
Das siehst du. Alles über 100ms Reaktions- oder Verzögerungszeit kann
der normale Mensch bewusst mit dem Auge erkennen. Schonmal mit dem
'Scope angesehen, was deine Ausgänge machen?
mfg mf
Das soll man ja auch sehen - an den beiden Timer1-Fadings tritt das
Problem ja nicht auf. Nur an dem "frisierten" Timer0.
Ja - das Scope zeigt die Ruckler auf dem dritten Kanal auch...
Ich habe nochmal die Interrupt-Routinen geändert:
jetzt wird der Low-Anteil als erstes verarbeitet. Danach dann der Timer
für High-Anteil Male wiederholt.
Das Ergebniss ist jetzt deutlich "weicher". Allerdings gibt es beim
Übergang von High 1 auf 0 immer noch Sprünge. Ausserdem scheint der
TCNT0 ab und an irgendwie überzulaufen. Jedenfalls gibt es beim
runterzählen Werte, an der die LED wieder heller zu werden scheint.
Hat noch jemand eine Idee dazu?
1 | T1ovf:
| 2 | Ocr0count = 0
| 3 | 'Beim Neustart des Timer1 zunaechst den Low-Teil des 16bit Wertes durch Timer0 ausgeben
| 4 | Ocr0a = Ocr0al
| 5 | 'Datenrichtungsbit vom OC0A auf Output schalten
| 6 | Set Ddrb.2
| 7 | 'Timer0 zurueck an den Start
| 8 | Set Tifr.tov0
| 9 |
| 10 | Return
| 11 |
| 12 |
| 13 | T0cm:
| 14 | 'Incr Ocr0count
| 15 | 'Wenn Anzahl der Durchlaeufe erreicht, dann Datenrichtungsbit aendern (Pin auf Input)
| 16 | 'Bleibt bis zum naechsten Start von Timer1 auf Input
| 17 | If Ocr0ah > Ocr0count Then
| 18 | Incr Ocr0count
| 19 | Ocr0a = 255
| 20 | Goto Raus
| 21 | End If
| 22 | Reset Ddrb.2
| 23 | Raus:
| 24 | Return
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|