Skocz do zawartości
Grzegorz1397

Obsługa przerwań na Arduino

Pomocna odpowiedź

Cześć, mam problem z przerwaniem na arduino. W pętli loop wykonuje się pętla for. Chciałbym żeby wciśnięcie jednego przycisku monostabilnego wywoływało zatrzymanie pętli do czasu wciśnięcia kolejnego przycisku. Czyli program ma zatrzymać petle for na czas od wciśnięcia jednego przycisku do wciśnięcia drugiego. Program obsługuje elektrozawory. Jeśli w instrukcji przerwania wpisywałem digitalWrite(dol=LOW): podobnie dla góra, lewo i prawo to faktycznie w momencie wciśnięcia przycisku zawory się wyłączały, ale pętla działała zwiększając na wyświetlaczu ilosc wykonanych cykli mimo, że zawory nie działały. Jeśli chcę do wywoływania pauzy programu użyć przycisku monostabilnego to pewnie będę musiał też w funkcji przerwania uwzględnić jakąś pętlę while i zmienną typu logicznego żeby przerwanie wykonywało się do czasu wciśnięcia kolejnego przycisku? Chciałbym prosić o pomoc w napisaniu samego środka funkcji przerwania. Nie do końca wiem też jaka jest praktyczna różnica w wywoływaniu przerwania stanem niskim, a zboczem opadającym.

 for(ilosc_wykonanych; ilosc_wykonanych<liczba_cykli; ilosc_wykonanych) {   
                      lcd.setCursor(3, 0); 
       lcd.print("WYKONANE CYKLE"); 
       lcd.setCursor(8, 1); 
       lcd.print(ilosc_wykonanych); 
       lcd.setCursor(0, 2); 
       lcd.print("ILOSC CYKLI"); 
       lcd.setCursor(11, 2); 
       lcd.print("="); 
       lcd.setCursor(12, 2); 
       lcd.print(liczba_cykli); 
       lcd.setCursor(0, 3); 
       lcd.print("CZAS ZANURZENIA"); 
       lcd.setCursor(15, 3); 
       lcd.print("="); 
       lcd.setCursor(16, 3); 
       lcd.print(t); 
       lcd.setCursor(19, 3);
       lcd.print("S");
       delay(300);
 delay(oczekiwanie);
 digitalWrite(gora, LOW);
 digitalWrite(dol, HIGH);
 delay(czas_zanurzenia);
 digitalWrite(dol, LOW);
 digitalWrite(gora, HIGH);
 delay(oczekiwanie);
 digitalWrite(prawo, LOW);
 digitalWrite(lewo, HIGH);
 delay(oczekiwanie);
 digitalWrite(dol, HIGH);
 digitalWrite(gora, LOW);
 delay(czas_zanurzenia);
 digitalWrite(dol, LOW);
 digitalWrite(gora, HIGH);
 delay(oczekiwanie);
 digitalWrite(lewo, LOW);
 digitalWrite(prawo, HIGH);
 lcd.clear();
ilosc_wykonanych = ilosc_wykonanych + 1;


 
    
 }
 lcd.clear();
 lcd.setCursor(3, 1); 
       lcd.print("KONIEC PROGRAMU");   
       delay(500);
}

 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
for(ilosc_wykonanych; ilosc_wykonanych<liczba_cykli; ilosc_wykonanych++) 
{ 
  ....
  //ilosc_wykonanych=ilosc_wykonanych+1	TO JEST ZBĘDNE  
 |

Taka konstrukcja tej pętli jest lepsza.

Edytowano przez Belferek

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
4 godziny temu, Grzegorz1397 napisał:

Jeśli w instrukcji przerwania wpisywałem digitalWrite(dol=LOW):

To niestety ale źle wpisywałeś. Poprawna składnia tego polecenia to digitalWrite(NR_PINU, STAN); Więc jak to działało nie wiem.

Może zanim użyjesz przerwań zainteresuj się biblioteką Bounce2 i przykładami jej użycia. Biblioteka dostępna jest z poziomu menadżera bibliotek: CTRL+SHIFT+I

Dzięki tej bibliotece wykryjesz zmiany stanu przycisków.

Edytowano przez Belferek

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
#include <LiquidCrystal.h>
#define dol 1
#define gora 0
#define lewo 5
#define prawo 4
#define LM35 A0
long liczba_cykli;
int ilosc_wykonanych;
int czas_zanurzenia;
int t;
int oczekiwanie=1500;
int oczekiwanie1=400; 
float temperatura=0;
#define RS  7      
#define EN  15    //A1
#define D4  16    //A2
#define D5  17    //A3
#define D6  18    //A4
#define D7  19    //A5

LiquidCrystal lcd(RS,EN,D4,D5,D6,D7);

void setup() {
int czas=czas_zanurzenia/1000;
pinMode(0, OUTPUT);
pinMode(2, INPUT_PULLUP);
pinMode(1, OUTPUT);
pinMode(3, INPUT_PULLUP);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
pinMode(13, INPUT_PULLUP);

            lcd.begin(20, 4); 
            lcd.setCursor(6, 0); 
            lcd.print("WITAJ"); 
            delay(3000);
            lcd.clear(); 
            lcd.begin(20, 4); 
          
                      bool cykle = true;
                      while(cykle == true){
                      lcd.clear();
                      lcd.setCursor(4, 0);
                      lcd.print("ILOSC CYKLI");
                      lcd.setCursor(8, 1);
                      lcd.print(liczba_cykli);
                      delay(300);      
    
     if(digitalRead(10) == LOW){
                 delay(500);
                 liczba_cykli=liczba_cykli+1;
                 lcd.clear();
                 lcd.setCursor(4, 0);
                 lcd.print("ILOSC CYKLI =");
                 lcd.setCursor(8, 1);
                 lcd.print(liczba_cykli);
      }
      
  if(digitalRead(9) == LOW){
                    delay(500);
                    liczba_cykli=liczba_cykli+10;
                    lcd.clear();
                    lcd.setCursor(4, 0);
                    lcd.print("ILOSC CYKLI =");
                    lcd.setCursor(8, 1);
                    lcd.print(liczba_cykli);
  } 
  
   if(digitalRead(11) == LOW){
                delay(500);
                liczba_cykli=liczba_cykli+100;
                lcd.clear();
                lcd.setCursor(4, 0);
                lcd.print("ILOSC CYKLI =");
                lcd.setCursor(8, 1);
                lcd.print(liczba_cykli);
   }
   
   if(digitalRead(13) == LOW){
                delay(500);
                liczba_cykli=liczba_cykli+1000;
                lcd.clear();
                lcd.setCursor(4, 0);
                lcd.print("ILOSC CYKLI =");
                lcd.setCursor(8, 1);
                lcd.print(liczba_cykli);
   }
   
     if(digitalRead(8) == LOW){
              delay(500);
              liczba_cykli=liczba_cykli+10000;
              lcd.clear();
              lcd.setCursor(4, 0);
              lcd.print("ILOSC CYKLI =");
              lcd.setCursor(8, 1);
              lcd.print(liczba_cykli);
     }
     
     if(digitalRead(12) == LOW){
            delay(500);
            liczba_cykli=liczba_cykli+100000;
            lcd.clear();
            lcd.setCursor(4, 0);
            lcd.print("ILOSC CYKLI =");
            lcd.setCursor(8, 1);
            lcd.print(liczba_cykli);
}

    if(digitalRead(6) == LOW){
              delay(300);
              cykle = false;
  }
}
                bool zanurzenie = true;
                while(zanurzenie == true){
                   lcd.clear();
                   lcd.setCursor(2, 0);
                   lcd.print("CZAS ZANURZENIA");
                   lcd.setCursor(8, 1);
                   lcd.print(t);
                   lcd.setCursor(12, 1);
                   lcd.print("S");
                   delay(300);      
    
     if(digitalRead(10) == LOW){
           delay(500);
           czas_zanurzenia=czas_zanurzenia+1000;
           t=czas_zanurzenia/1000;
           lcd.clear();
           lcd.setCursor(2, 0);
           lcd.print("CZAS ZANURZENIA =");
           lcd.setCursor(8, 1);
           lcd.print(t);
           lcd.setCursor(12, 1);
           lcd.print("S");
      }
  
    if(digitalRead(9) == LOW){
             delay(500);
             czas_zanurzenia=czas_zanurzenia+10000;
             t=czas_zanurzenia/1000;
             lcd.clear();
             lcd.setCursor(2, 0);
             lcd.print("CZAS ZANURZENIA =");
             lcd.setCursor(8, 1);
             lcd.print(t);
             lcd.setCursor(12, 1);
             lcd.print("S");
  }
  if(digitalRead(6) == LOW){
  delay(300);
  zanurzenie = false;
  }
  
}
              lcd.clear();
              lcd.setCursor(4, 0); 
              lcd.print("URUCHAMIANIE"); 
              lcd.setCursor(6, 1); 
              lcd.print("PROGRAMU");
              delay(3000);
      
      for(int i=5;i>0;i--){
              lcd.clear();
              lcd.setCursor(9,2);
              lcd.print(i);
              delay(1000);
      }
                      lcd.clear();
                      digitalWrite(prawo, HIGH);
                      digitalWrite(gora, HIGH);
                                         
    }
    
void loop(){
  temperatura = ((analogRead(LM35) * 5.0) / 1024.0) * 100;
 lcd.begin(20, 4);
 lcd.noCursor();
 lcd.noBlink();
      for(ilosc_wykonanych; ilosc_wykonanych<liczba_cykli; ilosc_wykonanych++) {   
       lcd.setCursor(0, 0); 
       lcd.print("WYK. CYKLE"); 
       lcd.setCursor(10, 0); 
       lcd.print("="); 
       lcd.setCursor(11, 0); 
       lcd.print(ilosc_wykonanych); 
       lcd.setCursor(0, 1); 
       lcd.print("TEMPERATURA"); 
       lcd.setCursor(11, 1); 
       lcd.print("=");
       temperatura = ((analogRead(LM35) * 5.0) / 1024.0) * 100;
       lcd.setCursor(12, 1); 
       lcd.print(temperatura); 
       lcd.setCursor(17, 1); 
       lcd.print("C");
       lcd.setCursor(0, 2); 
       lcd.print("ILOSC CYKLI"); 
       lcd.setCursor(11, 2); 
       lcd.print("="); 
       lcd.setCursor(12, 2); 
       lcd.print(liczba_cykli); 
       lcd.setCursor(0, 3); 
       lcd.print("CZAS ZANURZENIA"); 
       lcd.setCursor(15, 3); 
       lcd.print("="); 
       lcd.setCursor(16, 3); 
       lcd.print(t); 
       lcd.setCursor(19, 3);
       lcd.print("S");
       delay(300);
 delay(oczekiwanie);
 digitalWrite(gora, LOW);
 digitalWrite(dol, HIGH);
 delay(czas_zanurzenia);
 digitalWrite(dol, LOW);
 digitalWrite(gora, HIGH);
 delay(oczekiwanie1);
 digitalWrite(prawo, LOW);
 digitalWrite(lewo, HIGH);
 delay(oczekiwanie);
 digitalWrite(dol, HIGH);
 digitalWrite(gora, LOW);
 delay(czas_zanurzenia);
 digitalWrite(dol, LOW);
 digitalWrite(gora, HIGH);
 delay(oczekiwanie1);
 digitalWrite(lewo, LOW);
 digitalWrite(prawo, HIGH);
 lcd.clear();

 }
 lcd.clear();
 lcd.setCursor(3, 1); 
       lcd.print("KONIEC PROGRAMU");   
       delay(500);
}

Odświeżam nieco temat, wstawiam cały kod. Program działa tak jak powinien, natomiast nie wiem jak dorobić do niego dwie kwestie:
1. W skrzynce sterowniczej zamontowane są dwa wentylatory. Chciałbym, żeby wentylatory uruchamiały się kiedy czujnik temperatury wskaże powyżej określonej temperatury, załóżmy 30 stopni. 

2. Wciśnięciem jednego przycisku (obojętnie czy monostabliny czy bistabilny) chciałbym wywoływać zastopowanie wykonywania programu. Elektrozawory mają się po prostu zatrzymać, odliczanie w pętli for również do czasu wciśnięcia przycisku kolejny raz. 
Nie wiem jak te dwa problemy poprawnie zrealizować pod względem programowym. Będę wdzięczny za wszelkie sugestie.

Edytowano przez Grzegorz1397
zapomniałem wstawić kod programu

Udostępnij ten post


Link to post
Share on other sites
1 minutę temu, Grzegorz1397 napisał:

wstawiam cały kod

Z ciekawości: gdzie go wstawiasz?

Udostępnij ten post


Link to post
Share on other sites
7 minut temu, Grzegorz1397 napisał:

Będę wdzięczny za wszelkie sugestie.

  1. Wywalić pętlę for w loop()
  2. Wywalić delay

Wiesz jak się do tego zabrać?

Poza tym: wszelkie inicjalizacje lcd (begin, noBlink i tym podobne) mają siedzieć w setup, a nie być wykonywane za każdym obrotem pętli.

 

 

 

Udostępnij ten post


Link to post
Share on other sites
2 minuty temu, ethanak napisał:

Wiesz jak się do tego zabrać?

Niestety nie, nie jestem programistą i wszystko robiłem intuicyjnie. Nie wiem czym zastąpić pętle for i delay. Przy każdym uruchomieniu urządzenia muszę mieć możliwość ustawienia ilości cykli, czasu zanurzenia i właśnie delay ustalam jak długo. Wstawiam zdjęcie urządzenia, żeby ułatwić wyobrażenie co to właściwie ma robić. Czas zanurzenia to czas kiedy siłownik pionowy jest wysunięty. Nie mam pojęcia w jaki sposób sterować tam czasami jeśli nie za pomocą delay. 

91282580_214172203180499_1904244802325577728_n.jpg

Udostępnij ten post


Link to post
Share on other sites
5 minut temu, Grzegorz1397 napisał:

Nie wiem czym zastąpić pętle for i delay.

Przykład na zastąpienie for

Zamiast:

void loop()
{
  int n;
  for (n=0; n< 10; n++) {
    rób_coś();
  }
  rób_jeszcze_cos();
}

robisz:

void loop()
{
  static int n=0;
  if (n < 10) {
    rób_coś();
    n++;
  }
  else {
    rób_coś_innego();
    n=0;
  }
}

Wygląda na bardziej skomplikowane, ale pozostaje tylko jedna główna pętla której już nie trzeba przerywać.

Co do zastąpienia delay czymś bardziej strawnym - o millis() napisano już gigabajty różnych poradników, np. taki: https://forbot.pl/blog/kurs-arduino-ii-wielozadaniowosc-opoznienia-z-millis-id18418

Do tego jak wpiszesz do forumowej wyszukiwarki "delay millis" to parę sensownych wyników dostaniesz.

 

Udostępnij ten post


Link to post
Share on other sites

Już samo wyeliminowanie pętli for i zastąpienie jej if-ami wyeliminowało wszystkie problemy. Na if-ach dodałem też pauzę i uruchomienie wentylatorów, wszystko działa, dziękuję za pomoc.

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...