Pytanie:
Wykrywanie lokalizacji źródła światła za pomocą wielu fotorezystorów
jackgu1988
2017-04-02 05:25:37 UTC
view on stackexchange narkive permalink

Nie jestem jeszcze ekspertem, więc proszę wybaczyć wszelkie możliwe błędne terminy, których użyłem.

Planuję umieścić 6 czujników światła w odległości 1 metra (lub więcej) od siebie w ten sposób (przepraszam za zły schemat, nie jestem ekspertem, ale mam nadzieję, że ma to sens):

schematic

zasymuluj ten obwód - Schemat utworzony za pomocą CircuitLab

Zamierzam umieścić je w stosunkowo ciemnym pomieszczeniu. Moim celem jest skierowanie w ich kierunku lampy błyskowej, aby móc stwierdzić, który czujnik mierzy najwyższe wartości (skąd pochodzi światło) i jak długo (w milisekundach).

Wiem, jak wykonywać połączenia i mierzyć wartości. Moje pytania są dwa:

  1. Jaki jest najbardziej skuteczny sposób na wykrycie, który z 4 czujników rejestruje wyższe wartości? Zakładam, że muszę porównać wartości, które rejestrują. Myślę jednak, że jeśli w każdej pętli posortuję przechwycone wartości, proces może stać się ciężki. Myślę, że mógłbym zminimalizować porównania, ponieważ na przykład jeśli wartość LDR1 jest wyższa niż LDR2 i LDR3, mogę założyć, że źródło światła nie może być skierowane na przykład na LDR6. Myślę jednak, że może istniałby jeszcze skuteczniejszy sposób wykrycia tego (niekoniecznie w oprogramowaniu).

  2. Ponieważ pokój nie będzie całkowicie ciemny, analogowy szpilki zarejestrują pewne wartości, nawet jeśli nie kieruję w ich stronę lampy błyskowej. Czy istnieje sposób, aby to odfiltrować? Trafiłem na kalibrację ( https://www.arduino.cc/en/tutorial/calibration), ale nie jestem pewien, czy jest to optymalne rozwiązanie. Proszę wziąć pod uwagę, że źródło światła może nie być zbyt mocne (ale jego światło na pewno będzie jaśniejsze niż światło w pomieszczeniu).

Dwa odpowiedzi:
James Waldby - jwpat7
2017-04-02 10:53:11 UTC
view on stackexchange narkive permalink

Odpowiedź od Curt Sampson zawiera kilka dobrych rozważań projektowych, a także całkiem rozsądną sugestię, że należy przeprowadzić kilka eksperymentów w celu scharakteryzowania swoich LDR i ich umiejscowienia.

Pamiętaj, że jeśli chcesz wiedzieć, który czujnik ma najwyższy odczyt, zrobi to prosta pętla znajdowania wartości maksymalnej, bez żadnego sortowania:

  int maxR = reading [1], maxS = 1; for (byte i = 2; i < = nSensors; ++ i) {if (reading [i] > maxR) {maxR = reading [i]; maxS = i; }} // Teraz wiemy, że sensor maxS ma odczyt max, maxR  

Powyższy kod jest zgodny ze schematem numeracji 1–6 podanym w pytaniu i zakłada, że ​​ reading [i] oznacza odczyt z czujnika i.

Poniższy kod numeruje jednak czujniki i ich odczyty od 0 do 5 zamiast od 1 do 6, aby umożliwić prostsze warunki w pętli dla . Z programistycznego punktu widzenia sensowne jest wywołanie pierwszego czujnika 0, jeśli jego dane są przechowywane w komórce 0.


Znalezienie x, y kierunku światła

Założenia za poniższym kodem są takie, że wyższe odczyty oznaczają więcej światła i że w razie potrzeby wykonano pewną kalibrację oświetlenia tła, a oświetlenie tła zostało już odjęte od odczytów. Zakładamy również, że maksymalne odczyty są mniejsze niż (2¹⁵) / N, gdzie N to liczba czujników.

Celem poniższego kodu jest ustawienie dwóch zmiennych, x i y , które reprezentują względne położenie źródła światła. Na przykład, jeśli x i y są dodatnie, światło znajduje się powyżej i po prawej stronie prawego górnego LDR. Jeśli x jest ujemny, a y jest bliski zeru, światło znajduje się na lewo od środkowego lewego LDR. Jeśli znajomość znaków x i y jest odpowiednia do Twojego celu, nie ma potrzeby wykonywania większej liczby działań arytmetycznych niż pokazano. Z drugiej strony, jeśli chcesz obliczyć jakiś kąt, możesz użyć atan2 (y, x) do obliczenia kierunku światła w radianach.

  int reading [nSensors]; const int xdir [] = {-1, 1, -1, 1, -1, 1}; // czujnik kierunku x weightsconst int ydir [] = {1, 1, 0, 0, -1, -1}; // wagi czujnika kierunku yint x = 0, y = 0; for (byte i = 0; i < nSensors; ++ i) {x + = xdir [i] * reading [i]; y + = ydir [i] * reading [i];}  

Edycja 1: Śledzenie czasu włączenia światła

Problemy z synchronizacją światła obejmują poziomy rozpoczęcia i zakończenia pomiaru czasu; wymagana rozdzielczość (milisekundy? minuty?); niezbędny zakres (np. czy to, co wydarzyło się minutę temu, ma znaczenie); i kiedy zresetować zgromadzone dane dotyczące czasu. Najprościej może być śledzenie czasów włączenia wszystkich czujników w tym samym czasie, a następnie wybranie jednego z czasów lub połączenie kilku razy. Czy chcesz mieć największy czas, najnowszy czas, najnowszy duży czas czy czas odpowiadający największemu światłu?

Na przykład poniższy kod śledzi poziomy światła, które pozostają wystarczająco wysokie, aby zarejestrować, w wygładzone średnie, jak powyżej pewnego progu. W odstępach czasu bieżące wskazania są obracane w mapy bitowe, które śledzą ostatnie 16 poziomów włączenia-wyłączenia dla każdego LDR, a liczba włączeń jest również aktualizowana.

  // Inicjalizacja .. .uint16_t expAvg [nSensors] = {0}; // Wykładnicze średnie w czasie
uint16_t bitMaps [nSensors] = {0}; // Śledź ostatnie 16 poziomów włączania / wyłączania każdego czujnika bajt onCounts [nSensors] = {0}; // Liczba ostatnich razy czujnik avg > prógunsigned long prevMilli = millis (); const int markInterval = 50; // interwał ms do rejestrowania poziomów światłaconst int onThreshold = 547 * 16; // Próg światła jest włączony // W każdym przebiegu pętli () ... for (byte i = 0; i < nSensors; ++ i) expAvg [i] = reading [i] + 15 * expAvg [ ja]; // uśrednianie wykładnicze z wagą 1:16 // In loop (), w odstępach ... if (millis () - prevMilli > = markInterval) {prevMilli = millis (); for (byte i = 0; i < nSensors; ++ i) {onCounts [i] + = (expAvg [i] > onThreshold) - (! (bitMaps [i] & 0x8000)); bitMaps [i] = (bitMaps [i] <<1) | (expAvg [i] > onThreshold); }}  
Najprawdopodobniej to zrobi! Drugie rozwiązanie bardzo mi się podoba. Czy jednak, aby go skalibrować, metoda, którą zamieściłem w swoim pytaniu, prawdopodobnie zadziała? Muszę zmierzyć, jak długo świeciła się lampa błyskowa (w milisekundach), więc myślę, że będę potrzebował albo jakiejś kalibracji, albo filtra górnoprzepustowego.
@jackgu1988, zobacz edycję - chociaż wydaje mi się, że nie adresowałem ms on, ale zamiast tego ułamek czasu w ciągu ostatnich .8 sekund (z pokazanymi stałymi)
To prawdopodobnie wystarczy! Dziękuję Ci bardzo. Na razie czekam na dostawę jeszcze kilku czujników. Odniosę się, kiedy to przetestuję.
cjs
2017-04-02 06:36:08 UTC
view on stackexchange narkive permalink

W ATmega328P jest tylko jeden ADC (przetwornik analogowo-cyfrowy); analogowe piny wejściowe są multipleksowane, więc możesz wybrać konkretny pin, który chcesz próbkować. (Szczegółowe informacje można znaleźć w sekcji 28 arkusza danych).

Pobranie próbki zajmuje dużo czasu; jak długo zależy od tego, jak to zrobisz. Udokumentowano, że działanie funkcji analogRead () zajmuje około 100 mikrosekund. Odczytanie sześciu czujników zajmie więc co najmniej 600 mikrosekund.

Zwrócona próbka jest 10-bitową liczbą całkowitą i tak łatwo mieści się w dwóch bajtach, a nawet w jednym bajcie, jeśli pominiesz dwa młodsze bity ( co jest rozsądne dla niektórych aplikacji i prawdopodobnie dla Ciebie, ponieważ i tak będą prawdopodobnie bardziej przykładowym błędem niż danymi). Niezależnie od tego, czy to zrobisz, czy nie, pozostaje Ci bardzo mała ilość danych do sortowania z jednego zestawu odczytów: tylko sześć wartości.

Arduino obsługuje ATmega328P z częstotliwością 16 MHz, a większość instrukcje działają w jednym zegarze, co daje wydajność zbliżoną do 16 instrukcji na mikrosekundę.

Moglibyśmy obliczyć, w oparciu o typ używanego sortowania, liczbę porównań i zamian, które prawdopodobnie wykonasz w przeciętne i najgorsze przypadki, ale nie ma to sensu na tak małym zestawie danych, ponieważ całkowity czas, jaki zajmuje Twoja rutyna, prawie na pewno będzie zdominowany przez inne koszty ogólne. Więc powiem tylko, że sortowanie będzie rzędu stu cykli zegarowych.

Oznacza to, że sortowanie doda około 6 do 7 mikrosekund do całkowitego czasu odczytu wynoszącego 600 mikrosekund. już dotarliśmy, czyli 1%; w ogóle nie musisz się tym martwić.

W rzeczywistości spędzisz dużo więcej czasu na innych rodzajach przetwarzania. Ale jest to dość szybki procesor, jak widzieliśmy powyżej, więc jest duża szansa, jeśli uważasz, że twoja pętla będzie nadal zdominowana przez czas próbkowania ADC dla każdego z czujników.

Moja sugestia jest taka, aby pisać dalej i zapisywać rzeczywiste czasy w pętli dla próbkowania i przetwarzania. Po dłuższej zabawie będziesz mieć lepsze wyobrażenie o poszczególnych kosztach każdego z nich dla konkretnej aplikacji, a następnie możesz się martwić, czy potrzebujesz optymalizacji. Podejrzewam, że nie.

Jeśli chodzi o „filtrowanie”, będzie to integralna część algorytmu przetwarzania, ponieważ wartości „oświetlenia w pomieszczeniu” mogą się znacznie różnić od czasu do czasu w zależności od natężenia prądu oświetlenie w pomieszczeniu. Myślę, że nie chcesz niczego „odfiltrowywać”, ale zamiast tego porównać wartości wszystkich fotorezystorów; na pierwszy rzut oka podobne wartości wszystkich z nich oznaczałyby, że nie ma latarki, a niektóre, podając znacznie wyższe wartości, wskazywałyby, że istnieje. Ale moje drugie przypuszczenie jest takie, że a) chcesz, aby czujniki były oddalone od siebie o wiele dalej niż 1 metr (być może w rogach pokoju) oraz b) nie będzie to takie proste; prawdopodobnie zobaczysz dość różne wartości z czujników nawet w cichym pomieszczeniu. Tutaj możesz bawić się i eksperymentować, aby dowiedzieć się, jak to naprawdę działa!

Wydaje mi się również, że umieszczenie fotorezystorów kilka metrów od ADC będzie wymagało dużej ilości przewodów, co dodaje rezystancja, pojemność i szum, z których wszystkie będą zakłócać pomiary. Niewiele możesz z tym zrobić; możesz trochę pobawić się pomiarem rezystorów o znanej wartości na końcach przewodów, aby zobaczyć, jak poważny jest problem, ale jeśli jest okropny, prawdopodobnie musiałbyś użyć osobnego Arduino dla każdego czujnika i kazać im komunikować się z powrotem do centrali miejsce do analizy.

Dziękuję Ci! Ta informacja jest bardzo pomocna. Myślałem też, że może uda mi się okablować rezystory w taki sposób, aby zminimalizować ilość kontroli. Na przykład, mając 3 zamiast 6 wejść analogowych (każde wejście reprezentuje 2 czujniki) i zależnie od zwracanych wartości, aby móc stwierdzić, który czujnik otrzymuje więcej światła.
Możesz spróbować wymyślić sprytne sposoby podłączenia fotorezystorów szeregowo i / lub równolegle, aby zmniejszyć liczbę próbek, które musisz pobrać, ale jest to dość cholernie trudna rzecz. Prawdopodobnie najpierw zacząłbym od dodania większej liczby czujników, a jeśli pętla jest zbyt wolna ze względu na długość czasu potrzebnego do próbkowania ich wszystkich, wymyślę algorytm próbkowania tylko niektórych czujników, a inne zostawię w spokoju na podstawie tego, co zostało ostatnio samplowane. Ale najpierw dostałem coś naprawdę podstawowego.


To pytanie i odpowiedź zostało automatycznie przetłumaczone z języka angielskiego.Oryginalna treść jest dostępna na stackexchange, za co dziękujemy za licencję cc by-sa 3.0, w ramach której jest rozpowszechniana.
Loading...