Skocz do zawartości

Jak zapisać warunek dotyczący zmiany stanu na wejściu cyfrowym


Waldek575

Pomocna odpowiedź

Dzień dobry 

Ostatnio w mojej głowie pojawił się pomysł na zrobienie jednej rzeczy opartej o arduino. Większość rzeczy udało mi się zrobić ale teraz stanąłem na jednym szczególe. W projekcie wykorzystuje przełącznik trzy pozycyjny. Jest on podłączony do dwóch pinów cyfrowych i działa w taki sposób że w pierwszej pozycji zwiera jeden pin do masy, w środkowej nic nie zwiera, w ostatniej zwiera drugi pin do masy. I cały problem polega na tym że bezpośrednio po włączeniu zasilania nie chcę aby program w pętli loop był wykonywany. ale po przełączeniu przełącznika z dowolnej pozycji na dowolną(jeśli stan zmieni się na przeciwny) to załącza się pętla loop. 

Link do komentarza
Share on other sites

@Gieneq może nie do końca dobrze napisałem o co mi chodzi ale samo "zatrzymanie" programu można ogarnąć  przy użyciu pętli while ale nie mogę znaleźć tego w jaki sposób zapisać taki warunek wyciągający z tej pętli. Większość warunków wykorzystuje że tak to ujmę wiadome stany, czyli np. jeśli na pinie 10 będzie stan niski to zapal diodę. A ja potrzebuję czegoś takiego co będzie reagowało zarówno przy zmianie z wysokiego na niski, ale będzie też działało przy zmianie z niskiego na wysoki a bez zmiany stanu nie będzie reagowało. Fizycznie ma to wyglądać w ten sposób że po włączeniu zasilania większość przycisków jest nieaktywna. Dopiero po przełączeniu przełącznika 3 pozycyjnego bistabilnego całość zaczyna działać

Link do komentarza
Share on other sites

18 minut temu, Waldek575 napisał:

samo "zatrzymanie" programu można ogarnąć  przy użyciu pętli while ale nie mogę znaleźć tego w jaki sposób zapisać taki warunek wyciągający z tej pętli

O właśnie - i dlatego nie powinno się stosować żadnych "zatrzymujących" pętli typu oczekiwań na zdarzenie (no, są wyjątki, ale najpierw trzeba poznać reguły, potem wyjątki).

Gdybyś tak jak radził @Gieneq zainteresował się maszyną stanów to już byś wiedział, że "nic nie rób" to też czynność i że wspomniana maszyna stanów nie ma nic wspólnego ze stanami pinów...

21 minut temu, Waldek575 napisał:

A ja potrzebuję czegoś takiego co będzie reagowało zarówno przy zmianie z wysokiego na niski, ale będzie też działało przy zmianie z niskiego na wysoki a bez zmiany stanu nie będzie reagowało.

Czyli właśnie maszyny stanów.

 

  • Lubię! 1
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

#include <Servo.h>

int poz = 0;

int czas = 0;

int gora = 0;

int dol = 0;

Servo servo_9;

volatile int stan = 1;

void setup()
{
  pinMode(A6, INPUT); // kat serwo 3v3
  pinMode(A1, INPUT); //predkosc
  pinMode(A0, INPUT);  // max pozycja
  pinMode(A2, INPUT); //min pozycja
  pinMode(5, INPUT);  //3p dol
  pinMode(4, INPUT);  //3p gora
  pinMode(3, INPUT); // monostabilny dół
  pinMode(2, INPUT); // monostabilny gora
  servo_9.attach(9);
 }

void loop(){
  switch(stan) {
   case 1:
     if (???) { //nie wiem jak sformułować ten warunek
        stan = 2;
   break;
   case 2:
    poz = map(constrain(digitalRead(A5), 0, 676), 0, 676, 0, 180);
    czas = map(analogRead(A1), 0, 1023, 10, 60);
    gora = map(analogRead(A0), 0, 1023, 90, 180);
    dol = map(analogRead(A2), 0, 1023, 0, 90);
    if (digitalRead(5) == LOW && poz >= dol) {
      dol = map(analogRead(A2), 0, 1023, 0, 90);
      czas = map(analogRead(A1), 0, 1023, 10, 60);
      poz = (poz - 1);
      servo_9.write(poz);
      delay(czas);
    }
    if (digitalRead(4) == LOW && poz <= gora) {
      gora = map(analogRead(A0), 0, 1023, 90, 180);
      czas = map(analogRead(A1), 0, 1023, 10, 60);
      poz = (poz + 1);
      servo_9.write(poz);
      delay(czas);
    }
    if (digitalRead(5) == LOW && poz < dol) {
      poz = dol;
    }
    if (digitalRead(4) == LOW && poz > gora) {
      poz = gora;
    }
    delay(czas); 
    if (digitalRead(3) == LOW && poz >= dol) {
      dol = map(analogRead(A2), 0, 1023, 0, 90);
      czas = map(analogRead(A1), 0, 1023, 10, 60);
      poz = (poz - 1);
      servo_9.write(poz);
      delay(40); 
    }
    if (digitalRead(2) == LOW && poz <= gora) {
      gora = map(analogRead(A0), 0, 1023, 90, 180);
      czas = map(analogRead(A1), 0, 1023, 10, 60);
      poz = (poz + 1);
      servo_9.write(poz);
      delay(40);
    }

    break;
   }
}

 

Link do komentarza
Share on other sites

Nie, nie, to nie ma nic wspólnego z maszyną stanów oprócz wyglądu.

Jeśli nie chcesz aby Twój program nie reagował na żadne przyciski dopóki coś nie będzie włączone - po prostu sprawdzaj czy to coś jest włączone, i jeśli nie - po prostu nie rób nic. Poza tym nigdzie w programie nie masz reakcji na zmiany stanu czegokolwiek, a wyłącznie na aktualne odczyty z pinów.

Ujmijmy to tak:

void loop()
{
  if (przełącznik_nie_jest_włączony) return;
  // i tu cała zabawa z innymi przełącznikami i potencjometrami
}

Może zacznijmy inaczej: opisz słownie, jak to coś ma reagować na przełączniki (położenia i zmiany położeń). bo na razie napisałeś że czegoś nie wiesz - tyle że my tu niespecjalnie wiemy czego właściwie. Tylko zapomnij na razie o tym że tam istnieje jakieś Arduino, powiedzmy że są przełączniki, potencjometry, jakaś czarna skrzynka którą trzeba zaprojektować i serwo. Dopiero jak będziemy mieć dokładnie określone jaka ma być reakcja programu na wejścia będziemy mogli zacząć cokolwiek projektować.

Na przykład: widzę tu jakąś reakcję na dwa przełączniki "dół", ale nie rozumiem jak one mają działać. Kiedy serwo ma ruszyć, a kiedy nie...

 

 

 

Link do komentarza
Share on other sites

Całość odpowiada za sterowanie jednym serwem które podnosi i opuszcza przedmiot podczepiony do niego. Urządzenie posiada dwa przyciski monostabilne, jeden przełącznik trzy pozycyjny i trzy potencjometry odpowiadające kolejno za prędkość obrotu serwa, granicę obrotu serwa z jednej strony, granicę obrotu z drugiej strony. Załóżmy że przełącznik znajduje się w środkowej pozycji i nie dotykamy przycisków. Wtedy serwo stoi w miejscu. Kiedy przełączymy przełącznik 3 pozycyjny na pozycję dół to serwo opuszcza przedmiot do wysokości ustawionej na potencjometrze tym momencie możemy dokładnie sterować wysokością opuszczania (ale jeśli przestawimy przełącznik na środkową pozycję zanim serwo opuści przedmiot do zadanej wysokości to serwo musi się zatrzymać w tej pocycji w której się znajduje). Całość działa analogicznie dla ostatniej pozycji przełącznika i wysokości podnoszenia. Przyciski monostabilne działają identycznie. Jedyną różnicą jest to że przy ich użyciu nie można regulować prędkości opuszczania/podnoszenia. 

Układ ten działał ale chciałem dodać jeszcze jedną rzecz. Bezpośrednio po podaniu zasilania chcę aby przyciski monostabilne i serwo były nieaktywne. Chcę aby się aktywowały dopiero po przełączeniu przełącznika 3 pozycyjnego. I tutaj jest cała zagwozdka: Po skończeniu pracy i odłączeniu zasilania  przełącznik może znajdować się w dowolnej pozycji. Po ponownym uruchomieniu chcę aby wszystkie funkcje były nieaktywne dopóki nie przełączę przełącznika trzy pozycyjnego

Link do komentarza
Share on other sites

11 godzin temu, Waldek575 napisał:

Chcę aby się aktywowały dopiero po przełączeniu przełącznika 3 pozycyjnego.

No, to teraz jest jasne.

O wykrywaniu zmiany położenia napisano już tu wiele, ale Ty masz dodatkową trudność: wykrycie musi być jednorazowe. Możemy nieco zmienić warunek: niech urządzenie reaguje dopiero wtedy, jeśli przełącznik od momentu włączenia zasilania znalazł się w pozycji neutralnej. Nie zmienia to nic w działaniu: jeśli po włączeniu zasilania przełącznik jest na zerze, i tak trzeba go przełączyć w inne położenie. Jeśli nie, czekamy na zero i dopiero wtedy cały układ może zacząć reagować. Czy coś Ci to przypomina?

Ależ tak, prosty wskaźnik biegu w motocyklu! Wskaźnik pokazuje prawidłowy bieg dopiero wtedy, gdy "złapał" luz, dopóki tego nie zrobi pokazuje błąd[1].

No i teraz życie staje się prostsze (możemy podejrzeć jakieś kilka tysięcy opublikowanych w sieci kodów wskaźnika). Trzeba wprowadzić dodatkową zmienną, np. "zezwolenie". Początkowo ma wartość false, a jeśli przełącznik znajdzie się w pozycji zero zmienia się na true i tak zostaje.

Czyli w kodzie byłoby coś takiego:

bool zezwolenie = false;

void loop()
{
  if (przełącznik na zerze) zezwolenie = true;
  if (!zezwolenie) return;
  // i tu reszta kodu
}

  

Oczywiście, można to zrobić maszyną stanów (co prawda nie do tego ona służy, ale niech już będzie):

switch(StanProgramu) {
    
  case BRAK_ZEZWOLENIA:
    if (przełącznik_na_zerze) {
      stanProgramu = JEST_ZEZWOLENIE;
    }
    break;
    
  case JEST_ZEZWOLENIE:
    // i tu kod pdpowiadający za resztę

Oczywiście warunek "przełącznik_na_zerze" musisz sobie dopisać, ale to już najprostsza prostota 🙂

---

[1] Oczywiście chodzi tu o najprostszy wskaźnik, czyli ze skrzyni biegów dostaję tylko sygnał "luz" a układ w jakiś sposób liczy wychylenia wajchy góra/dół.

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.