Forum: Compiler & IDEs Ausgänge gegenseitig verriegeln


von Georg (Gast)


Lesenswert?

Hallo!

Ich schreibe gerade mein erstes C Programm:
8 Relais, 8 Taster ... Relaispaare 1+2,3+4,5+6,7+8 sollen ggf. 
gegenseitig verriegelt werden:
1
  // Ausgänge verriegeln. Bit0 = 1+2, Bit1 = 3+4, Bit2 = 5+6, Bit3 = 7+8
2
  uint8_t lock = 0b00000000;
3
  
4
  // Status der Relais. Bit0 = 1, ...
5
  uint8_t state = 0b00000000;
6
  
7
  while(1){
8
    // Status der Relais einlesen
9
    // Rueckmeldung von Relais 1
10
    if (PINA & (1<<PA0))
11
    {
12
      // Relais eingeschaltet
13
      state |= (1<<1);
14
    }
15
    else
16
    {
17
      // Relais ausgeschaltet
18
      state &= ~(1<<1);
19
    }
20
    
21
    // Rueckmeldung von Relais 2
22
    if (PINA & (1<<PA1))
23
    {
24
      // Relais eingeschaltet
25
      state |= (1<<2);
26
    }
27
    else
28
    {
29
      // Relais ausgeschaltet
30
      state &= ~(1<<2);
31
    }
32
    
33
    // Eingang 1 wurde gedrückt => Relais 1 umschalten
34
    if (PINB & (1<<PB0))
35
    {
36
      // Relais nur schalten, wenn kein Lock auf Ausgängen existiert UND Ausgang2 ausgeschaltet ist
37
      if (!(state & (1<<2)) || !(lock & (1<<1)))
38
      {
39
        // Relais umschalten
40
        PORTD ^= ( 1 << PD0 );
41
      }
42
      
43
    }
44
    
45
    // Eingang 2 wurde gedrückt => Relais 2 umschalten
46
    if (PINB & (1<<PB1))
47
    {
48
      // Relais nur schalten, wenn kein Lock auf Ausgängen existiert UND Ausgang1 ausgeschaltet ist
49
      if (!(state & (1<<1)) || !(lock & (1<<1)))
50
      {
51
        // Relais umschalten
52
        PORTD ^= ( 1 << PD1 );
53
      }
54
      
55
    }

Wo ich mir nicht sicher bin ist:
1
// Relais nur schalten, wenn kein Lock auf Ausgängen existiert UND Ausgang2 ausgeschaltet ist
2
      if (!(state & (1<<1)) || !(lock & (1<<1)))

Die If Abfrage prüft zuerst ob der andere Ausgang überhaupt 
eingeschaltet ist. Wenn nicht, ist die Prüfung auf Verriegelung obsolet.

Danach prüft es ob es ein Lock gesetzt ist.
Diese Prüfung erfolgt ja NUR, wenn der Ausgang eingeschaltet ist, oder? 
Sonst wäre die erste Bedingung ja schon erfüllt.

Wenn kein Lock, dann auch Freigabe zum einschalten.

Kann das so stimmen? :-)

Danke

Georg

von Georg (Gast)


Lesenswert?

Mir ist gerade aufgefallen, dass am Eingang der aktuelle Status der 
Relais immer anliegt.
Ich bräuchte also nur den Wert des Eingang in meine Variable "state" 
bringen.
1
state = PINA;

das würde passen?

ich möchte den Wert beim Schleifenstart einmal in eine Variable kopieren 
und nicht immer den aktuellen Wert vom Eingang lesen im Code.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Zunächst solltest Du einmal genau formulieren, was der Zweck dieser 
Verriegelung ist. Dann solltest Du Normalzustände, Fehlerzustände, usw. 
identifizieren. Hierbei solltest Du auch darauf achten, dass die Relais 
verzögert gegenüber den Portpins schalten. Dann gilt es zu klären, 
welche formalen Anforderungen bezüglich der funktionalen Sicherheit 
bestehen.

Es macht in der Tat sehr viel Sinn, Unterschiede zwischen Soll- und 
Ist-Zuständen der Relais zu erfassen, um z.B. Defekte zu erkennen. Es 
gibt auch Relais mit zwangsgeführten Kontakten, um verklebte 
Lastkontakte auch auf den Hilfskontakten zu signalisieren.

Und erst nach Klärung all dieser funktionalen Anforderungen sollte man 
damit beginnen, irgendwelchen Programmcode zu schreiben.

Aber wie so viele Leute, die hier Threads eröffnen, verschweigst auch Du 
jegliche Anforderungen an das System... :-(

von Georg (Gast)


Lesenswert?

Hallo Andreas!

Danke für deine Hilfe!

Ich habe den Umfang nicht genau erwähnt, da es mir um die Logik geht.

Gerne formuliere ich die Anwendung besser aus:
Hardware gibt es noch nicht
8 bistabile Relais mit single coil
Relais haben 2 Schließer. Einmal Last, einmal Rückmeldung und LED.

Verriegelung soll optional sein, falls an 2 Ausgängen ein Motor 
angeschlossen wird (Jalousie, Markise, ...)

Es gibt 8 Taster um die Relais zu schalten.
Auch sollen die Relais über UDP geschaltet werden. Aber das mache ich 
später.

Einen definierten Relais Zustand kann ich also nicht schalten. Ich weiß 
aber über die Rückmeldung, wie die Relais stehen.

Georg

von Harald W. (wilhelms)


Lesenswert?

Georg schrieb:

> Ausgänge gegenseitig

Eine "echte" Verriegelung, die z.B. Kurzschlüsse verhindern soll,
sollte man nicht per Software, sondern per Hardware, z.B. über
Relaiskontakte machen.

von Georg (Gast)


Lesenswert?

Hallo Harald!

Interessanter Ansatz.
Aber mit Bistabile Relais wohl nicht ganz einfach durchführbar, oder?

Denn ich muss die Verriegelung ja ein und aus schalten können.

Georg

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Du hast einen Aufbau skizziert, aber nicht die funktionalen 
Anforderungen beschrieben. Man kann ganz dunkel entnehmen, dass das eine 
Baugruppe zur Hausautomatisierung o.ä. werden soll.

Die Motoren von Jalousien und Rolläden werden nur kurzzeitig aktiviert. 
Daher ist es grundsätzlich eine schlechte Idee, hierfür bistabile Relais 
zu verwenden. Wie schon von Harald erwähnt, sollte man die Verriegelung 
auch möglichst in Hardware durchführen.

Ist Dir auch klar, dass man für solche Motoren unbedingt Relais mit 
deutlich höheren Spannungsfestigkeit als 230V verwenden muss, da sich 
die Induktionsspannung der nicht aktivierten Motorwicklung zur 
Netzspannung addiert?

von Georg (Gast)


Lesenswert?

Hallo Andreas!

Motoren benötigen für die Lamellen Stellung kurze Impulse.
Für die Fahrt selbst ist es OK.

Bistabile haben eben Vor und Nachteile.
Die Auswahl des passenden Relais überlasse ich den der die Hardware 
baut.
Aber die erhöhte Spannungsfestigkeit war mir zum Teil bekannt.

Heute werden fast nur mehr Kombiaktoren gebaut/genutzt, die Motoren und 
Licht schalten. Muss nochmal schauen aber meine die sind alle Bistabile.

In dem Thread gings es mir eher um das lernen von C und Logiken.

von Georg (Gast)


Lesenswert?

Hier noch die Antwort von TE Connectivity:
Wenn der Pol für die AC Last keine hohen Einschaltströme (<15A) 
aushalten soll und der Pol für die DC Last einen Strom von >10mA 
schaltet, wäre ein Relais mit AgNi Kontakten möglich.

z.B. mit 2 Schließern RT444F05          3-1415542-1
Contact arrangement 2 form C (CO)
Rated voltage 250VAC
Max. switching voltage 400VAC
Rated current 8A, UL: 10A
Limiting continuous current 8A, UL: 10A
Limiting making current, max. 4s, duty factor 10% 15A
Breaking capacity max. 2000VA
Contact material AgNi 90/10
Frequency of operation, with/without load 900/72000h-1
Operate/Reset time max. 10/5ms
Bounce time max., form A/form B 4/9ms


Welches Relais es genau wird ist aber noch nicht definiert.

von Georg (Gast)


Lesenswert?

Um auf meine Frage zurückzukommen:
Habe nun mal eine Version die zu funktionieren scheint:
1
#define FEEDBACK_DDR    DDRB
2
#define FEEDBACK_PORT   PORTB
3
#define FEEDBACK_PINS   PINB
4
#define FEEDBACK1       0
5
#define FEEDBACK2       1
6
#define FEEDBACK3       2
7
#define FEEDBACK4       3
8
#define FEEDBACK5       4
9
#define FEEDBACK6       5
10
#define FEEDBACK7       6
11
#define FEEDBACK8       7
12
13
#define LED_DDR         DDRC
14
#define LED_PORT        PORTC
15
#define LED_PINS        PINC
16
#define LED_RUNNING     0
17
18
#define RELAY_DDR       DDRD
19
#define RELAY_PORT      PORTD
20
#define RELAY_PINS      PIND
21
#define RELAY1          0
22
#define RELAY2          1
23
#define RELAY3          2
24
#define RELAY4          3
25
#define RELAY5          4
26
#define RELAY6          5
27
#define RELAY7          6
28
#define RELAY8          7

1
// Eingang 1 wurde gedrückt => Relais 1 umschalten
2
    if (get_key_press( 1<<KEY1 ))
3
    {
4
      if ( FEEDBACK_PINS & ( 1<<FEEDBACK1 )) // Relais ist eingeschaltet und kann IMMER gleich ausgeschaltet werden
5
      {
6
        // Relais ausschalten
7
        RELAY_PORT ^= 1 << RELAY1;
8
      }
9
      else // Relais ist ausgeschaltet und soll eingeschaltet werden
10
      {
11
        // Wenn kein lock auf Ausgang 1+2 existiert
12
        if (!( lock_address & ( 1<<0 )))
13
        {
14
          // Relais einschalten
15
          RELAY_PORT ^= ( 1 << RELAY1 );
16
        }
17
        else // Lock existiert
18
        {
19
          if (!( RELAY_PORT & ( 1<< RELAY2 ))) // Wenn Ausgang 2 NICHT eingeschaltet ist
20
          {
21
            // Relais einschalten
22
            RELAY_PORT ^= ( 1 << RELAY1 );
23
          }
24
        }
25
      }
26
      
27
    }
28
    
29
    // Eingang 2 wurde gedrückt => Relais 2 umschalten
30
    if (get_key_press( 1<<KEY2 ))
31
    {
32
      if ( FEEDBACK_PINS & ( 1<<FEEDBACK2 )) // Relais ist eingeschaltet und kann IMMER gleich ausgeschaltet werden
33
      {
34
        // Relais ausschalten
35
        RELAY_PORT ^= 1 << RELAY2;
36
      }
37
      else // Relais ist ausgeschaltet und soll eingeschaltet werden
38
      {
39
        // Wenn kein lock auf Ausgang 1+2 existiert
40
        if (!( lock_address & ( 1<<0 )))
41
        {
42
          // Relais einschalten
43
          RELAY_PORT ^= ( 1 << RELAY2 );
44
        }
45
        else // Lock existiert
46
        {
47
          if (!( RELAY_PORT & ( 1<< RELAY1 ))) // Wenn Ausgang 1 NICHT eingeschaltet ist
48
          {
49
            // Relais einschalten
50
            RELAY_PORT ^= ( 1 << RELAY2 );
51
          }
52
        }
53
      }
54
      
55
    }

Ich habe auch die Debounce Funktion aus dem Forum hier eingebaut. Testen 
kann ich ja erst wenn mein Pollin Board kommt.

Man könnte die 2. else Abfrage auch in die erste IF einbauen:
1
// Eingang 1 wurde gedrückt => Relais 1 umschalten
2
    if (get_key_press( 1<<KEY1 ))
3
    {
4
      if ( FEEDBACK_PINS & ( 1<<FEEDBACK1 )) // Relais ist eingeschaltet und kann IMMER gleich ausgeschaltet werden
5
      {
6
        // Relais ausschalten
7
        RELAY_PORT ^= 1 << RELAY1;
8
      }
9
      else // Relais ist ausgeschaltet und soll eingeschaltet werden
10
      {
11
        // Wenn kein lock auf Ausgang 1+2 existiert ODER ein Lock existiert aber der andere Ausgang ist ausgeschaltet
12
        if (!( lock_address & ( 1<<0 )) || (( lock_address & ( 1<<0 )) & !( RELAY_PORT & ( 1<< RELAY2 ))))
13
        {
14
          // Relais einschalten
15
          RELAY_PORT ^= ( 1 << RELAY1 );
16
        }
17
        
18
      }
19
      
20
    }
einbauen ... aber würde das einen Vorteil bringen?
Einzig der Code würde sich verkürzen.


Danke!

Georg

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.