Всем привет. Сделал подсветку колбы кальяна на ардуино и адресной светодиодной ленте.
Жду ваших идей доработки и реализации!
Сначала сделал только подсветку с эффектом огня, а потом решил добавить еще пару эффектов.
Схема подключения элементарная, чуть позже нарисую (хочу добвить еще плату контроля заряда аккума)
Видео работы прототипа:
Жду ваших идей доработки и реализации!
Сначала сделал только подсветку с эффектом огня, а потом решил добавить еще пару эффектов.
Схема подключения элементарная, чуть позже нарисую (хочу добвить еще плату контроля заряда аккума)
Видео работы прототипа:
hookan.ino:
#define NUM_LEDS 14 // количество светодиодов 84
#define LED_PIN 12 // пин ленты
#define BTN_PIN 3 // пин кнопки
uint8_t effect = 1; // номер эффекта
uint8_t total_effects = 5; // всего эффектов
uint32_t safeDelay;
#include <FastLED.h>
#include "GyverButton.h"
#include <EEPROM.h>
GButton btn(BTN_PIN);
struct CRGB leds[NUM_LEDS];
void setup() {
//Serial.begin(115200);
//Serial.println("\nSTART!");
effect = EEPROM.read(0);
next_effect();
// инициализация ленты
LEDS.addLeds<WS2811, LED_PIN, GRB>(leds, NUM_LEDS);
LEDS.setBrightness(255); // ограничить максимальную яркость
}
void loop() {
run_programm(effect);
btnTick();
}
// функция эффектов
void run_programm(int effect){
switch(effect){
case 1: EFFECT_fire(); // огонь
break;
case 2: EFFECT_rainbow(); // радуга
break;
case 3: EFFECT_rainbow2();
break;
case 4: EFFECT_SnowSparkle();
break;
case 5: EFFECT_random_march();
break;
}
}
01_effects.ino:
/* =================================================== FIRE */
// настройки пламени
#define HUE_GAP 20 // заброс по hue
#define FIRE_STEP 15 // шаг огня
#define HUE_START 0 // начальный цвет огня (0 красный, 80 зелёный, 140 молния, 190 розовый)
#define MIN_BRIGHT 70 // мин. яркость огня
#define MAX_BRIGHT 255 // макс. яркость огня
#define MIN_SAT 245 // мин. насыщенность
#define MAX_SAT 255 // макс. насыщенность
int fire_counter = 0;
// ленивая жопа
#define FOR_i(from, to) for(int i = (from); i < (to); i++)
void EFFECT_fire() {
static uint32_t prevTime;
// двигаем пламя
if (millis() - prevTime > 30) {
prevTime = millis();
int thisPos = 0, lastPos = 0;
FOR_i(0, NUM_LEDS) {
leds[i] = getFireColor((inoise8(i * FIRE_STEP, fire_counter)));
}
fire_counter += 10;
LEDS.show();
}
}
// возвращает цвет огня для одного пикселя
CRGB getFireColor(int val) {
// чем больше val, тем сильнее сдвигается цвет, падает насыщеность и растёт яркость
return CHSV(
HUE_START + map(val, 0, 255, 0, HUE_GAP), // H
constrain(map(val, 0, 255, MAX_SAT, MIN_SAT), 0, 255), // S
constrain(map(val, 0, 255, MIN_BRIGHT, MAX_BRIGHT), 0, 255) // V
);
}
/* =================================================== EFFECT_rainbow */
int ihue = 0;
void EFFECT_rainbow() {
if (millis() - safeDelay > 15) {
safeDelay = millis();
ihue -= 1;
fill_rainbow( leds, NUM_LEDS, ihue );
LEDS.show();
}
}
/* =================================================== EFFECT_rainbow2 */
DEFINE_GRADIENT_PALETTE ( heatmap2 ) {
0, 255, 0, 0,
127, 0, 0, 255,
255, 255, 0, 0,
};
uint8_t startIndex = 0;
CRGBPalette16 myPal2 = heatmap2;
float mindex2 = (float)255 / NUM_LEDS; // коэффициент перевода для палитры 1 к 1
void EFFECT_rainbow2(){
if (millis() - safeDelay > 20) {
safeDelay = millis();
for( int i = 0; i < NUM_LEDS; ++i) {
leds[i] = ColorFromPalette(myPal2, (i * mindex2 * .5) + startIndex);
}
startIndex += 2;
FastLED.show();
}
}
/* =================================================== EFFECT_SnowSparkle */
byte red = 5;
byte green = 0;
byte blue = 15;
uint32_t rndDelay;
int Pixel;
void EFFECT_SnowSparkle() {
if (millis() - safeDelay > 20) {
safeDelay = millis();
for (int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
FastLED.show();
}
if (millis() - rndDelay > random(200, 1000)) {
rndDelay = millis();
Pixel = random(NUM_LEDS);
setPixel(Pixel, 0xff, 0xff, 0xff);
FastLED.show();
}
}
void setPixel(int Pixel, byte red, byte green, byte blue) {
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
}
/* =================================================== EFFECT_random_march */
int ledsX[NUM_LEDS][3];
void EFFECT_random_march() {
if (millis() - safeDelay > 120) {
safeDelay = millis();
copy_led_array();
int iCCW;
leds[0] = CHSV(random(0, 255), 255, 255);
for (int idex = 1; idex < NUM_LEDS ; idex++ ) {
iCCW = adjacent_ccw(idex);
leds[idex].r = ledsX[iCCW][0];
leds[idex].g = ledsX[iCCW][1];
leds[idex].b = ledsX[iCCW][2];
}
LEDS.show();
}
}
void copy_led_array() {
for (int i = 0; i < NUM_LEDS; i++ ) {
ledsX[i][0] = leds[i].r;
ledsX[i][1] = leds[i].g;
ledsX[i][2] = leds[i].b;
}
}
int adjacent_ccw(int i) {
int r;
if (i > 0) {
r = i - 1;
}
else {
r = NUM_LEDS - 1;
}
return r;
}
02_controls.ino:
// нажатие кнопки
void btnTick() {
btn.tick();
if (btn.isSingle()) {
next_effect();
}
if (btn.isHolded()) {
}
}
void next_effect() {
effect++;
if (effect > total_effects) effect = 1;
EEPROM.write(0, effect);
}