Stránka 1 z 2

Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 12:45
od rex001
Zdraví, potřebuji poradit, mám naprogramované relé ve smyčce, ale potřebuji ho občas sepnout kapacitním tlačítkem, zkoušel jsem různé varianty ale nemůžu to pořád správně sestavit. Jsem v tom trochu začátečník a určitě mi chybí nějaký základní / banální příkaz.

zatím to mám sestaveno takto:
#define RELE1_PIN 6
#define RELE2_PIN 5
#define pinTlacitko 2

int stavTlacitka = 0;


void setup() {
pinMode(RELE1_PIN, OUTPUT);
pinMode(RELE2_PIN, OUTPUT);
pinMode(pinTlacitko, INPUT);
attachInterrupt(digitalPinToInterrupt(pinTlacitko), prerus, RISING);

}

void loop() {

{ digitalWrite(RELE1_PIN, HIGH);
digitalWrite(RELE2_PIN, HIGH);
delay(10000);
digitalWrite(RELE1_PIN, LOW);
digitalWrite(RELE2_PIN, LOW);
delay(5000); }

{ if (stavTlacitka == HIGH)
digitalWrite(RELE1_PIN, HIGH);
delay (500);
digitalWrite(RELE1_PIN, LOW);
stavTlacitka = LOW;
}
}
void prerus(){
stavTlacitka = HIGH;
}

Předem děkuji.

Re: Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 12:49
od pavel1tu
Kod se vklada pomoci tlacitka </>

Mas tam nejak divne pouzivane zavorky { } u podminek IF
Pokud se nikdo neozve, vecer ti to opravim

Re: Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 13:19
od rex001
Dobře, děkuji. :)

Re: Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 13:54
od rex001
pavel1tu píše:
06 bře 2020, 12:49
Kod se vklada pomoci tlacitka </>

Mas tam nejak divne pouzivane zavorky { } u podminek IF
Pokud se nikdo neozve, vecer ti to opravim
Ještě jsem zkoušel tuhle metodu, ale taky to nefunguje. :D

Kód: Vybrat vše

#define RELE1_PIN 6
#define RELE2_PIN 5 
#define pinTlacitko 2
bool stav1, rezim1;
int stavTlacitka = 0;


void setup() {
 pinMode(RELE1_PIN, OUTPUT);
 pinMode(RELE2_PIN, OUTPUT);
 pinMode(pinTlacitko, INPUT);
}

void loop() {
 
 digitalWrite(RELE1_PIN, HIGH);   //relé1 rozepnuto (záleží také na typu)
 digitalWrite(RELE2_PIN, HIGH);   //relé2 rozepnuto (záleží také na typu)
 delay(10000);                     //1 s čekání
 digitalWrite(RELE1_PIN, LOW);    //relé1 sepnuto (záleží také na typu relé)                 //1 s čekání
 digitalWrite(RELE2_PIN, LOW);    //relé2 sepnuto (záleží také na typu relé)
 delay(5000);{
 stav1 = false;
}
 if (stavTlacitka == HIGH){
 digitalWrite(RELE1_PIN, HIGH);
 delay (500);
 digitalWrite(RELE1_PIN, LOW);
 stavTlacitka = LOW;
 rezim1 = true;
  
}
}
void NastaveniVystupu() {
 digitalWrite(RELE1_PIN, stav1 || rezim1); 
}

Re: Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 15:40
od ondraN
Ta proměnná ošetřovaná v interruptu by měla být definována takto

Kód: Vybrat vše

volatile int stavTlacitka = 0;

Re: Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 16:28
od pavel1tu
Ty delay() jsou v programu kde chceš dělat ještě něco jiného dost naprd
pokud program stojí na delay(), nic jiného nedělá, tak musíš v tom přerušení zpracovat vše co chceš uělat od tlačítka

Takto budou neustále dělat rele
ON - 10s
OFF - 5s
a dokola

když stiskneš tlačítko, tak když bude rele1 OFF se sepne a po 500ms vypne
pokud bude zapnuté, tak se jen po 500ms vypne
(chtělo by to přesný popis co chceš aby to dělalo)

Stisknuti tlacitka musi privest na pin 2 log HIGH

Kód: Vybrat vše

#define RELE1_PIN 6
#define RELE2_PIN 5
#define pinTlacitko 2

volatile int stavTlacitka = 0;


void setup() 
{
  pinMode(RELE1_PIN, OUTPUT);
  pinMode(RELE2_PIN, OUTPUT);
  pinMode(pinTlacitko, INPUT);
  attachInterrupt(digitalPinToInterrupt(pinTlacitko), prerus, RISING);

}

void loop() 
{ // tady se bude pora dokola spinat a vypinat obe rele 
  digitalWrite(RELE1_PIN, HIGH);
  digitalWrite(RELE2_PIN, HIGH);
  delay(10000);
  digitalWrite(RELE1_PIN, LOW);
  digitalWrite(RELE2_PIN, LOW);
  delay(5000); 
}
void prerus()
{  
  detachInterrupt(digitalPinToInterrupt(pinTlacitko));  //pozastavi interup kvuli zakmitum tlacitka
  stavTlacitka = HIGH;            //kdyby bylo potreba jinde
  digitalWrite(RELE1_PIN, HIGH);
  delay (500);
  digitalWrite(RELE1_PIN, LOW);
  stavTlacitka = LOW;            //kdyby bylo potreba jinde
  attachInterrupt(digitalPinToInterrupt(pinTlacitko), prerus, RISING);
}

Re: Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 16:46
od pavel1tu
Tohle je cistsi - nemam jak vyzkouset a jsou tammozna preklepy
prvni smycka zkouma zda ubehlo 5s a pokud jsou rele vypnuty, sepne je
druha smycka zkouma zda ubehlo 10s a pokud jsou rele zapnuty, vypne je
treti smycka provede to co jsi mel predtim, pokud probehlo preruseni od tlacitka
v preruseni se dělá cojsi chtěl + par věci pro jistotu

pokud to nebude fungovat napis, ja si to postavím doma a testnu

Kód: Vybrat vše

#define RELE1_PIN 6
#define RELE2_PIN 5
#define pinTlacitko 2

volatile int stavTlacitka = 0;
unsigned long currentMillis, previousMillis;
int stavRele = 0;

void setup() 
{
  pinMode(RELE1_PIN, OUTPUT);
  pinMode(RELE2_PIN, OUTPUT);
  pinMode(pinTlacitko, INPUT);
  attachInterrupt(digitalPinToInterrupt(pinTlacitko), prerus, RISING);
  previousMillis = millis();   //nacteni casu od spusteni

}

void loop() 
{ // tady se bude zapinat rele po 5s pokud je VYP
   currentMillis = millis();      
   if(currentMillis - previousMillis > 5000 && stavRele == 0) {   
        previousMillis = currentMillis;  
        digitalWrite(RELE1_PIN, HIGH);
        digitalWrite(RELE2_PIN, HIGH);
        stavRele = 1;
   }
   // tady se bude vypinat rele po 10s pokud je ZAP
   if(currentMillis - previousMillis > 10000 && stavRele == 1) {   
        previousMillis = currentMillis;  
        digitalWrite(RELE1_PIN, LOW);
        digitalWrite(RELE2_PIN, LOW);
        stavRele = 0;
   }

  if (stavTlacitka == HIGH) {
      digitalWrite(RELE1_PIN, HIGH);
      delay (500);
      digitalWrite(RELE1_PIN, LOW);
      stavTlacitka = LOW;           
  }


}
void prerus()
{  
  detachInterrupt(digitalPinToInterrupt(pinTlacitko));  //pozastavi interup kvuli zakmitum tlacitka
  stavTlacitka = HIGH; 

  // proti zakmitum tlacitka muze se zrusit pokud nejsou nebo zvetsit pokud jsou velke             
  delay (50);             
  
  attachInterrupt(digitalPinToInterrupt(pinTlacitko), prerus, RISING);  //obnovi interup kvuli zakmitum tlacitka 
}





Re: Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 17:19
od gilhad
obavam se, ze dettachInterrupt sice vymaze danou funkci ze seznamu interruptu (tedy dalsi stisk tlacitka tam nezkusi skocit), ale interrupty sam o sobe nepovoli, takze nasledujici delay() rozhodne nebude fungovat spravne (porad je v kontextu probihajiciho inerruptu) a nejspis Arduino zablokuje zcela (protoze v kontextu interruptu se mu neupdatuje cas)

Re: Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 17:38
od pavel1tu
Takže detachInterrupt zrušit a proti zákmitu dát jen delay() ?
Já ošetřuji tlačítka HW, tak toto neřeším,
tady se to jednou probíralo, že je ideální hned dát "detachInterrupt",
pak zpracovat co se chce při přerušení a opět přerušení zapnout.

Ach, nemám místo kde to vyzkoušet a ani čas ....
Pája pájí - mám jich teprve 6 hotových a ještě 14 mne čeká

Obrázek

Re: Sepnutí relé pomocí kapacitního tlačítka

Napsal: 06 bře 2020, 19:31
od gilhad
Nedavat delay vubec, v interruptu nema co delat.

Nebo pred nim aspon povolit interrupty (v interruptu jsou zakazane).

(ten detach s tim problemem delay vubec nesouvisi)

----

Interruptum je v datasheetu venovano spousta stranek a neni to zcela trivialni. Ale se znacnym zjednodusenim to probiha nejak takto:

Pokud nastane nejaka sance na interrupt (treba je pin stazen dolu), tak se overi, zda je interrupt tohoto typu povolen a kdyz ne, tak se nic nestane.

Pokud jsou interrupty povolene, tak se dokonci rozdelana (ASM) instrukce, zakazou se interrupty, ulozi adresa na zasobnik a skoci na adresu interruptu (do tabulky/vektoru), kde s trochou stesti je skok na osetrujici funkci ci navrat z interruptu (IRET).

Kdyz se zavola IRET (napr. na konci te funkce), tak se povoli interrupty a ze zasobniku se nacte adresa, kam se to vrati a provede aspon jednu instrukci.

Pokud jsou interrupty zakazany, tak se poznaci zdroj interruptu do registru cekajicich interruptu. Az se interrupty povoli (a provede ta jedna instrukce), tak pokud je neco v registru cekajicich interruptu, tak se vycisti+provede interrupt s nejnizsim cislem (tedy zakazi interrupty atd ...). Pokud jsou interrupty zakazane a dojde k nekolikanasobne aktivaci zdroje, tak se tam vzdy zapise priznak (ale nikoli pocet), takze na konci se ten dotycny provede max jednou.

Pokud je i pote neco v registru, tak se postup opakuje.

(Ve skutecnosti je to samozrejme vyrazne slozitejsi)

Attach/detach vlastne jen prepisuji vektor interruptu a povoluji/zakazuji prislusny zdroj - pokud to udelas pri provadeni interruptu, tak se to provadeni stejne dokonci a az pak se povoli dalsi interrupty.

millis ctou neco, co casovy interrupt inkrementuje, tedy pri provadeni interruptu (kdy jsou interrupty zakazany) se jim to neinkrementuje a vraci furt stejnou hodnotu. Pokud interrupt trva dlouho, tak klidne muzou "ztratit" nekolik volani sveho casovace a hodnota se jim zvedne jen jednou o jeden krok. ("ztrati" se udaj o tom, kolikrat to melo inkrementovat = hodiny "stoji/ tiknou jen jednou na konci")

delay mam v .../Arduino/hardware/arduino/avr/cores/arduino/wiring.c okolo radky 106 a zavisi na micros ktere (stejne jako millis) zavisi na TIMER0_OVF_vect coz je interrupt pro timer 0 a ten se pri zakazanych interruptech nespusti, takze delay proste nekonecne ceka, az se zvetsi hodnota, ktera se nemeni (= cti proste to zatuhne).


attach/detach Interrupt jen zmanipuluje vektor interruptu a povoli/zakaze konktertni zdroj, ale celkove interrupty pochopitelne nemeni (nepovoluje/nezakazuje). Na Arduinu od zacatku jsou interrupty povoleny (kvuli milli napr.) takze neni potreba je pri pridani dalsiho povolovat (a naopak by se tim rozbila obsluha stavajicich), detach do vektoru da prazdnou funkci a zakaze zdroj, ale nikoli interrupty celkove (protoze by prestaly jit treba prave ty millis)