• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Przekazywanie wartości w funkcjach
#1
Cześć,
piszę własnie program którego zadaniem jest sterowanie adresowaną taśmą led RGB.

Niestety, ale ustawianie kolorów w RGB jest dla mnie nieintuicyjne. Nie jestem w stanie napisać kodu który będzie płynnie przechodził przez całą paletę barw. Postanowiłem więc, ze będę zamienia RGB na HSV i odwrotnie.
Poszukałem gotowego kodu który wykonuje taką operacje, ale w jego konstrukcji są elementy których jeszcze nie znam i nie bardzo wiem czego szukać w internecie żeby je poznać więc tutaj pojawia się pojawia prośba do was.

Generalnie wiem, że zmienne podane w nawiasie za nazwą funkcji to wartości, które przekazuję do niej. Dlaczego przy niektórych z nich jest gwiazdka, dlaczego funkcja wymaga ode mnie podania zarówno wartości HSV jak i rgb skoro rgb powinny być zwracane jako wynik na podstawie podanych wartości SHV, oraz ostatnie pytanie: jak funkcja zwraca więcej niż jedną wartość, bo przecież zgodnie z założeniem powinienem dostać r, g, b w odpowiedzi. 

Kod:
void HSV_to_RGB(float h, float s, float v, byte *r, byte *g, byte *b)
{
 int i,f,p,q,t;
 
 h = max(0.0, min(360.0, h));
 s = max(0.0, min(100.0, s));
 v = max(0.0, min(100.0, v));
 
 s /= 100;
 v /= 100;
 
 if(s == 0) {
   // Achromatic (grey)
   *r = *g = *b = round(v*255);
   return;
 }

 h /= 60; // sector 0 to 5
 i = floor(h);
 f = h - i; // factorial part of h
 p = v * (1 - s);
 q = v * (1 - s * f);
 t = v * (1 - s * (1 - f));
 switch(i) {
   case 0:
     *r = round(255*v);
     *g = round(255*t);
     *b = round(255*p);
     break;
   case 1:
     *r = round(255*q);
     *g = round(255*v);
     *b = round(255*p);
     break;
   case 2:
     *r = round(255*p);
     *g = round(255*v);
     *b = round(255*t);
     break;
   case 3:
     *r = round(255*p);
     *g = round(255*q);
     *b = round(255*v);
     break;
   case 4:
     *r = round(255*t);
     *g = round(255*p);
     *b = round(255*v);
     break;
   default: // case 5:
     *r = round(255*v);
     *g = round(255*p);
     *b = round(255*q);
   }
}
 
Odpowiedź
#2
Byłbym również rad gdyby ktoś się pokusił o dodanie komentarzy opisujących krok po kroku działanie powyższej funkcji, abym mógł lepiej zrozumieć jej działanie.
 
Odpowiedź
#3
Kolego mam zgadywać że to Taśma led z WS2812. Czy co innego . Jeżeli to jest z WS2812 to masz gotowe biblioteki wystarczy ściągnąć potem piszesz program i wpisujesz ile masz diud
a kolor masz 8bitowy
(256,000,000) to masz red
(000.256.000) green
(000.256.000)blue
(256.256,256)biały
(150,150,150)biały tylko słabiej świeci
 
Odpowiedź
#4
Nie kolego. Nie musisz zgadywać, czy chodzi o WS2812. Liczyłem jedynie, że przeczytasz mój wpis zanim udzielisz odpowiedzi.
Tak na prawdę nie ma znaczenia czy do zapalenia diod (a nie diud) używam sterownika WS2812 czy może zapalam je używając samego arduino.

Problem dotyczy tego, że standard RGB jest dla mnie nieintuicyjny (nie mylić z niezrozumiały) i napisanie kodu, który będzie płynnie zmieniał kolor zapalonej diody od niebieskiego, aż po czerwony jest zbyt skomplikowane.
Dużo łatwiej byłoby wykonać to używając standardu HSV, ale jak słusznie zauważyłeś, w przypadku sterownika WS2812 konieczne jest wyrażenie koloru w postaci RGB (zupełnie tak jak w przypadku diody rgb bez sterownika).

Postanowiłem więc w swoim programie ustalać kolor w standardzie HSV, a następnie konwertować to do RGB przy pomocy załączonego w pierwszym poście fragmentu kodu.

Niestety, ale zarówno ten kod jak i inne które wykonują podobną operacje zawierają elementy których nie rozumiem.
 
Odpowiedź
#5
Witam,
Funkcja "typu" void nie zwraca żadnej wartości. Natomiast z jej (tej konkretnej) definicji wynika, że przekazujesz do niej 6 parametrów wejściowych. Te bez gwiazdki nie zmienią trwale wartości, tzn. jeżeli wewnątrz funkcji nadasz im nową wartość to będzie ona "obowiązywać" tylko podczas wykonywania tej funkcji, natomiast po jej zakończeniu będzie posiadać wartość sprzed wywołania funkcji. Parametry z gwiazdką mogą być trwale zmieniane w ciele funkcji, czyli ich zmiana będzie "trwać" po zakończeniu jej działania. Takie rozwiązanie stosuje się gdy wewnątrz funkcji potrzeba trwale zmienić wartość więcej niż jednej zmiennej. Czyli, w tym konkretnym przypadku, można pierwsze trzy zmienne traktować jako wejściowe, a te kolejne trzy z gwiazdką, jako zwracane (wyjściowe).
Pozdrawiam,
Tomek.
 
Odpowiedź
#6
Smaczek, ubiegłeś mnie Smile
No ale skoro już napisałem...
Hmmm... no to tak:
Najpierw o nieszczęsnych zmiennych 'z gwiazdką'. Pokrótce, to są wskaźniki. Wskaźnik jest swego rodzaju zmienną, która nie przechowuje wartości, ale adres komórki, która przechowuje wartość. Gwiazdka jest sposobem dostania się do wartości. Ma to wiele ciekawych cech. Poczytaj sobie o wskaźnikach, bo warto, choć kolega Smaczek już opowiedział o ich właściwościach.
Funkcja max() i min(). Te funkcje zwracają odpowiednio wartości maksymalne i minimalne dwóch liczb.
Operator /= - dzieli zmienną przez daną wartość. To tak, jak operator += dodaje do zmiennej daną wartość.
Funkcja round(x) zaokrągla wartość x.
Funkcja floor(x) zwraca największą wartość całkowitą, która jest mniejsza niż x.
Funkcja switch to coś w rodzaju if, z tym że if przewiduje tylko warunek spełniony lub nie spełniony, natomiast switch potrafi obsłużyć kilka wartości i w zależności od nich wykonać jakieś działanie. Da się to zrobić na ifach, ale switch jest nieco bardziej eleganckie i czytelne.
Kod wygląda na dość prosty. Postaraj się sam go zrozumieć na podstawie znajomości 'klocków'.
 
Odpowiedź
#7
Wielkie dzięki.
Dzięki wam i dodatkowej lekturze udało mi się to rozkminić.
Utwierdźcie mnie tylko proszę jeszcze w jednym przekonaniu.
Dokładnie to samo można by uzyskać bez używania wskaźników, operując wewnątrz instrukcji na zmiennych, z tą różnicą, że używając wskaźników nie muszę w trakcie pisania instrukcji decydować do których zmiennych zostaną zapisane wyniki bo robię to dopiero przy jej wywołaniu.

Przy okazji, w samej instrukcji znalazłem błąd. Zmienne f,p,q,t powinny być typu float. Smile
 
Odpowiedź
#8
Witam,
Jeśli zadeklarujesz zmienne jako globalne (na początku programu) to możesz zmieniać ich wartości- bez używania wskaźników- wewnątrz dowolnej funkcji, pod warunkiem, że zmienne te nie będą parametrami wywołania (zmiennymi wejściowymi). Nie jest to jednak dobra praktyka programistyczna.
Pozdrawiam,
Tomek.
 
Odpowiedź
#9
(30-01-2018, 00:37)BorokaMan napisał(a): Dokładnie to samo można by uzyskać bez używania wskaźników, operując wewnątrz instrukcji na zmiennych, z tą różnicą, że używając wskaźników nie muszę w trakcie pisania instrukcji decydować do których zmiennych zostaną zapisane wyniki bo robię to dopiero przy jej wywołaniu.
Generalnie tak, zresztą odpowiedział Ci na to już kolega Smaczek. 
Poczytaj sobie o zmiennych globalnych i lokalnych, ich widoczności w programie, ich wpływie na inne zmienne, także poza strukturami, w których ich użyłeś. Przy okazji, weź pod uwagę to, co Smaczek napisał w ostatnim zdaniu.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości