Stránka 1 z 2

Zpožděné sepnutí relé 2x spínač s millis

Napsal: 16 srp 2021, 22:53
od johnyhol
Ahoj, potřeboval bych poradit s projektem na automatické zavírání branky po setmění. Mám funkční program, ale funguje pouze pokud ho ovládám jedním spínačem (fotobuňkou). Potřeboval bych ale ještě přidat jeden spínač (koncák pro kontrolu stavu zavřeno/otevřeno), aby po setmění a při otevřené brance po určitém čase sepnulo relé a branka se zavřela. Myslel jsem si, že jenom upravím podmínku, aby se relé sepnulo jen pokud bude sepnutá fotobuňka a zároveň sepnutý spínač koncáku, ale takto to nefunguje. Spíná to i pokud zapnu jenom jeden ze spínačů. Poradí mi prosím někdo co s tím?

Díky

Tady můj kód:

Kód: Vybrat vše

//Automaticke zavirani branky po setmeni.

#define KONCAK 2 // koncak vrat
#define FOTOBUNKA 3 // fotobunka
#define CHODEC 4 // rele ovladani branky - zelena LED
 
unsigned long FotobunkaMillis; // cas sepnuti fotobunky
unsigned long ChodecSepnuto; // CHODEC sepnuto
unsigned long ZpozdeneSepnuti = 5000; // zpozdeni sepnuti
unsigned long ZpozdeneVypnuti = 500; // zpozdeni vypnuti
bool ChodecReady = false; // vypnuti po zpozdeni
bool ChodecStav = false; // stav sepnuti
 
void setup() {
 pinMode(FOTOBUNKA, INPUT);
 pinMode(KONCAK, INPUT);
 pinMode(CHODEC, OUTPUT);
 digitalWrite(CHODEC, LOW);
}
 
void loop() {
 
  unsigned long currentMillis = millis(); 

  //if (digitalRead(FOTOBUNKA) == LOW) { //funkcni, ale pouze s jednim spinacem (fotobunkou)
  if ((digitalRead(FOTOBUNKA) == LOW) && (digitalRead(KONCAK) == LOW)) { //takto to nefunguje 2x spinac (fotobunka+koncak)
     FotobunkaMillis = currentMillis;
     ChodecReady = true;
 }
  
  if (ChodecReady) {
     if ((unsigned long)(currentMillis - FotobunkaMillis) >= ZpozdeneSepnuti) {
     digitalWrite(CHODEC, HIGH);
     ChodecStav = true;
     ChodecSepnuto = currentMillis;
     ChodecReady = false; // odkomentovat pro zmenu reakce na tlacitko - zakom. porad sviti pri drzeni
  }
 }
  
  if (ChodecStav) {
     if ((unsigned long)(currentMillis - ChodecSepnuto) >= ZpozdeneVypnuti) {
     ChodecStav = false;
     digitalWrite(CHODEC, LOW);
  }
 }
}

Re: Zpožděné sepnutí relé 2x spínač s millis

Napsal: 17 srp 2021, 05:12
od gilhad
Nevím, jaké máš schéma, ale předpokládám z kódu, že jak fotobuňka, tak koncák spínají na nulu (zem,LOW), ale máš tam zajištěno, že při rozepnutí se na nich objeví HIGH? Tedy nejspíš nějaký pullup přiměřené velikosti?

Přetrvá problém, i když změníš

Kód: Vybrat vše

 pinMode(FOTOBUNKA, INPUT);
 pinMode(KONCAK, INPUT);
na

Kód: Vybrat vše

 pinMode(FOTOBUNKA, INPUT_PULLUP);
 pinMode(KONCAK, INPUT_PULLUP);
?

Re: Zpožděné sepnutí relé 2x spínač s millis

Napsal: 17 srp 2021, 09:23
od johnyhol
Mám to zapojené jako testovací obvod vždy s pomocným rezistorem proti zemi:
Obrázek

Zkoušel jsem to i jak píšeš s interním odporem (INPUT_PULLUP), ale pořád to nefunguje. Jenom když nechám jedno tlačítko tak to funguje jak má. Pokud to zkouším jako jednoduchý program s delay:

Kód: Vybrat vše

void loop() {

  if ((digitalRead(FOTOBUNKA) == LOW) && (digitalRead(KONCAK) == LOW)){
    
    delay (5000);
  
    digitalWrite(LED, HIGH);
  
    delay (2000);
  
    digitalWrite(LED, LOW);
  
  }else{
    digitalWrite(LED, LOW);
  }
}
tak to taky funguje.

Re: Zpožděné sepnutí relé 2x spínač s millis

Napsal: 17 srp 2021, 10:09
od ondraN
Tak, jak to máš zapojené, je při sepnutí přečtená úroveň HIGH a při rozepnutí úroveň LOW. Pokud chceš udělat nějakou akci, když jsou oba spínače sepnuté tak bude podmínka

Kód: Vybrat vše

if ((digitalRead(FOTOBUNKA) == HIGH) && (digitalRead(KONCAK) == HIGH)) {
//akce pri sepnuti obou
}
Při tomto zapojení nepoužívej INPUT_PULLUP, to by se tlouklo.

Re: Zpožděné sepnutí relé 2x spínač s millis

Napsal: 17 srp 2021, 16:51
od johnyhol
To už jsem zkoušel taky, jen se invertuje styl ovládání, ale pořád to nedělá co má tzn. nespíná to pouze když jsou sepnuty (nebo při obrácené logice vypnuty) oba spínače. Prostě když jeden uvolním/sepnu tak to po nastaveném čase sepne relé i když je podmínka složená. S časováním pomocí millis nemám zkušenosti tak nevím co je v kódu špatně, když to s časováním pomocí delay funguje při stejné podmínce správně.

Re: Zpožděné sepnutí relé 2x spínač s millis

Napsal: 17 srp 2021, 18:20
od Pacok
Zbytocne si podla mna komplikujes zivit.V zapojeni pphonov bran original z obchodu mas tiez na koncakoch len odpojenie motora.Ziadne serepeticky.Tym vies ze ak prejde koncakom nic ti brana neznici.

Re: Zpožděné sepnutí relé 2x spínač s millis

Napsal: 17 srp 2021, 22:00
od johnyhol
Já vím že si komplikuju život, ale nedá mi to spát a tak to chci vyřešit a pak to případně použít i jinde kde aktuálně používám delay.

Re: Zpožděné sepnutí relé 2x spínač s millis

Napsal: 18 srp 2021, 10:25
od kiRRow
Ze sériové linky si vyčti skutečné stavy (neocenitelný pomocník při debugování a trasování programu), co když jedna věc je aktivní HIGH a druhá je aktivní LOW ?

Re: Zpožděné sepnutí relé 2x spínač s millis

Napsal: 26 srp 2021, 06:57
od johnyhol
Ahoj, stavy znám(přesto jsem to ještě prověřil přes sériovou linku), problém je jinde. Po přidání druhé podmínky (když vznikne složená) to reaguje až po znovu sepnutí jednoho ze spínačů a to je špatně. Já potřebuju takovou reakci, že když se rozepnou oba spínače, tak hned začne odpočet (např. 5s) a pak sepne relé na 1s.
Jako je to tady:

Kód: Vybrat vše

//Automaticke zavirani branky po setmeni.

#define KONCAK 2 // koncak vrat
#define FOTOBUNKA 3 // fotobunka
#define CHODEC 4 // rele ovladani branky - zelena LED
 
unsigned long FotobunkaMillis; // cas sepnuti fotobunky
unsigned long ChodecSepnuto; // CHODEC sepnuto
unsigned long ZpozdeneSepnuti = 5000; // zpozdeni sepnuti
unsigned long ZpozdeneVypnuti = 1000; // zpozdeni vypnuti
bool ChodecReady = false; // vypnuti po zpozdeni
bool ChodecStav = false; // stav sepnuti
 
void setup() {
 pinMode(FOTOBUNKA, INPUT);
 pinMode(KONCAK, INPUT);
 pinMode(CHODEC, OUTPUT);
 digitalWrite(CHODEC, LOW);
 Serial.begin(600);
}
 
void loop() {
  
  if ((digitalRead(FOTOBUNKA) == LOW) && (digitalRead(KONCAK) == LOW)) {
     Serial.println("otevreno+tma");
     delay(5000);
     digitalWrite(CHODEC, HIGH);
     delay(1000);
     digitalWrite(CHODEC, LOW);
 }
  if (digitalRead(FOTOBUNKA) == HIGH){
     Serial.println("svetlo");
  }else{
    Serial.println("tma");
 }

  if (digitalRead(KONCAK) == HIGH){
     Serial.println("zavreno");
  }else{
    Serial.println("otevreno");
  }
 }

      

Re: Zpožděné sepnutí relé 2x spínač s millis

Napsal: 26 srp 2021, 10:20
od ondraN
Mohl bys nějak rozumně napsat, jak to má vlastně fungovat? Možná jsem nějak přibržděný, ale stále v tom nemám jasno.
Označ spínače třeba Tma, Open, Rele a vypiš do tabulky co se má stát s označením stavů. To ti pak i velmi pomůže s tvorbou programu.
Např.
Zap-->stav0

stav0 Tma=r, Open=r, -->stav0
Tma=r, Open=s,-->stav0
Tma=s, Open=s, -->Rele=on na 1s, stav1

stav1 Tma=s, Open=r, -->stav1
Tma=s, Open=s,-->stav0
atd.
A pak v programu uděláš nekonečnou smyčku a stavovou proměnou a v příkazu switch budeš řešit jednotlivé akce a přechod mezi stavy. Je to maximálně přehledné a jednoduché na programování. V technické terminologii se tomu říká stavový automat. Je to taky ideální řešení pro zpracování více souběžných činností na jednojádrovém procesoru.