Hallo zusammen, habe vor mein Zimmer mit RGB-LEDs zu beleuchten, habe dem entsprechend auch schon so ziemlich alle Beiträge gelesen die es hier gibt... Das was ich anders habe als bei den anderen Projekten ist, das ich pro LED (rgb) ein Poti habe der an jeweils an einem AD-Wandler hängt. Danach soll der Wert (1:1) als PWM wieder ausgegeben werden, aber nur auf einem PWM-Port. Ein MUX schaltet zwischen den 3 LEDs. Habe das soweit auch alles geschafft. Mein Problem ist, dass wenn ich einen Poti hochdrehe, ab einer gewissen Stelle eine andere LED mit aufleuchtet, obwohl ich den Poti dazu garnicht verändert habe.... Habe dann erstmal die Potis und den AD-Wandler weggelassen um zu überprüfen ob es vielleicht am MUX liegt und alle LEDs mit einem festen wert über den MUX angesteuert, aber der hat seine arbeite richtig getan! Daher denke ich das es irgendwie an den AD-Wandlern liegt?! Benutze übrigens einen ATMega16 dafür mit 12Mhz Hoffe ich konnte mein Problem soweit gut erklären.... Grüße Roberto
Äh, "PWM multiplexen", wie soll das gehen? Wenn Du ein PWM signal per Multiplexer an die LEDs weitergibst wirst Du nie 100% Helligkeit erreichen. Oder verstehe ich Dich falsch? Schick mal Deinen Schaltplan.
PORTA = pwm[pwm_count]; cli(); OCR1BL = werte[pwm_count][0]; OCR1BH = werte[pwm_count][1]; pwm_count++; if(pwm_count > 2) pwm_count=0; sei();
Naja, also das mit der Helligkeit ist sicher richtig, aber macht sich nicht soo bemerkbar Also wie gesagt, am Multiplexer liegt das nicht.... Leider geht trotzdem noch die eine LED mit an, wenn ich den Poti einer anderen LED hochdrehe.... Weiß jemand woran es liegt und was ich dagegen tun kann?
@ Roberto (Gast)
>Weiß jemand woran es liegt und was ich dagegen tun kann?
Dein Programm ist sehr merkwürdig.
cli() und sei() in einer ISR ist ziemlich sinnlos bis gefährlich.
Dein Umschaltung der AD-MUX ist falsch. Das muss eher heissen.
BYTE ad[3] = {0, 1, 2}; //AD-Wandler
Denn nur so misst du nacheinander den ADC-Kanal 0, 1, und 2.
Das mmit einem Array zu machen ist aber wie man sieht eher sinnlos.
Das merkwürdige trennen von ad_count++; und der Überlaifprüfung ist
keine gute Idee, spätestens wenn deine Programme grösser werden schiesst
du dir damit ins Knie.
Seinen eigenen Datentyp Byte zu erfinden ist Unsinn, schau dir mal
stdint.h an, dort ist alles schön und standardisiert verfügbar.
Probiers mal so
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | //Globale Variablen
|
5 | uint8_t pwm_count, ad_count, werte[3][2]; |
6 | uint8_t pwm[3] = {0, (1<<PA3), (1<<PA4)}; //Ports f?r LED-MUX |
7 | |
8 | //PWM-Interrupt
|
9 | ISR(TIMER1_COMPB_vect) { |
10 | |
11 | PORTA = pwm[pwm_count]; |
12 | OCR1BL = werte[pwm_count][0]; |
13 | OCR1BH = werte[pwm_count][1]; |
14 | pwm_count++; |
15 | if(pwm_count > 2) pwm_count=0; |
16 | }
|
17 | |
18 | |
19 | //AD-Interrupt
|
20 | ISR(ADC_vect) |
21 | {
|
22 | werte[ad_count-1][0] = ADCL; |
23 | werte[ad_count-1][1] = ADCH; |
24 | ADMUX = ad_count; |
25 | ADCSRA |= (1<<ADSC); |
26 | ad_count++; |
27 | if(ad_count > 2) ad_count = 0; |
28 | }
|
29 | |
30 | int main() |
31 | {
|
32 | |
33 | //Richtungskonfiguration der Ports
|
34 | DDRA = (1<<PA3) | (1<<PA4); //Port A 3/4 als Ausgang f?r MUX definieren |
35 | DDRD = (1<<PA4); //PWM Port OC1B |
36 | |
37 | |
38 | ad_count = 1; |
39 | pwm_count = 1; |
40 | |
41 | //PWM OC1B gew?hlt mit 10 Bit, Vorteiler 1 f?r PWM OC1B
|
42 | TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1B1) | (1<<COM1B0); |
43 | TCCR1B = (1<<CS10) | (1<<WGM12); |
44 | |
45 | TIMSK = (1<<OCIE1B); //Interrupt einschalten |
46 | |
47 | |
48 | //Vorteiler bei 12 MHz auf 187.5 kHz stellen, Interrupt ausl?sen wenn fertig, Wandler einschalten
|
49 | ADCSRA = (1<<ADIE) | (1<<ADPS2) | (1<<ADEN); |
50 | |
51 | |
52 | sei(); //Interrupts allg. aktivieren |
53 | |
54 | |
55 | ADMUX = ad[0]; //AD-Wandler 0 w?hlen, ADLAR=0 |
56 | |
57 | ADCSRA |= (1<<ADSC); //AD-Wandlung starten |
58 | |
59 | OCR1BH = 0x00; |
60 | OCR1BL = 0x00; |
61 | |
62 | PORTA = pwm[0]; |
63 | |
64 | //Unendlich-Schleife
|
65 | |
66 | while(1) |
67 | {}
|
68 | |
69 | return 0; |
70 | }
|
MFG Falk
@Falk: Vielen Dank, aber leider hat sich an dem Problem damit nicht verabschiedet :( Aber der Quellcode ist schonmal etwas kleiner geworden... Hab eben mal das Oszilloskop an die Stuerports vom MUX getan, und nun weiß ich denk ich woran es liegt, aber nicht wie ich es beheben kann. Und zwar habe ich die PWM invertiert laufen, "Top" heißt das meine ich, also so das wenn ich ne 0 drauf gebe der 5V ausgibt und bei 255 (8 Bit) dann 0V (RGB-LED hat gemeinsame Anode) Also wenn ich nun an das Poti hochdrehe, wird dadurch ja das Signal des PWMs immer kleiner, und irgendwann dann mal so klein, das der MUX es nicht mehr schafft mitzu schalten.... Das war meine Überlegung, kann das sein? Wenn das richitg ist, was könnte ich dagegen tun? Grüße und vielen dank (schonmal) an alle!!!
Eben, ein PWM Signal zu Multiplexen ist quatsch... Welchen Vorteil versprichst Du Dir davon? Bitte poste doch mal Deinen Schaltplan.
Wieso sollte das quatsch sein? Wenn man nur einen PWM-Port zur verfügung hat ist das doch ne top sache! Das läuft zZt ja nur auf dem Mega16, soll aber später auf dem Tiny2313 (vormals AT90S2313) laufen, und der hat nur einen PWM.
@ Gast (Gast) >Eben, ein PWM Signal zu Multiplexen ist quatsch... Nöö, das passt schon. Sowas macht man auch, wenn man eine LED-Matrix dimmen will. Been there, done that. MFg Falk
@ Roberto Leonardi (robertino) >Dateianhang: Plan.JPG (18,2 KB, 2 Downloads) Mal abgesehen vom Hinweis auf Bildformate, sind solche hingeschmierten Schaltpläne nicht sehr viel wert. Hast du das dritte MUX-Eingangspin fest auf 0V gelegt? Und auch alle anderen Eingänge auf festes Potential? MFG Falk
Weiß das das nicht viel Sinn macht, hatte eigentlich auch nicht vor dieses hier hochzuladen, da es einfach ein zu simpler Schaltplan ist... Ja, alle anderen Pins liegen auf festem Potential.
Ok, Muxen macht Sinn, wenn man zu Anzeigezwecken eine RGB LED ansteuern will. Aber für den genannten Zweck der Zimmerbeleuchtung gehe ich davon aus, dass man die volle Leistung der LEDs ausnutzen will / muss. Und ab hier macht das Multiplexen meiner Meinung nach keinen Sinn mehr, da man ja nie eine 100% An-Phase je LED realisieren kann. Jede einzelne RGB LED ist also max. 1/3tel der Zeit an. Um dies zu kompensieren müsstest Du in den An-Phasen den Strom entsprechend erhöhen. Ob dies einer Power LED (alles andere macht für eine Zimmerbeleuchtung imo keinen Sinn) so zuträglich ist? Da Dein Kontroller ja vermutlich nicht mehr viel mehr macht als das RGB PWM Signal zu erzeugen, überlege Dir ob Du nicht eine Soft PWM realisierst. Grüße
Hm ja, das habe...das hört sich gut an, allerdings habe ich noch nicht ganz verstanden wie das funktioniert...werd ich mich wohl mal reinlesen Wieso ist denn eine LED beim Multiplexen max nur 1/3tel an? Der MUX wartet ja bis das Signal komplett rüber ist und schaltet dann erst um. Und das bei 12MHz, da drüfte es doch keine Verluste geben, oder doch? Vielen Dank für euren gazen Beiträge!
@ Roberto Leonardi (robertino) >Wieso ist denn eine LED beim Multiplexen max nur 1/3tel an? Das ist das Prinzip von Multiplexen, siehe auch LED-Matrix. >Und das bei 12MHz, da drüfte es doch keine Verluste geben, oder doch? ;-) Denk mal in RUHE drüber nach und nicht solche Schnellschüsse aus der Hüfte. MfG Falk
Dein Problem liegt im Prinzip der A/D Wandlung: Du schaltest den Kanal des A/D Mux um und liest direkt danach den Wert des Kanals ein! Das funktioniert nicht, da im A/D Wandler sich die Sample & Hold Schaltung erstmal umladen muss, bis du den A/D Vorgang starten darfst. Beispiel: Poti 1: 5V Poti 2: 0V Zuerst hat sich der Kondensator auf 5V geladen. Anschliessend soll er sich in einem Taktzyklus sofort auf 0 Volt entladen? Das kann nicht funktionieren. Deshalb wird ein Wert bei ca. 1V o.ä. eingelesen. Schau dir mal das Datenblatt zum Prozessor an. Dort sind die Timings beschrieben!
@ Falk Ah ok....jetzt hab ichs auch ;) @ Sven Ich habe mir irgendwie schon immer gedacht das es an den AD-Wandlern liegt...könnte ich das Problem denn dann so lösen, das ich da einfach ein delay reinbastel im Interrupt vom AD-Wandler?
@ Roberto Leonardi (robertino) >liegt...könnte ich das Problem denn dann so lösen, das ich da einfach >ein delay reinbastel im Interrupt vom AD-Wandler? Patsch Delays haben im Interrupt nichts zu suchen! Einfach den ADC richtig ansteuern und es läuft. Den Interrupt brauchst du dazu nicht. Lies den ADC ohne interrupt in der Hauptschleife aus, dort ist dann ausnahmsweise auch ein Delay zulässig. MFG Falk
@ Sven H. (Gast) >Du schaltest den Kanal des A/D Mux um und liest direkt danach den Wert >des Kanals ein! Nöö, er list das Ergebnis der letzten Umwandlung ein. Was wahrscheinlich fehlt ist ein Kondensator von 2..100nF an dem AD-Eingangspin. MfG Falk
Bei eine Soft PWM erzeugst Du softwaregesteuert die jeweiligen Signale an drei Pins, je ein Pin pro LED. Da das Auge recht träge ist reicht imo eine PWM Cycle Frequenz von z.B. 100hz, vermutlich auch weniger, dann kann es aber vorkommen, dass das Auge bei Bewegung ein Flackern wahrnimmt. Dass heißt, dass Du immer dann einen Timer Interrupt auslösen musst, wenn sich einer der PWM Ausgangszustände ändern soll. Im Interrupt änderst Du dann den Zustand des Pins. Außerdem berechnest Du die Zeit bis zum nächsten Wechsel und setzt den Timer entsprechend. 1 1 2 5 9 0 2 t(ms) 0 5 0 0 0 5 usw ___ ___ R _____| |______________| |______________ 25% ________ ________ G _____| |_________| |_________ 50% ________________ ________________ B _____| |_| |_ 90% Das Abtasten der AD Eingänge kannst Du sogar noch deutlich langsammer machen z.B. nur alle 200ms und die Werte in globale Variablen speichern. Damit hast Du insgesamt recht entspannte Verhältnisse und bekommst 100% LED Power je LED und hast keine Probleme mit der AD Wandlung der Potispannungen. Grüße
@ Gast Das hört sich gut an...dann werd ich das wohl mal testen! Meld mich bei Problemen wieder ;) Vielen Dank @Falk Hab einen Kondensator und eine Spule am Aref Pin, wie es im Datenblatt es Mega16 drin steht.... Soll ich pro Poti einen 100nF C dran tun, oder wie?
@ Roberto Leonardi (robertino)
>Soll ich pro Poti einen 100nF C dran tun, oder wie?
Ja.
Hm... wegen dem TP-Verhalten? Meine da liegt ja eigentlich nur Gleichspannung an....
@Falk: ADMUX = ad_count; ADCSRA |= (1<<ADSC); Das beißt sich direkt untereinander!
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.