Tak się napatrzyłem na różne projekty ledowe na youtubie i niektóre mi się spodobały, więc spróbowałem sam coś skleić.
W pobliskim markecie nabyłem elementy składowe projektu.
Kilka wieczorów dłubania i wyszła amatorska lampa DIY na taśmie ledowej WS2812B.
Do budowy użyłem: listwa drewniana 20x30mm x 2,4m,naluminiowy profil do taśm led, klej do drewna, kilka wkrętów, pleksa mleczna, mała puszka (200ml) białej farby + wałek + pędzel, taśma ledowa WS2812B, wemos d1mini, tymczasowo zasliacz 12V 3A + przetwornica step-down LM2596 ustawiona na 5V
2 krótkie filmiki z przezentacji działania
https://youtu.be/sfJkrrcNDJQ
https://youtu.be/iQaIDBlvyhM
KOD również amatorski sklejony metodą Ctrl+C, Ctrl+V z przykładu supli oraz z biblioteki FastLED.
Code: Select all
// TEST_LAMPA_DIY_WS2812B//
/*
Copyright (C) AC SOFTWARE SP. Z O.O.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <SPI.h>
#include <SuplaDevice.h>
#include <supla/control/virtual_relay.h>
#include <supla/control/rgbw_base.h>
// ESP8266 based board:
#include <supla/network/esp_wifi.h>
Supla::ESPWifi wifi("your_wifi_ssid", "your_wifi_password");
#include <FastLED.h>
#define LED_PIN 5
#define COLOR_ORDER GRB
#define CHIPSET WS2812B
#define NUM_LEDS 53
#define RED_PIN 101
#define GREEN_PIN 102
#define BLUE_PIN 103
#define COLOR_BRIGHTNESS_PIN 104
#define BRIGHTNESS_PIN 105
#define BRIGHTNESS 150
#define FRAMES_PER_SECOND 60
#define FASTLED_ALLOW_INTERRUPTS 0
FASTLED_USING_NAMESPACE
#define TEMPERATURE_1 Tungsten100W
#define TEMPERATURE_2 OvercastSky
#define DISPLAYTIME 30
bool gReverseDirection = false;
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
CRGB leds[NUM_LEDS];
CRGBPalette16 gPal;
Supla::Control::RGBWBase *r_g_b_w = nullptr;
Supla::Control::VirtualRelay *virtual_relay1 = nullptr; // name for relay 1
Supla::Control::VirtualRelay *virtual_relay2 = nullptr; // name for relay 2
Supla::Control::VirtualRelay *virtual_relay3 = nullptr; // name for relay 3
Supla::Control::VirtualRelay *virtual_relay4 = nullptr; // name for relay 4
Supla::Control::VirtualRelay *virtual_relay5 = nullptr; // name for relay 5
// zmienne pomocnicze //
int X0, X1, X2, X3, X4, X5 = false;
int FUNKCJA = 100;
int R_G_B_W = false;
class RgbwLeds : public Supla::Control::RGBWBase {
public:
RgbwLeds(int redPin,
int greenPin,
int bluePin,
int colorBrightnessPin,
int brightnessPin)
: redPin(redPin),
greenPin(greenPin),
bluePin(bluePin),
colorBrightnessPin(colorBrightnessPin),
brightnessPin(brightnessPin) {
}
void setRGBWValueOnDevice( uint8_t red,
uint8_t green,
uint8_t blue,
uint8_t colorBrightness,
uint8_t brightness) {
// analogWrite(brightnessPin, (brightness * 255) / 100);
// analogWrite(colorBrightnessPin, (colorBrightness * 255) / 100);
// analogWrite(redPin, red);
// analogWrite(greenPin, green);
// analogWrite(bluePin, blue);
if ( colorBrightnessPin > 5) {
R_G_B_W = true;
// włączenie KOLORU RGB wyłącza pozostałe kanały jeżeli któryś jest włączony //
if ( virtual_relay1->isOn()) virtual_relay1->turnOff();
if ( virtual_relay2->isOn()) virtual_relay2->turnOff();
if ( virtual_relay3->isOn()) virtual_relay3->turnOff();
if ( virtual_relay4->isOn()) virtual_relay4->turnOff();
if ( virtual_relay5->isOn()) virtual_relay5->turnOff();
for (int i = 0; i < NUM_LEDS; i++) {
leds[i].r = red * colorBrightness / 200 ; // max red 255 * max colorBrightness 100 / 170 = 150 maksymalna jasność (zasilacz 2A)
leds[i].g = green * colorBrightness / 200 ; // max green 255 * max colorBrightness 100 / 170 = 150 maksymalna jasność (zasilacz 2A)
leds[i].b = blue * colorBrightness / 200 ; // max blue 255 * max colorBrightness 100 / 170 = 150 maksymalna jasność (zasilacz 2A)
}
FastLED.show();
}
}
protected:
int redPin;
int greenPin;
int bluePin;
int brightnessPin;
int colorBrightnessPin;
};
void setup() {
Serial.begin(115200);
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness( BRIGHTNESS );
gPal = HeatColors_p;
// Replace the falowing GUID with value that you can retrieve from https://www.supla.org/arduino/get-guid
char GUID[SUPLA_GUID_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// Replace the following AUTHKEY with value that you can retrieve from: https://www.supla.org/arduino/get-authkey
char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
WiFi.mode(WIFI_STA);
/*
Having your device already registered at cloud.supla.org,
you want to change CHANNEL sequence or remove any of them,
then you must also remove the device itself from cloud.supla.org.
Otherwise you will get "Channel conflict!" error.
*/
r_g_b_w = new RgbwLeds(RED_PIN, GREEN_PIN, BLUE_PIN, COLOR_BRIGHTNESS_PIN, BRIGHTNESS_PIN); // kanał RGBW
virtual_relay1 = new Supla::Control::VirtualRelay(); // wirtualny kanał // Confetti(
virtual_relay2 = new Supla::Control::VirtualRelay(); // wirtualny kanał // ColorTemperature()
virtual_relay3 = new Supla::Control::VirtualRelay(); // wirtualny kanał // Pacifica()
virtual_relay4 = new Supla::Control::VirtualRelay(); // wirtualny kanał // Fire2012()
virtual_relay5 = new Supla::Control::VirtualRelay(); // wirtualny kanał // Fire2012WithPalette()
OFF();
/*
SuplaDevice Initialization.
Server address is available at https://cloud.supla.org
If you do not have an account, you can create it at https://cloud.supla.org/account/create
SUPLA and SUPLA CLOUD are free of charge
*/
SuplaDevice.setName("LAMPA_DIY_WS2812B");
SuplaDevice.begin(GUID, // Global Unique Identifier
"svr1.supla.org", // SUPLA server address
"email@address", // Email address used to login to Supla Cloud
AUTHKEY); // Authorization key
}
void loop() {
if ( virtual_relay1->isOn() && X1 == false) {
Serial.println("kanał 1 On");
X1 = true;
X0 = true;
// jeżeli włączony 1 kanał to wyłącza pozostałe jeżeli któryś jest włączony //
if ( virtual_relay2->isOn()) virtual_relay2->turnOff();
if ( virtual_relay3->isOn()) virtual_relay3->turnOff();
if ( virtual_relay4->isOn()) virtual_relay4->turnOff();
if ( virtual_relay5->isOn()) virtual_relay5->turnOff();
/* // włączenie wirtualnego kanału wyłącza RGBW // niestety użycie tego resetuje esp
if ( R_G_B_W == true) {
r_g_b_w->setRGBWValueOnDevice(0, 0, 0, 0, 150);
// mirgbw->setRGBWValueOnDevice(hw_red, hw_green, hw_blue, hw_colorBrightness, hw_brightness);
R_G_B_W = false;
}
*/
FUNKCJA = 1; Serial.print(" FUNKCJA: "); Serial.print(FUNKCJA); Serial.println(" Confetti()");
}
if ( !virtual_relay1->isOn() && X1 == true) {
X1 = false;
Serial.println("kanał 1 Off");
}
if ( virtual_relay2->isOn() && X2 == false) {
Serial.println("kanał 2 On");
X2 = true;
X0 = true;
// jeżeli włączony 2 kanał to wyłącza pozostałe jeżeli któryś jest włączony //
if ( virtual_relay1->isOn()) virtual_relay1->turnOff(); // jeżeli włączony 2 kanał to wyłącza pozostałe //
if ( virtual_relay3->isOn()) virtual_relay3->turnOff();
if ( virtual_relay4->isOn()) virtual_relay4->turnOff();
if ( virtual_relay5->isOn()) virtual_relay5->turnOff();
FUNKCJA = 2; Serial.print(" FUNKCJA: "); Serial.print(FUNKCJA); Serial.println(" ColorTemperature()");
ON();
}
if ( !virtual_relay2->isOn() && X2 == true) {
X2 = false;
Serial.println("kanał 2 Off");
}
if ( virtual_relay3->isOn() && X3 == false) {
Serial.println("kanał 3 On");
X3 = true;
X0 = true;
// jeżeli włączony 3 kanał to wyłącza pozostałe jeżeli któryś jest włączony //
if ( virtual_relay1->isOn()) virtual_relay1->turnOff();
if ( virtual_relay2->isOn()) virtual_relay2->turnOff();
if ( virtual_relay4->isOn()) virtual_relay4->turnOff();
if ( virtual_relay5->isOn()) virtual_relay5->turnOff();
FUNKCJA = 3; Serial.print(" FUNKCJA: "); Serial.print(FUNKCJA); Serial.println(" Pacifica()");
ON();
}
if ( !virtual_relay3->isOn() && X3 == true) {
X3 = false;
Serial.println("kanał 3 Off");
}
if ( virtual_relay4->isOn() && X4 == false) {
Serial.println("kanał 4 On");
X4 = true;
X0 = true;
// jeżeli włączony 4 kanał to wyłącza pozostałe jeżeli któryś jest włączony //
if ( virtual_relay1->isOn()) virtual_relay1->turnOff();
if ( virtual_relay2->isOn()) virtual_relay2->turnOff();
if ( virtual_relay3->isOn()) virtual_relay3->turnOff();
if ( virtual_relay5->isOn()) virtual_relay5->turnOff();
FUNKCJA = 4; Serial.print(" FUNKCJA: "); Serial.print(FUNKCJA); Serial.println(" Fire2012()");
}
if ( !virtual_relay4->isOn() && X4 == true) {
X4 = false;
Serial.println("kanał 4 Off");
}
if ( virtual_relay5->isOn() && X5 == false) {
Serial.println("kanał 5 On");
X5 = true;
X0 = true;
// jeżeli włączony 5 kanał to wyłącza pozostałe jeżeli któryś jest włączony //
if ( virtual_relay1->isOn()) virtual_relay1->turnOff();
if ( virtual_relay2->isOn()) virtual_relay2->turnOff();
if ( virtual_relay3->isOn()) virtual_relay3->turnOff();
if ( virtual_relay4->isOn()) virtual_relay4->turnOff();
FUNKCJA = 5; Serial.print(" FUNKCJA: "); Serial.print(FUNKCJA); Serial.println(" Fire2012WithPalette()");
}
if ( !virtual_relay5->isOn() && X5 == true) {
X5 = false;
Serial.println("kanał 5 Off");
}
if ( !virtual_relay1->isOn() && !virtual_relay2->isOn() && !virtual_relay3->isOn() && !virtual_relay4->isOn() && !virtual_relay5->isOn() && X0 == true) {
Serial.println("kanał ALL Off");
X0 = false;
FUNKCJA = 0;
Serial.println("lampa OFF");
}
SuplaDevice.iterate();
// funkcje z biblioteki FastLed //
switch (FUNKCJA) {
case 0:
FUNKCJA = 100;
OFF();
break;
case 1:
Confetti();
FastLED.show();
FastLED.delay(1000 / FRAMES_PER_SECOND);
break;
case 2:
COLORTEMPERATURE();
FastLED.show();
FastLED.delay(1000 / FRAMES_PER_SECOND / 2);
break;
case 3:
EVERY_N_MILLISECONDS( 20) {
Pacifica_loop();
FastLED.show();
}
break;
case 4:
Fire2012(); // run simulation frame
FastLED.show(); // display this frame
FastLED.delay(1000 / FRAMES_PER_SECOND * 2);
break;
case 5:
Fire2012WithPalette(); // run simulation frame, using palette colors
FastLED.show(); // display this frame
FastLED.delay(1000 / FRAMES_PER_SECOND);
break;
case 100:
break;
}
}
void ON() {
for ( int i = 0; i < 100; i++ ) {
long Number0 = random(0, NUM_LEDS);
long Number1 = random(0, 100);
long Number2 = random(0, 100);
long Number3 = random(0, 100);
leds[Number0] = CHSV(Number1, Number2, Number3);
FastLED.show();
delay(1);
}
}
// wyłączenie lampy//
void OFF() {
for (int i = 0; i < NUM_LEDS; i++) {
leds[NUM_LEDS - i - 1] = CHSV(0, 0, 0);
FastLED.show();
delay(10);
}
}
#define COOLING 55
#define SPARKING 120
void Fire2012()
{
// Array of temperature readings at each simulation cell
static byte heat[NUM_LEDS];
// Step 1. Cool down every cell a little
for ( int i = 0; i < NUM_LEDS; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
for ( int k = NUM_LEDS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
if ( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160, 255) );
}
// Step 4. Map from heat cells to LED colors
for ( int j = 0; j < NUM_LEDS; j++) {
CRGB color = HeatColor( heat[j]);
int pixelnumber;
if ( gReverseDirection ) {
pixelnumber = (NUM_LEDS - 1) - j;
} else {
pixelnumber = j;
}
leds[pixelnumber] = color;
}
}
void Fire2012WithPalette()
{
// Array of temperature readings at each simulation cell
static byte heat[NUM_LEDS];
// Step 1. Cool down every cell a little
for ( int i = 0; i < NUM_LEDS; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
for ( int k = NUM_LEDS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
if ( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160, 255) );
}
// Step 4. Map from heat cells to LED colors
for ( int j = 0; j < NUM_LEDS; j++) {
// Scale the heat value from 0-255 down to 0-240
// for best results with color palettes.
byte colorindex = scale8( heat[j], 240);
CRGB color = ColorFromPalette( gPal, colorindex);
int pixelnumber;
if ( gReverseDirection ) {
pixelnumber = (NUM_LEDS - 1) - j;
} else {
pixelnumber = j;
}
leds[pixelnumber] = color;
}
}
void COLORTEMPERATURE() {
// draw a generic, no-name rainbow
static uint8_t starthue = 0;
fill_rainbow( leds + 5, NUM_LEDS - 5, --starthue, 20);
// Choose which 'color temperature' profile to enable.
uint8_t secs = (millis() / 1000) % (DISPLAYTIME);
if ( secs < DISPLAYTIME) {
FastLED.setTemperature( TEMPERATURE_1 ); // first temperature
leds[0] = TEMPERATURE_1; // show indicator pixel
} else {
FastLED.setTemperature( TEMPERATURE_2 ); // second temperature
leds[0] = TEMPERATURE_2; // show indicator pixel
}
}
void Confetti()
{
// random colored speckles that blink in and fade smoothly
fadeToBlackBy( leds, NUM_LEDS, 10);
int pos = random16(NUM_LEDS);
leds[pos] += CHSV( gHue + random8(64), 200, 255);
}
CRGBPalette16 pacifica_palette_1 =
{ 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117,
0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x14554B, 0x28AA50
};
CRGBPalette16 pacifica_palette_2 =
{ 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117,
0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x0C5F52, 0x19BE5F
};
CRGBPalette16 pacifica_palette_3 =
{ 0x000208, 0x00030E, 0x000514, 0x00061A, 0x000820, 0x000927, 0x000B2D, 0x000C33,
0x000E39, 0x001040, 0x001450, 0x001860, 0x001C70, 0x002080, 0x1040BF, 0x2060FF
};
void Pacifica_loop()
{
// Increment the four "color index start" counters, one for each wave layer.
// Each is incremented at a different speed, and the speeds vary over time.
static uint16_t sCIStart1, sCIStart2, sCIStart3, sCIStart4;
static uint32_t sLastms = 0;
uint32_t ms = GET_MILLIS();
uint32_t deltams = ms - sLastms;
sLastms = ms;
uint16_t speedfactor1 = beatsin16(3, 179, 269);
uint16_t speedfactor2 = beatsin16(4, 179, 269);
uint32_t deltams1 = (deltams * speedfactor1) / 256;
uint32_t deltams2 = (deltams * speedfactor2) / 256;
uint32_t deltams21 = (deltams1 + deltams2) / 2;
sCIStart1 += (deltams1 * beatsin88(1011, 10, 13));
sCIStart2 -= (deltams21 * beatsin88(777, 8, 11));
sCIStart3 -= (deltams1 * beatsin88(501, 5, 7));
sCIStart4 -= (deltams2 * beatsin88(257, 4, 6));
// Clear out the LED array to a dim background blue-green
fill_solid( leds, NUM_LEDS, CRGB( 2, 6, 10));
// Render each of four layers, with different scales and speeds, that vary over time
pacifica_one_layer( pacifica_palette_1, sCIStart1, beatsin16( 3, 11 * 256, 14 * 256), beatsin8( 10, 70, 130), 0 - beat16( 301) );
pacifica_one_layer( pacifica_palette_2, sCIStart2, beatsin16( 4, 6 * 256, 9 * 256), beatsin8( 17, 40, 80), beat16( 401) );
pacifica_one_layer( pacifica_palette_3, sCIStart3, 6 * 256, beatsin8( 9, 10, 38), 0 - beat16(503));
pacifica_one_layer( pacifica_palette_3, sCIStart4, 5 * 256, beatsin8( 8, 10, 28), beat16(601));
// Add brighter 'whitecaps' where the waves lines up more
pacifica_add_whitecaps();
// Deepen the blues and greens a bit
pacifica_deepen_colors();
}
// Add one layer of waves into the led array
void pacifica_one_layer( CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff)
{
uint16_t ci = cistart;
uint16_t waveangle = ioff;
uint16_t wavescale_half = (wavescale / 2) + 20;
for ( uint16_t i = 0; i < NUM_LEDS; i++) {
waveangle += 250;
uint16_t s16 = sin16( waveangle ) + 32768;
uint16_t cs = scale16( s16 , wavescale_half ) + wavescale_half;
ci += cs;
uint16_t sindex16 = sin16( ci) + 32768;
uint8_t sindex8 = scale16( sindex16, 240);
CRGB c = ColorFromPalette( p, sindex8, bri, LINEARBLEND);
leds[i] += c;
}
}
// Add extra 'white' to areas where the four layers of light have lined up brightly
void pacifica_add_whitecaps()
{
uint8_t basethreshold = beatsin8( 9, 55, 65);
uint8_t wave = beat8( 7 );
for ( uint16_t i = 0; i < NUM_LEDS; i++) {
uint8_t threshold = scale8( sin8( wave), 20) + basethreshold;
wave += 7;
uint8_t l = leds[i].getAverageLight();
if ( l > threshold) {
uint8_t overage = l - threshold;
uint8_t overage2 = qadd8( overage, overage);
leds[i] += CRGB( overage, overage2, qadd8( overage2, overage2));
}
}
}
// Deepen the blues and greens
void pacifica_deepen_colors()
{
for ( uint16_t i = 0; i < NUM_LEDS; i++) {
leds[i].blue = scale8( leds[i].blue, 145);
leds[i].green = scale8( leds[i].green, 200);
leds[i] |= CRGB( 2, 5, 7);
}
}
Kanał RGB służy do ustawiania kolorów na całej listwie natomiast wirtualne kanały służą do uruchamiania zaprogramowanych funkcji, w moim przypadku 5 wybranych funkcji z biblioteki FastLED.