Month: September 2016

Virtual Serial Port over IP

Posted on

If you like to connect from your Windows environment to your newly ESP8266 ESP-Link, you may use the very good software from Tibbo to create a virtual serial port.

http://tibbo.com/support/downloads/tdst.html

Download the version corresponding to your system (x32 or x64).

Install the package.

Open Tibbo VSP Manager and Add a port

step_0

Set the properties of the port as following to creat a TCP connection to the ESP8266 flashed with ESP-Link. The IP at the bottom is the IP address of the ESP82266!

Once done, a virtual port will be created in the COM section of the Device Manager.

For testing, use the serial console of Arduino IDE. (One of my temperature logger is sending data through the ESP8266).

From the console of the ESP-Link

step_7

 

I don’t know if it is possible to use the serial port to program an arduino that way but I know that the control lines could be changed from the setting. Let’s see, I will give it a try later.

Enjoy.

 

Advertisements

CNC -Makercam

Posted on Updated on

Just a quick note: I have been testing makercam (http://www.makercam.com) as a replacement for Gcode tools extension in Inkscape to generate the gcode for my CNC controlled by Mach3.

Works great and the stuff takes care of the tool offset, things I never managed automatically with Gcode tool.

I will add a couple of tips from my first test soon.

 

Steps to flash ESP-Link to ESP8266 4 Mbyte (ESP12)

Posted on Updated on

Just few words about flashing ESP-Link on ESP8266 (I posted first working on the ESP01 but gave it up. It bugs a lot. I use now a 4 Mbyte version.)

Yesterday I was looking (bit lazy) to make an ESP8266 TCP / Serial bridge in order to remote control one of my Nextion screen with Node-red (development and testing only).

While browsing I found out ESP-Link. Very nice tool. (Pity, I found that too late)

So, in few steps, to flash it you need to:

  • Download ESP-Link flasher software

http://www.espressif.com/en/support/download/other-tools?keys=&field_type_tid%5B%5D=14

  • Download firmware

https://github.com/jeelabs/esp-link/releases/tag/v2.2.3

  • Get the hardware info of the ESP

To do so, connect to the ESP the tool ESP flash download tool and press start.

step_1

Once the button start is pressed, you will get the hardware details in the Detected Info window.

step_2

Use the info for setting the right flash size and also the right address for flashing.

  • Use this setting for flashing:

step_3

  • Connect to the ESP8266 AP
  • In your browser go to: 192.168.4.1
  • You are good to go for more setting from the webpage

If you like to erase the flah, use the method of Patrik @

Completely format or erase ESP8266 flash memory

Pinball Key controller

Posted on Updated on

Part of my Pinball project: Key Controller.

I am making a pinball game based on 46″ screen. I am running Pinball fx2 or Ultra Pinball.

To control the flips I made a small button interface using an Arduino due. We the Due one can easily create a USB keyboard interface using the USB host library.

Here is the program and some photos of the hardware wiring.

arcade_controller_4

 

 

Word Clock

Posted on Updated on

This is a project I started a while ago and not yet completed. Just posting part of the design

  1. First Part of the Project: The front

The spaces between letters are 31.25mm (pitch of my led stripes). Font: Varsity Regular

word_clock_4

Word Clock Front

Here is a photo of the real things made from plastic sheets black and white. It is made by a local supplier (advertising display shop). Not bad.

916434330

2. Second Part of the Project: The back

Drawing of the laser cut back (layer 1)

g4168

Since I am limited by the cutting area of my laser cutter, I had to divide the area in 4 pieces.

Laser Cutting…

l_cut_2 l_cut_3 l_cut_1

Actually I need a thicker layer, the led are going to be too close to the front.

I am going to change to thick foam board. I will do the same design but CNC cut.

Foam board and CNC:

Result…

The result is OK, I still have to CNC three more pieces to complete the back.

Will finish that during the WE.

Soldering the stripes now.

Today is December 4th, I haven’t touch the thing for a while.

Here, the latest progress. All stripes are done and connected. Just need to think about the final look…

clock

Don’t know how I am going to control them yet?

Today, December 15th.

I have decided to make the clock running with an Arduino Nano + RTC DS3231.

I started with the code from Javelin Word Clock (google Javelin Word Clock) but changed it a bit!

Have a look and play with it. The code only runs the clock, there are no fanzy things yet…

#include <Adafruit_NeoPixel.h>
#include <Time.h>
#include <Wire.h>  
#include <DS1307RTC.h>        // a basic DS1307 library that returns time as a time_t
#include <avr/pgmspace.h>

#define N_LEDS 110
#define BRIGHTNESSDAY 200 // full on
#define BRIGHTNESSNIGHT 55 // half on
#define RGBLEDPIN 6

#define TIME_HEADER "T"

typedef const unsigned char prog_uchar;

Adafruit_NeoPixel grid = Adafruit_NeoPixel(N_LEDS, RGBLEDPIN, NEO_GRB + NEO_KHZ800);

int intBrightness = BRIGHTNESSDAY; // the brightness of the clock (0 = off and 255 = 100%)
 int intTestMode; // set when both buttons are held down
 String strTime = ""; // used to detect if word time has changed
 int intTimeUpdated = 0; // used to tell if we need to turn on the brightness again when words change

unsigned long previousMillis = 0;
 const long interval = 10000;

uint32_t colorWhite = grid.Color(255, 255, 255);
 uint32_t colorBlack = grid.Color(0, 0, 0);
 uint32_t colorRed = grid.Color(255, 0, 0);
 uint32_t colorGreen = grid.Color(0, 255, 0);
 uint32_t colorBlue = grid.Color(0, 0, 255);
 uint32_t colorJGreen = grid.Color(50, 179, 30);

#define arrIT {2,0,19}
#define arrIS {2,39,40}
#define arrAQUARTER {8,80,18,21,38,41,58,61,78}
#define arrHALF {4,3,16,23,36}
#define arrPAST {4,4,15,24,35}
#define arrOCLOCK {6,49,69,70,89,90,109}
#define arrTO {2,96,103}
#define arrONE {3,5,14,25}
#define arrTWO {3,34,45,54}
#define arrTHREE {5,65,74,85,94,105}
#define arrFOUR {4,6,13,26,33}
#define arrFIVE {4,46,53,66,73}
#define arrSIX {3,86,93,106}
#define arrSEVEN {5,55,64,75,84,95}
#define arrEIGHT {5,8,11,28,31,48}
#define arrNINE {4,7,12,27,32}
#define arrTEN {3,9,10,29}
#define arrELEVEN {6,51,68,71,88,91,108}
#define arrTWELVE {6,52,67,72,87,92,107}
#define arrTWENTY {6,2,17,22,37,42,57}
#define arrTWENTYFIVE {10,2,17,22,37,42,57,77,82,97,102}
#define arrMFIVE {4,77,82,97,102}
#define arrMTEN {3,56,63,76}

prog_uchar words[23][11] PROGMEM ={arrIT, arrIS, arrAQUARTER, arrMFIVE, arrMTEN, arrTWENTY, arrTWENTYFIVE, arrHALF,
 arrTO, arrPAST, arrONE, arrTWO, arrTHREE,
 arrFOUR, arrFIVE, arrSIX, arrSEVEN, arrEIGHT,
 arrNINE, arrTEN, arrELEVEN, arrTWELVE,
 arrOCLOCK};

prog_uchar m[12][2] PROGMEM ={{0,22},{5,3},{10,4},{15,2},{20,5},{25,6},{30,7},{35,6},{40,5},
 {45,2},{50,4},{55,3}};

prog_uchar h_a[13] PROGMEM ={0,10,11,12,13,14,15,16,17,18,19,20,21};
 prog_uchar h_b[13] PROGMEM ={0,11,12,13,14,15,16,17,18,19,20,21,10};

void setup() {

Serial.begin(9600);
 setSyncProvider(RTC.get); // the function to get the time from the RTC
 setSyncInterval(60); // sync the time every 60 seconds (1 minutes)
 if(timeStatus() != timeSet){
 Serial.println("Unable to sync");
 RTC.set(1481781666); // set the RTC to Thu, 15 Dec 2016 06:01:06 +00:00
 setTime(1481781666);
 }

// setup the LED strip
 grid.begin();
 grid.show();

// set the brightness of the strip
 grid.setBrightness(intBrightness);

}

void loop(){

unsigned long currentMillis = millis();

// if there is a serial connection lets see if we need to set the time
 if (Serial.available()) {
 time_t t = processSyncMessage();
 if (t != 0) {
 Serial.print("Time set via connection to: ");
 Serial.print(t);
 Serial.println();
 RTC.set(t); // set the RTC and the system time to the received value
 setTime(t);
 }
 }
 // check to see if the time has been set
 if (timeStatus() == timeSet){
 // time is set lets show the time
 if((hour() < 7) | (hour() >= 19)){
 intBrightness = BRIGHTNESSNIGHT;
 }else{
 intBrightness = BRIGHTNESSDAY;
 }
 grid.setBrightness(intBrightness);

}

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

for (byte z =0; z<110; z++){
 grid.setPixelColor(z,colorBlack);
 }

pushtime();
 grid.show();

}
 }

unsigned long processSyncMessage() {
 unsigned long pctime = 0L;
 const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

if(Serial.find(TIME_HEADER)) {
 pctime = Serial.parseInt();
 pctime = pctime + 28800; // + 8 hours - winter asia time
 return pctime;
 if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013) pctime = 0L; // return 0 to indicate that the time is not valid } Serial.println("Set"); } return pctime; } void pushtime(){ int Minute = minute(); int Hour = hourFormat12(); boolean past = true; Minute = Minute - (Minute % 5); if((minute()>34) && (minute()<= 59)) {
 past = false;
 }

Serial.print (hourFormat12());
 Serial.print (" : ");
 Serial.println (Minute);

// push IT
 for(int i = 1; i <= pgm_read_byte ( & words [0][0]); i++){
 Serial.println( pgm_read_byte ( & words [0][i]) );
 grid.setPixelColor(pgm_read_byte ( & words [0][i]),colorWhite);
 }
 // push IS
 for(int i = 1; i <= pgm_read_byte ( & words [1][0]); i++){
 Serial.println( pgm_read_byte ( & words [1][i]) );
 grid.setPixelColor(pgm_read_byte ( & words [1][i]),colorWhite);
 }
 // push minute
 byte a;
 for (byte i=0; i<12; i++) {
 if (pgm_read_byte ( & m [i][0]) == Minute) {
 a = pgm_read_byte ( & m [i][1]);
 break;
 }
 }
 for(int i = 1; i <= pgm_read_byte ( & words [a][0]); i++){  Serial.println( pgm_read_byte ( & words [a][i]));  grid.setPixelColor(pgm_read_byte ( & words [a][i]),colorWhite);  } //push to or past if (Minute > 0){
 if (past == true) {
 for(int i = 1; i <= pgm_read_byte ( & words [9][0]); i++){
 Serial.println( pgm_read_byte ( & words [9][i]) );
 grid.setPixelColor(pgm_read_byte ( & words [9][i]),colorWhite);
 }
 }
 if (past == false) {
 for(int i = 1; i <= pgm_read_byte ( & words [8][0]); i++){
 Serial.println( pgm_read_byte ( & words [8][i]) );
 grid.setPixelColor(pgm_read_byte ( & words [8][i]),colorWhite);
 }
 }
}
//push hour
 if (past == true){
 byte a = pgm_read_byte ( & h_a [Hour]);

for(int i = 1; i <= pgm_read_byte ( & words [a][0]); i++){
 Serial.println( pgm_read_byte ( & words [a][i]));
 grid.setPixelColor(pgm_read_byte ( & words [a][i]),colorWhite);
 }
 }

if (past == false){
 byte a = pgm_read_byte ( & h_b [Hour]);

for(int i = 1; i <= pgm_read_byte ( & words [a][0]); i++){
 Serial.println( pgm_read_byte ( & words [a][i]));
 grid.setPixelColor(pgm_read_byte ( & words [a][i]),colorWhite);
 }
 }
 }

Back and finally the clock is ticking…

Here is the last code. I used FastLed library and other nice stuff like PaletteKnife for FastLED. Really cool.

#include "FastLED.h"
#include <Time.h>
#include <Wire.h>  
#include <DS1307RTC.h>
#include <avr/pgmspace.h>
#include <IRremote.h>

#define N_LEDS 110
#define DATA_PIN 6
#define LED_TYPE    WS2812
#define BRIGHTNESS  255
#define UPDATES_PER_SECOND 50

#define TIME_HEADER  "T"

typedef const unsigned char prog_uchar;

CRGB leds[N_LEDS];

unsigned long previousMillis = 0;        
const long interval = 5000;
         
int RECV_PIN = 11;
boolean IR = false;
byte bb = 100;

#define arrIT         {2,0,19}
#define arrIS         {2,39,40}
#define arrAQUARTER   {8,80,18,21,38,41,58,61,78}
#define arrHALF       {4,3,16,23,36}
#define arrPAST       {4,4,15,24,35}
#define arrOCLOCK     {6,49,69,70,89,90,109}
#define arrTO         {2,96,103}
#define arrONE        {3,5,14,25}
#define arrTWO        {3,34,45,54}
#define arrTHREE      {5,65,74,85,94,105}
#define arrFOUR       {4,6,13,26,33}
#define arrFIVE       {4,46,53,66,73}
#define arrSIX        {3,86,93,106}
#define arrSEVEN      {5,55,64,75,84,95}
#define arrEIGHT      {5,8,11,28,31,48}
#define arrNINE       {4,7,12,27,32}
#define arrTEN        {3,9,10,29}
#define arrELEVEN     {6,51,68,71,88,91,108}
#define arrTWELVE     {6,52,67,72,87,92,107}
#define arrTWENTY     {6,2,17,22,37,42,57}
#define arrTWENTYFIVE {10,2,17,22,37,42,57,77,82,97,102}
#define arrMFIVE      {4,77,82,97,102}
#define arrMTEN       {3,56,63,76}

#define IR_ON           0xFFA25D
#define IR_AUTO         0xFF629D
#define IR_OFF          0xFFE21D
#define IR_SUP          0xFF22DD
#define IR_MUP          0xFF02FD
#define IR_BUP          0xFFC23D
#define IR_SDN          0xFFE0AF
#define IR_MDN          0xFFA857
#define IR_BDN          0xFF906F
#define IR_RED          0xFF6897
#define IR_GREEN        0xFF9867
#define IR_BLUE         0xFFB04F
#define IR_LIGHTYELLOW  0xFF30CF
#define IR_YELLOW       0xFF18E7
#define IR_LIGHTORANGE  0xFF7A85
#define IR_ORANGE       0xFF10EF
#define IR_GREY         0xFF38C7
#define IR_LIGHTBLUE    0xFF5AA5
#define IR_PINK         0xFF42BD
#define IR_LIGHTGREEN   0xFF4AB5
#define IR_WHITE        0xFF52AD



prog_uchar words[23][11] PROGMEM ={arrIT, arrIS, arrAQUARTER, arrMFIVE, arrMTEN, arrTWENTY, arrTWENTYFIVE, arrHALF, 
                                  arrTO, arrPAST, arrONE, arrTWO, arrTHREE,
                                  arrFOUR, arrFIVE, arrSIX, arrSEVEN, arrEIGHT,
                                  arrNINE, arrTEN, arrELEVEN, arrTWELVE,
                                  arrOCLOCK};
                                  
prog_uchar m[12][2] PROGMEM ={{0,22},{5,3},{10,4},{15,2},{20,5},{25,6},{30,7},{35,6},{40,5},
                                  {45,2},{50,4},{55,3}};

prog_uchar h_a[13] PROGMEM ={0,10,11,12,13,14,15,16,17,18,19,20,21};
prog_uchar h_b[13] PROGMEM ={0,11,12,13,14,15,16,17,18,19,20,21,10};

DEFINE_GRADIENT_PALETTE( p_orange ) {
    0,   9,  5,  1,
   48,  25,  9,  1,
   76, 137, 27,  1,
   96,  98, 42,  1,
  124, 144, 79,  1,
  153,  98, 42,  1,
  178, 137, 27,  1,
  211,  23,  9,  1,
  255,   9,  5,  1};


DEFINE_GRADIENT_PALETTE( p_green ) {
    0,   1, 22,  1,
  130,   1,168,  2,
  255,   1, 22,  1};



DEFINE_GRADIENT_PALETTE( p_red ) {
    0,  14,  2,  5,
   63,  40,  1,  7,
  130, 182,  1,  1,
  188,  40,  1,  7,
  255,  14,  2,  5};



DEFINE_GRADIENT_PALETTE( p_blue ) {
    0,   0,  0,  8,
   45,   0,  0, 45,
   79,   7, 12,255,
  119,  42, 55,255,
  158,   7, 12,255,
  209,   0,  0, 45,
  255,   0,  0,  8};


DEFINE_GRADIENT_PALETTE( p_yellow ) {
    0, 208,186, 19,
   53, 232,215, 42,
   84, 255,255, 45,
  127, 255,255,125,
  165, 255,255, 45,
  196, 232,215, 42,
  247, 208,186, 19,
  255, 208,186, 19};


DEFINE_GRADIENT_PALETTE( p_lightyellow ) {
    0, 159,142, 27,
   51, 192,180, 82,
  127, 255,255,255,
  201, 192,180, 82,
  255, 159,142, 27};


DEFINE_GRADIENT_PALETTE( p_lightorange ) {
    0,  47, 28,  2,
   76, 229, 73,  1,
  163, 255,255,  0,
  255, 229, 73,  1};


DEFINE_GRADIENT_PALETTE( p_grey ) {
    0,   1,  2,  1,
   51,  42, 55, 45,
   89, 144,178,170,
  130, 255,255,255,
  146, 194,215,210,
  175, 144,178,170,
  255,   1,  2,  1};


DEFINE_GRADIENT_PALETTE( p_lightblue ) {
    0,   1, 10, 19,
  132, 126,201,255,
  255,   1, 10, 19};


DEFINE_GRADIENT_PALETTE( p_pink ) {
    0,   2,  1,  8,
   94,  79,  2,212,
  140, 110, 11,197,
  255,   2,  1,  8};


DEFINE_GRADIENT_PALETTE( p_lightgreen ) {
    0,  30,186, 72,
   81,  77,255,105,
  127, 184,250,186,
  175,  77,255,105,
  255,  30,186, 72};


DEFINE_GRADIENT_PALETTE( p_white ) {
    0, 121,136,125,
   38, 173,180,172,
  107, 255,255,255,
  140, 255,255,255,
  219, 173,180,172,
  255, 121,136,125};


CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {

  FastLED.addLeds<LED_TYPE, DATA_PIN, GRB>(leds, N_LEDS);
  FastLED.setBrightness(  BRIGHTNESS );
    
    currentPalette = p_orange;
    currentBlending = LINEARBLEND;
    
  Serial.begin(9600);
  setSyncProvider(RTC.get);       // the function to get the time from the RTC
  setSyncInterval(60);            // sync the time every 60 seconds (1 minutes)

  irrecv.enableIRIn(); // Start the receiver
  
  if(timeStatus() != timeSet){
     Serial.println("Unable to sync");
     RTC.set(1481781666);         // set the RTC to Thu, 15 Dec 2016 06:01:06 +00:00
     setTime(1481781666);
  }
  
}

void loop(){
  
  
 if (irrecv.decode(&results)) {

    IR = true;
    previousMillis = millis();
  
   // Serial.println(results.value, HEX);

    //if results.value == 0xFFE21D display time

    switch (results.value) {
      case IR_OFF:          //exit IR Loop
        IR = false;
        break;
        case IR_GREEN:
        currentPalette = p_green;
        IR = false;
        break;
        case IR_RED:
        currentPalette = p_red;
        IR = false;
        break;
        case IR_BLUE:
        currentPalette = p_blue;
        IR = false;
        break;
        case IR_LIGHTYELLOW:
        currentPalette = p_lightyellow;
        IR = false;
        break;
        case IR_YELLOW:
        currentPalette = p_yellow;
        IR = false;
        break;
        case IR_LIGHTORANGE:
        currentPalette = p_lightorange;
        IR = false;
        break;
        case IR_ORANGE:
        currentPalette = p_orange;
        IR = false;
        break;
        case IR_GREY:
        currentPalette = p_grey;
        IR = false;
        break;
        case IR_LIGHTBLUE:
        currentPalette = p_lightblue;
        IR = false;
        break;
        case IR_PINK:
        currentPalette = p_pink;
        IR = false;
        break;
        case IR_LIGHTGREEN:
        currentPalette = p_lightgreen;
        IR = false;
        break;
        case IR_WHITE:
        currentPalette = p_white;
        IR = false;
        break;
        case IR_MUP:
        RTC.set(now() + 300);                       // set the RTC and the system time to the received value
        setTime(now() + 300);
        IR = false;
        break;
        case IR_MDN:
        RTC.set(now() - 300);                       // set the RTC and the system time to the received value
        setTime(now() - 300);
        IR = false;
        break;
        case IR_BUP:
        bb = bb + 10;
        IR = false;
        break;
        case IR_BDN:
        bb = bb - 10;
        IR = false;
        break;
    }
    
    irrecv.resume(); // Receive the next value
 }
 
 if (!IR) {
      unsigned long currentMillis = millis();
  // if there is a serial connection lets see if we need to set the time
  if (Serial.available()) {
    time_t t = processSyncMessage();
    if (t != 0) {
      Serial.print("Time set via connection to: ");
      Serial.print(t);
      Serial.println();
      RTC.set(t);                       // set the RTC and the system time to the received value
      setTime(t);          
    }
  }

   static uint8_t startIndex = 0;
    startIndex = startIndex + 1; /* motion speed */
    
    FillLEDsFromPaletteColors( startIndex);
    pushtime();
  
    FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
    }

if (IR) {
  //unsigned long currentMillis = millis();
  
if ( millis() - previousMillis >= interval) {
  IR = false; 
}
}
}
unsigned long processSyncMessage() {
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 

  if(Serial.find(TIME_HEADER)) {
     pctime = Serial.parseInt();
     pctime = pctime + 28800;       // + 8 hours - winter asia time
     return pctime;
     if( pctime < DEFAULT_TIME) {   
       pctime = 0L;                 // return 0 to indicate that the time is not valid
     }
     Serial.println("Set");
  }
  return pctime;
}

void pushtime(){

int Minute = minute();
int Hour = hourFormat12();
boolean past = true;

Minute = Minute - (Minute % 5);

if((minute()>34) && (minute()<= 59)) {
    past = false;
  }


// push IT
   for(int i = 1; i <= pgm_read_byte ( & words [0][0]); i++){
   leds[pgm_read_byte ( & words [0][i])] = CRGB::White;
  }
// push IS
   for(int i = 1; i <= pgm_read_byte ( & words [1][0]); i++){
   leds[pgm_read_byte ( & words [1][i])] = CRGB::White;
  }
// push Minute
  byte a;
  for (byte i=0; i<12; i++) {
   if (pgm_read_byte ( & m [i][0])  == Minute) {
     a = pgm_read_byte ( & m [i][1]);
     break;
   }
  }
   for(int i = 1; i <= pgm_read_byte ( & words [a][0]); i++){
   leds[pgm_read_byte ( & words [a][i])] = CRGB::White;
  }
  
//push to or past excepted 0
if ( Minute > 0){
if (past == true) {
  for(int i = 1; i <= pgm_read_byte ( & words [9][0]); i++){
   leds[pgm_read_byte ( & words [9][i])] = CRGB::White;
  }
}
if (past == false) {
  for(int i = 1; i <= pgm_read_byte ( & words [8][0]); i++){
   leds[pgm_read_byte ( & words [8][i])] = CRGB::White;
  }
}
}

//push hour
if (past == true){
   byte a = pgm_read_byte ( & h_a [Hour]);
  
   for(int i = 1; i <= pgm_read_byte ( & words [a][0]); i++){
   leds[pgm_read_byte ( & words [a][i])] = CRGB::White;
  }
}


if (past == false){
    byte a = pgm_read_byte ( & h_b [Hour]);
  
   for(int i = 1; i <= pgm_read_byte ( & words [a][0]); i++){
   leds[pgm_read_byte ( & words [a][i])] = CRGB::White;
  } 
}
}


void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
    for( int i = 0; i < N_LEDS; i++) {
        leds[i] = ColorFromPalette( currentPalette, colorIndex, bb, currentBlending);
        colorIndex += 3;
    }
}

I added a IR remote to set the time, change the effect and brightness.

If you look at the program, I stopped the led refresh to be able to use the IR receiving. I  check the millis once in the IR receiving mode and after 5 sec hte refresh starts again. Not as nice as I want it to be but it does the job.

Some photos…

remote
Remote Control used