Hallo allerseits
Ich häng schon eine Weile an dem Problem...und ich bin ein Neuling:
Ich will mit dem Mikrocontroller einen Motor ansteuern, welcher über
eine Zahnstange einen Deckel auf und ab fährt...das nur zur Info.
Um die Position des Deckels zu detektieren, benutze ich einfach oben
einen Endschalter (S1) und einen für unten (S2).
Dann hab ich noch einen Haupttaster S3.
Wenn der Deckel geschlossen ist und ich den S3 betätige, soll der Deckel
den oberen Endschalter S1 anfahren und der Motor soll stoppen.
Wenn der Deckel offen ist, soll sich der Deckel bei erneuter Betätigung
des S3 schließen bis Endschalter unten schaltet und der Motor stoppen.
Hat jemand eine Idee für ein Programmieransatz in C?
Danke!
MFG
Das hört sich im ersten Moment recht einfach an. Wenn du da selbst
keinen Ansatz hast, dann solltest du dir erst mal ein paar Tutorials
durchlesen. Vielleicht sogar hier auf mikrocontroller.net die Hinweise
zur Programmierung des AVR. Einarbeiten eben...
kontrolliere einfach in einer if-Abfrage, welcher der endschalter
betätigt ist und reagiere dann entsprechend, indem du den motor einmal
links oder rechts rum drehen lässt.
vorher vielleicht noch prüfen, ob der motor grad aktiv ist und den
tastendruck dann verwerfen.
die endschalter fragst du auf die selbe weise ab, wenn er betätigt wird,
stoppst du den motor
Mach das doch als Statemachine mit 4 States.
1 = Deckel ist offen, Warten auf S3
2 = Deckel wird geschlossen, Motor vorwärts, Warten auf S2
3 = Deckel ist geschlossen, Warten auf S3
4 = Deckel wird geöffnet, Motor rückwärts, Warten auf S1
Ach ja, states als variablentyp macht man sich mit enum, du könntest das
aber genausogut mit 4 defines machen und ein uint8_t nehmen.
mfg mf
Startvariable, Zählervariable
z.B.: Start = S1 gedrückt und Motor aus, Zählervariable 0
Beim Drücken von S3, Motor an und auf S2 warten , dann Motor aus und
Zählervariable 1
Dann bei druck auf S3 vergleichen , ist Zähler 1, dann nur Abwärts und
Zähler wieder 0 oder ist unten dann nur aufwärts und Zähler wieder
1.....usw.
na? hilfts ?
lg
hey,
lso ich habs mal so ähnlich versucht, wahrscheinlich denk ich aber zu
kompliziert bzw die Logik funktioniert garnicht.
Sicher braucht ihr dafür nur 8 Zeilen :D !!
Aber würde das, was ich da programmiert habe, funktionieren?
^^und ja...war sehr hifreich :)
mfg
Punkt 1:
Sieh dir das File an.
Wenn du ernsthaft programmieren willst, dann darf sowas wie das was du
da am Anfang produziert hast nicht passieren (ich meine die äussere
Form). Der untere Teil ist so einigermassen ok.
Punkt 2:
Du hast dich für eine Zustandsmaschine entschieden.
Das ist ok
So eine Zustandsmaschine sieht in Code im Grundgerüst so aus
zustand = 1;
while( 1 ) {
switch( zustand ) {
case 1: // wenn im Zustand 1
if( Bedingung um den Zustand zu verlassen ) {
Aktionen die ausgeführt werden, wenn der Zustand
verlassen wird.
zustand = neuer Zustand;
}
break;
case 2: // wenn im Zustand 2
if( Bedingung um den Zustand zu verlassen ) {
Aktionen die ausgeführt werden, wenn der Zustand
verlassen wird.
zustand = neuer Zustand;
}
break;
usw. usw.
}
}
Das kannst du natürlich noch nicht wissen, daher ist das schon ok.
Zustandsmaschinen haben einen enormen Vorteil.
Man kann die Logik, die sie verkörpern, ganz einfach grafisch
anschaulich machen.
Sieh dir beiliegendes Bild an.
Das Runde sind die Zustände. Jeder Zustand hat einen Namen. Das ist der
schwarze Text im Oval.
Von jedem Zustand gehen ein (oder mehrere) Pfeile aus. Das sind die
Zustandsübergänge, wann also die Maschine in einen anderen Zustand
wechselt. An jedem Pfeil steht dabei, unter welcher Bedingung dieser
Pfeil genommen werden kann (der blaue Text). Und an jedem Pfeil steht
dabei, welche Aktion dabei auszuführen ist (der rote Text).
Sieh dir das Diagramm an, du kommst sicher drauf, welcher Vorgang hier
beschrieben wird ( :-) zumindest in Ansätzen )
In Code würde dasselbe dann so aussehen
1
#define STATE_START 0
2
#define STATE_CURRENT 1
3
#define STATE_NORMAL 2
4
#define STATE_STARTER 3
5
6
...
7
8
9
state=STATE_START;
10
11
while(1){
12
13
switch(state){
14
15
caseSTATE_START:
16
if(Key_Detected){
17
PowerUp_Electronics();
18
state=STATE_CURRENT;
19
}
20
break;
21
22
caseSTATE_CURRENT:
23
if(!Key_Detected){
24
PowerDown_Electronics();
25
state=STATE_START;
26
}
27
elseif(Key_Turned_Right){
28
PowerUp_Ignition();
29
state=STATE_NORMAL;
30
}
31
break;
32
33
caseSTATE_NORMAL:
34
if(Key_Turned_Right){
35
PowerUp_Starter();
36
state=STATE_STARTER;
37
}
38
elseif(Key_Turned_Left){
39
PowerDown_Ignition();
40
state=STATE_CURRENT;
41
}
42
break;
43
44
caseSTATE_STARTER:
45
if(Key_Turned_Left){
46
PowerDown_Starter();
47
state=STATE_NORMAL;
48
}
49
break;
50
}
51
}
wie man sieht übersetzt sich das Schaubild fast kochrezeptartig in eine
erste Programmversion. Aber: Auf dem Schaubild ist es viel leichter die
Logik zu verfolgen und auf Sinnhaftigkeit bzw. Fehler abzuklappern. Im
schlimmsten Fall fährt man einfach mir dem Finger die Pfeile entlang,
fragt sich was im jeweiligen Kreis alles passieren kann und sieht nach
wo man landet, wenn man einfach mal annimmt, dass diese Bedingung
vorliegt.
Eine erste Version des Zustandsautomaten, der deine Schaltlogik
repräsentiert könnte zb so aussehen (Siehe Bild)
Darauf kann man jetzt weiter aufbauen.
Was soll zb passieren, wenn der Haupttaster gedrückt wird, während der
Motor fährt, die Maschine sich also entweder im Zustand 'öffnend' bzw
'schliessend' befindet. Im Moment passiert nichts, aber das muss ja
nicht so sein.
(zb sollte man sich auch überlegen, was passieren soll, wenn der Deckel
nach dem Einschalten der Steuerung weder komplett offen noch komplett zu
ist. Man könnte zb vereinbaren, das der erste Zustand nach dem
Einschalten der Zustand öffnen ist. Dann fährt der Deckel erst mal auf.
Man könnte aber auch neue Zustände einführen, die auf
Benutzerinteraktion mit dem Hauptschalter warten oder man könnte ....)
Je mehr und je besser du dir die Logik im Vorfeld aufbereitest, umso
weniger Ärger wirst du dann bei der tatsächlichen Programmierung haben.
Dabei geht es nicht darum, sich an irgendwelche formalen Zwänge zu
halten. Du kannst im Schaubild rummalen wie du lustig bist und Begriffe
erfinden wie du lustig bist. Es muss nur gewährleistet sein, dass sich
Pfeile nicht widersprechen (also 2 Pfeile mit derselben Bedingung aus
einem Oval rausführen) und dass die Abfolge der Pfeile deiner Logik
entspricht. Aber ansonsten interessiert sich auf dieser Ebene keiner für
Klammern oder Strichpunkte oder .... Auf dieser Ebene darfst du kreativ
sein.
ich glaub ich habs verstanden :)...diese Zustandsmaschine verkürzt mein
erstes Programm um einiges und es wird viel übersichtlicher....
also ich werd mein Program mal auf diese art schreiben...kann etwas
dauern ;)
Die Bilder und die Erklärungen haben mir sehr geholfen
danke vorerst
mfg
Chillxx schrieb:> ich glaub ich habs verstanden :)...diese Zustandsmaschine verkürzt mein> erstes Programm um einiges
Ich denke kürzer wirds nicht werden, ...
> und es wird viel übersichtlicher....
... ganz genau.
Vor allen Dingen, wenn du dir dann noch Makros machst, die die Dinge
beim Namen nennen, anstelle von PB1, PB2 etc.
TURN_ON_MOTOR( OPEN );
TURN_OFF_MOTOR;
TURN_ON_MOTOR( CLOSE );
liest sich nun mal schon viel besser und aussagekräftiger als
PORTC |= ( 1 << PC0 );
PORTC &= ~( ( 1 << PC0 ) | ( 1 << PC1 ) );
PORTC |= ( 1 << PC1 );
obwohl es genau dasselbe in anderer Verpackung ist.
Karl heinz Buchegger schrieb:> Vor allen Dingen, wenn du dir dann noch Makros machst, die die Dinge>> beim Namen nennen, anstelle von PB1, PB2 etc.
dann sag ich einfach am Anfang zB:
PC0=MotorAUF
...oder Funktioniert es bei der "PIN Zuweisung" anders
...ihr wisst eh-->Anfänger ;)
Karl heinz Buchegger schrieb:> liest sich nun mal schon viel besser und aussagekräftiger als> PORTC |= ( 1 << PC0 );>> PORTC &= ~( ( 1 << PC0 ) | ( 1 << PC1 ) );>> PORTC |= ( 1 << PC1 );
das stimmt, allerdings - muss selber ständig nachschaun!
mfg
Chillxx schrieb:> PC0=MotorAUF> ...oder Funktioniert es bei der "PIN Zuweisung" anders> ...ihr wisst eh-->Anfänger ;)
An dieser Stelle kommt der von Insidern lange erwartete Hinweis:
Du brauchst ein C Buch!
[C]
#define MOTOR_PORT PORTC
#define OPEN PC0
#define CLOSE PC1
#define SET_BIT(p,b) (p) |= (1<<(b))
#define TURN_ON_MOTOR(bit) MOTOR_PORT |= (1<<(bit) )
#define TURN_OFF_MOTOR MOTOR_PORT &= ~( (1<<OPEN) | (1<<CLOSE) )
....
TURN_ON_MOTOR( OPEN );