Arduino Polska Forum

Pełna wersja: Fotopułapka do lustrzanki oparta na sensorach activ IR i arduino cz.2
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Witam! Mój poprzedni wątek dotyczący tego projektu został zamknięty ponieważ temat zdryfował na zupełnie inne tematy dlatego bardzo proszę o trzymanie się tematu Smile

Celem projektu jest fotopułapka uruchamiająca po wykryciu ruchu lustrzankę DSLR i lampy błyskowe w celu sfotografowania obiektu którego ruch został wykryty. Jako, że w takiej sytuacji ważne jest żeby wiedzieć gdzie dokładnie jest fotografowany obiekt projekt oparłem na nadajniku i odbiorniku active IR zamiast mało precyzyjnego sensora IR.

Założenia:
- w celu optymalizacji zużycia energii zastąpiłem arduino uno Adafruit Pro Trinket 
- kabel sygnałowy z odbiornika IR podłączony został do pinu 3 (INT1) - po wykryciu ruchu LOW
- do pin 4 podłączone zostało przez transoptor (optoizolator) wyjście na ustawianie ostrości
- do pin 8 podłączone zostało przez transoptor (optoizolator) wyjście na migawkę (czyli de facto wykonanie zdjęcia)

Działanie:
 wszystko działało bardzo fajnie ale zużycie energii było wysokie i w celu jej zaoszczędzeniu dodałem do kodu tryb "deep-sleep mode". W teorii wszystko super. Urządzenie przechodzi w tryb deep-sleep i zużycie energii obniża się praktycznie tylko do zasilenia czuwającego odbiornika IR. Wybudza się też praktycznie natychmiast i ponownie przechodzi po określonym czasie w deep-sleep. 

Problem:
- niestety nie jest tak kolorowo. Przed dopisaniem do kodu deep-sleep mode - czujnik wyzwalał migawkę za każdym razem, teraz bardzo szybkie naruszenie nie wyzwala migawki. To bym jeszcze przeżył, bo przynajmniej małe zwierzątka (myszy itp. ) nie wyzwalały by migawki. Chociaż oczywiście chciałbym wiedzieć co jest przyczyną takiej sytuacji.
- drugi problem jest znacznie poważniejszy - przy serii nieregularnych naruszeń w niewielkich odstępach czasu (imitujących powiedzmy przechodzące stadko dzików) następuje zawieszenie płytki i niezbędny jest reset. 

Jest to zapewne spowodowane nieudolnym zaimplementowaniem przeze mnie deep-sleep bo bez tego kod działa bezbłędnie. Niestety niewiele jeszcze umiem i liczę, że ktoś wskaże mi na czym polega błąd.

Kod:
Kod:
/*
* Fotopułapka DSLR AIR (active infrared) - 28/11/2019
*
*  Fotopułapka DSLR oparta na aktywnych czujnikach IR (infrared)(komplet: nadajnik/odbiornik) i adafruit pro trinket
* odbiornik active IR po wykryciu ruchu przechodzi w stan niski (LOW)
*
*/

// **** INCLUDES *****
#include "LowPower.h"  //dodaje biliotekę obsługującą zaawansowane tryby oszczędzenia energii

/*-----( Declare Constants )-----*/
#define IRsensor 3    // przewód sygnałowy z odbiornika AIR (active IR)wchodzi na pin 3 (jest to równoczesnie pin interrupt #1(INT1))
#define shutter  4    // wyjscie cyfrowe 4 poprzez transoptor 4n26 do wyzwolenia migawki
#define focus    8    // wyjscie cyfrowe 8 poprzez transoptor 4n26 do ustawienia ostrości

/*-----( Declare Variables )-----*/
int  detector_state;  // zmienna utrzymuje ostatni stan przełącznika
int trigger = 2;      // Ilość wykonanych zdjęć
int odliczanie = 5;  //zmienna odpowiedzialna za odliczanie czasu do uśpienia ATMegi

void setup()   /*----( SETUP: RUNS ONCE )----*/
{
  pinMode(LED_BUILTIN, OUTPUT);       //określa cyfrowy pin LED_BUILTIN jako wyjście
  digitalWrite(LED_BUILTIN, LOW);    // wyłącza diodę LED poprzez odcięcie napięcia (LOW)
  detector_state = 0;             
  pinMode (IRsensor, INPUT );
  pinMode (shutter, OUTPUT );
  pinMode (focus, OUTPUT );


  CLKPR = 0x80; 
  CLKPR = 0x04;  // przetaktowanie z 16Mhz do 1Mhz Ważne: przetaktowanie nie ma wpływu na opisany problem - na standardowej prędkości 16Mhz jest dokładnie to samo

  Serial.begin(9600);
  delay(312); // aby zrekompensować underclocking z 16Mhz do 1Mhz należy podzielić rządany czas przez 16 - w tym przypadku 5000:16=312 (5sekund)
}
/*--(end setup)---*/

void  loop ()  /*----( LOOP: RUNS CONSTANTLY )----*/
{
  detector_state = digitalRead (IRsensor);
  if ( HIGH == detector_state)
  {

    digitalWrite (shutter, LOW );
    digitalWrite (focus, LOW );
   
 
  odliczanie--;                                 //dekrementujemy (zmniejszamy) zmienną odliczanie o 1
  delay(62);                                    //ustawiamy opóźnienie 1 sekundy


  if (odliczanie <= 0) {                        //jeżeli zmienna odliczanie jest mniejsza równa 0
                     
      odliczanie = 5;                           //ustaw zmienną odliczanie na 5, aby po przebudzeniu można było
                                                //wykonywać odliczanie
     
      Spanie();                                  //przenieś wykonywanie programu do klasy Spanie
   }
  }
  else
   {
    for (int x = 0; x < 2; x++)  // ilość wykonanych zdjęć (w tym przypadku 2: zdjęcie 0 i zdjęcie 1)
    {
    digitalWrite (focus, HIGH );
    delay (7);                // czas opożnienia w tym wypadku 5x16 = 80ms
    digitalWrite (shutter, HIGH );
    delay (7); 
    digitalWrite (focus, LOW );
    digitalWrite (shutter, LOW);
    delay (62);              // czas opożnienia 1 sek.
    }
  }
  delay (7); // czas opożnienia 0,1 sek.
}

/*--(end loop)---*/

void Spanie() /*----( Spanie: Sleep Mode )----*/
{

     attachInterrupt(1, Budzenie, LOW);                     //jeżeli na pinie 3 pojawi się stan niski to wybudź ATMegę i przenieś do klasy budzenie

     LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);  //wybieramy tryb Power-down i ustawiamy żeby ATMega spała cały czas spała przy wyłączonom ADC i BoD do momentu wystąpienia przerwania
}

/*--(end sleep mode)---*/

void Budzenie()  /*----( Budzenie: Wake Mode )----*/
{
   
      detachInterrupt(1);                         //ustawiamy debounce pinu 3, żeby układ nie "wybudził się" dwa razy

}

/*--(end wake mode)---*/

// ( THE END ) //
Może ciut do okola ale najpierw zamień wszystkie Delay na timery (biblioteka) żeby nie powodowało to błędów.
Po tym dodaj WatchDoga, który może nie załata problemu ale przynajmniej płytka się zresetuje po zawieszeniu.
A jaki błąd mialby powodować delay w tym programie?
Spróbuj tego kodu:


Kod:
/*
* Fotopułapka DSLR AIR (active infrared) - 28/11/2019
*
*  Fotopułapka DSLR oparta na aktywnych czujnikach IR (infrared)(komplet: nadajnik/odbiornik) i adafruit pro trinket
* odbiornik active IR po wykryciu ruchu przechodzi w stan niski (LOW)
*
*/

// **** INCLUDES *****
#include "LowPower.h"  //dodaje biliotekę obsługującą zaawansowane tryby oszczędzenia energii

/*-----( Declare Constants )-----*/
#define IRsensor 3    // przewód sygnałowy z odbiornika AIR (active IR)wchodzi na pin 3 (jest to równoczesnie pin interrupt #1(INT1))
#define shutter  4    // wyjscie cyfrowe 4 poprzez transoptor 4n26 do wyzwolenia migawki
#define focus    8    // wyjscie cyfrowe 8 poprzez transoptor 4n26 do ustawienia ostrości

/*-----( Declare Variables )-----*/
int  detector_state;  // zmienna utrzymuje ostatni stan przełącznika
int trigger = 2;      // Ilość wykonanych zdjęć
int odliczanie = 5;  //zmienna odpowiedzialna za odliczanie czasu do uśpienia ATMegi

void setup()   /*----( SETUP: RUNS ONCE )----*/
{
  pinMode(LED_BUILTIN, OUTPUT);       //określa cyfrowy pin LED_BUILTIN jako wyjście
  digitalWrite(LED_BUILTIN, LOW);    // wyłącza diodę LED poprzez odcięcie napięcia (LOW)
  detector_state = 0;             
  pinMode (IRsensor, INPUT );
  pinMode (shutter, OUTPUT );
  pinMode (focus, OUTPUT );


  CLKPR = 0x80;
  CLKPR = 0x04;  // przetaktowanie z 16Mhz do 1Mhz Ważne: przetaktowanie nie ma wpływu na opisany problem - na standardowej prędkości 16Mhz jest dokładnie to samo

  Serial.begin(9600);
  delay(312); // aby zrekompensować underclocking z 16Mhz do 1Mhz należy podzielić rządany czas przez 16 - w tym przypadku 5000:16=312 (5sekund)
}
/*--(end setup)---*/

void  loop ()  /*----( LOOP: RUNS CONSTANTLY )----*/
{
  attachInterrupt(1, Budzenie, LOW);

  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);

  detachInterrupt(1);

   // tu robimy 2 zdjęcia
    for (int x = 0; x < 2; x++)  // ilość wykonanych zdjęć (w tym przypadku 2: zdjęcie 0 i zdjęcie 1)
    {
    digitalWrite (focus, HIGH );
    delay (7);                // czas opożnienia w tym wypadku 5x16 = 80ms
    digitalWrite (shutter, HIGH );
    delay (7);
    digitalWrite (focus, LOW );
    digitalWrite (shutter, LOW);
    delay (62);              // czas opożnienia 1 sek.
    }
 
  delay (7); // czekamy po 2 zdjęciach i idziemy spać jak nie ma na pinie 3 LOW
}

void Budzenie() 
{
   // tu nic nie robimy
}
Dzięki wielkie. Sprawdzę jak wrócę do domu i oczywiście dam znać jakie są efekty Smile
Sorry za post pod postem. Oczywiście Twój wpis @Agregacik kolejny raz był bardzo pomocny. Jest znaczna poprawa Smile Różnicą jest teraz to, że urządzenia po ustaniu ruchu w ułamku sekundy przechodzi w tryb uśpienia bez żadnej zwłoki na ewentualne kolejne naruszenia. Natomiast układ przestał się wieszać i wybudza się również. Jeszcze raz ogromne dzięki.

Uzmysłowiło mi to, że muszę się zabezpieczyć przed podobnymi problemami związanymi ze specyfiką sensorów ActiveIR opartych na połączeniu wiązką między nadajnikiem i odbiornikiem takie jak: moment w którym się wyczerpują baterie w nadajniku, lub nadajnik się psuje, lub źle zabezpieczony przesuwa na wietrze i traci kontakt z odbiornikiem. Odbiornik uznaje to za wykrycie ruchu i wyzwala migawkę bez końca pstrykając zdjęcia "niczemu" Sad Muszę to jakoś rozwiązać. Nie bardzo mam pomysł jak. Albo jakieś ograniczenie czasowe uruchamiania migawki (po określonym czasie koniec wyzwalania) albo ilościowe (po określonej liczbie wykonanych w jednym ciągu zdjęć koniec wyzwalania). Bardziej skomplikowanym, ale najbardziej eleganckim rozwiązaniem było by dołączenie tradycyjnego czujnika ruchu (PIR) i napisanie zależności - jeśli tradycyjny sensor ruchu PIR (mający zazwyczaj bardzo duży kąt widzenia 90- 120 st.) nie wykryje ruchu przez określony czas to migawka zostanie zatrzymana nawet jeśli nadal nie ma połączenia między nadajnikiem i odbiornikiem ActiveIR. A może jest jakiś inny, sprytniejszy sposób? Jeśli ktoś ma taki proszę o opis, a może jakiś link do poczytania o podobnych rozwiązaniach. Z góry bardzo dziękuję.
Może w tym wierszu
attachInterrupt(1, Budzenie, LOW);
zmienić na
attachInterrupt(1, Budzenie, FALLING);
Czyli wybudzanie nastąpi przy zmianie stanu z wysokiego na niski. Wykonają się zdjęcia w zadanej ilości po czym zapada w stan uśpienia. Dopiero jak stan zmieni się na wysoki i z powrotem na niski to się wybudzi i operacja wykona się ponownie. Pewnie rozwiąże to tylko część problemów i spowoduje nowe Smile.
Dzięki. Chyba rozumiem to rozwiązanie, ale ono tak jak napisałeś spowoduje nowe problemy. Taki jaki widzę na szybko: wyobraźmy sobie, że w obręb pułapki wchodzi Yeti, Wielka Stopa czy Chupacabra . Zaskoczone dźwiękiem migawki zamiera i rozgląda się stojąc idealnie w obrębie działania pułapki dając Ci jedyną okazję do zrobienia zdjęć które obiegną świat Wink A Twoja pułapka zrobi tylko trzy czy nawet cztery zdjęcia Smile Ok! Można ustawić i 100, ale wtedy napewno zamiast Yeti będziesz miał tysiące zdjęć polnej myszy czy zająca, na dodatek zwróconego do Ciebie tym czym kończą się plecy Wink Na pewno wiesz o co mi chodzi Smile Rozwiązanie musi być jednak bardziej elastyczne i dopasowane do sytuacji. Coraz bardziej skłaniam się do dodania pasywnego sensora IR jako swego rodzaju potwierdzenia sprawności układu. Zużywa 0.1mA i pozwala zweryfikować czy nastąpił błąd czy rzeczywiście coś żywego znajduje się w obrębie jego zasięgu. Ktoś by mógł powiedzieć - to dlaczego nie zbudować całego układu na czujniku PIR - odpowiedź brzmi "precyzja" i brak fałszywych wzbudzeń od ruszającej się gałązki czy promieni słonecznych. Każdy kto używał takiej zwykłej fotopułapki wie o czym piszę. Kiedy coś przekracza wiązkę active IR to wiesz praktycznie co do centymetra gdzie się znajduje.
Jakie są wyjścia z tych urządzeń. Czy to są styki przekaźnika czy stan logiczny? Przy przekaźnikach można połączyć szeregowo ich styki i wyzwalać zdjęcia jak obydwa zadziałają.
Zarówno sensor PIR jak i odbiornik aIR mają wyjście cyfrowe na którym następuje zmiana stanu. Na czujniku PIR naruszenie powoduje stan wysoki na przewodzie sygnałowym, a na odbiorniku aIR (to te z którch korzystam obecnie) na naruszenie reagują stanem niskim na przewodzie sygnałowym. Tylko nie wiem czy o to pytasz Smile
Stron: 1 2