Кальян на ардуино

diversant123

★✩✩✩✩✩✩
19 Окт 2020
16
13
Всем привет. Сделал подсветку колбы кальяна на ардуино и адресной светодиодной ленте.

Жду ваших идей доработки и реализации!

Сначала сделал только подсветку с эффектом огня, а потом решил добавить еще пару эффектов.
Схема подключения элементарная, чуть позже нарисую (хочу добвить еще плату контроля заряда аккума)

Видео работы прототипа:


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);
}
 

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
@diversant123, Не пробовали сделать как мини матрицу? Чтобы не только по краям диоды были, а еще и сверху.
Переключать режимы под колбой не очень удобно, в идеале бы по WiFi, да и реакция на музыку не помешала бы. В таком случае за основу лучше всего брать Огненную Лампу (на ESP8266)
 

WoTeM

✩✩✩✩✩✩✩
4 Май 2022
21
0
это больше подсветка для паяльника, а то я думал тут будет огромный вейпирище только калик