Skip to content

Instantly share code, notes, and snippets.

@nayutaya
Last active March 23, 2016 15:27
Show Gist options
  • Save nayutaya/9b25c03eb9e3dd3bdb5e to your computer and use it in GitHub Desktop.
Save nayutaya/9b25c03eb9e3dd3bdb5e to your computer and use it in GitHub Desktop.
マガジンラックLEDのコントローラ。UDP経由で色を設定する。
/*
* magazine-rack-led.ino
* (C) 2016 Yuya Kato.
* MIT License
*/
#include "application.h"
#include "neopixel/neopixel.h"
SYSTEM_MODE(AUTOMATIC);
const uint16_t NUMBER_OF_STRIPS = 2;
const uint16_t LEDS_PER_STRIP = 3;
const uint16_t NUMBER_OF_LEDS = LEDS_PER_STRIP * NUMBER_OF_STRIPS;
const uint32_t DEFAULT_COLOR = 0xFFFE961C;
const uint8_t PIN_STRIP1 = D2;
const uint8_t PIN_STRIP2 = D3;
const uint8_t PIN_FOOT_SWITCH = D5;
const uint16_t UDP_LISTEN_PORT = 12345;
const int16_t UDP_BUFFER_SIZE = 32;
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(LEDS_PER_STRIP, PIN_STRIP1, WS2812B);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(LEDS_PER_STRIP, PIN_STRIP2, WS2812B);
UDP udp;
uint8_t udpBuffer[UDP_BUFFER_SIZE] = {0};
uint32_t currentColors[NUMBER_OF_LEDS] = {0};
uint32_t overrideColors[NUMBER_OF_LEDS] = {0};
uint8_t countOfSwitchPushed = 0;
uint32_t switchCounterLastUpdatedTime = 0;
bool overrideRequested = false;
uint16_t readUInt16(const uint8_t *buffer) {
return (buffer[0] << 8) | buffer[1];
}
uint32_t readUInt32(const uint8_t *buffer) {
return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
}
uint32_t convertArgbToRgb(const uint32_t color) {
const uint32_t alpha = (color >> 24) & 0xFF;
const uint32_t red = (((color >> 16) & 0xFF) * alpha) >> 8;
const uint32_t green = (((color >> 8) & 0xFF) * alpha) >> 8;
const uint32_t blue = (((color >> 0) & 0xFF) * alpha) >> 8;
return (red << 16) | (green << 8) | blue;
}
uint32_t mixColor(const uint32_t color1, const uint32_t color2, const float ratio) {
const uint32_t alpha = (uint32_t)((((color1 >> 24) & 0xFF) * (1.0 - ratio)) + ((color2 >> 24) & 0xFF) * ratio);
const uint32_t red = (uint32_t)((((color1 >> 16) & 0xFF) * (1.0 - ratio)) + ((color2 >> 16) & 0xFF) * ratio);
const uint32_t green = (uint32_t)((((color1 >> 8) & 0xFF) * (1.0 - ratio)) + ((color2 >> 8) & 0xFF) * ratio);
const uint32_t blue = (uint32_t)((((color1 >> 0) & 0xFF) * (1.0 - ratio)) + ((color2 >> 0) & 0xFF) * ratio);
return (alpha << 24) | (red << 16) | (green << 8) | blue;
}
void showColors(const uint32_t *colors) {
for ( uint16_t led = 0; led < 3; led++ ) {
strip1.setPixelColor(led, convertArgbToRgb(colors[led + 0]));
strip2.setPixelColor(led, convertArgbToRgb(colors[led + 3]));
}
strip1.show();
strip2.show();
}
void fadeColors(const uint32_t *colors1, const uint32_t *colors2, const uint16_t durationInMilliseconds) {
const uint32_t startTimeInMilliseconds = millis();
uint32_t currentTimeInMilliseconds = 0;
uint32_t elapseTimeInMilliseconds = 0;
float elapseRatio = 0;
uint32_t intermediateColors[NUMBER_OF_LEDS] = {0};
while ( true ) {
currentTimeInMilliseconds = millis();
elapseTimeInMilliseconds = (currentTimeInMilliseconds - startTimeInMilliseconds);
if ( elapseTimeInMilliseconds >= durationInMilliseconds ) break;
elapseRatio = ((float)elapseTimeInMilliseconds / (float)durationInMilliseconds);
for ( uint16_t i = 0; i < NUMBER_OF_LEDS; i++ ) {
intermediateColors[i] = mixColor(colors1[i], colors2[i], elapseRatio);
}
showColors(intermediateColors);
delay(10);
}
showColors(colors2);
}
const uint16_t COMMAND_ID_FADE_COLORS = 0x0001;
struct FADE_COLORS_DATA {
uint16_t durationInMilliseconds;
uint32_t colors[NUMBER_OF_LEDS];
};
void readFadeColorsData(const uint8_t *buffer, struct FADE_COLORS_DATA *data) {
memset(data, 0, sizeof(FADE_COLORS_DATA));
data->durationInMilliseconds = readUInt16(buffer + 0);
for ( uint16_t i = 0; i < NUMBER_OF_LEDS; i++ ) {
data->colors[i] = readUInt32(buffer + 2 + (4 * i));
}
}
void updateSwitchCounter() {
const uint32_t now = millis();
if ( now - switchCounterLastUpdatedTime > 100 ) {
//countOfSwitchPushed++;
if ( currentColors[0] == 0x00000000 ) {
for ( uint16_t i = 0; i < NUMBER_OF_LEDS; i++ ) {
overrideColors[i] = DEFAULT_COLOR;
}
} else {
for ( uint16_t i = 0; i < NUMBER_OF_LEDS; i++ ) {
overrideColors[i] = 0x00000000;
}
}
overrideRequested = true;
}
switchCounterLastUpdatedTime = now;
}
void setup() {
pinMode(PIN_FOOT_SWITCH, INPUT_PULLUP);
attachInterrupt(PIN_FOOT_SWITCH, updateSwitchCounter, FALLING);
switchCounterLastUpdatedTime = millis();
Serial.begin(9600);
Serial.println(WiFi.localIP());
Serial.println(WiFi.SSID());
Serial.println(UDP_LISTEN_PORT);
udp.begin(UDP_LISTEN_PORT);
strip1.begin();
strip2.begin();
for ( uint16_t i = 0; i < NUMBER_OF_LEDS; i++ ) {
currentColors[i] = DEFAULT_COLOR;
}
showColors(currentColors);
}
void loop() {
const int16_t packetSize = udp.parsePacket();
if ( packetSize > 0 ) {
// Serial.print("packetSize: ");
// Serial.println(packetSize);
if ( packetSize <= UDP_BUFFER_SIZE ) {
memset(udpBuffer, 0x00, UDP_BUFFER_SIZE);
udp.read(udpBuffer, UDP_BUFFER_SIZE);
}
udp.flush();
const uint16_t commandId = readUInt16(udpBuffer + 0);
if ( commandId == COMMAND_ID_FADE_COLORS ) {
struct FADE_COLORS_DATA data;
readFadeColorsData(udpBuffer + 2, &data);
fadeColors(currentColors, data.colors, data.durationInMilliseconds);
memcpy(currentColors, data.colors, sizeof(data.colors));
}
}
if ( overrideRequested ) {
overrideRequested = false;
fadeColors(currentColors, overrideColors, 500);
memcpy(currentColors, overrideColors, sizeof(currentColors));
}
delay(100);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment