Last active
March 23, 2016 15:27
-
-
Save nayutaya/9b25c03eb9e3dd3bdb5e to your computer and use it in GitHub Desktop.
マガジンラックLEDのコントローラ。UDP経由で色を設定する。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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