Forum: Compiler & IDEs Motor stoppt nicht wenn Endanschlagschalter außgelöst wird


von Rocco L. (kaufparkangucker)


Angehängte Dateien:

Lesenswert?

Hallo,

ein Atmega16 bekommt von 3 DS18S20 3 Temperaturen:
p_temp  //Temperatur der Probe
k_temp  //Temperatur vom Kältebad (kaltes Wasser mit einem Eiswürfel)
w_temp  //Temperatur vom Wärmebad (heißes Wasser aus der Leitung)

Die Temperaturen werden alle richtig erkannt.
Ein Motor soll die Probe imer wieder zwischen den Bädern hin und her 
fahren. Bei Beiden Bädern ist noch jeweils ein Anschlagschalter, damit 
der Motor weis wann er mit drehen aufhören soll.
Das soll eigentlich so ablaufen das die Probe sofort in das andere Bad 
gefahren wird wenn die Probe die Temperatur des Bades angenommen hat.

Nun ist das Problem das der Motor entweder einfach so los fährt, bevor 
die Probe auch nur im entferntesten die Temperatur des Bades angenommen 
hat.
1
      //+-2 damit das Testen schneller geht.
2
      k_temp = k_temp + 2;
3
      w_temp = w_temp - 2;
4
5
      //Wenn Taster vom K?ltebad an (d.h. Probe ist im Kältebad)
6
      if((PINB & (1<<KB)))
7
      {
8
        //Motor erst mal grundlegend ausschalten, um einen definierten Startwert zu haben
9
      PORTB &= ~ (1<<CCW);  //Motor aus
10
      PORTB &= ~ (1<<CW);    //Motor aus
11
12
13
        if((p_temp <= k_temp))   //fals Probentemp gleich Kältebadtemp ist
14
        {
15
16
         //ins Wärmebad fahren)
17
         //PORTB &= ~ (1<<CCW);
18
         PORTB |= (1<<CW); 
19
        }
20
      }
21
         
22
      //Wenn Taster vom Wärmebad an (d.h. Probe ist im Wärmebad)
23
      if((PINB & (1<<WB)))
24
      {
25
        //Motor erst mal grundlegend ausschalten, um einen definierten Startwert zu haben
26
      PORTB &= ~ (1<<CCW);  //Motor aus
27
      PORTB &= ~ (1<<CW);    //Motor aus
28
        
29
      
30
        if((p_temp >= w_temp))// fals Probentemp gleich Wärmebadtemp ist
31
        {
32
         //ins Kältebad fahren
33
         //PORTB &= ~ (1<<CW);
34
         PORTB |= (1<<CCW);
35
         
36
        }
37
      }

von Frank L. (franklink)


Lesenswert?

Hallo,
zeig mal Deine Initialisierung der Ports vorallem der Eingänge.
Desweiteren solltest Du Dir um die Entprellung des/der Taster noch 
Gedanken machen, falls Du sie nicht hardwaremässig bereits entprellt 
hast.

Gruß
Frank

von oszi40 (Gast)


Lesenswert?

Mechanische Trägheit und Hysterese der Sensoren bedacht?

von Reiner (Gast)


Lesenswert?

Das sollte mit einer Ablaufkette (State Machine) programmiert werden.
Nur mit Abfragen zu arbeiten für in der Regel zu instabilen Systemen.

wenn k_temp <= k_soll und p_temp == k_temp
dann setzen Motor zum Wärmebad

wenn Endschalter Wärmebad
dann rücksetzen Motor zum Wärmebad

warte Zeit x Sekunden für Messung

wenn w_temp >= w_soll und p_temp == w_temp
dann setzen Motor zum Kältebad

wenn Endschatler Kältebad
dann rücksetzen Motor zum Kältebad

warte Zeit x Sekunden für Messung

zurück zum Anfang

Gruß Reiner

von Rocco L. (kaufparkangucker)


Lesenswert?

Tasten entprellen ist Neuland, habe mir angesehen was die Idee dahinter 
ist, kann es aber nicht programmiertechnisch umsetzen... Reicht es im 
einfachsten Fall delay_us() auszuführen?
Kann mir jemand mal soetwas an meinem Programm zeigen damit ich verstehe 
wie so etwas aussehen muss?

Hoffe der Code ist nicht zu lang
1
//B2 Taster K?ltebad
2
//B3 Taster W?rmebad
3
4
5
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
#define F_CPU 2000000
9
#include <util/delay.h>
10
#include <inttypes.h>
11
#include <stdint.h>
12
13
#define TRUE 1
14
#define FALSE 0
15
16
// Anchlussbelegung:
17
18
#define KTEMP_DDR DDRD        //Temperatur Input vom Kältebad
19
#define WTEMP_DDR DDRC        //Temperatur Input vom Wärmebad
20
#define PTEMP_DDR DDRA        //Temperatur Input von Probe
21
22
#define MOTOR_DDR DDRB        //Datenrichtung zum Motor-Steuer-Atmega festlegen
23
#define MOTOR_OUT PORTB        //Ausgänge zum Motor-Steuer-Atmega
24
#define MOTOR_IN  PINB
25
26
#define CW   PB0          //Motor cw richtung Kältebad
27
#define CCW  PB1          //Motor ccw richtung Wärmebad
28
#define KB   PB2          //Taster Kältebad abfragen 
29
#define WB   PB3          //Taster Wärmebad abfragen
30
31
32
int main(void)
33
{
34
    uint8_t w_temp = 0;          //Variable zum speichern der Zustände vom Wärmebad
35
    uint8_t k_temp = 0;          //Variable zum speichern der Zustände vom Kältebad
36
    uint8_t p_temp = 0;          //Variable zum speichern der Zustände von der Probe
37
         
38
        const uint16_t pause = 200;
39
    const uint16_t pause_2 =80;
40
    
41
    
42
    KTEMP_DDR = 0x00;    //Eing?nge D
43
        WTEMP_DDR = 0x00;    //Eing?nge C
44
    PTEMP_DDR = 0x00;    //Eing?nge A
45
46
    //B0 un B1 als Ausgänge, B2 und B3 als Eingänge:
47
    MOTOR_DDR = (1 << DDB0) | (1 << DDB1);
48
49
    //Pause für 20 Sekunden damit alles andere initialisieren kann
50
    for(int a=0; a<20; a++){_delay_ms( 1000 );}
51
52
        do
53
        {
54
      k_temp = 0;          
55
      p_temp = 0;          
56
      w_temp = 0;          
57
  
58
      //Temperaturen von den LED Anzeigen abholen.
59
      if ( PINA & (1<<PINA0) ) {p_temp = p_temp + 1;}
60
      if ( PINA & (1<<PINA1) ) {p_temp = p_temp + 2;}
61
      if ( PINA & (1<<PINA2) ) {p_temp = p_temp + 4;}
62
      if ( PINA & (1<<PINA3) ) {p_temp = p_temp + 8;}
63
      if ( PINA & (1<<PINA4) ) {p_temp = p_temp + 10;}
64
      if ( PINA & (1<<PINA5) ) {p_temp = p_temp + 20;}
65
      if ( PINA & (1<<PINA6) ) {p_temp = p_temp + 40;}
66
      if ( PINA & (1<<PINA7) ) {p_temp = p_temp + 80;}
67
68
      if ( PINC & (1<<PINC0) ) {w_temp = w_temp + 1;}
69
      if ( PINC & (1<<PINC1) ) {w_temp = w_temp + 2;}
70
      if ( PINC & (1<<PINC2) ) {w_temp = w_temp + 4;}
71
      if ( PINC & (1<<PINC3) ) {w_temp = w_temp + 8;}
72
      if ( PINC & (1<<PINC4) ) {w_temp = w_temp + 10;}
73
      if ( PINC & (1<<PINC5) ) {w_temp = w_temp + 20;}
74
      if ( PINC & (1<<PINC6) ) {w_temp = w_temp + 40;}
75
      if ( PINC & (1<<PINC7) ) {w_temp = w_temp + 80;}
76
77
      if ( PIND & (1<<PIND0) ) {k_temp = k_temp + 1;}
78
      if ( PIND & (1<<PIND1) ) {k_temp = k_temp + 2;}
79
      if ( PIND & (1<<PIND2) ) {k_temp = k_temp + 4;}
80
      if ( PIND & (1<<PIND3) ) {k_temp = k_temp + 8;}
81
      if ( PIND & (1<<PIND4) ) {k_temp = k_temp + 10;}
82
      if ( PIND & (1<<PIND5) ) {k_temp = k_temp + 20;}
83
      if ( PIND & (1<<PIND6) ) {k_temp = k_temp + 40;}
84
      if ( PIND & (1<<PIND7) ) {k_temp = k_temp + 80;}
85
86
      //+-2 damit das Testen schneller geht.
87
      k_temp = k_temp + 2;
88
      w_temp = w_temp - 2;
89
90
      //Wenn Taster vom K?ltebad an (d.h. Probe ist im Kältebad)
91
      if((PINB & (1<<KB)))
92
      {
93
        //Motor erst mal grundlegend ausschalten, um einen definierten Startwert zu haben
94
      PORTB &= ~ (1<<CCW);  //Motor aus
95
      PORTB &= ~ (1<<CW);    //Motor aus
96
97
98
        if((p_temp <= k_temp))   //fals Probentemp gleich Kältebadtemp ist
99
        {
100
101
         //ins Wärmebad fahren)
102
         //PORTB &= ~ (1<<CCW);
103
         PORTB |= (1<<CW); 
104
        }
105
      }
106
         
107
      //Wenn Taster vom Wärmebad an (d.h. Probe ist im Wärmebad)
108
      if((PINB & (1<<WB)))
109
      {
110
        //Motor erst mal grundlegend ausschalten, um einen definierten Startwert zu haben
111
      PORTB &= ~ (1<<CCW);  //Motor aus
112
      PORTB &= ~ (1<<CW);    //Motor aus
113
        
114
      
115
        if((p_temp >= w_temp))// fals Probentemp gleich Wärmebadtemp ist
116
        {
117
         //ins Kältebad fahren
118
         //PORTB &= ~ (1<<CW);
119
         PORTB |= (1<<CCW);
120
         
121
        }
122
      }
123
124
        } //ENDE do
125
    while(1);
126
127
} //ENDE main

von Frank L. (franklink)


Lesenswert?

Hallo,
schaumal in die Codesammlung, da findest Du einige Routinen zu diesem 
Thema, zusätzlich gibt es in der Artikelsammlung noch einen Artikel 
dazu.

Gruß
Frank

von Sam .. (sam1994)


Lesenswert?

Ist das nicht ein bisschen overkill: 4 Megas für eine Aufgabe, die einer 
erledigen könnte?

von Rocco L. (kaufparkangucker)


Lesenswert?

Die 4 Atmegas sind auf jeden Fall zu viele. Ich habe das Projekt 
angefangen, weil ich so ein Gerät unbedingt brauche. allerdings habe ich 
programmieren auch parallel dazu gelernt. Bin und war also Einsteiger.
Ich hoffe Ihr helft mir trotzdem.

Entprellen würde ich damit, weil ich hier zumindest noch den code 
kapiere, alle anderen Routinen sind mir zu kompliziert um sie zum 
verstehen:
1
unsigned char PINC_clean(){
2
    wait_ms(20);
3
    return PINC;
4
  }

^^ich weis nur nicht wo ich die Funktion aufrufen soll?
Schreiben würde ich das ganze vor der main.

Danke für die Hilfe

von Klaus (Gast)


Lesenswert?

Das da oben soll nicht im Ernst ein Schaltplan sein, oder???

von Sam .. (sam1994)


Lesenswert?

Vergiss das mit dem Warten mal ganz schnell und benutze es nie wieder!

Die gebräuchlichste Methode zum Entprellen ist Mehrfaches Messen. D.h. 
der Eingang wird mehrmals gemessen und wenn er bei allen Messungen wahr 
war gilt es als Tastendruck.

Z.b. 4 Messungen:
1 1 0 1 --> Taste nicht gedrückt
1 1 1 1 --> Taste gedrückt

Das ganze wird mit einem Zähler in Verbindung mit einem Timer 
realisiert.

Wenn der Timer überläuft, wird geprüft ob die Taste gedrückt ist, wenn 
ja wird der Zähler erhöht wenn nein auf 0 gesetzt. Erreicht der Zähler 
den Wert x gilt die Taste als gedrückt.

Probier das mal aus selbst zu schreiben - dann hast du es auch 
verstanden.

PS: Ich habe noch nie mehrere Avs gleichzeitig benutzt. Aber schon viele 
Tasten mit einem entprellt. Das letztere ist deutlich einfacher.

von Rocco L. (kaufparkangucker)


Lesenswert?

mag sein, aber noch einmal: ICH BIN ANFÄNGER! Alles was ich weis ist 
irgendwie selbst angelesen und durch Probieren entstanden.

Ich bräuchte immer noch einen Tip wie ich die Tastenentprellung in 
meinen Code einbauen soll. Ich würde ja die Super-Entprell Routine von 
Peter Dannegger nehmen, aber davon kapier ich rein garnichts.

Ich versuch es mal mit der Warteschleifenvariante mit Maske und Pointer 
(nach Christian Riggenbach).
http://www.mikrocontroller.net/articles/Entprellung

Trotzdem macht es nicht was es soll. Ich habe ja 3 DS18S20 (je einen im 
Kältebad, einen im Wärmebad und einen zur Probentemperaturermittlung). 
Im Kältebad werden 7°C angezeigt, Im Wärmebad 36°C und die Probe hat 
22°C.
Laut meinem Programm sollte sich der Motor nun nicht drehen, bis Die 
Brobe die Temperatur vom Kältebad angenommen hat...Motor dreht sich aber 
trotzdem. << ich hoffe da sieht einer von Euch den Fehler

Damit sieht der Code nun so aus:
1
//B2 Taster K?ltebad
2
//B3 Taster W?rmebad
3
4
5
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
#define F_CPU 2000000
9
#include <util/delay.h>
10
#include <inttypes.h>
11
#include <stdint.h>
12
13
#define TRUE 1
14
#define FALSE 0
15
16
// Anchlussbelegung:
17
18
#define KTEMP_DDR DDRD        //Temperatur Input vom Kältebad
19
#define WTEMP_DDR DDRC        //Temperatur Input vom Wärmebad
20
#define PTEMP_DDR DDRA        //Temperatur Input von Probe
21
22
#define MOTOR_DDR DDRB        //Datenrichtung zum Motor-Steuer-Atmega festlegen
23
#define MOTOR_OUT PORTB        //Ausgänge zum Motor-Steuer-Atmega
24
#define MOTOR_IN  PINB
25
26
#define CW   PB0          //Motor cw richtung Kältebad
27
#define CCW  PB1          //Motor ccw richtung Wärmebad
28
#define KB   PB2          //Taster Kältebad abfragen 
29
#define WB   PB3          //Taster Wärmebad abfragen
30
31
void entprellung( volatile uint8_t *port, uint8_t maske ) {
32
  uint8_t   port_puffer;
33
  uint8_t   entprellungs_puffer;
34
 
35
  for( entprellungs_puffer=0 ; entprellungs_puffer!=0xff ; ) {
36
    entprellungs_puffer<<=1;
37
    port_puffer = *port;
38
    _delay_us(150);
39
    if( (*port & maske) == (port_puffer & maske) )
40
      entprellungs_puffer |= 0x01;
41
  }
42
}
43
44
45
int main(void)
46
{
47
    uint8_t w_temp = 0;          //Variable zum speichern der Zustände vom Wärmebad
48
    uint8_t k_temp = 0;          //Variable zum speichern der Zustände vom Kältebad
49
    uint8_t p_temp = 0;          //Variable zum speichern der Zustände von der Probe
50
         
51
        const uint16_t pause = 200;
52
    const uint16_t pause_2 =80;
53
    
54
    
55
    KTEMP_DDR = 0x00;    //Eing?nge D
56
        WTEMP_DDR = 0x00;    //Eing?nge C
57
    PTEMP_DDR = 0x00;    //Eing?nge A
58
59
    //B0 un B1 als Ausgänge, B2 und B3 als Eingänge:
60
    MOTOR_DDR = (1 << DDB0) | (1 << DDB1);
61
62
    //Pause für 20 Sekunden damit alles andere initialisieren kann
63
    for(int a=0; a<20; a++){_delay_ms( 1000 );}
64
65
        do
66
        {
67
      k_temp = 0;          
68
      p_temp = 0;          
69
      w_temp = 0;          
70
  
71
      //Temperaturen von den LED Anzeigen abholen.
72
      if ( PINA & (1<<PINA0) ) {p_temp = p_temp + 1;}
73
      if ( PINA & (1<<PINA1) ) {p_temp = p_temp + 2;}
74
      if ( PINA & (1<<PINA2) ) {p_temp = p_temp + 4;}
75
      if ( PINA & (1<<PINA3) ) {p_temp = p_temp + 8;}
76
      if ( PINA & (1<<PINA4) ) {p_temp = p_temp + 10;}
77
      if ( PINA & (1<<PINA5) ) {p_temp = p_temp + 20;}
78
      if ( PINA & (1<<PINA6) ) {p_temp = p_temp + 40;}
79
      if ( PINA & (1<<PINA7) ) {p_temp = p_temp + 80;}
80
81
      if ( PINC & (1<<PINC0) ) {w_temp = w_temp + 1;}
82
      if ( PINC & (1<<PINC1) ) {w_temp = w_temp + 2;}
83
      if ( PINC & (1<<PINC2) ) {w_temp = w_temp + 4;}
84
      if ( PINC & (1<<PINC3) ) {w_temp = w_temp + 8;}
85
      if ( PINC & (1<<PINC4) ) {w_temp = w_temp + 10;}
86
      if ( PINC & (1<<PINC5) ) {w_temp = w_temp + 20;}
87
      if ( PINC & (1<<PINC6) ) {w_temp = w_temp + 40;}
88
      if ( PINC & (1<<PINC7) ) {w_temp = w_temp + 80;}
89
90
      if ( PIND & (1<<PIND0) ) {k_temp = k_temp + 1;}
91
      if ( PIND & (1<<PIND1) ) {k_temp = k_temp + 2;}
92
      if ( PIND & (1<<PIND2) ) {k_temp = k_temp + 4;}
93
      if ( PIND & (1<<PIND3) ) {k_temp = k_temp + 8;}
94
      if ( PIND & (1<<PIND4) ) {k_temp = k_temp + 10;}
95
      if ( PIND & (1<<PIND5) ) {k_temp = k_temp + 20;}
96
      if ( PIND & (1<<PIND6) ) {k_temp = k_temp + 40;}
97
      if ( PIND & (1<<PIND7) ) {k_temp = k_temp + 80;}
98
99
      //+-2 damit das Testen schneller geht.
100
      k_temp = k_temp + 2;
101
      w_temp = w_temp - 2;
102
103
      //Wenn Taster vom K?ltebad an (d.h. Probe ist im Kältebad)
104
      entprellung( &PINB, (1<<PINB2) ); // ggf. Prellen abwarten
105
      if((PINB & (1<<KB)))
106
      {
107
        //Motor erst mal grundlegend ausschalten, um einen definierten Startwert zu haben
108
      PORTB &= ~ (1<<CCW);  //Motor aus
109
      PORTB &= ~ (1<<CW);    //Motor aus
110
111
112
        if((p_temp <= k_temp))   //fals Probentemp gleich Kältebadtemp ist
113
        {
114
115
         //ins Wärmebad fahren)
116
         //PORTB &= ~ (1<<CCW);
117
         PORTB |= (1<<CW); 
118
        }
119
      }
120
         
121
      //Wenn Taster vom Wärmebad an (d.h. Probe ist im Wärmebad)
122
      entprellung( &PINB, (1<<PINB3) ); // ggf. Prellen abwarten
123
      if((PINB & (1<<WB)))
124
      {
125
        //Motor erst mal grundlegend ausschalten, um einen definierten Startwert zu haben
126
      PORTB &= ~ (1<<CCW);  //Motor aus
127
      PORTB &= ~ (1<<CW);    //Motor aus
128
        
129
      
130
        if((p_temp >= w_temp))// fals Probentemp gleich Wärmebadtemp ist
131
        {
132
         //ins Kältebad fahren
133
         //PORTB &= ~ (1<<CW);
134
         PORTB |= (1<<CCW);
135
         
136
        }
137
      }
138
139
        } //ENDE do
140
    while(1);
141
142
} //ENDE main

Gruß Rocco

von Helmut L. (helmi1)


Lesenswert?

Rocco L. schrieb:
> if ( PIND & (1<<PIND0) ) {k_temp = k_temp + 1;}
>       if ( PIND & (1<<PIND1) ) {k_temp = k_temp + 2;}
>       if ( PIND & (1<<PIND2) ) {k_temp = k_temp + 4;}
>       if ( PIND & (1<<PIND3) ) {k_temp = k_temp + 8;}
>       if ( PIND & (1<<PIND4) ) {k_temp = k_temp + 10;}
>       if ( PIND & (1<<PIND5) ) {k_temp = k_temp + 20;}
>       if ( PIND & (1<<PIND6) ) {k_temp = k_temp + 40;}
>       if ( PIND & (1<<PIND7) ) {k_temp = k_temp + 80;}

Das geht auch einfacher.

k_temp = PIND;

von Sam .. (sam1994)


Lesenswert?

Ich weiß dass du Anfänger bist, aber du machst dir das Leben unnötig 
kompliziert. Ein Avr reicht. Und Warteschleifen sollte man halt nur bei 
Initialisierungen verwenden. Schreibe dir deine eigene Entprellroutine 
und du wirst es verstehen. Es nützt nichts 90% des Prozessors mit warten 
zu verbraten, dafür aber dann 5 Stück zu nehmen.

von Peter D. (peda)


Lesenswert?

Helmut Lenzen schrieb:
> Das geht auch einfacher.
>
> k_temp = PIND;

Das ist nicht das gleiche, aber das hier:
1
uint8_t bcd2bin( uint8_t val )
2
{
3
  return (val & 0x0F) + (val >> 4) * 10;
4
}
5
6
k_temp = bcd2bin( PIND );
7
p_temp = bcd2bin( PINC );
8
w_temp = bcd2bin( PINB );


Peter

von Rocco L. (kaufparkangucker)


Lesenswert?

Helmut Lenzen schrieb:
> Rocco L. schrieb:
>> if ( PIND & (1<<PIND0) ) {k_temp = k_temp + 1;}
>>       if ( PIND & (1<<PIND1) ) {k_temp = k_temp + 2;}
>>       if ( PIND & (1<<PIND2) ) {k_temp = k_temp + 4;}
>>       if ( PIND & (1<<PIND3) ) {k_temp = k_temp + 8;}
>>       if ( PIND & (1<<PIND4) ) {k_temp = k_temp + 10;}
>>       if ( PIND & (1<<PIND5) ) {k_temp = k_temp + 20;}
>>       if ( PIND & (1<<PIND6) ) {k_temp = k_temp + 40;}
>>       if ( PIND & (1<<PIND7) ) {k_temp = k_temp + 80;}
>
> Das geht auch einfacher.
>
> k_temp = PIND;

^^das geht nicht, weil die Temp über ein Pseudobinäres LED Array 
ausgegeben und eingelesen wird. So wird die Temp an die LED ausgegeben 
und kann durch adieren der brennenden LED abgelesen werden:
1
           //Konfiguration der Pins für LEDs setzen
2
                // (0 = LED an, 1 = LED aus)
3
                if(tC >= 80) { p |=(1<<7); tC -= 80; } //Pin7 f?r 80?C an
4
                if(tC >= 40) { p |=(1<<6); tC -= 40; } //Pin6 f?r 40?C an
5
                if(tC >= 20) { p |=(1<<5); tC -= 20; } //Pin5 f?r 20?C an
6
                if(tC >= 10) { p |=(1<<4); tC -= 10; } //Pin4 f?r 10?C an
7
                if(tC >= 8)  { p |=(1<<3); tC -= 8;  } //Pin3 f?r 8?C  an
8
                if(tC >= 4)  { p |=(1<<2); tC -= 4;  } //Pin2 f?r 4?C  an
9
                if(tC >= 2)  { p |=(1<<1); tC -= 2;  } //Pin1 f?r 2?C  an
10
                if(tC >= 1)  { p |=(1<<0); tC -= 1;  } //Pin0 f?r 1?C  an

Immernoch dreht sich der Motor einfach so, obwohl die Probentemperatur 
noch nicht <= der Kältebadtemperatur ist...

von Helmut L. (helmi1)


Lesenswert?

@Peter

Stimmt, hatte im lesen nicht gesehen das die Werte Dezimal und nicht in 
Hex sind.  Bei 10,20,40,80  liesst man irgendwie automatisch immer Hex. 
Aber deine Lösung ist ja auch wesentlich einfacher als die 
ursprüngliche.

von Peter D. (peda)


Lesenswert?

Reiner schrieb:
> Das sollte mit einer Ablaufkette (State Machine) programmiert werden.

Sehe ich auch so.
Das ist die Methode, um beliebige Abläufe verstehbar und zuverlässig zu 
implementieren.
Und dann sieht man auch, ob es wirklich am Entprellen liegen könnte.

In Deinem Code kann ich jedenfalls nicht durchsteigen.
Liegt zum Teil auch daran, daß Du die Forenregeln mißachtest:
1
Wichtige Regeln - erst lesen, dann posten!
2
3
    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang


Peter

von Rocco L. (kaufparkangucker)


Angehängte Dateien:

Lesenswert?

@Peter, ok, das habe ich übersehen, war garnicht mit Absicht. Ich hänge 
es nochmal an.

Ich kann ansonsten nochmal versuchen den Code etwas besser zu Ordnen - 
weis aber nicht ob das die Sache wirklich besser macht ;)

Gruß Rocco

von Peter D. (peda)


Lesenswert?

Eine State-Maschine hat etwa dieses Gerüst:
1
#include <avr/io.h>
2
3
enum { RESET, STOP_KALT, FAHRT_WARM, STOP_WARM, FAHRT_KALT };
4
5
void init()
6
{
7
  // hier alles Init-Zeugs
8
}
9
10
int main()
11
{
12
  uint8_t state = RESET;
13
14
  init();
15
  
16
  for(;;){                      // Main-Loop
17
    switch( state ){
18
      case RESET:
19
                        // teste Bedingung
20
                        state = STOP_KALT;      // Aktion
21
                        break;
22
      case STOP_KALT:
23
                        // teste Bedingung
24
                        // Aktion
25
                        break;
26
      case STOP_WARM:
27
                        // teste Bedingung
28
                        // Aktion
29
                        break;
30
      case FAHRT_KALT:
31
                        // teste Bedingung
32
                        // Aktion
33
                        break;
34
      case FAHRT_WARM:
35
                        // teste Bedingung
36
                        // Aktion
37
                        break;
38
    }
39
  }
40
}


Rocco L. schrieb:
> Ich kann ansonsten nochmal versuchen den Code etwas besser zu Ordnen -
> weis aber nicht ob das die Sache wirklich besser macht ;)

Nein.

Peter

von Volkmar D. (volkmar)


Lesenswert?

Hallo,

bei welchen Temperaturen passiert es das der Motor losfährt?

Hast Du kontrolliert, das die Temperaturen richtig gelesen werden?

Wie oft/schnell änderen sich die Temperaturwerte?

Den Vorschlag von Peter Dannegger mit der Funktion bcd2bin() solltest Du 
auf jeden Fall umsetzen, und zwar nicht deswegen weil es eleganter ist 
sondern weil es eine wichtige Fehlerquelle ausschließt: Was passiert 
wenn sich die Temperaturanzeigen ändern während der Prozesser einen Pin 
nach dem anderen abfragt?

Wie werden die Temperatur-Anzeigen angesteuert? Sind das statische 
Signale oder Multiplex-Signale?

Gruß
Volkmar

von Rocco L. (kaufparkangucker)


Angehängte Dateien:

Lesenswert?

Ich habe jetzt versucht nach meinen Möglichkeiten so etwas wie eine 
state machine zu konstruieren.

Soweit passt auch alles. Die switch-case tut auch was sie soll, solange 
ich sc_temp "von Hand" auf 1 oder 2 setze (Zeile 77).

Nutze ich den Vergleich in Zeile 72 / 73 geht es generell nur in 
Richtung Kältebad :(

von Matthias L. (Gast)


Lesenswert?

Du hast das mit der StateMaschine noch nicht so ganz verstanden:
1
void main ( void )
2
{
3
  ...
4
5
  while(1)
6
  {
7
    switch ( state )
8
    //-- warte auf aktion --------------------------------
9
    case 0:
10
      //-- Aktion -------------------
11
      PORTB=...;
12
      //-- weiter? ------------------
13
      if ( ... ) state= 0;
14
      if ( ... ) state= 1;
15
      break;
16
17
    //-- Richtung Wärmebad -------------------------------
18
    case 1:
19
      //-- Aktion -------------------
20
      PORTB=...;  // heizen
21
      //-- weiter? ------------------
22
      if ( ... ) state= 0;
23
      if ( ... ) state= 2;
24
      break;
25
26
    //-- Richtung Kältebad -------------------------------
27
    case 2:
28
      //-- Aktion -------------------
29
      PORTB=...;  // kühlen
30
      //-- weiter? ------------------
31
      if ( ... ) state= 0;
32
      if ( ... ) state= 1;
33
      break;
34
35
    //-- ungültig ----------------------------------------
36
    default:
37
      state:= 0;
38
    }

Das while hat in der Statemaschine nicht zu suchen.

Die
1
if (..) state=
musst du abhängig noch detailieren.

von Helmut L. (helmi1)


Lesenswert?

Was mir an deiner Statemachine auffaellt, man wartet in einer 
Statemachine nicht. Wenn man einen Portpin abfragt in einem State dann 
geht man wenn die Bedingung erfuellt ist zum naechsten State. Also keine 
for oder while Schleifen die auf etwas wrten. Auch sollte man den 
einzelnen States sprechende Namen geben als einfache Ziffern. Wenn du 
das so machst kannst du auch mehrere Aktion quasi gleichzeitig von 
deinem Prozessor steuern lassen.


Also in etwa so:
for(;;)
{
   switch(State) {
   case WARTENPINB:
     if(PINB & (1 << KB)) State = PINBOK;
     break;

   case PINBOK:
     .... und weiter
     State = NEXTSTATE;
     break;
   case NEXTSTATE:
   }

   Hier koennte noch eine weiter Statemachine stehen die einen anderen
   Prozess steuern kann

}

von Peter D. (peda)


Lesenswert?

Rocco L. schrieb:
> Die switch-case tut auch was sie soll, solange
> ich sc_temp "von Hand" auf 1 oder 2 setze (Zeile 77)

Was soll denn sc_temp = 1 oder 2 bedeuten?

Ich hab doch nicht aus purem Jux und Dollerei den Zuständen Namen 
gegeben. Die Zustände sollen beschreiben, was eben gerade gemacht wird. 
Du willst doch das Programm auch verstehen.
Du kannst Dir gerne andere Namen ausdenken. Aber keine Zahlen nehmen, 
das ist Pfui-Bäh.


Und um die Statemaschine gibt es nur ein einziges while und zwar die 
Mainloop.
In der Statemaschine gibt es nur if.
While ist verboten, damit blockierst Du die Statemaschine, sie kann 
nicht mehr arbeiten.
Wie soll in einem while sich ein Zustand ändern oder etwas gemacht 
werden?
Richtig, das geht nicht.


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.