Skocz do zawartości
startrek1p2p

Arduino i czujnik koloru TCS3200

Pomocna odpowiedź

Napisano (edytowany)

Hej, napotkałem na problem przy czujniku koloru.

Ten czujnik został podłączony jak w różnych poradnikach, ale dalej pokazywał dziwne wartości. Chciałem aby odczytywał kolory RGB w skali 0-255 i następnie żeby ten wynik wyświetlał na diodzie WS2812.

Niestety ten czujnik wyświetla dziwne wyniki " R= -1350  G= -1615  B= -1887 "

Gdzie tutaj leży błąd ? Kod już próbowałem zmieniać kilkukrotnie i nigdy nie otrzymywałem prawdziwego wyniku. Może czujnik jest zepsuty? Czy może jeszcze coś innego?

Włączałem i wyłączałem podświetlenie, też to nic nie daje.
Obecny kod został praktycznie skopiowany i wklejony z tej strony  i dodana tylko linijka WS2812 abym na bieżąco widział, jaki jest kolor. 

 
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8
#include <Adafruit_NeoPixel.h>

int frequency = 0;
int R = 0;
int G = 0;
int B = 0;

Adafruit_NeoPixel linijka = Adafruit_NeoPixel(8, A0, NEO_GRB + NEO_KHZ800);

void setup() {
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(sensorOut, INPUT);
  
  // Setting frequency-scaling to 20%
  digitalWrite(S0,HIGH);
  digitalWrite(S1,LOW);
  digitalWrite(2, HIGH); 
  Serial.begin(9600);

   linijka.begin(); //Inicjalizacja
  linijka.show(); 
  
}

void loop() {
  // Setting red filtered photodiodes to be read
  digitalWrite(S2,LOW);
  digitalWrite(S3,LOW);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  //Remaping the value of the frequency to the RGB Model of 0 to 255
  frequency = map(frequency, 25,72,255,0);
  // Printing the value on the serial monitor
  Serial.print("R= ");//printing name
  Serial.print(frequency);//printing RED color frequency
  Serial.print("  ");
  R = frequency;
  delay(100);

  // Setting Green filtered photodiodes to be read
  digitalWrite(S2,HIGH);
  digitalWrite(S3,HIGH);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  //Remaping the value of the frequency to the RGB Model of 0 to 255
  frequency = map(frequency, 30,90,255,0);
  // Printing the value on the serial monitor
  Serial.print("G= ");//printing name
  Serial.print(frequency);//printing RED color frequency
  Serial.print("  ");
  G = frequency;
  delay(100);

  // Setting Blue filtered photodiodes to be read
  digitalWrite(S2,LOW);
  digitalWrite(S3,HIGH);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  //Remaping the value of the frequency to the RGB Model of 0 to 255
  frequency = map(frequency, 25,70,255,0);
  // Printing the value on the serial monitor
  Serial.print("B= ");//printing name
  Serial.print(frequency);//printing RED color frequency
  Serial.println("  ");
  B = frequency;
  delay(100);
  linijka.setPixelColor(5, linijka.Color(R, G, B));
  linijka.show();

  delay(500);
  Serial.print(" ");
  Serial.print(R);
  Serial.print(" ");
  Serial.print(G);
  Serial.print(" ");
  Serial.println(B);
  
  
}

 

IMG_20191116_184816.jpg

IMG_20191116_184804.jpg

IMG_20191116_184653.jpg

wycinek kodu.png

IMG_20191116_184536.jpg

IMG_20191116_184611_1.jpg

Edytowano przez startrek1p2p

Udostępnij ten post


Link to post
Share on other sites

Co to za czujnik? Umieść jego notę katalogowa na forum.

Aktualizacja:

Note znalazłem https://pdf1.alldatasheet.com/datasheet-pdf/view/560507/AMSCO/TCS3200.html

Aktualizacja:

Deklarujesz int frequency a spodziewana wartość frequency  to 0..255. Dlaczego deklarujesz int (+/-32kB)? To powód otrzymywania wartości ujemnych.

Wyświelt co otrzymujesz z pulseIn(sensorOut, LOW);

Aktualizacja:

Z tego co widzę to pulseIn zwraca unsigned long. Programista spodziewa się wartości 25..72. Łatwo wywnioskować, że przekroczony jest zakres. Obstawiam, że na wejściu sensorOut nie ma sygnału. Sprawdź oscyloskopem czy i jaki sygnał tam jest.

  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

@startrek1p2p wyłącz na chwilę wywołania funkcji map(), będzie można wtedy zobaczyć jak wyglądają same odczyty z czujnika. Wygląda na to że, twój czujnik zwraca wartości z innego przedziału niż zakładasz - zacznij więc od sprawdzenia, jakie są to wartości i czy zmieniają się zgodnie z oczekiwaniami.

  • Lubię! 1
  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

@RFM niestety nie mam oscyloskopy i żadnego znajomego który by go posiadał. 
Zamieniłem z int na byte wiec tutaj już powinno byc lepiej,

int frequency = 0;
byte R = 0;
byte G = 0;
byte B = 0;

na razie wartość frequency zostawiłem aby zobaczyć co dalej będzie wychodzić 

Wartości pulseIn :
PulseIn.thumb.png.509346bff919dd46ec4b2b01c3a68364.png

 

 

@Elvis

zmieniłem ale nie do końca wiem czego mam sie spodziewać w sensie jakich wartości. To, że sie zmieniają to widać. Oznaczyłem kolorami przedmioty o tych samych kolorach do czujnikach. 

1574862168_Koloryrgbbezmapowania.thumb.png.48503dd81723fedbfed2f1538a12dd3b.png

 

 

posprawdzałem wszytko i widzę, że tutaj odległość 3/5 mm wpływa diametralnie na cały odczyt. wiec nawet jak ustawie pod kątem to wynik jest zafałszowany. 

i już mniej więcej mogę utalic ale tylko pod konkretny kolor ( czerwony, zielony, niebieski) ale juz ma problem przy innych kolorach oraz innych odcieniach 


 

Edytowano przez startrek1p2p

Udostępnij ten post


Link to post
Share on other sites
22 minuty temu, startrek1p2p napisał:

niestety nie mam oscyloskopy i żadnego znajomego który by go posiadał. 

Na to nic nie poradzę. Nie zabieram się do budowy domu jak nie mam betoniarki.

 

23 minuty temu, startrek1p2p napisał:

na razie wartość frequency zostawiłem aby zobaczyć co dalej będzie wychodzić 

Wyniki stabilne ale niezgodne z tym czego spodziewał się autor programu.

 

24 minuty temu, startrek1p2p napisał:

 

@Elvis

zmieniłem ale nie do końca wiem czego mam sie spodziewać w sensie jakich wartości.

Pisałem jakich wartości spodziewa się autor programu.

Udostępnij ten post


Link to post
Share on other sites

No to na razie sie pobawię z samymi karteczkami i kolorami, zobaczymy co sie uda to jednak trochę zajmie. Początkowy projekt jest jednak trochę po za moimi granicami, przynajmniej na razie 🙂

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Nie musisz testować wszystkich możliwych kolorów - potrzebujesz tak naprawdę 6 liczb, czyli minimalnej i maksymalnej wartości, która jest zwracana przez pulseIn() dla trzech kolorów w używanym przez Ciebie otoczeniu.

Później możesz te wartości wstawić do map(). Musisz tylko doczytać jak działa ta funkcja: https://www.arduino.cc/reference/en/language/functions/math/map/

Wykonuje ona proste skalowanie, czyli:

long map(long x, long in_min, long in_max, long out_min, long out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Więc jeśli wartość x, czyli wejście jest poza zakresem in_min - in_max, to i wynik jest poza zakresem out_min i out_max. Będziesz musiał więc odczytany wynik ograniczyć jeśli wyszedł poza zakres, albo jeszcze lepiej - ograniczyć wartość danej wejściowej, czyli x.

Edytowano przez Elvis
  • Lubię! 1
  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

Coś pokombinuje i zobaczę co z tego wyjdzie. Najgorsze jest to, że ta odległość zawsze musi być taka sama, więc jeszcze do tego muszę zrobić obudowę która będzie dotykała bezpośrednio przedmiot i dopiero mogę coś robić z kolorem. Czyli z tymi kolorami to mam szukać maksymalnej i minimalnej wartości  Która ogólnie mi się pojawi w otoczeniu(np biały kolor na szafce) ? Czy tylko na konkretnym głównym kolorze (kartki R G B z oświetleniem i bez) ? 

Udostępnij ten post


Link to post
Share on other sites

Moim zdaniem warto przetestować jak zachowa się program i czujnik przy maksymalnych wartościach - ale nie musisz się nimi szczególnie przejmować.

Jak będziesz znał zakres, który Cię interesuje wystarczy wpisać go do funkcji map(), ale przed jej użyciem wywołać funkcję constrain() https://www.arduino.cc/reference/en/language/functions/math/constrain/

Wtedy wszystko powinno działać jak należy 🙂

  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

Ten czujnik zawsze na początku sprawia problemy, bo zapominamy, że:

  • Nie ma żadnej optyki i widzi dokładnie całą przednią półsferę. Ch-ka kierunkowa pokazuje, że spadek czułości do 50% następuje dopiero powyżej 70° odchylenia od osi a i przy 90° wciąż jeszcze jest 10%. Gdyby chcieć zrozumieć jak ten czujnik widzi otoczenie trzeba wyobrazić sobie okulary z mleczną szybą. Czy zakłądając je na nos możemy określić kolor czerwonej kartki A4 w odległości 50cm od oczu? Nie ma szans, bo jej pole powierzchni stanowi jedynie niewielki fragment wszytskiego co widzimy. Do naszych oczu dociera średnia z całego pola widzenia i zwykle będzie to mniej lub bardziej średnio szare. Natomiast gdy przyłożymy tę kartkę sobie do nosa, wtedy nasze okulary wyraźnie poczerwienieją. Jeżeli chcesz by ten czujnik określał kolor czegoś co mu pokazujesz musisz sprawić, by widział tylko to. Albo robisz czarną puszkę z okienkiem odsłaniającym dobrze oświetlony przedmiot badany albo wstawiasz czujnik w czarną (matową, tekturową?) rurkę kończącą się przy powierzchni badanej. Im dalejbędzie przedmiot i im mniejszy jest musisz go jaśniej oświetlić, to chyba oczywiste. Dziłające rozwiązania spokojni eodrózniające kolory to a) zbliżenie tego czegoś na 2-3mm od czoła, b) rurka, c) puszka z okienkiem, d) najtańszy obiektyw od kamerki z filtrem IR.
  • Wszystkie trzy diody RGB bardzo dobrze widzą podczerwień. Filtry kolorów mają "dziurę" w paśmie od 800nm do 1um więc w otoczeniu czujnika (nawet "z tyłu") nie może być żadnych żarówek, świetlówek, ekranów LCD itp rzeczy. "Światło" podczerwone z tego typu źródeł jednakowo intensywnie oddziaływuje na każdą fotodiodę i wtedy kolor przedmiotu który chcemy analizować zwyczajnie znika w śmieciach. A jeśli weźmiemy pod uwagę, że od żarówek/świetlówek zwykle są to sygnały 100Hz to zaczyna wyglądać, że dostajemy zupełnie losowy sygnał kolorów.
  • Popróbowałbym ze zmniejszeniem częstotliwości sygnałów. W programie widzę, że czujnik jest ustawiony na średni zakres częstotliwości wyjściowych (S0=1, S1=0) co oznacza, że może wygenerować sygnał nawet ponad 100kHz. Ponieważ pulseIn() mierzy długość "jedynki" to polegnie już powyżej 50kHz, bo z opisu tej funkcji wiemy, że mierzy od 10us. Swoją drogą pomiar długości stanu wysokiego nie daje "frequency" jak nazywa się zmienna w kodzie a wręcz przeciwnie: im więcej światła tym częstotliwość z czujnika będzie wyższa czyli okres krótszy, więc liczba oddana przez pulseIn() będzie mniejsza. Po zrobieniu dobrego układu mechaniczno-optycznego (to podstawa, bez tego w żadne pomiary nie mają sensu) spróbuj jakie liczby się mierzą dla S0=0 i S1=1, tylko zmień typ zmiennych frequency, R, G i B na taki który te pomiary pomieści, np. uint32_t.
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@RFM Sory, że dopiero teraz, ale jakoś twój komentarz mi umkną.

3 godziny temu, RFM napisał:

Na to nic nie poradzę. Nie zabieram się do budowy domu jak nie mam betoniarki.

 

nie od razu Kraków zbudowano. Zabawę z Arduino nie zaczyna się od przygotowania całego laboratorium, bo główną zaletą tej całej platformy jest niewielkie potrzebne zaplecze do startu, i na tym bazuje. 
 

3 godziny temu, RFM napisał:

Wyniki stabilne ale niezgodne z tym czego spodziewał się autor programu.

wtedy jeszcze myślałem, że wartość RGB będzie zawsze taki sam dla każdego koloru i czujnika tego typu. 

 

@marek1707
Dzięki, Twoja odpowiedz idealnie uzmysłowiła mi co mam teraz zrobić i tutaj posprawdzam co sie stanie, już mam pomysł jak to zrobić. Za kilka dni dam znać 😄 
 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
1 godzinę temu, startrek1p2p napisał:

wtedy jeszcze myślałem, że wartość RGB będzie zawsze taki sam dla każdego koloru

Nie będzie. Zarówno oko, jak i czujnik, ma różną charkterystykę dla każdej podstawowej barwy. Kolor biały nie da równych wartości wszystkich składowych RGB np 250, 250, 250.

Edytowano przez Gieneq

Udostępnij ten post


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!

Gość
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...