Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Pavel.H
Člen
Avatar
Pavel.H:8.12.2016 14:54

Zdravím, poradíte?
Mam na pinu s interuptem připojeno pohybové čidlo.
Při zjištění pohybu se vola funkce detekce.

Potřebují, aby se při detekcí pohybu sepnul pin 22 na 1 minutu.
Pokud za tu minutu je detekován další pohyb, aby se čas prodloužil.
Koukal jen na netu a našel knihovny TimerOne, Timer.h.
Nebo to nějak pořešít přes millis.

 
Odpovědět
8.12.2016 14:54
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Pavel.H
ostrozan:8.12.2016 16:40

Stoprocentně přes timer

při první aktivaci si nastav nějaký příznak a ten shoď po uplynutí času - při každém dalším přerušení pak ten příznak zkontroluj a podle něj buď nastav čas a nebo ne

stačí takhle - zvládneš to?

 
Nahoru Odpovědět
8.12.2016 16:40
Avatar
Pavel.H
Člen
Avatar
Pavel.H:8.12.2016 17:11

To jasně ale použít nějakou tu knihovnu, nebo přes millis?

 
Nahoru Odpovědět
8.12.2016 17:11
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Pavel.H
ostrozan:8.12.2016 23:00

Knihovnu , samozřejmě

 
Nahoru Odpovědět
8.12.2016 23:00
Avatar
Pavel.H
Člen
Avatar
Pavel.H:9.12.2016 9:07

Jsem to zkoušel přes millis a rele si děla co chce.
Co jsem po ?

unsigned long aktualnicas;
unsigned long Time;

void setup() {
  Serial.begin(9600);
  digitalWrite(13, HIGH);
  pinMode(13, OUTPUT);
  aktualnicas = millis();

  pinMode(2, INPUT);
  attachInterrupt(0, detekce, RISING);
}

void loop() {

 if(aktualnicas >= (Time + 60000)){
    digitalWrite(13, HIGH);
    Time = aktualnicas;
  }
}

void detekce() {
  Serial.println("Zaznamenana detekce pohybu");
  digitalWrite(13, LOW);
  aktualnicas = millis();
}
 
Nahoru Odpovědět
9.12.2016 9:07
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na Pavel.H
Martin Dráb:9.12.2016 11:03

Jsi si jistý,k že uvádíš správnou hodnotu prvního parametru funkce attachInterrupt? Také s k ní přčti dokumentaci - https://www.arduino.cc/…achInterrupt. Nezdá se mi, že by bylo vhodné v ní provádět synchronní sériovou komunikaci. Odhadoval bych, že ta funkce detekce je volána v rámci přerušení, takže by měla proběhnout co nejrychleji. A sériová komunikace je pomalá, v závislosti na baudrate může trvat klidně pěkných pár milisekund.

Nahoru Odpovědět
9.12.2016 11:03
2 + 2 = 5 for extremely large values of 2
Avatar
Pavel.H
Člen
Avatar
Pavel.H:9.12.2016 11:46

Jasně, je to jen na zkoušku, pak to půjde pryč.
Vzhledem k tomu že mi stačí jeden pohyb za 1 minutu by to nemělo vadít.
Při každém pohybu se mi to vypisuje.
Ve void loop to mam nějak pokokocene.
if(aktualnicas >= (Time + 60000)

 
Nahoru Odpovědět
9.12.2016 11:46
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Martin Dráb
ostrozan:10.12.2016 7:58

. A sériová komunikace je pomalá, v závislosti na baudrate může trvat klidně pěkných pár milisekund.

"Slušně vychované" (rozuměj dobře napasné) funkce pracující s periferiemi mcu - jako třeba zde arduinovské print/println s USARTem nijak nezdržují program.

ve skutečnosti to funguje tak, že zpráva se uloží do bufferu a pak se nezávisle na programu po jendotlivých bajtech odešle.
Využívá se k tomu přerušení od UDRE (USART data register empty)

void HardwareSerial::_tx_udr_empty_irq(void)
{
  // If interrupts are enabled, there must be more data in the output
  // buffer. Send the next byte
  unsigned char c = _tx_buffer[_tx_buffer_tail];
  _tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE;

  *_udr = c;

  // clear the TXC bit -- "can be cleared by writing a one to its bit
  // location". This makes sure flush() won't return until the bytes
  // actually got written
  sbi(*_ucsra, TXC0);

  if (_tx_buffer_head == _tx_buffer_tail) {
    // Buffer empty, so disable interrupts
    cbi(*_ucsrb, UDRIE0);
  }
}
Editováno 10.12.2016 8:01
 
Nahoru Odpovědět
10.12.2016 7:58
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Pavel.H
ostrozan:10.12.2016 11:36

Nejdřív jsem chtěl napsat, co všechno je ve tvém kódu špatně , ale pak jsem se rozhodl, že ti radši ukážu, jak to má vypadat správně.
Příklad využívá ten Timer, co jsem ti doporučil, ale tys radši zvolil špatné řešení s millis()

knihovnu si stáhni tady

komentáře snad dostatečně vysvětlují, jak se to chová - všimni si taky, že v hlavní smyčce loop() není žádný kód , takže vše funguje "na pozadí" mimo hlavní program

#include <TimerOne.h>

#define PIR 2// pohybove cidlo
#define OUT 13//spinany vystup
unsigned long t1_tick = 1000000;//preruseni kazdych 1000000 us (1 sec)
int nastaveny_cas;//cas sepnuti vystupu po aktivaci z cidla


void setup()
{
        //inicializace timeru a periody, zaroven timer spusti
        Timer1.initialize(t1_tick);
        //jeste ho nepotrebujem, tak ho vypnem
         Timer1.stop();
        //prirazeni funkce,ktera se ma vykonat
        Timer1.attachInterrupt(Counter);

        Serial.begin(9600);
        pinMode(PIR, INPUT);
        pinMode(OUT, OUTPUT);

        //prirazeni vstupu a funkce,ktera se ma vykonat
        attachInterrupt(digitalPinToInterrupt(PIR), detekce, HIGH);
}

void loop()
{

  /* add main program code here */

}

//funkce vykonavana v preruseni od EXT INT
//nastavi cas na 60 sekund
//spusti Timer1
//nastavi pozadovanou hodnotu na vystup
void detekce()
{
        Serial.println("Zaznamenana detekce pohybu");
        nastaveny_cas = 60;
        Timer1.start();
        digitalWrite(OUT, LOW);
}

//funkce vykonavana v preruseni od Timer1
//kazdou sekundu odecte z nastavene hodnoty 1
//po uplynuti doby zastavi timer
void Counter()
{
        if (--nastaveny_cas == 0)
        {
                digitalWrite(OUT, HIGH);
                Timer1.stop();
        }
}

pokud bys chtěl naopak vstup během probíhajícího času blokovat - stačí jednoduchá úprava ve funci detekce()

void detekce()
{
        if (nastaveny_cas != 0)return;// pokud bezi cas odejdi
        Serial.println("Zaznamenana detekce pohybu");
        nastaveny_cas = 6;
        Timer1.start();
        digitalWrite(OUT, LOW);
}
 
Nahoru Odpovědět
10.12.2016 11:36
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na ostrozan
Martin Dráb:10.12.2016 12:38

Jestli je to takto asynchronně, tak pohoda. Jen jsem viděl dost USART knihoven pro MCU, která byly právě napsány dosti primitivně (synchronně). Podonbě I2C.

Nahoru Odpovědět
10.12.2016 12:38
2 + 2 = 5 for extremely large values of 2
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Martin Dráb
ostrozan:10.12.2016 12:45

Arduinovské (oficiální, nebo jimi doporučené) knihovny jsou v tomto ohledu kvalitní

 
Nahoru Odpovědět
10.12.2016 12:45
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 11 zpráv z 11.