Skocz do zawartości

Obsługa przerwań na Arduino


Grzegorz1397

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);
}

 

Link do komentarza
Share on other sites

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
Link do komentarza
Share on other sites

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
Link do komentarza
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
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

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.

 

 

 

Link do komentarza
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

Link do komentarza
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.

 

Link do komentarza
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!

Anonim
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...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.