Ovdje pročitajte kako se registrirati na forum.

Kako prekinuti radnju ?

Zapeli ste s projektom? Ovdje je pravo mjesto za postaviti pitanje. Imajte na umu da ekipa e-radionice neće uvijek i/ili redovno odgovarati na pitanja postavljena u ovom podforumu.
Odgovorite
kresimirvladic#1527
Novak
Novak
Postovi: 2
Pridružen/a: pon lip 10, 2019 9:00 am

Kako prekinuti radnju ?

Post Postao/la kresimirvladic#1527 » sri lip 12, 2019 7:18 pm

Pozdrav svima :D

Početnik sam, danas sam napisao svoj prvi program tj prepisao Lekciju 1 od e-radionice sa youtube-a i sve 5, sve radi.
Onda sam išao korak dalje pa sam dodao funkciju delay(5000); i to se odradilo, dakle ne drži se tipka nego samo kratki impuls preko tipke i LED-ica svijetli 5 sec tj koliko napišem u delayu.

Nakon toga korak dalje, e na tom koraku sam zapeo.

Zahtjev je sljedeći:

Imamo jednu ledicu na pinu 13
tipkalo_1 na pinu 8
tipkalo_2 na pinu 9

1.) Led na 13 pinu je ugašen
2.) Kad pin 9 dobije HIGH impuls LED zasvijetli i svijetli po delayu 5 sec i nakon 5 sec se ona ugasi - TO RADI I SVE 5 :clap:

ALI sada iz nekog razloga (nebitno kojeg) želim prekinuti da ledica svijetli nakon cca 2 sec, tako da čim PIN 9 dobije HIGH impuls preko tipke 2 i da se istog trena LED-ica ugasi. :think:

Hvala na odgovoru

// Lekcija broj 3

Kod: Označite sve

int led1 = 13;
int tipka1 = 8;
int tipka2 = 9;
int stanje_tipka_1=0;
int stanje_tipka_2=0;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(tipka1, INPUT);
  pinMode(tipka2, INPUT);
}

void loop(){

  stanje_tipka_1 = digitalRead(tipka1);
  stanje_tipka_2 = digitalRead(tipka2);

  if (stanje_tipka_1==HIGH &&stanje_tipka_2==LOW){
    //turn LED 0n:
    digitalWrite(led1,HIGH);
    delay(5000);
  }else if (stanje_tipka_2 == HIGH && stanje_tipka_1 == LOW){
    //turn LED Off:
    digitalWrite(led1, LOW);
  
  }
  
}
domagoj#5679
Hobist
Hobist
Postovi: 61
Pridružen/a: ned tra 15, 2018 2:59 pm
Lokacija: Zagreb

Re: Kako prekinuti radnju ?

Post Postao/la domagoj#5679 » sri lip 12, 2019 8:39 pm

Krešo bok!
Ključna stvar je u tome što naredba delay(5000) blokira procesor na 5 sekundi, a to znači da dok ne istekne zadano vrijeme procesor ne radi ništa, pa tako ni ne čita stanje tipki na pinovima 8 i 9. U prikazanom programu to znači da program više čeka, nego se izvršava, pa onda tipke ne reagiraju kako bi čovjek htio. Kao i sve drugo u životu i ovo se može riješiti na više načina, jednostavnije i kompliciranije. Neću ti napisati cijeli program ali te mogu navesti na jedno od rješenja koje bi mogao sam napisati.
Preuredi program na način da broji sekunde, npr. ovako:

Kod: Označite sve

int brojalica;

delay(1000)
brojalica++;
if(brojalica==5)
{
brojalica=0;
//ovdje upiši što želiš da se dogodi na 5 sekundi
}
//ovdje u nastavku stavi provjeru tipki
Dakle, ovaj primjer blokira procesor na 1 sekundu što ipak 5x kraće nego 5 sekundi, pa je interakcija s čovjekom, odnosno odziv tipki puno realniji. Naravno, umjesto delay(1000) se može staviti i kraće vrijeme, npr. delay(100), samo što onda za 5 sekundi uvijet treba biti: if(brojalica=50). U tom slučaju bi odziv tipki bio još bolji jer sekunda je još uvijek dovoljno dugo da odziv tipki nije trenutni.
Pozdrav, Domagoj
kresimirvladic#1527
Novak
Novak
Postovi: 2
Pridružen/a: pon lip 10, 2019 9:00 am

Re: Kako prekinuti radnju ?

Post Postao/la kresimirvladic#1527 » sri lip 12, 2019 9:13 pm

Najljepše ti hvala Domagoj ! Sviđa mi se tvoje poonuđeno riješenje......idem sada probati

Pozz i još jednom Hvala
Avatar
david.zovko#6633
e-radionica.com team
e-radionica.com team
Postovi: 206
Pridružen/a: ned tra 15, 2018 2:59 pm
Lokacija: Osijek, Croatia
Kontakt:

Re: Kako prekinuti radnju ?

Post Postao/la david.zovko#6633 » pon lip 24, 2019 3:05 pm

Pozdrav Krešimire

razlog zašto ne možeš prekinuti to što ti ledica svijetli 5 sekundi, bez obzira što si pritisnuo tipku, je da delay blokira sve ostale radnje i doslovno stoji na mjestu sve dok ne istekne vrijeme. Da bi postigao da možeš prekinuti svoju radnju, ne smiješ koristiti delay. Domagojev pristup je dobar, jer je napravio provjeru svake sekunde umjesto 5 sekundi.

Idealno bi bilo da u bilokojem trenutku se može napraviti promjena. Da bi to postigao, mora se izbjeći korištenje delay-a te koristiti neki drugi način za pauzu. U ovom primjeru koristit ću millis() funkciju koja vraća vrijeme od pokretanja programa u ms. Tako ćemo, uspoređujući dva vremena, znati koliko vremena LEDica radi i kada ju ugasiti.
"Blink without delay" je klasičan primjer kako to odraditi. Službena Arduino stranica ima tutorijal: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
-- probaj sam implementirati taj dio u svoj kod. Ako ne bude išlo, evo rješenja ispod:

Kod: Označite sve

int led1 = 13;
int tipka1 = 8;
int tipka2 = 9;
int stanje_tipka_1 = 0;
int stanje_tipka_2 = 0;

int program_state = 0;
unsigned long startTime = 0;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(tipka1, INPUT);
  pinMode(tipka2, INPUT);
}

void loop() {

  stanje_tipka_1 = digitalRead(tipka1);
  stanje_tipka_2 = digitalRead(tipka2);

  switch (program_state)
  {
    case 0: // ceka se pritisak bilokoje od dvije tipke
      if (stanje_tipka_1 == HIGH && stanje_tipka_2 == LOW) {
        //turn LED 0n:
        program_state = 1;
        startTime = millis(); // zabiljezi stanje pocetka
      } else if (stanje_tipka_1 == LOW && stanje_tipka_2 == HIGH) {
        //turn LED Off:
        program_state = 2;
        startTime = millis(); // zabiljezi stanje pocetka
      }
      break;

    case 1: // pritisnuta je tipka br 1
      // zelimo u ovom stanju ostati 5 sekundi ILI do pristika neke druge tipke
      if (stanje_tipka_1 == HIGH) {
        program_state = 0; // nije proslo 5 sekundi, ali je tipka pritisnuta! vrati se u pocetno stanje
      }
      if ( (millis() - startTime) > 5000) {
        program_state = 0; // proslo je 5 sekundi, vracamo se u pocetno stanje
      }
      break;

    case 2: // pritisnuta je tipka br 2
      if (stanje_tipka_2 == HIGH) {
        program_state = 0; // nije proslo 5 sekundi, ali je tipka pritisnuta! vrati se u pocetno stanje
      }
      if ( (millis() - startTime) > 5000) {
        program_state = 0; // proslo je 5 sekundi, vracamo se u pocetno stanje
      }
      break;
  }
}

Drugi način bi bio spojiti tvoje inpute na interrupt pinove, ali o tome drugom prilikom/ako bude bilo potrebe.. :)
domagoj#5679
Hobist
Hobist
Postovi: 61
Pridružen/a: ned tra 15, 2018 2:59 pm
Lokacija: Zagreb

Re: Kako prekinuti radnju ?

Post Postao/la domagoj#5679 » pon srp 01, 2019 10:10 pm

Krešo bok!
Nisam stigao prije, ali eto sad sam malo preuredio tvoj program na način koji sam prije opisao. Pauzu sam smanjio na 1s i brojim do 5. Nakon toga se ledica sama gasi. Ako se u međuvremenu stisne tipka 2, odmah se ugasi. Kako je delay 1000ms to znači da u najgorem slučaju tipku treba držati barem 1s da bi se detektirala promjena. Kako sam prije napisao, ta 1s se osjeti. Nešto bolji rezultat se dobiva ako se stavi 500ms i broji do 10.
Evo programa:

Kod: Označite sve

int led1 = 13;
int tipka1 = 8;
int tipka2 = 9;
int stanje_tipka_1=0;
int stanje_tipka_2=0;
int brojalica;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(tipka1, INPUT);
  pinMode(tipka2, INPUT);
}

void loop(){

  stanje_tipka_1 = digitalRead(tipka1);
  stanje_tipka_2 = digitalRead(tipka2);

  if(brojalica==0)
    //turn LED Off:
    digitalWrite(led1, LOW);
  else if(brojalica==5)
    brojalica=0; //to će ugasiti ledicu
  else
    brojalica++; //ako nije ni 0 ni 5, uvećaj za 1
  if (stanje_tipka_1==HIGH && stanje_tipka_2==LOW){
    //turn LED 0n:
    digitalWrite(led1,HIGH);
    brojalica=1;
  }
  else if (stanje_tipka_2 == HIGH && stanje_tipka_1 == LOW){
    //turn LED Off:
    digitalWrite(led1, LOW);
  }

  delay(1000);
}
Bolji rezultat se dobiva kako je David opisao. Ja sam za svoje potrebe primjenu funkcije millis() malo preuredio (napisao sam funkciju Pause), pa je u nastavku tvoj program napisan na taj način. U ovom primjeru funkcija Pause je neblokirajuća i izvršit će se kada istekne zadano vrijeme, odnosno kad se jednom aktivira, funkcija vraća false sve dok ne istekne vrijeme kad vrati true. U ovom primjeru sam u isti if stavio i uvjet da je led upaljen kako se funkcija ne bi pozivala ako led ne svijetli. Ali to su već varijacije na temu. Evo programa:

Kod: Označite sve

int led1 = 13;
int tipka1 = 8;
int tipka2 = 9;
int stanje_tipka_1=0;
int stanje_tipka_2=0;
bool led_upaljen=false;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(tipka1, INPUT);
  pinMode(tipka2, INPUT);
}

void loop(){

  stanje_tipka_1 = digitalRead(tipka1);
  stanje_tipka_2 = digitalRead(tipka2);

  if (stanje_tipka_1==HIGH && stanje_tipka_2==LOW){
    //turn LED 0n:
    digitalWrite(led1,HIGH);
    led_upaljen=true;
  }
  else if (stanje_tipka_2 == HIGH && stanje_tipka_1 == LOW){
    //turn LED Off:
    digitalWrite(led1, LOW);
    led_upaljen=false;
  }
  if (led_upaljen && Pause(5000)) {
    //turn LED Off:
    digitalWrite(led1, LOW);
    led_upaljen=false;
  }
}

bool Pause(unsigned long pause) //pause=vrijeme u ms
{
  static bool start; //start=true -> timer je pokrenut
  static unsigned long Start_Time; //vrijeme pokretanja
  unsigned long Current_Time=millis();
  //Serial.println(Current_Time);
  if(pause==0) { start=false; return false; } //ako je vrijeme 0 zaustavlja timer
  if(start!=true) //ako mjerenje nije pokrenuto, pokreni ga
  {
    start=true;
    Start_Time=Current_Time; //očitaj vrijeme pokretanja, može biti i micros()
    return false;
  }
  if(start==true) //ako je mjerenje pokrenuto
  {
    if((Current_Time-Start_Time)>=pause) //ako je prošlo zadano vrijeme zaustavi timer
    {
      start=false; //zaustavlja timer
      return true; //vrijeme je isteklo
    }
    else
      return false; //vrijeme još nije isteklo
  }
}//end Pause

Bok, Domagoj
Odgovorite