Skocz do zawartości

Automatyczne sterowanie drzwiami przesuwnymi / enkoder, przerwania


Pomocna odpowiedź

Napisano (edytowany)

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

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
  • 3 miesiące później...

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...