Hi @ all
ich versuche seit mehreren Wochen ein ganz einfaches Programm zu
scheiben welches eine LED langsam an und wieder aus faded. Da ich aber
ein absoluter Newbie in der Welt der uC bin und ich im Internet zumeist
nur auf unvollständige Forenbeiträge stoße, klappt bis dato nahezu
garnichts.
Geplant war ein Programm in C zu schreiben welches auf einen PIC12F683
läuft und mittels PWM die LED dimmt. Als Compiler würde ich gerne den
CC5X (kostenlos) benutzen.
Ein vernünftiges Beispiel habe ich jedoch nur für einen ATMEL gefunden.
Da ich mir jedoch schon mehrere PICs + Programmiergerät angeschafft habe
würde ich dieses Programm gerne für den PIC12F683 umschreiben.
Daher die Frage: Kann mir jemand diesen Code für den PIC umschreiben?
http://www.mikrocontroller.net/articles/LED-Fading
Ich würde mich auch erkenntlich (€) zeigen.
Vielen Dank schonmal im Voraus.
Servus,
das ist durchaus machbar. Könntest du etwas mehr die Parameter des
Möglichen defninieren. (Umgebung, Taktquelle, etc.)
Für Software PWM braucht man eine möglichst schnelle Taktquelle.
Welche Gründe habe dich diesen PIC auswählen lassen? Hat nur ein PWM
Modul - den Rest muss man per Software generieren.
Erzähl mal ein bisschen mehr - dann lässt sich da schon was machen ...
Der 12F683 hat ein PWM-Modul eingebaut. Damit ist LED-Fading absolut
easy, Du brauchst die Register PR2, CCPR1L und CCP1CON sowie den Timer2
mit dem Register T2CON. Nachfolgend ein Snippet aus einem
Assembler-Programm, darin ist alles aufgeführt, Du musst nur die
Register belegen und ab geht die Post, in C geht das sogar noch
einfacher.
Mehr über PWM bei PICs erfährts Du bei
http://sprut.de/electronic/pic/grund/pwm.htm
1
; Timer 2 für PWM einstellen
2
3
bank0
4
clrf T2CON
5
; bsf T2CON, T2CKPS1 ; Vorteiler 16:1
6
; bsf T2CON, T2CKPS0
7
bsf T2CON, TMR2ON ; Timer2 ein
8
9
; Frequenz + duty cycle
10
11
bank1
12
movlw d'128' ; xxx kHz
13
movwf PR2
14
15
bank0
16
movlw d'64' ; duty cycle: 50% von xxx sind yyy
17
movwf CCPR1L
18
19
movlw b'00001100' ; Start, PWM active high
20
movwf CCP1CON
21
22
bank0
bank0 und bank1 sind Makros, welche die Speicherbank einstellen.
Also dann mal von vorne:
@Michael, @all
Ich möchte über diesen PIC mehrere LEDs ansteuern. Diese sollen dabei
gleichzeitig ein und aus faden, sodass ein PIN des Controlles genügt
(dieser schällt einen Transistor / kein Software-PWM nötig). Der PIC hat
dabei nur diese eine Aufgabe. Auf die Rechenlast muss daher nicht
geachtet werden. Da ich diese Schaltung mehrfach bauen möchte, würde ich
die Anzahl an Bauteilen gerne möglichst gering halten --> Interner Takt.
Den PICF683 hatte ich nur deshalb gewählt weil er der kleinste und auch
günstigste PIC mit einem CCP-Modul ist.
@Stephan, @Claus
In dem Beispiel wird ein 'logarithmisches' PWM erzeugt woruch der
Dimmeffekt für die menschliche Wahrnehmung besser zur Geltung kommt.
Dies würde ich wenn möglich auch so realisieren.
> In dem Beispiel wird ein 'logarithmisches' PWM erzeugt woruch der> Dimmeffekt für die menschliche Wahrnehmung besser zur Geltung kommt.> Dies würde ich wenn möglich auch so realisieren.
In meinem Beispiel steht die Zahl 64 für einen 50% duty cycle von 128
(für 25% wären es 32 usw); das habe ich einfach aus einem Programm von
mir kopiert, um Dir zu zeigen, wie die PWM programmiert wird.
Du kannst ja das PR2-Register mit 255 setzen und das CCPR1L-Register mit
einer exponetiell abgestuften Zahl von 0 bis 255 setzen, die Du einer
voher berechneten Tabelle entnimmst. Das musst Du schon selber machen.
Was hast du in den mehreren Wochen denn bisher bereits geschafft? Kannst
bereits mit MPLAB umgehen und den PIC12F683 programmieren und z.B. die
LED zumindest direkt an- und ausschalten? Ab da kann man dir dann
weiterhelfen.
Hallo Frank,
ja Ausgänge ein und wieder ausschalten kann ich schon. Was ich bisher
geschafft habe:
MPLAB + C Colpiler (CC5X) installiert
PIC-Brenner installiert, erste Testprogramme in PIC geladen -->
funktioniert!
Schaltung entworfen
Jetzt scheitert es nur noch an dem Programm (s. ersten Post)
Ich habe den Artikel über die PWM-Tastverhältnisberechnung nicht ganz
verstanden. Die Werte der Excel-Tabelle stimmen nicht mit den Werten des
Beispielprogramms überein. Scheint vielmehr so, daß das Beispielprogramm
einfach eine Potenzreihe mit Basis 2 hat, wobei es ein wenig manuell
angepasst wurde, daß der erste Wert 0 ist und der letzte Wert 65535 (für
das lange Beispiel).
Bei der angegebenen Formel verstehe ich nicht, was ich für rx und ry
einsetzen muß. Vielleicht kann mir das aber einer erklären.
Ich habe mal die Excel-Formel in ein kleines Java-Programm übersetzt:
Das kann man per javac compilieren und per java ausführen (JRE vorher
installieren und Pfad setzen, oder Eclipse o.ä. installieren). Die
Ausgabe sieht so aus:
1
steps: 122.0
2
max: 1023.0
3
start: 20.0
4
base: 1.0330532092859641
5
20, 21, 21, 22, 23, 24, 24, 25,
6
26, 27, 28, 29, 30, 31, 32, 33,
7
34, 35, 36, 37, 38, 40, 41, 42,
8
44, 45, 47, 48, 50, 51, 53, 55,
9
57, 58, 60, 62, 64, 67, 69, 71,
10
73, 76, 78, 81, 84, 86, 89, 92,
11
95, 98, 102, 105, 108, 112, 116, 120,
12
124, 128, 132, 136, 141, 145, 150, 155,
13
160, 166, 171, 177, 183, 189, 195, 201,
14
208, 215, 222, 229, 237, 245, 253, 261,
15
270, 279, 288, 297, 307, 317, 328, 339,
16
350, 361, 373, 386, 398, 412, 425, 439,
17
454, 469, 484, 500, 517, 534, 551, 570,
18
589, 608, 628, 649, 670, 692, 715, 739,
19
763, 789, 815, 842, 869, 898, 928, 959,
20
990, 1023,
und kann man direkt als C-Array verwenden.
Ich habe den PIC12F683 nicht, daher konnte ich es nur per MPLAB Logic
Analyzer testen, aber sollte eigentlich funktionieren:
// ist normalerweise in stdint.h enthalten, was der Hi-Tech Compiler aber nicht kennt
19
typedefsignedcharint8_t;
20
typedefunsignedcharuint8_t;
21
typedefsignedintint16_t;
22
typedefunsignedintuint16_t;
23
typedefsignedshortlongint24_t;// Microchip specific
24
typedefunsignedshortlonguint24_t;// Microchip specific
25
typedefsignedlongint32_t;
26
typedefunsignedlonguint32_t;
27
28
// PWM-Werte
29
staticconstuint16_tg_pwm[]=
30
{
31
20,21,21,22,23,24,24,25,
32
26,27,28,29,30,31,32,33,
33
34,35,36,37,38,40,41,42,
34
44,45,47,48,50,51,53,55,
35
57,58,60,62,64,67,69,71,
36
73,76,78,81,84,86,89,92,
37
95,98,102,105,108,112,116,120,
38
124,128,132,136,141,145,150,155,
39
160,166,171,177,183,189,195,201,
40
208,215,222,229,237,245,253,261,
41
270,279,288,297,307,317,328,339,
42
350,361,373,386,398,412,425,439,
43
454,469,484,500,517,534,551,570,
44
589,608,628,649,670,692,715,739,
45
763,789,815,842,869,898,928,959,
46
990,1023
47
};
48
49
// main Funktion
50
voidmain(void)
51
{
52
// Ports initialisieren: alles auf Ausgang
53
GPIO=0;
54
TRISIO=0;
55
56
// Oszillator auf 8 MHz einstellen
57
OSCCON=(1<<6)|(1<<5)|(1<<4)|1;
58
59
// Timer0 Counter zurücksetzen
60
TMR0=0;
61
62
// keine Pullups, Fosc/4 als Taktquelle für Timer0, 1:32 Prescaler:
63
// ergibt bei 8 MHz also Fosc/4/32/256 = 244 Hz
64
OPTION=(1<<7)|(1<<2);
65
66
// Period Register von Timer2 auf Maximum
67
PR2=255;
68
69
// Timer2 on, Prescaler 1
70
// zusammen mit PR2 ergibt das eine Frequenz von 8 MHz/4/(PR2+1)=4 MHz / 256 = 7812.5 Hz
71
T2CON=1<<2;
72
73
// keine Interrupts für Timer2
74
PIE1=0;
75
76
// PWM-Mode für das CCP-Modul aktivieren
77
CCP1CON=15;
78
79
// global interrupt enable, Timer0 overflow enable und Interrupt Flag löschen
80
INTCON=(1<<7)|(1<<5);
81
82
// der Rest läuft im Interrupt ab
83
while(1){
84
}
85
}
86
87
// Interruptroutine
88
voidinterrupttimerInterrupt(void)
89
{
90
// LED mit ca. 1 Hz blinken lassen
91
staticuint8_tcounter=0;
92
staticuint8_tvalue=0;
93
if(counter++==122){
94
GPIO=value;
95
value=255-value;
96
counter=0;
97
}
98
99
// Tastverhältnis vom PWM-Ausgang aktualisieren
100
staticuint8_tpwmIndex=0;
101
staticuint8_tdirection=0;
102
uint16_tpwm=g_pwm[pwmIndex];
103
CCPR1L=(pwm>>2)&0xff;
104
CCP1CON=15|((pwm&3)<<4);
105
106
// PWM-Index aktualisieren: zählt einmal rauf und dann wieder runter
107
if(direction){
108
if(pwmIndex==sizeof(g_pwm)/sizeof(uint16_t)-1){
109
direction=0;
110
}else{
111
pwmIndex++;
112
}
113
}else{
114
if(pwmIndex==0){
115
direction=1;
116
}else{
117
pwmIndex--;
118
}
119
}
120
121
// Interruptflag zurücksetzen
122
T0IF=0;
123
}
Vom Konzept her läuft die ganze Steuerung im Interrupt ab, damit man,
unabhängig von Programmlaufzeiten für unterschiedliche Code-Pfade, immer
ein regelmäßiges Update der PWM-Werte hinbekommt. Auf Pin 5 (GP2) sollte
das PWM-Signal anliegen. Eine LED da dran sollte mit 1 Hz sanft an und
wieder ausgehen. Alle anderen Pins sollten hart mit 1 Hz blinken.
Resourcenverbrauch:
1
Memory Summary:
2
Program space used 1B9h ( 441) of 800h words ( 21.5%)
3
Data space used 11h ( 17) of 80h bytes ( 13.3%)
4
EEPROM space used 0h ( 0) of 100h bytes ( 0.0%)
5
Configuration bits used 1h ( 1) of 1h word (100.0%)
6
ID Location space used 0h ( 0) of 4h bytes ( 0.0%)
Anbei das ganze Projekt. Ich habe auch den CC5X Compiler nicht, das ist
mit dem Hi-Tech Compiler erstellt, der in der Lite-Version (keine
Code-Optimierung) ebenfalls frei ist. Hoffe es hilft dir weiter, kannst
du wahrscheinlich leicht für den CC5X Compiler anpassen, falls du den
verwenden willst. Das HEX-File, mit Configuration-Bits, ist aber auch im
ZIP-Archiv. Das kannst du importieren und brennen, sollte dann
eigentlich direkt laufen.
Geld möchte ich keins, aber wenn du noch einen PIC12F683 zum Spielen für
mich übrig hättest, würde ich mich freuen :-)
Hi Frank,
super vielen Dank für deine spitzen Hilfe. Hab's natürlich schon
ausprobiert und es funktioniert! Allerdings in das Fading nicht wirklich
so schöne wie gedacht. Wirkt immer noch ein wenig holprig. Aber auf
jeden Fall kann man damit arbeiten (und lernen).
Eine Frage hab ich aber trotzdem noch: Was sind das denn für
Headerdateien? "HTC.h, stdio.h, limits.h"
Werde mich gleich noch per PM bei dir melden.
Niko schrieb:> Eine Frage hab ich aber trotzdem noch: Was sind das denn für> Headerdateien? "HTC.h, stdio.h, limits.h"
HTC.h hat was mit dem untergeordneten pic.h und anderen
prozessor-spezifischen Einbindungen zu tun. Manche Makros funktionieren
nicht, etc...
Daher weiß der Comiler was/wo z.B. sämtliche Register zu finden sind
(LATA, ...)
stdio.h ist allgemein aus ANSI C bekannt und regelt
Standart-Ein-und-Ausgabe-bezogene Dinge
limits.h hat was mit Datentypen (int, double, etc...) zu schaffen. Es
definiert spez. Charakteristika der entsprechenden Datentypen, etc.
Genaueres kann man ergooogln ...
limits.h braucht man für den Sourcecode aktuell nicht. Hatte ich aus
einem anderen Projekt kopiert und dort dann noch dieses Makro vor den
typedefs geschrieben:
1
#if LONG_MAX < 0x7fffffff
2
#error "this program needs long with 4 bytes"
3
#endif
Dadurch konnte ich dann sicherstellen, daß "typedef signed long
int32_t;" tatsächlich einen 32-Bit typen definiert, was man ja manchmal
in den Compiler-Settings umstellen kann und was dann zu Überaschungen
führen kann. Wenn das falsch eingestellt ist, dann gibt das durch dieses
Makro zur Compilierzeit einen Compilerfehler. Aber für den Code könnte
man einige der Typedefs sowieso löschen und stdio.h ist auch vom
copy-and-paste des größeren Projekts übriggeblieben.
Danke für den PIC, ist heute angekommen. Habe ihn eben programmiert und
sieht so aus:
http://www.youtube.com/watch?v=ii2mPdSiErs
Das Fading ist perfekt, zumindest vom Scope her ist es genauso, wie
gedacht, aber du hast schon recht, sieht dennoch nicht allzu sanft aus.
Ich denke das liegt daran, wenn es für das Auge linear bis zur maximalen
Helligkeit einblendet und dann sofort wieder linear ausblendet usw., es
quasi ein Dreieck ist.
Eine Idee wäre, die Tabellengenerierung so zu ändern, daß statt des
linearen Zählers erst ein Sinus generiert wird, der dann nochmals
logarithmisch umgesetzt wird, sodaß daß Auge also den Sinus wahrnimmt.
Dabei könnte man sich noch überlegen, ob man einen "springenden" Effekt
haben will, also nur eine Halbwelle nimmt (bzw. eine viertel Welle, da
man ja nur die Einblendung speichern braucht), sodaß es also relativ
schnell hell wird, dann sanft bis zum Maximum einblendet, dort etwas
bleibt und schnell wieder dunkel wird. Danach vielleicht noch etwas
Auszeit und dann wieder von Anfang los. Oder auch sanft beim
Dunkelwerden abbremsen.
Hallo,
hast die den PWM Source Code für den PIC 12f683 für den CC5X Compiler ?
Im internet findet mall allerlei C-Beispiele an PWM aber sogur wie
nichts für den PIC und den CC5X ..
Grüße Ralf
Hallo Niko,
hast du den PWM Code vom Frank auf den CC5X für den PIC12f683 umgestellt
? Ich hätte gerne den C Code um einen eine LED-Beleuchtung mit einer
digitalen Poti-Lösung auf PWM mit dem 12f683 umzustellen ...
Grüße Ralf