Forum: Mikrocontroller und Digitale Elektronik 3 Kanal 16 bit PWM mit Tiny2313 (Bascom)


von Arne G. (kywalda)


Angehängte Dateien:

Lesenswert?

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

von Achim M. (minifloat)


Lesenswert?

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

von Arne G. (kywalda)


Lesenswert?

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...

von Arne G. (kywalda)


Angehängte Dateien:

Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.