Forum: Mikrocontroller und Digitale Elektronik Mit Drehimpulsgeber RGB Farbe einstellen


von Avusgalaxy (Gast)


Lesenswert?

Hi.

Ich möchte mit meinem Atmel 89C52 ein Programm schreiben, mit dem ich
dann mit dem Drehimpulsgeber die Farbe einstellen kann. Die Software
für den Drehimpulsgeber habe ich schon.

Es sollte folgender Maßen aussehen:

Wenn ich den MC einschalte, dann sollte einfach nur die rote Led
leuchten. Drehe ich dann den Drehimpulsgeber nach rechts, dann sollte
die rote Led bei jedemmal drehen dünkler werden und die grüne dann
immer  heller werden. Wenn die grüne dann ganz hell ist, dann sollte es
auf blau übergehen und von blau dann wieder auf rot.

Mein erstes Problem ist, wie kann ich das realisieren und mein zweites
ist, daß wenn nur die rote Led leuchtet und ich eins nach rechts drehe,
das die grüne Led schon zu hell leuchtet, obwohl sie eigentlich fast
dunkel sein sollte.

von Florian -der Flo- Scharf (Gast)


Lesenswert?

Hi .. viele Wege führen nach Rom. Einer davon wäre eine Zählervariable
hoch- oder runterzuzählen und eine mathematische Zuordnung zu finden,
z.b. mit if ((x>20) and (x<30)) {rot=x-20;}
Das zweite Problem was Du hast, ist die Nichtlinearität von LEDs.
Darüber wurde hier schon oft diskutiert und diverse Lösungsansätze
vorgeschlagen. Such einfach mal nach PWM und LED. Tendenziell läufts
auf eine Quadrierung des Sollwertes hinaus. Also 10 Stufen -->
PWM-Werte 1,4,9,16,...,100.

der Flo

von Avusgalaxy (Gast)


Lesenswert?

Hi Flo.

Also ich hätte es mir so vorgestellt:

P2.0 = Rot
P2.1 = Grün
P2.2 = Blau

Zuerst läuft das Programm die Farbe Rot durch.

Programm:
setb P2.0
Rot_ein:
djnz 255mal,Rot_ein ;255 mal leuchtet Rot

clr P2.0
Rot_aus:
djnz 0mal,Rot_aus ;0 mal leuchtet sie nicht


setb P2.1
Grün_ein:
djnz 0mal,Grün_ein ;0 mal leuchtet Grün

clr P2.1
Grün_aus:
djnz 255mal,Grün_aus ;255 mal leuchtet sie nicht


setb P2.2
Blau_ein:
djnz 0mal,Blau_ein ;0 mal leuchtet Blau

clr P2.2
Blau_aus:
djnz 255mal,Blau_aus ;255 mal leuchtet sie nicht

jmp Programm

So würde das Programm schon ganz gut funktionieren.
Nur grün und blau leuchten dabei auch schon. Zwar nicht hell, aber sie
leuchten. Wenn ich jetzt die Pausen für blau und grün verlängere, dann
wird rot wieder dunkel. Es ist ein hin und her, da wo ich kein
mittelmaß finden kann.

Verstehst du Flo?

von Avusgalaxy (Gast)


Lesenswert?

Hi.

Könnte mir jemand sagen, ob ich da den richtigen weg gehe, oder ob ich
es anders machen sollte.?

von Peter D. (peda)


Lesenswert?

Das dürfte sehr schwer sein, wenn man alles so zusammen manscht.


Du must die verschiedenen Aufgaben trennen:

1.
Du brauchst erstmal 3 PWM-Ausgänge, entweder mit dem PCA (z.B. im
AT89C51ED2) oder in Software mit einem Timerinterrupt.

2.
Dann brauchst Du einen Timerinterrupt, der den Drehgeber abfragt (kann
der gleiche sein).

3.
Und im Hauptprogramm wird mit dem Wert vom Drehgeber eine Variable
hoch- bzw. runtergezählt.

4.
Diese Variable zeigt nun auf eine Tabelle, wo je 3 Byte (für jede LED)
logarithmisch gestuft abgelegt sind, die dann in die 3 PWM geladen
werden.


Damit laufen diese 4 Aufgaben voneinander unabhängig und es können
leicht noch weitere Aufgaben eingefügt werden (z.B. Abspeichern des
letzten Wertes im EEPROM).

Bzw. Du kannst die Aufgaben überhaupt erstmal einzeln entwickeln und
testen.


Peter

von Avusgalaxy (Gast)


Lesenswert?

Hallo Peter.

Das Problem mit dem Drehimpulsgeber habe ich schon gelöst.

Ich habe das Programm dafür auf einen 89C2051 abgelegt. Dre tut nichts
anderes, als den Drehimpulsgeber abfragen. Sobald ich dann drehe, dann
kommt entweder bei P1.0 oder bei P1.1 ein kurzez Signal heraus. Diese
beiden Signale steuern dann die Interupt's des 89c52. Habe es deshalb
so gemacht, weil es so 100 % läuft und ich brauche keine Timer dafür.


1.) Ich hab nur zwei Timer, was kann ich dagegen machen?
     Wie würde das im allgemeinen ausschauen.Brauch ich dann3 oder nur
    einen Timer?

2.) hab ich oben erklärt.

3.) Das mit dem ruf und runterzählen mache ich mit den Interuppts

4.) meinst du das so?::

DB #00000001b,
DB #00000010b,
DB #00000100b,

Wenn ja, wie soll ich das dann realisieren?

von Florian -der Flo- Scharf (Gast)


Lesenswert?

Gegen zwei Timer kann man nichts machen ;)

Aber versuch das ganze Programm mal umzustricken, denn so wie Du es im
Moment hast, beeinflussen sich die Helligkeiten gegenseitig, so wie ich
das verstehe.
Dass das Programm läuft, nutzt dir nichts, wenn es nicht das tut was es
soll. Also mein Vorschlag: Nutze die PWM Ausgänge von deinem
Controller.

Da kannst Du dann direkt über die Compare Register einen Sollwert sowie
eine Skalierung der PWM angeben. Das ist die eigentlich gängige Methode,
so etwas zu realisieren. Lies dich erstmal ein wenig in die Timer
Behandlung ein.

Die Tipps von Peter zielen genau darauf ab, aber dazu muss man erstmal
verstanden haben, wieso das so funktioniert, wie es funktioniert.
Wenn man es verstanden hat, ist es nicht mehr wirklich schwer, da so
etwas selber zu bauen. Vielen anderen Leuten hier im Forum ging das
schon genauso. ;)

der Flo

von Avusgalaxy (Gast)


Lesenswert?

Ups, ich hab ja drei Timer. Da läßt sich doch was machen...

Ich werde mal probieren, hab zwar nicht sehr viel Ahnung, was ihr hier
geschreiben habt, aber trotzdem Danke.

Vielleicht gehts mit den 3 Timern.

von Peter D. (peda)


Lesenswert?

"1.) Ich hab nur zwei Timer, was kann ich dagegen machen?"


Dann hast du ja schon einen mehr als Du brauchst.

Irgendwo gabs hier mal einen Link zu Software-PWM (8 bzw. 12 Kanäle).


Sinn macht es keinen, nur für den Drehgeber eine extra CPU zu
verschwenden. Eher im Gegenteil, so lernt man nie effektives Planen des
Programmablaufs.



Peter

von Avusgalaxy (Gast)


Lesenswert?

Mann kann mit einem Timer die Drei Farben ansteuern?

Wie kann man das machen?
----------------------------------------------------------
In meinem 2051 habe ich dieses Programm:


INCLUDE 89C2051.mc



abfrage:


IF P1 = #11111111b THEN JMP aus
IF P1 = #11111100b THEN JMP ein

JMP abfrage

aus:

IF P1 = #11111110b THEN
CLR P3.0
NOP
NOP
SETB P3.0
LCALL wait_20000
JMP abfrage
END IF

IF P1 = #11111101b THEN
CLR P3.1
NOP
NOP
SETB P3.1
LCALL wait_20000
JMP abfrage
END IF
JMP aus

ein:

IF P1 = #11111110b THEN
CLR P3.1
NOP
NOP
SETB P3.1
LCALL wait_20000
JMP abfrage
END IF

IF P1 = #11111101b THEN
CLR P3.0
NOP
NOP
SETB P3.0
LCALL wait_20000
JMP abfrage
END IF
JMP ein


INCLUDE wait.asm


Ich bin leider nur auf diese Idee gekommen, bzw ein Bekannter. Wie ich
es mit einem MC machen kann, bin ich leider noch nicht draufgekommen.

von Avusgalaxy (Gast)


Lesenswert?

Hallo Peter.

Du hattest recht. Weg mit dem 2051...

Es funktioniert jetzt mit dem Drehimpulsgeber und mit einem Timer. Da
Spare ich mir ja viel Hardware und so wie ich es sehe, läuft es auch zu
100 Prozent.

Danke Peter. Jetzt muß ich nur mehr mit der PWM draufkommen...

von Avusgalaxy (Gast)


Lesenswert?

Hm....
Lassen wir mal den Drehimpulsgeber weg.

Im Grunde schaut ja eine PWM so aus:

254 Schritte Led ein
1 Schritt Led aus

dann leuchtet die Led ganz hell

1 Schritt Led ein
254 Schritte Led aus

dann ist die Led ganz dunkel.

127 Schritte Led ein
128 Schritte Led aus

dann ist die Led im mittleren Bereich.

Ist das richtig so?

Nehmen wir an, ich möchte nur eine Led mit dem Drehimpulsgeber dimmen,
wie kann ich das dann mit einem Timer realisieren=?

Ich könnte es mir so vorstellen:

Ich sage R0=#0Ah
Mit dem Drehimpulsgeber kann ich dann R0 erhöhen oder verringern.

Dann könnte ich R1 immer Inkrementieren.
Wenn R1 < R0 ist, dann soll die Led leuchten.
Wenn R1 > R0 ist, dann soll sie nicht leuchten.

Nur geht dieser Befehl nicht:

if R0 < R1 then setb bit 2.0

Bin ich da am richtigen weg?

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Eine Software-PWM macht man im Timerinterrupt.

Im Interrupt hat man einen Zähler, der nach einer bestimmten Zeit alle
LEDs ausschaltet.

Und für jeden benötigten Ausgang hat man einen weiteren Zähler, der die
ihm zugeordnete LED einschaltet.

Die Differenz zwischen beiden Zählern ist dann das Tastverhältnis.

Läßt man die Zähler bis 255 zählen, spart man sich das Rücksetzen, da
nach 255 automatisch 0 kommt.

Für einfachere Software zählt man nicht hoch, sondern runter, da der
8051 dafür einen speziellen Befehl hat, der zählt und gleichzeitig auf
0 testet (DJNZ).


Bei einem AT89C2051 mit 24MHz Quarz setzt man z.B. den Timer T0 in den
Reloadmode, so daß er alle 52 Zyklen einen Interrupt auslöst:

MOV TH0, #-52

Dann ergibt sich eine PWM-Frequenz von:

24MHz  12  52 / 256 = 150Hz

Benötigt man noch andere Interrupts, dann muß T0 auf die hohe Priorität
gesetzt werden, damit die LEDs nicht flackern.


Peter

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.