Hallo, ich bin zur Zeit dabei 3 Güterwagen meiner Modellbahn umzubauen. Die originale Platine der Herstellers leucht einfach nur wenn der Wagen auf den Gleisen steht und das ist mir einfach zu fade. Deswegen dachte ich mir, einen Fadereffekt einzusetzen. Das ganze habe ich bereits mit einem LM324D und einem TL494BD gemacht mit mäßigem Erfolg. Das Poti für die Helligkeit beeinflusst die Geschwindigkeit der PWM und dazu leuchten die Platinen unterschieldich schnell und hell. Zudem würde ich gerne ein paar Bauteile einsparen. Mit Mikrocontroller habe ich keinerlei Erfahrung aber ich habe hier ein Tutorial dafür gefunden https://www.mikrocontroller.net/forum/mikrocontroller-elektronik Die Schaltung sieht vorläufig mal so aus. Ich muss nur noch rausfinden wo ich den Sockel für die ISP Programmierung anschließe. Funktioniert die Schaltung so wie ich es mir gedacht habe bzw. auch verstanden? Kann ich das Programm aus dem Tutorial einfach so übernehmen? Zum programmieren habe ich ein Arduino Uno Board.
D1 ist überflüssig, an jeden Vcc gehört ein 100nF gegen GND Der IPS-Connector gehort an die Pins 1-4+Vcc+GND R1 ist etwas klein, 10k sind üblich Ob Du die LEDs so ansteuern kannst, kommt auf die Typen und elektrischen Daten an. Die Aufgabe könnte auch ein Tiny45 machen, mit einem Viertel des Platzen.
Das alte Mega32 Schlachtschiff ist genau das, welches für deine Zwecke am wenigsten geeignet ist, es ist gross und hat zuwenig PWM Ausgänge. Spar dir den für andere Basteleien. Ein z.B. Mega48/88/168/328 hat schon mal 6 fertige PWM Kanäle. Der Tiny461/861 hat 6 Kanäle (davon 2 nur als Software) und ein recht kleines Gehäuse, was dem Einbau zugute kommt.
So, ich habe mich jetzt für den ATMega88-20AU entschieden. Das Layout ist hoffentlich auch soweit richtig. Das Programm habe ich noch soweit angepasst und hoffe das es so passt...!? //********************************************************************** **** //* //* LED fading test //* uses exponential PWM settings to achive visual linear brightness //* //* ATmega88 @ 8 MHz //* //********************************************************************** **** #include <avr/io.h> #include <avr/pgmspace.h> #define F_CPU 8000000L #include <util/delay.h> #define STK500 0 #if STK500 // inverted PWM on OC1A for STK500 #define INVERT_PWM (1 << COM1A0) #else // non-inverted PWM on OC1A #define INVERT_PWM 0 #endif // STK500 const uint16_t pwmtable_16[256] PROGMEM = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 35, 36, 38, 40, 41, 43, 45, 47, 49, 52, 54, 56, 59, 61, 64, 67, 70, 73, 76, 79, 83, 87, 91, 95, 99, 103, 108, 112, 117, 123, 128, 134, 140, 146, 152, 159, 166, 173, 181, 189, 197, 206, 215, 225, 235, 245, 256, 267, 279, 292, 304, 318, 332, 347, 362, 378, 395, 412, 431, 450, 470, 490, 512, 535, 558, 583, 609, 636, 664, 693, 724, 756, 790, 825, 861, 899, 939, 981, 1024, 1069, 1117, 1166, 1218, 1272, 1328, 1387, 1448, 1512, 1579, 1649, 1722, 1798, 1878, 1961, 2048, 2139, 2233, 2332, 2435, 2543, 2656, 2773, 2896, 3025, 3158, 3298, 3444, 3597, 3756, 3922, 4096, 4277, 4467, 4664, 4871, 5087, 5312, 5547, 5793, 6049, 6317, 6596, 6889, 7194, 7512, 7845, 8192, 8555, 8933, 9329, 9742, 10173, 10624, 11094, 11585, 12098, 12634, 13193, 13777, 14387, 15024, 15689, 16384, 17109, 17867, 18658, 19484, 20346, 21247, 22188, 23170, 24196, 25267, 26386, 27554, 28774, 30048, 31378, 32768, 34218, 35733, 37315, 38967, 40693, 42494, 44376, 46340, 48392, 50534, 52772, 55108, 57548, 60096, 62757, 65535 }; /* Diese Tabellen sind nicht nach der Theorie (s. oben) berechnet, sondern wie folgt: a = Anzahl an Schritte (4, 8, 16, 32, 64, 256) b = Auflösung des PWM's (256, 1024, 65536) y = Errechneter Wert an einer stelle x y = 0 wenn x = 0 y = pow(2, log2(b-1) * (x+1) / a) wenn x > 0 Gerne wird auch diese alternative Formel genutzt: y = pow(2, log2(b) * (x+1) / a) - 1 Obige Funktionen wurden in den LibreOffice Calc Sheet eingearbeitet. */ // long, variable delays void my_delay (uint16_t milliseconds) { for (; milliseconds > 0; milliseconds--) _delay_ms (1); } void pwm_up_down (const uint16_t pwm_table[], int16_t size, uint16_t delay) { int16_t tmp; for (tmp = 0; tmp < size; tmp++) { OCR1A = pgm_read_word (& pwm_table[tmp]); my_delay (delay); } for (tmp = size-1; tmp >= 0; tmp--) { OCR1A = pgm_read_word (& pwm_table[tmp]); my_delay (delay); } } // 16-Bit PWM with 256 different settings void pwm_16_256 (uint16_t delay) { // 16 Bit Fast PWM TCCR1A = 0x82 | INVERT_PWM; // stop timer TCCR1B = 0; // TOP for PWM, full 16 Bit ICR1 = 0xFFFF; // prescaler 1 -> ~122 Hz PWM frequency TCCR1B = (1 << WGM12) | (1 << WGM13) | 1; pwm_up_down (pwmtable_16, 256, delay); } int main (void) { int8_t i; // delay in milliseconds for one fading step int16_t step_time = 400; // LED uses OC1A DDRD &= ~(1 << PD0); DDRD &= ~(1 << PD1); DDRD &= ~(1 << PD2); DDRD &= ~(1 << PD3); DDRD &= ~(1 << PD4); // test all fading routines while (1) { for (i=0; i<3; i++) pwm_16_256 (step_time/16); my_delay (1000); } return 0; }
>Das Programm habe ich noch soweit angepasst und hoffe das es so >passt...!? Was soll das Fragezeichen? Probier es aus. Zwei LEDs in Reihe wird bei Rot und Grün evtl. funktionieren, bei Blau und Weiss sicher nicht. Und ist das eigentlich so schwer sich das Bils was man posten möcht mal selber anzuschauen? Da ist kaum was zu erkennen.
Steffen P. schrieb: > // LED uses OC1A > DDRD &= ~(1 << PD0); > DDRD &= ~(1 << PD1); > DDRD &= ~(1 << PD2); > DDRD &= ~(1 << PD3); > DDRD &= ~(1 << PD4); Da stimmt was nicht. Ohne die restliche Logik zu verfolgen, sieht man schon, das hier kein einziger Ausgang deklariert wird. Wenn du OC1A als PWM Ausgang nurzen möchtest, solltest du zumindest ein
1 | PORTB |= (1 << PB1); |
während der Initialisierung ausführen. PB1 ist der PWM Ausgang OC1A, siehe Datenblatt. Die Schaltung passt auch in keiner Weise zum Programm.
:
Bearbeitet durch User
Aaaalso:
1 | DDRD &= ~(1 << PD0); |
2 | DDRD &= ~(1 << PD1); |
3 | DDRD &= ~(1 << PD2); |
4 | DDRD &= ~(1 << PD3); |
5 | DDRD &= ~(1 << PD4); |
6 | |
7 | //Wird zu:
|
8 | |
9 | DDRB &= ~((1<< PD0) | (1<< PD1) | (1<< PD2) | (1<< PD3) | (1<< PD4)); |
Und das:
1 | TCCR1B = (1 << WGM12) | (1 << WGM13) | 1; |
2 | |
3 | // Macht das, was fällt dir auf:
|
4 | |
5 | TCCR1B = (1<< WGM12); |
6 | TCCR1B = (1<< WGM13); |
7 | TCCR1B = 1; |
So beim überfliegen aufgefallen.
Matthias S. schrieb: >> // LED uses OC1A >> DDRD &= ~(1 << PD0); >> DDRD &= ~(1 << PD1); >> DDRD &= ~(1 << PD2); >> DDRD &= ~(1 << PD3); >> DDRD &= ~(1 << PD4); > > Da stimmt was nicht. Ohne die restliche Logik zu verfolgen, sieht man > schon, das hier kein einziger Ausgang deklariert wird. Wenn du OC1A als > PWM Ausgang nurzen möchstest, solltest du zumindest ein PORTB |= (1 << PB1); > während der Initialisierung ausführen. PB1 ist der PWM Ausgang OC1A, > siehe Datenblatt. Ich muss zugeben das ich nur die Teile raus gelöscht habe die ich nicht verwenden möchte. Verwenden wollte ich PD0 - PD4. Muss ich, da ich 5 Pins verwenden diesen Schritt void pwm_up_down (const uint16_t pwm_table[], int16_t size, uint16_t delay) { int16_t tmp; for (tmp = 0; tmp < size; tmp++) { OCR1A = pgm_read_word (& pwm_table[tmp]); my_delay (delay); } for (tmp = size-1; tmp >= 0; tmp--) { OCR1A = pgm_read_word (& pwm_table[tmp]); my_delay (delay); } } für jeden Pin eingeben? Woran erkenne ich eigentlich welcher Pin PWM unterstützt? > Die Schaltung passt auch in keiner Weise zum Programm. Ok, ich dachte, es reicht wenn ich meine LEDs an die Pins lege die ich auch vorhabe zu verwenden.
Draco schrieb: > Und das: > > TCCR1B = (1 << WGM12) | (1 << WGM13) | 1; > > // Macht das, was fällt dir auf: > > TCCR1B = (1<< WGM12); > TCCR1B = (1<< WGM13); > TCCR1B = 1; Ich würde sagen das es auf das gleiche heraus kommt, nur mit dem Unterschied das es vereinfacht geschrieben ist.
Steffen P. schrieb: > Woran erkenne ich eigentlich welcher Pin PWM unterstützt? Aus dem f*ing Manual. Im Datenblatt unter Pin Configuration siehst du z.B. OC1A und OC1B. Diese Ausgänge können mit den OC Registern A und B des Timers1 PWM moduliert werden. Das entsprechende für OC0A und OC0B, sowie OC2A und OC2B - summa summarum 6 Hardware PWM Kanäle mit 3 Timern. Steffen P. schrieb: >> TCCR1B = (1<< WGM12); >> TCCR1B = (1<< WGM13); >> TCCR1B = 1; > > Ich würde sagen das es auf das gleiche heraus kommt, nur mit dem > Unterschied das es vereinfacht geschrieben ist. Da solltest du nochmal drüber nachdenken, was so ein Gleichheitszeichen bedeutet.
:
Bearbeitet durch User
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.