Ten post chciałbym poświęcić na przygotowanie drugiego programu, który w nieco szerszym zakresie zaprezentuje możliwości diod programowalnych WS2812B.
Podłączenie:
W przykładzie wykorzystam enkoder bez przycisku oraz diody WS2812B. Drugi przykład natomiast będzie obsługiwał enkoder z przyciskiem.
Jeśli chodzi o podłączenie to wygląda ono następująco:
Enkoder:
- Pin 2;
- Pin 3;
- Wspólny (przeważnie środkowy) do GND;
- Przycisk od Enkodera Pin 4;
Diody:
- GND - NC
- DIN - 6 Pin Arduino Uno
- 4-7VDC - 5V
- GND - GND
Program 1:
W tym programie podłączony będzie jeden enkoder pod piny umożliwiające przerwanie czyli pin 2 oraz 3. Zmiana enkodera będzie powodowała zmiany wszystkich składowych koloru od 0 do 255. Większą ilość enkoderów pod przerwania można by było podłączyć dla układu Mega, Mega2560 lub MegaADK gdzie dostępne jest 6 pinów pod przerwania. Program obsługujący jeden enkoder wygląda następująco:
- #include <Adafruit_NeoPixel.h>
- #define LICZBA_DIOD 8
- #define PIN_GPIO_DIODE_DATA 6
- #define ENC_PIN_1 2
- #define ENC_PIN_2 3
- #define ENC_PIN_BUTTON 8
- volatile int Last_Encoded = 0;
- volatile int encoderValue_GREEN = 0;
- volatile int encoderValue_RED = 0;
- volatile int encoderValue_BLUE = 0;
- int lastMSB = 0;
- int lastLSB = 0;
- Adafruit_NeoPixel strip = Adafruit_NeoPixel(LICZBA_DIOD, PIN_GPIO_DIODE_DATA, NEO_GRB + NEO_KHZ800);
- void setup() {
- Serial.begin (9600);
- while (!Serial)
- Serial.println();
- Serial.println("Inicjalizacja...");
- Serial.flush();
- strip.begin();
- strip.show();
- Serial.println();
- Serial.println("OK");
- pinMode(ENC_PIN_1, INPUT);
- pinMode(ENC_PIN_2, INPUT);
- //Pin1 i Pin2 na HIGH, z rezystor podciągającym
- digitalWrite(ENC_PIN_1, HIGH);
- digitalWrite(ENC_PIN_2, HIGH);
- //Dolaczenie przerwanie,
- attachInterrupt(0, Encoder_Check, CHANGE);
- attachInterrupt(1, Encoder_Check, CHANGE);
- }
- void loop()
- {
- Serial.print("R: ");
- Serial.print(encoderValue_RED);
- Serial.print(" G: ");
- Serial.print(encoderValue_GREEN);
- Serial.print(" B: ");
- Serial.println(encoderValue_BLUE);
- delay(1000);
- }
- void Encoder_Check(){
- int MSB = digitalRead(ENC_PIN_1);
- int LSB = digitalRead(ENC_PIN_2);
- int encoded = (MSB << 1) |LSB; //konwersja wartosci do jednej wartosci
- int sum = (Last_Encoded << 2) | encoded; //dodawanie wartosci do wczesniej zdekodowanej wartosci
- if(sum == 0x0D || sum == 0x04 || sum == 0x02 || sum == 0x0B)
- {
- if(encoderValue_RED >= 255)
- {
- encoderValue_RED = 0;
- }
- else
- {
- encoderValue_RED++;
- encoderValue_GREEN++;
- encoderValue_BLUE++;
- for(int i=0; i<LICZBA_DIOD; i++)
- {
- strip.setPixelColor(i, encoderValue_RED, encoderValue_GREEN, encoderValue_BLUE);
- strip.show();
- }
- }
- }
- if(sum == 0x0E || sum == 0x07 || sum == 0x01 || sum == 0x08)
- {
- if(encoderValue_RED <= 0)
- {
- encoderValue_RED = 0;
- }
- else
- {
- encoderValue_RED--;
- encoderValue_GREEN--;
- encoderValue_BLUE--;
- for(int i=0; i<LICZBA_DIOD; i++)
- {
- strip.setPixelColor(i, encoderValue_RED, encoderValue_GREEN, encoderValue_BLUE);
- strip.show();
- }
- }
- }
- Last_Encoded = encoded;
- }
Program 2:
- #include <Adafruit_NeoPixel.h>
- #define LICZBA_DIOD 8
- #define PIN_GPIO_DIODE_DATA 6
- #define ENC_PIN_1 2
- #define ENC_PIN_2 3
- #define ENC_PIN_BUTTON 8
- volatile int Last_Encoded = 0;
- volatile int encoderValue_GREEN = 0;
- volatile int encoderValue_RED = 0;
- volatile int encoderValue_BLUE = 0;
- volatile int test = 0;
- int lastMSB = 0;
- int lastLSB = 0;
- int color_value = 0;
- typedef enum{
- Color_NONE = 0,
- Color_RED = 1,
- Color_GREEN = 2,
- Color_BLUE = 3
- }Color_Change_t;
- Adafruit_NeoPixel strip = Adafruit_NeoPixel(LICZBA_DIOD, PIN_GPIO_DIODE_DATA, NEO_GRB + NEO_KHZ800);
- void Color_Value_Up();
- void Color_Value_Down();
- int Check_Value(int Value);
- void Update_Diod();
- void Print_RGB_Data();
- void setup()
- {
- Serial.begin (9600);
- while (!Serial)
- Serial.println();
- Serial.println("Inicjalizacja...");
- Serial.flush();
- strip.begin();
- strip.show();
- Serial.println();
- Serial.println("OK");
- pinMode(ENC_PIN_1, INPUT);
- pinMode(ENC_PIN_2, INPUT);
- pinMode(ENC_PIN_BUTTON, INPUT);
- digitalWrite(ENC_PIN_1, HIGH);
- digitalWrite(ENC_PIN_2, HIGH);
- digitalWrite(ENC_PIN_BUTTON, HIGH);
- attachInterrupt(0, Encoder_Check, CHANGE);
- attachInterrupt(1, Encoder_Check, CHANGE);
- }
- void loop()
- {
- if(digitalRead(ENC_PIN_BUTTON))
- {;}
- else{
- if(Color_BLUE==color_value) { color_value=0;}
- color_value++;
- Serial.println(color_value);
- }
- Print_RGB_Data();
- }
- void Encoder_Check()
- {
- int MSB = digitalRead(ENC_PIN_1); //MSB = most significant bit
- int LSB = digitalRead(ENC_PIN_2); //LSB = least significant bit
- int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
- int sum = (Last_Encoded << 2) | encoded; //adding it to the previous encoded value
- if(sum == 0x0D || sum == 0x04 || sum == 0x02 || sum == 0x0B) { Color_Value_Up(); }
- if(sum == 0x0E || sum == 0x07 || sum == 0x01 || sum == 0x08) { Color_Value_Down(); }
- Last_Encoded = encoded; //store this value for next time
- }
- void Color_Value_Up()
- {
- if(color_value == Color_NONE)
- { }
- else if(color_value == Color_RED)
- {
- encoderValue_RED++;
- encoderValue_RED = Check_Value(encoderValue_RED);
- Update_Diod();
- }
- else if(color_value == Color_GREEN)
- {
- encoderValue_GREEN++;
- encoderValue_GREEN = Check_Value(encoderValue_GREEN);
- Update_Diod();
- }
- else if(color_value == Color_BLUE)
- {
- encoderValue_BLUE++;
- encoderValue_BLUE = Check_Value(encoderValue_BLUE);
- Update_Diod();
- }
- }
- void Color_Value_Down()
- {
- if(color_value == Color_NONE)
- { }
- else if(color_value == Color_RED)
- {
- encoderValue_RED--;
- encoderValue_RED = Check_Value(encoderValue_RED);
- Update_Diod();
- }
- else if(color_value == Color_GREEN)
- {
- encoderValue_GREEN--;
- encoderValue_GREEN = Check_Value(encoderValue_GREEN);
- Update_Diod();
- }
- else if(color_value == Color_BLUE)
- {
- encoderValue_BLUE--;
- encoderValue_BLUE = Check_Value(encoderValue_BLUE);
- Update_Diod();
- }
- }
- int Check_Value(int Value)
- {
- if(Value >= 255) { Value = 255; }
- else if(Value <= 0) {Value = 0; }
- return Value;
- }
- void Update_Diod()
- {
- for(int i=0; i<LICZBA_DIOD; i++)
- {
- strip.setPixelColor(i, encoderValue_RED, encoderValue_GREEN, encoderValue_BLUE);
- strip.show();
- }
- }
- void Print_RGB_Data()
- {
- Serial.print("R: ");
- Serial.print(encoderValue_RED);
- Serial.print(" G: ");
- Serial.print(encoderValue_GREEN);
- Serial.print(" B: ");
- Serial.println(encoderValue_BLUE);
- delay(1000);
- }
W tym przykładzie wykorzystam enkoder obrotowy z przyciskiem. Wciśnięcie przycisku będzie powodowało zmianę koloru, który będzie ustawiany:
To zadania można także całkiem fajnie wykonać za pomocą trzech potencjometrów. Gdzie wartość z przetwornika. Jest on 10 bitowy (0 do 1023) wobec tego dobrze byłoby zmapować te wartości na akceptowane dla diod (0 do 255). Dzięki temu można by było dynamicznie regulować podawanymi wartościami za pomocą trzech pokręteł. Wydaje mi się, że takie rozwiązanie byłoby bardziej wygodne niż za pomocą enkodera z przyciskiem.
Jeśli chodzi o zapalanie ich pojedynczo to wykorzystuje się tą samą funkcję czyli setPixelColor oraz show. Jedyną różnicą jest wywołanie jej ponownie dla diody którą chcemy zgasić z wartościami kolorów 0,0,0.