Forum: Mikrocontroller und Digitale Elektronik Assembler Dimmbare Treppenlichtsteuerung


von Dennis H. (denn1s)


Angehängte Dateien:

Lesenswert?

Hallo,

ich möchte gerne eine Treppenlichtsteuerung mit dem Pic 16F887 
programmieren.
Ein Teil eines Programms habe ich fertiggestellt, doch nun kommen 
Probleme die ich leider nicht mehr lösen kann ich bitte daher um Hilfe 
=D.

Das Programm soll einzelnde LED's ansteuern die unter den Treppenstufen 
angebracht sind. Diese sollen mit einer Lichtschranke eingeschaltet 
werden und dann Treppenstufe für Treppenstufe hochdimmen.

Meine Frage ist nun wie binde ich eine Tabelle mit verschiedenen Werten 
in das Programm ein, dass die LED unterschiedlich angesteuert.

Außerdem habe ich noch ein weiteres Problem und zwar muss man die Taste 
gedrückt halten das die LED's hochdimme ich weiß leider nicht wie er 
dies mit nur einem Tastendruck macht und sie dann automatisch 
hochdimmen.

Es wäre sehr freundlich wenn mir jemand bei meinem Problem helfen kann

Im Anhang befindet sich das Programm

MfG Dennis

von Peter D. (peda)


Lesenswert?

Dein Problem ist, daß Dein Programm einfach an einer Stelle anhält.

Für Ablaufsteuerungen nimmt man daher Statemachines, die ständig 
durchlaufen werden und nirgends anhalten.
Und ist mal nichts zu tun, ändern sie einfach nur ihren State nicht.
Aber sämtliche Abfragen, die den State ändern könnten, laufen weiter.

von Dietrich L. (dietrichl)


Lesenswert?

Das betrifft zwar nicht direkt Deine Frage, aber:

Falsch (es fehlt ein "return" am Ende):
1
Bereich    movlw  0xFF
2
...
3
    goto  ist_Max
4
    return
5
ist_Null  incf  Dimmer,F
6
    return
7
ist_Max    decf  Dimmer,F

Richtig ("goto  ist_Max" ist hier unnötig):
1
Bereich    movlw  0xFF
2
...
3
    decf  Dimmer,F
4
    return
5
ist_Null  incf  Dimmer,F
6
    return

Gruß Dietrich

von Dennis H. (denn1s)


Lesenswert?

Das "return" am Ende des Unterprogrammes Bereich ist mir schon 
aufgefallen,
ändert aber nichts am Problem.

Mit dem Begriff Statemachine kann ich leider nichts anfangen hab ich so 
auch noch nie benutzt und durch google werde ich auch nicht schlauer

MfG Dennis

von Dietrich L. (dietrichl)


Lesenswert?

Dennis Hoppen schrieb:
> Mit dem Begriff Statemachine kann ich leider nichts anfangen hab ich so
> auch noch nie benutzt und durch google werde ich auch nicht schlauer

http://www.mikrocontroller.net/articles/Statemachine

von Max B. (theeye)


Lesenswert?

Dennis Hoppen schrieb:
> Außerdem habe ich noch ein weiteres Problem und zwar muss man die Taste
> gedrückt halten das die LED's hochdimme ich weiß leider nicht wie er
> dies mit nur einem Tastendruck macht und sie dann automatisch
> hochdimmen.

Wenn ich dich richtig verstehe, musst du mit dem Drücken des Tasters 
eine flag setzen. Dann dimmt alles hoch und wenn alles hochgedimmt ist, 
wird die flag zurückgesetzt.
1
int dimmen = 0;
2
***Taster wird gedrückt***
3
dimmen = 1;
4
***wenn hochgedimmt***
5
dimmen = 0;

Gruß Max

von Dennis H. (denn1s)


Lesenswert?

Danke erstmal für die schnellen und hilfreichen Antworten.

Max B. schrieb:
> Wenn ich dich richtig verstehe, musst du mit dem Drücken des Tasters
> eine flag setzen. Dann dimmt alles hoch und wenn alles hochgedimmt ist,
> wird die flag zurückgesetzt.
> int dimmen = 0;
> ***Taster wird gedrückt***
> dimmen = 1;
> ***wenn hochgedimmt***
> dimmen = 0;

kann man dies so in Assembler übernehmen, da ich dies nur von C kenne.

von Karl H. (kbuchegg)


Lesenswert?

Dennis Hoppen schrieb:
> Danke erstmal für die schnellen und hilfreichen Antworten.
>
> Max B. schrieb:
>> Wenn ich dich richtig verstehe, musst du mit dem Drücken des Tasters
>> eine flag setzen. Dann dimmt alles hoch und wenn alles hochgedimmt ist,
>> wird die flag zurückgesetzt.
>> int dimmen = 0;
>> ***Taster wird gedrückt***
>> dimmen = 1;
>> ***wenn hochgedimmt***
>> dimmen = 0;
>
> kann man dies so in Assembler übernehmen, da ich dies nur von C kenne.

Natürlich kannst du das in Assembler dem Prinzip nach genauso machen. 
Ob Du jetzt in C schreibst oder in Assembler - Speicherzelle ist 
Speicherzelle. Schreibst du einen Wert rein, dann behält sie den Wert 
und der kann wieder geladen und abgefragt werden.

Häng dich nicht an der Syntax auf. Es geht um Prinzipien, unabhängig 
davon wie die dann in der konkreten Programmiersprache formuliert 
werden.

Wird eine Taste gedrückt, dann wird ein 'Flag' auf einen bestimmten Wert 
gesetzt. In der zentralen Hauptschleife wird dieses Flag wieder 
abgefragt und wenn es auf 'hochdimmen' steht, dann wird eben pro 
Zeiteinheit der Dimmgrad deiner LED um zum Beispiel 1 erhöht. Oder dann 
eben beim Drücken auf die andere Taste wird der Dimmgrad um 1 
verringert.

Hier
1
Loop    movf  PORTA    ;Hauptschleife
2
    btfsc  STATUS,Z  ;Taste gedrückt?
3
    goto  Loop
ist deine zentrale Schleife.
Eine Möglichkeit ist es eben, die zu erweitern. Nach dem Muster
1
Loop
2
     Ist eine Taste gedrückt?
3
     Wenn ja -> Tastenasuwertung
4
5
     steht das Flag (der Status) auf hochdimmen
6
     Wenn ja -> Dimmgrad erhöhen
7
8
     steht das Flag (der Status) auf runterdimmen
9
     Wenn ja -> Dimmgrad erniedrigen
10
11
     goto Loop

Ein Problem stellt natürlich dar, dass dieses Dimmen hier in einem 
Affenzahn durchgeführt wird. Denn bis diese Schleife von 0 auf maximum 
gedimmt hat, vergehen gerade mal ein paar µs. Da wirst du dir zum Thema 
Zeitsteuerung etwas einfallen lassen müssen.

von Max B. (theeye)


Lesenswert?

Dennis Hoppen schrieb:
> kann man dies so in Assembler übernehmen, da ich dies nur von C kenne.
Karl Heinz hat es schon beantwortet.
Karl Heinz schrieb:
> Natürlich kannst du das in Assembler dem Prinzip nach genauso machen.

Assembler habe ich mal programmieren (müssen), aber nur ganz wenig. 
Daher mein Beispiel in C :)

Gruß Max

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> gedimmt hat, vergehen gerade mal ein paar µs. Da wirst du dir zum Thema
> Zeitsteuerung etwas einfallen lassen müssen.

Eine Möglichkeit dafür ist zb folgende Vorgehensweise:

Du legst das eigentliche Dimmen in deine sowieso schon vorhandene 
Timer-getrieben Software-PWM mit rein. Denn da hast du ja bereits eine 
Zeitsteuerung: Die Interrupt Routine wird in regelmässigen Zeitabständen 
aufgerufen, auf die du dich auch verlassen kannst.

Du wandelst das Prinzip wie folgt um:
Mit den Tasten wird nicht mehr der tatsächliche Dimmgrad der LED 
eingestellt, sondern ein Vorgabewert. D.h. wenn du zb auch 'Hochdimmen' 
drückst, dann wird dieser Vorgabewert zb auf 255 gesetzt.
Das bedeutet NICHT, dass der tatsächliche Dimmgrad, der zur Anwendung 
kommt, auch 255 ist. Der tatsächliche Dimmgrad wird nach wie vor mit 
ihrem eigenen Wert über die Software-PWM realisiert. Aber: in der 
Interrupt Routine wird dieser tatsächliche Wert mit der Vorgabe 
verglichen. Ist er kleiner, dann wird der tatsächliche Wert erhöht, ist 
er größer, dann wird er verringert. Das führt, über mehrere (viele) 
Aufrufe der Interrupt Routine dazu, dass dieser tatsächliche PWM-Wert 
langsam und in Schritten auf den Vorgabewert nachgeführt wird.
1
Interrupt Routine:
2
3
   ... Software-PWM basierend auf 'Dimmer'
4
5
   wenn 'Dimmer' kleiner als 'Dimmer_Vorgabe'
6
   inkrementiere 'Dimmer'
7
8
   wenn 'Dimmer' größer als 'Dimmer_Vorgabe'
9
   dekrementiere 'Dimmer'
10
11
   ..
12
   return
13
14
15
16
....
17
Taste_Aufdimmen:
18
   setze 'Dimmer_Vorgabe' auf 255
19
   return
20
21
Taste_Abdimmen:
22
   setze 'Dimmer_Vorgabe' auf 0
23
   return

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.