Hallo zusammen. Ich möchte ein Modellauto (Trabant 601) im Maßstab 1:18 beleuchten. Dazu möchte ich bedrahtete SMD LED´s der Baugröße 0805 bzw 0603 verwenden. Die Verschiedenen Leuchtmodi (Blinker links, Blinker rechts, Warnblinker, Standlicht, Abblendlicht, Bremslicht usw.) sollen mittels IR Empgänger / IR Fernbedienung umschaltbar sein. Als Spannungsquelle sollen 3 oder 4 AA Batterien/Akkus dienen. Zu meinen Fragen: Welchen µC würdet ihr empfehlen? Ich habe mir einen PIC18F14K22 ausgesucht, da ich schonmal mit dsPics zu tun hatte. Um das Modell realistischer wirken zu lassen, sollen die Blinker dimmen/faden, da ja der Trabant herkömmliche Leuchtmittel verbaut hatte und keine LED. Das Soll mittels PWM realisiert werden. Da 12 LED´s recht viel sind, würde ich einen LED-Treiber dazunehmen, zumal ich mir unsicher bin ob ich die LED´s direkt an den µC anschließen sollte. Die 20 mA welche die LED´s maximal ziehen sind halt genau die Grenze was der µC pro PIN als Output schalten kann. Als LED-Treiber habe ich mir den TLC 5940 ausgeschaut. Das ganze soll auf einen kleinen Platine (ca. 4x6 cm ) im Modell seinen Platz finden. Habt ihr Tipps zur Hardware welche ihr verwenden würdet? Gerne auch Alternativen zum LED Treiber z.B. durch Multiplexen. --> 12 LEDs einzeln/paarweise Ansteuern (dimmbar/fading) --> Analog in für IR-Empfänger --> Festpannungsregler auf 5 oder halt 3,3 V je nach µC Ich hätte auch nix gegen Atmel, nur ist die Entwicklungsumgebung für Microchip schon da und ich habe damit schon mal gearbeitet. Sowas soll realisiert werden: https://www.youtube.com/watch?v=vivnPwefRlo Danke für eure Tips und ein paar ruhige Feiertage!
@Daniel Bach (daniel_bach) >Welchen µC würdet ihr empfehlen? Da geht fast jeder halbwegs aktuelle Typ. >Ich habe mir einen PIC18F14K22 Klingt OK. >der Trabant herkömmliche Leuchtmittel verbaut hatte und keine LED. Das >Soll mittels PWM realisiert werden. Normal. >Da 12 LED´s recht viel sind, würde ich einen LED-Treiber dazunehmen, Brauchst du nicht, die 20mA/Port können die meisten uCs allein treiben. Außerdem braucht man bei ultrahellen LEDs keine 20mA, da wird man eher blind! Da reichen 2-5mA locker! >Grenze was der µC pro PIN als Output schalten kann. Als LED-Treiber habe >ich mir den TLC 5940 ausgeschaut. Overkill. >Das ganze soll auf einen kleinen Platine (ca. 4x6 cm ) im Modell seinen >Platz finden. Kriegt man hin. >Habt ihr Tipps zur Hardware welche ihr verwenden würdet? Gerne auch >Alternativen zum LED Treiber z.B. durch Multiplexen. Kein Treiber, kein Multiplexen. Einfach Soft-PWM + IRMP. >Microchip schon da und ich habe damit schon mal gearbeitet. Dann bleib dabei.
Daniel B. schrieb: > Da 12 LED´s recht viel sind, würde ich einen LED-Treiber dazunehmen, > zumal ich mir unsicher bin ob ich die LED´s direkt an den µC anschließen > sollte. Die 20 mA welche die LED´s maximal ziehen sind halt genau die > Grenze was der µC pro PIN als Output schalten kann. Als LED-Treiber habe > ich mir den TLC 5940 ausgeschaut. Du brauchst keinen Treiber. Die 20mA sind viel zu viel. Allerdings weder für die Leds noch für den Controller, sondern für deine Augen. Geh mal davon aus, daß maximal 5mA ausreichen. Die roten Leds(Rück-, Bremslicht) könntest du bei Vcc=5V zudem in Reihe schalten. Bei den gelben Blinkern (jeweils links/rechts) sollte das auch noch klappen. Nur die weißen müssen einzeln angesteuert werden.
:
Bearbeitet durch User
Hallo zusammen, da Projekt existiert noch und hat fortschrittte gemacht. Ich habe mich für einen PIC18F45k22 entschieden, als IR-Receiver verwende ich einen TSOP4838. Das Verfahren zum decodieren gibt´s ja im Netz nachzulesen, ich verwende eine Arduino-Fernbedienung welche mit dem NEC Protokoll arbeitet. LED ansteuern funktioniert also schonmal. Nun hänge ich an einer wahrscheinlich banalen Stelle. Das Verfahren zum Decodieren setzt bei erfolgreicher Dekodierung eine Variable auf TRUE welche dann als Bedingung einer Weilschleife dient. Im Hauptprogramm kann ich dann je nach gedrückter Taste verschiedene Ports anschalten usw. Ich möchte jedoch das so realisieren, dass eine Unterfunktion, z.B. Led-Fading solange ausgeführt wird bis ich die Taste erneut drücke. Wenn ich die Codierung mit if abfrage, rollt er einmal durch die Fading-Funktion und das wars. Wenn ich Taste a drücke soll er praktisch solange etwas machen bzw starten bis ich die Taste nochmal drücke. Ich hänge mal meinen Code hier an, vllt ist die Lösung ja so simpel als das ich nicht drauf komme. Hauptprogramm:
1 | void main(void) |
2 | {
|
3 | Pmd_Init(); |
4 | Ports_Init(); |
5 | Config_Init(); |
6 | Timer_Init(); |
7 | Irq_Init(); |
8 | |
9 | __delay_ms(1000); // wait 1 second |
10 | |
11 | while(1) |
12 | {
|
13 | while (!remote_decoder_g_decode_ok); // wait until NEC code receiver |
14 | |
15 | remote_decoder_g_decode_ok = 0; // reset decoding process |
16 | remote_decoder_g_decode_status = 0; |
17 | T1CONbits.TMR1ON = 0; // disable Timer1 |
18 | |
19 | U8_T empfang_code = 0u; |
20 | |
21 | empfang_code = remote_decoder_g_remote_code; |
22 | |
23 | if(empfang_code == 0x3f) |
24 | {
|
25 | Led_Control_Fade_On(); |
26 | Led_Control_Fade_Off(); |
27 | |
28 | empfang_code = 0; |
29 | }
|
30 | |
31 | INTCONbits.RBIE = 1; // enable PORTB change interrupt |
32 | |
33 | }
|
34 | |
35 | }
|
Decodierroutine:
1 | void __interrupt() EXT(void) |
2 | {
|
3 | /*************** start external interrupt ISR ***************/
|
4 | if (INTCONbits.RBIF && (PORTBbits.RB4 || !PORTBbits.RB4)) // PORTB change ISR (& clear mismatch condition) |
5 | {
|
6 | INTCONbits.RBIF = 0; // clear PORTB interrupt flag bit |
7 | if(remote_decoder_g_decode_status != 0) |
8 | {
|
9 | remote_decoder_g_timer_val = (TMR1H << 8) | TMR1L; // store Timer1 value |
10 | TMR1H = TMR1L = 0; // reset Timer1 |
11 | }
|
12 | |
13 | switch(remote_decoder_g_decode_status) |
14 | {
|
15 | case 0 : // start receiving IR data (we're at the beginning of 9ms pulse) |
16 | TMR1H = TMR1L = 0; // reset Timer1 |
17 | T1CONbits.TMR1ON = 1; // enable Timer1 |
18 | remote_decoder_g_decode_status = 1; // next state: end of 9ms pulse (start of 4.5ms space) |
19 | remote_decoder_g_fill_up_bits = 0; |
20 | break; |
21 | |
22 | case 1 : // End of 9ms pulse |
23 | if((remote_decoder_g_timer_val > 19000) || (remote_decoder_g_timer_val < 17000)) |
24 | { // invalid interval ==> stop decoding and reset |
25 | remote_decoder_g_decode_status = 0; // reset decoding process |
26 | T1CONbits.TMR1ON = 0; // disable Timer1 |
27 | }
|
28 | else
|
29 | remote_decoder_g_decode_status = 2; // next state: end of 4.5ms space (start of 562µs pulse) |
30 | break; |
31 | |
32 | case 2 : // End of 4.5ms space |
33 | if((remote_decoder_g_timer_val > 10000) || (remote_decoder_g_timer_val < 8000)) |
34 | { // invalid interval ==> stop decoding and reset |
35 | remote_decoder_g_decode_status = 0; // reset decoding process |
36 | T1CONbits.TMR1ON = 0; // disable Timer1 |
37 | }
|
38 | else
|
39 | remote_decoder_g_decode_status = 3; // next state: end of 562µs pulse (start of 562µs or 1687µs space) |
40 | break; |
41 | |
42 | case 3 : // End of 562µs pulse |
43 | if((remote_decoder_g_timer_val > 1400) || (remote_decoder_g_timer_val < 800)) |
44 | { // invalid interval ==> stop decoding and reset |
45 | T1CONbits.TMR1ON = 0; // disable Timer1 |
46 | remote_decoder_g_decode_status = 0; // reset decoding process |
47 | }
|
48 | else
|
49 | remote_decoder_g_decode_status = 4; // next state: end of 562µs or 1687µs space |
50 | break; |
51 | |
52 | case 4 : |
53 | if((remote_decoder_g_timer_val > 3600) || (remote_decoder_g_timer_val < 800)) |
54 | { // invalid interval ==> stop decoding and reset |
55 | T1CONbits.TMR1ON = 0; // disable Timer1 |
56 | remote_decoder_g_decode_status = 0; // reset decoding process |
57 | }
|
58 | |
59 | else
|
60 | {
|
61 | if( remote_decoder_g_timer_val > 2000) // if space width > 1ms (short space) |
62 | remote_decoder_g_remote_code |= (U32_T)1 << (31 - remote_decoder_g_fill_up_bits); // write 1 to bit (31 - remote_decoder_g_fill_up_bits) |
63 | |
64 | else // if space width < 1ms (long space) |
65 | remote_decoder_g_remote_code &= ~((U32_T)1 << (31 - remote_decoder_g_fill_up_bits)); // write 0 to bit (31 - remote_decoder_g_fill_up_bits) |
66 | remote_decoder_g_fill_up_bits++; |
67 | |
68 | if(remote_decoder_g_fill_up_bits > 31) |
69 | {
|
70 | remote_decoder_g_decode_ok = 1; // decoding process OK |
71 | INTCONbits.RBIE = 0; // disable PORTB change interrupt |
72 | }
|
73 | |
74 | else
|
75 | remote_decoder_g_decode_status = 3; // next state: end of 562µs pulse (start of 562µs or 1687µs space) |
76 | |
77 | break; |
78 | } // end " else " |
79 | |
80 | } // end " switch(remote_decoder_g_decode_status) " |
81 | |
82 | } // end " if (RBIF && (RB0 || !RB0)) " |
83 | /*************** end external interrupt ISR ***************/
|
84 | |
85 | /*************** start Timer1 ISR ***************/
|
86 | if (PIR1bits.TMR1IF) // Timer1 ISR |
87 | {
|
88 | PIR1bits.TMR1IF = 0; // clear Timer1 overflow flag bit |
89 | remote_decoder_g_decode_status = 0; // reset decoding process |
90 | T1CONbits.TMR1ON = 0; // disable Timer1 |
91 | }
|
92 | }/* end function */ |
93 | |
94 | /* EOF */
|
Hallo, eine LED mit pwm zu betreiben funktioniert soweit, und zwar mit Timer Interrupt und dem Timer 0. Der Chip läuft mit 16 MHz, der Timer ist so eingestellt dass alle 30 µs ein Überlauf und somit ein Timer-Interrupt ausgelöst wird. In der ISR wird nun eine Variable hochgezählt(time), und mit einem voreingestellten Wert pwm_val verglichen. Ist der Zählerwert kleiner als der PWM-Wert (time<pwm_val) wird der Pin an dem die LEd angeschlossen isr auf 1 gestellt, ansosnten 0. Somit kann ich mit unterschiedlichen Werten von pwm_val die Helligkeit der LED einstellen. Nun zu meinem Anliegen: wie kann ich damit ein sanftes ein/aus faden machen? Es soll damit einmal ein Blinken mit ein/ausfaden von 4 LEDs verwirklicht werden. Ansatz: Ich würde einen 2. Timer nehmen (ca. alle 50ms ein Interrupt, und da bei jedem Interrupt die Variable pwm_val ändern welche wiederum die Helligkeit der LED beeinflusst. Ich würde gerne das hier auf der Seite gezeigte Verfahren mit Soft-PWM benutzen, leider bekomme ich es einfach nicht hin das für den Atmega32 gedachte Beispiel auf meine PIC18F45K22 umzumünzen. Init:
1 | |
2 | /* Timer 0 */
|
3 | T0CON = 0x88; |
4 | TMR0H = 0xFF; |
5 | TMR0L = 0x88; |
6 | INTCONbits.GIE = 1; |
7 | T0CONbits.TMR0ON = 1; |
PWM Funktion:
1 | U16_T time = 0; |
2 | const U8_T pwm_val = 1; |
3 | /*************************** main function *********************/
|
4 | void main(void) |
5 | {
|
6 | Pmd_Init(); |
7 | Ports_Init(); |
8 | Config_Init(); |
9 | Timer_Init(); |
10 | Irq_Init(); |
11 | |
12 | __delay_ms(1000); // wait 1 second |
13 | |
14 | while(1) |
15 | {
|
16 | if (INTCONbits.T0IF) |
17 | {
|
18 | INTCONbits.T0IF = 0; |
19 | TMR0H = 0xFF; |
20 | TMR0L = 0x88; |
21 | |
22 | time++; |
23 | |
24 | if (time>20) |
25 | {
|
26 | time=0; |
27 | }
|
28 | |
29 | if (time<pwm_val) |
30 | {
|
31 | LATCbits.LATC7 = 1; |
32 | }
|
33 | else
|
34 | {
|
35 | LATCbits.LATC7 = 0; |
36 | }
|
37 | }
|
38 | |
39 | |
40 | }
|
41 | }
|
42 | /*************************** end main function ********************************/
|
Daniel B. schrieb: > Nun zu meinem Anliegen: wie kann ich damit ein sanftes ein/aus faden > machen? Artikel LED-Fading
Danke, das Beispiel habe ich mir natürlich mehrfach durchgelesen vorher, sosnt hätte ich nicht die Frage geschrieben. Das das Beispiel hier für den AVR war, war die Umsetzung mit einem PIC nicht ganz trivial. Das Problem wurde jedoch gelöst und ich habe mittels Timer-Interrupt welcher einen PWM-Multiplexer erstellt. Sanftes an/ausfaden funktioniert. Mein Problem ist nun dass ich den Dekodiervorgang (max. ca. 100ms) der Fernbedienung und die Soft-PWM vereinen muss. Da der Timer Interrupt für das PWM ca. alle 500 µs kommt, müsste ich den Dekodiervorgang der Fernbedienung mit NEC Protokoll so anpassen / aufsplitten dass die neuen Werte für die PWM trotzdem alle 500 µs erstellt werden und nicht ca. 100ms gewartet wird bis der dekodiervorgang abgeschlossen ist. Der Code zum dekodieren steht schon weiter oben (Post vom 23.11.2018). Meine Idee wäre nach jedem Timer Interrupt (evtl. mit einem 2. Timer) am Portpin an dem der IR Empfänger angeschlossen ist zu schauen ob sich der Pegel geändert hat. Hat jemand eine Idee wie man den Dekodiervorgang sinnvoll aufsplitten kann ohne 100ms warten zu müssen?
Daniel schrieb: > Das Problem wurde ... gelöst und ich habe mittels Timer-Interrupt > welcher einen PWM-Multiplexer erstellt. Sanftes an/ausfaden > funktioniert. Schön. Und Soft-PWM nimmst du, weil dein PIC keine Hardware-PWM kann? Also ich hätte ja lieber nach einem µC Ausschau gehalten, der das hat. > Mein Problem ist nun dass ich den Dekodiervorgang (max. ca. 100ms) der > Fernbedienung und die Soft-PWM vereinen muss. Da der Timer Interrupt für > das PWM ca. alle 500 µs kommt, müsste ich den Dekodiervorgang der > Fernbedienung mit NEC Protokoll so anpassen / aufsplitten dass die neuen > Werte für die PWM trotzdem alle 500 µs erstellt werden und nicht ca. > 100ms gewartet wird bis der dekodiervorgang abgeschlossen ist. Aka "verschachtelte Interrupts". Das englische Wort wäre "nested" > Hat jemand eine Idee wie man den Dekodiervorgang sinnvoll aufsplitten > kann ohne 100ms warten zu müssen? Das einzige, was an der IR-Empfangs ISR zeitkritisch ist, ist das Abtasten des Pins, an dem der IR-Empfänger hängt. Der Rest danach darf verzögert werden (aber natürlich nicht länger als bis kurz vor dem nächsten Interrupt). Auf einem AVR wird das I-Flag beim Eintritt in eine ISR gelöscht, was weitere Interrupts blockiert. Hier würde man das so lösen, daß man in der IR-Empfangs ISR direkt nach dem Abtasten des Pins ein sei() unterbringt, was Interrupts (die jetzt die ISR unterbrechen) erlaubt. Beim PIC sollte etwas ähnliches gehen. Ich erinnere mich dunkel, gelesen zu haben, daß es da ohnehin zwei Interrupt-Level gibt. Da würde es dann reichen, das so zu konfigurieren, daß der PWM-Interrupt die IR-Empfangs ISR unterbrechen kann.
Auch ich denke, dass Low-Power-LEDs für dieses Modell gehen, um Treiber zu vermeiden. Meine Empfehlung für den Chip wäre allerdings ein AVR, programmiet in BASCOM, denn einen halben Roman für ein entsprechendes kompliziertes Programm zu schreiben, erachte ich als unnötige Zeitverschwendung VG Micha
Der PIC würde bewusst gewählt, da ich damit schon mal zu tun hatte und mir so die Entwicklungsumgebung und Einstellungen bekannt waren. Weiterhin habe ich schon einen Prgrammer für den PIC hier liegen. Warum keine Hardware PWM? Weil es keinen Mikrocontroller mit 13 unabhängigen PWM-Kanälen gibt und man durch Soft PWM flexibler ist. Für mich wäre es Zeit (und Geld) Verschwendung wenn ich mir erst einen neuen Chip kaufen muss inkl. Programmer und ihn in einer mir unbekannten Sprache programmieren muss (BASCOM) wahrscheinlich ist meine Frage im Microchip Forum besser aufgehoben.
Bevor du dich mit PWM quälst, sei es nun HW oder SW PWM, nehme doch einfach WS2812 LEDs. Die kannst du schön von Ort zu Ort durchverbinden und hast die gewünschte Farbe und Helligkeit. Sicher, Du brauchst nicht an jedem Ort alle Farben, aber das ist bei dem Preis egal. Am Ende einfach ein Arduino Nano, da gibt es fertige LIBSs und die Anwendung ist in einem Tag komplett fertig, auch für weniger Geübte. Die WS2812 gibt es als Strip (schneiden und mit Litze verlängern), auf Einzelplatine, als SMD und auch bedrahtet. Verdrahtung ist gegenüber klassischen LEDs vermutlich eleganter. Noch besser finde ich persönlich APA102 LEDs, die haben ein fast klassisches SPI Interface und sind absolut zeitunkritisch in der Ansteuerung. Ist dann ein Draht mehr von LED zu LED.
:
Bearbeitet durch User
Die APA102 gibt es auch superklein im 2020 Gehäuse, falls es mal irgendwo eng wird.
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.