Skocz do zawartości

Automatyczne sterowanie drzwiami przesuwnymi / enkoder, przerwania


Pomocna odpowiedź

Dzień dobry,

Robię projekt który realizuje otwieranie i zamykanie drzwiami przesuwnymi w trybie automatycznym i ręcznym, pozycja drzwi ustalana jest za pomocą enkodera oraz przerwań w programie. Pytanie moje brzmi jak ustalić w programie że drzwi podczas zamykania lub otwierania się zatrzymały, czyli enkoder przestał zmieniać wartość. W praktyce chodzi o rewers, czyli jak drzwi np przy zamykaniu natrafią na jakąś przeszkodę to odbiją i zaczną się otwierać. Kombinowałem już na wiele różnych sposobów i jak na razie bezskutecznie. 

Poniżej załączam kod na jakim działam.

#define PinA 2
#define PinB 3
#define AR 5
#define O 6
#define Z 7
#define RSD 8
#define RO 9
#define RZ 10
#define PO 11
#define PZ 12
#define PS 13

volatile long ilosc_impulsow = 0;

long x = 30000;    
long y = (x / 5);  
long z = (x / 10); 

void setup()
{
    pinMode(PinA, INPUT);
    pinMode(PinB, INPUT);
    pinMode(AR, INPUT);
    pinMode(O, INPUT);
    pinMode(Z, INPUT);
    pinMode(RSD, INPUT);
    pinMode(RO, INPUT);
    pinMode(RZ, INPUT);
    pinMode(PO, OUTPUT);
    pinMode(PZ, OUTPUT);
    pinMode(PS, OUTPUT);
    pinMode(4, OUTPUT);

    digitalWrite(PO, HIGH);
    digitalWrite(PZ, HIGH);
    digitalWrite(PS, HIGH);

    attachInterrupt(0, blinkA, CHANGE);
    attachInterrupt(1, blinkB, CHANGE);
}

void loop()
{
    if (digitalRead(AR) == HIGH && digitalRead(RSD) == LOW && digitalRead(Z) == HIGH && digitalRead(O) == LOW) 
    {
        while (ilosc_impulsow > 0 ) 
        {
            digitalWrite(PZ, LOW);  
            digitalWrite(PO, HIGH); 
            digitalWrite(PS, HIGH); 
        }
    }

    if (digitalRead(AR) == HIGH && digitalRead(RSD) == LOW && digitalRead(Z) == LOW && digitalRead(O) == HIGH)  
    {
       
        while (ilosc_impulsow < x ) 
        {

            digitalWrite(PZ, HIGH); 
            digitalWrite(PO, LOW);  
            digitalWrite(PS, HIGH); 
        }
    }

    if (digitalRead(AR) == LOW && digitalRead(RSD) == HIGH && digitalRead(RZ) == HIGH && digitalRead(RO) == LOW) 
    {
        
        while (ilosc_impulsow > 0) 
        {
            if (ilosc_impulsow > x - z) 
            {
                digitalWrite(PZ, LOW);  
                digitalWrite(PO, HIGH); 
                digitalWrite(PS, HIGH); 
            }

            if (ilosc_impulsow > y && ilosc_impulsow < x - z) 
            {
                digitalWrite(PZ, LOW);  
                digitalWrite(PO, HIGH); 
                digitalWrite(PS, LOW);  
            }

            if (ilosc_impulsow < y) 
            {
                digitalWrite(PZ, LOW);  
                digitalWrite(PO, HIGH); 
                digitalWrite(PS, HIGH); 
            }
        }
    }

    if (digitalRead(AR) == LOW && digitalRead(RSD) == HIGH && digitalRead(RZ) == LOW && digitalRead(RO) == HIGH) 
    {
      
        while (ilosc_impulsow < x ) 
        {
            if (ilosc_impulsow < y) 
            {
                digitalWrite(PZ, HIGH); 
                digitalWrite(PO, LOW);  
                digitalWrite(PS, HIGH); 
            }

            if (ilosc_impulsow < x - z && ilosc_impulsow > y) 
            {
                digitalWrite(PZ, HIGH); 
                digitalWrite(PO, LOW);  
                digitalWrite(PS, LOW);  
            }

            if (ilosc_impulsow > x - z) 
            {
                digitalWrite(PZ, HIGH); 
                digitalWrite(PO, LOW);  
                digitalWrite(PS, HIGH); 
            }
        }
    }
    else 
    {

        digitalWrite(PZ, HIGH); 
        digitalWrite(PO, HIGH); 
        digitalWrite(PS, HIGH); 
    }
}

void blinkA()
{
    if (digitalRead(PinB) == LOW && digitalRead(PinA) == HIGH && ilosc_impulsow > 0)
    {

        ilosc_impulsow--;
        
    }
}

void blinkB()
{
    if (digitalRead(PinB) == HIGH && digitalRead(PinA) == LOW && ilosc_impulsow < x)
    {

        ilosc_impulsow++;
      
    }
}
     




 

 

 

 

 

Edytowano przez daniel3005
Link to post
Share on other sites
(edytowany)
3 godziny temu, daniel3005 napisał:

Poniżej załączam kod na jakim działam.

Nie, zamieściłeś zdjęcie kodu. [...]

Nad tym okienkiem gdzie wpisujesz treść posta masz grubymi czerwonymi literami wypisane "wstaw kod programu". Jeśli tam klikniesz - jest duża szansa, że ktoś odpowie. Jeśli nie... no cóż, wyobrażasz sobie, że ktoś kto chciałby np. skompilować Twój kod na swoim komputerze będzie go przepisywać ze zdjęć?

 

Edytowano przez Treker
Cenzura w związku z PPF.
Link to post
Share on other sites
(edytowany)

Dziękuję za podpowiedź, już poprawiłem post

Dodam jeszcze że udało mi się już rozwiązać mój problem i to w następujący sposób 

void blinkA()
{
    static unsigned long lasttime;
    unsigned long time = millis();
    rewers2 = (time - lasttime);
    if (digitalRead(PinB) == LOW && digitalRead(PinA) == HIGH && ilosc_impulsow > 0)
    {

        ilosc_impulsow--;
        lasttime = time;
    }
}

void blinkB()
{
    static unsigned long lasttime;
    unsigned long time = millis();
    rewers = (time - lasttime);
    if (digitalRead(PinB) == HIGH && digitalRead(PinA) == LOW && ilosc_impulsow < x)
    {

        ilosc_impulsow++;
        lasttime = time;
    }
}

ale niestety nie spełnia to w pełni moich oczekiwań i nie jest to pewne rozwiązanie bo zdarzają się sytuacje kiedy to nie działa, stąd czy są może jeszcze inne rozwiązanie lub mam błędy w kodzie które można poprawić aby działanie było lepsze. 

Edytowano przez daniel3005
Link to post
Share on other sites

Strasznie ciężko czyta się kod, w którym masz nazwy typu "x" czy "AR" bez komentarzy co one właściwie oznaczają... tak więc dość trudno by było sprawdzić prawidłowość kodu kiedy nie wiemy, co on właściwie robi... ale do rzeczy.

Pytałeś:

7 godzin temu, daniel3005 napisał:

jak ustalić w programie że drzwi podczas zamykania lub otwierania się zatrzymały, czyli enkoder przestał zmieniać wartość.

Odpowiedź: właśnie poprzez sprawdzenie, czy enkoder przestał zmieniać wartość.

Najprostszym rozwiązaniem wydaje mi się sprawdzanie okresowo czy licznba impulsów odczytanych przez program się zmieniła. Czyli coś w stylu (pseudokod):

if (drzwi_w_ruchu) {
  if (minął_czas_przeznaczony_na_odczyt) {
	if (poprzedna_ilość_impulsów == ilość_impulsów) alarm();
    else poprzednia_ilość_impulsów = ilość_impulsów;
  }
}

i takie coś w loop(). Oczywiście trzeba zagwarantować, że w momencie ruszenia drzwi do zmiennej "poprzednia ilość" będzie podstawiona aktualna wartość ilości impulsów, ale to już szczegół techniczny. Można też sprawdzać jakąś minimalną ilość impulsów w jednostce czasu, czyli

if (abs(poprzednia_ilość_impulsów - ilość_impulsów) < minimalna_ilość_impulsów) {

Przy okazji: zadeklarowanie zmiennej jako volatile nie wystarczy do tego, aby odczyty były bezbłędne. Jeśli wartość ilosc_impulsow zmienia się na skutek przerwania, musisz:

  1. wyłączyć przerwania
  2. pobrać wartość zmiennej do jakiejś zmiennej roboczej
  3. przywrócić przerwania

Do poczytania: https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/

 

 

  • Lubię! 1
Link to post
Share on other sites

Kolega @ethanak juz zaproponowal najlepsze chyba rozwiazanie...czyli sprawdzanie ilosci impulsow w pewnym okresie czasu...jak wporzadku to jada dalej..a jak za maly przyrost impulsow to cofnij...

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!

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.