Chris Hockuba
Published © CC BY-NC-SA

IOT TOMTA Lamp from IKEA

I changed ordinary boring desk lamp into Blynk controlled device :)

BeginnerFull instructions provided1 hour1,535
IOT TOMTA Lamp from IKEA

Things used in this project

Hardware components

SparkFun Blynk Board - ESP8266
SparkFun Blynk Board - ESP8266
×1
WS2812B
×18
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
×1
5V USB Charger
×1

Software apps and online services

Blynk
Blynk

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Code

Main Code

C/C++
There are some defines with comments in the code but everything is explained.
 //#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Adafruit_NeoPixel.h>
#include <TimeLib.h>
#include <WidgetRTC.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "**********************";

//Global variables
//
bool leds_enable;
bool blynk_connection;
bool change;
uint8_t red, green, blue, effect, led_speed;
float brightness = 1.0;
bool autoLED = false;
bool autoTime = false;
bool syncOnChange = false;

//WS2812B Config
//
#define PIXEL_PIN   4     // Digital IO pin connected to the NeoPixels. Pin 4 is on Blynk Board.
#define PIXEL_COUNT 18    // Pixels Count

//Config leds used to display connection status
//LED0 is red
//LED1 is green
//If you don want to use, comment out LED0, LED1 or both.
//
#define LED0 13 //RED
#define LED1 4  //GREEN

//For multiple config
//
#define LED_SET 1
int currentLedSet = 0; // if not using multiple LED sets please set to current LED_SET

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
WidgetLCD lcd(V0);
WidgetRTC rtc;

BLYNK_ATTACH_WIDGET(rtc, V7);

///Prototypes so some ArduinoIDEs wont cri
void leds_off();
void leds_on();
void colorWipe(uint32_t c, uint8_t wait);
void rainbow(uint8_t wait);
void rainbowCycle(uint8_t wait);
void theaterChase(uint32_t c, uint8_t wait);
void theaterChaseRainbow(uint8_t wait);
uint32_t Wheel(byte WheelPos);


void setup()
{
  led_speed = 0;
  red = 255;
  green = 255;
  blue = 255;
  leds_enable = true;
  #ifdef LED0
  pinMode(LED0, OUTPUT);
  digitalWrite(LED0, HIGH);
  #endif
  #ifdef LED1
  pinMode(LED1, OUTPUT);
  digitalWrite(LED1, HIGH);
  #endif
  Serial.begin(115200);
  Blynk.begin(auth, "SSID", "PASSWORD");
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  Serial.print("Connecting");
  while (Blynk.connect() == false) {
    // Wait until connected
    Serial.print(".");
    delay(100);
  }
  Serial.println();
  Blynk.syncAll();
  rtc.begin();
  lcd.clear();
  lcd.print(0, 1, "Welcome!");
}

BLYNK_WRITE(V1) {
  if (currentLedSet == LED_SET) {
    leds_enable = param.asInt();
    change = true;
    if (leds_enable) {
      Blynk.virtualWrite(8, 0);
      autoLED = false;
    }
  }
}

BLYNK_WRITE(V2) {
  if (currentLedSet == LED_SET) {
    brightness = (float)param.asInt()/100;
  }
}

BLYNK_WRITE(V3) {
  if (currentLedSet == LED_SET) {
    green = param.asInt();
    change = true;
  }
}

BLYNK_WRITE(V4) {
  if (currentLedSet == LED_SET) {
    red = param.asInt();
    change = true;
  }
}

BLYNK_WRITE(V5) {
  if (currentLedSet == LED_SET) {
    blue = param.asInt();
    change = true;
  }
}

BLYNK_WRITE(V6) {
  if (currentLedSet == LED_SET) {
    led_speed = param.asInt();
  }
}

BLYNK_WRITE(V8) {
  if (currentLedSet == LED_SET) {
    autoLED = param.asInt();
    if (autoLED) {
      Blynk.virtualWrite(1, 0);
      leds_enable = false;
    }
  }
}

BLYNK_WRITE(V9) {
  if (currentLedSet == LED_SET) {
    effect = param.asInt();
    change = true;
    lcd.clear();
    switch (effect) {
      case 0:
        lcd.print(0, 0, "LEDS OFF");
        break;
      case 1:
        lcd.print(0, 0, "LEDS ON");
        break;
      case 2:
        lcd.print(0, 0, "Color Wipe");
        break;    
      case 3:
        lcd.print(0, 0, "Theater Chase");
        break;
      case 4:
        lcd.print(0, 0, "Theater Chase");
        lcd.print(0, 1, "Rainbow");
        break;
      case 5:
        lcd.print(0, 0, "Rainbow");
        break;
      case 6:
        lcd.print(0, 0, "Rainbow Cycle");
        break;
    }
  }
}

BLYNK_READ(V10) {
  if (currentLedSet == LED_SET) {
    String timeString = String(hour()) + ":" + String(minute()) + ":" +  String(second());
    Blynk.virtualWrite(10, timeString);
  }
}


BLYNK_WRITE(V11) {
  autoTime = param.asInt();
  (autoTime) ? Blynk.virtualWrite(12, 255) : Blynk.virtualWrite(12, 0);
}

BLYNK_WRITE(V13) {
  if (currentLedSet != LED_SET) syncOnChange = true;
  currentLedSet = param.asInt();
}

void loop()
{
  if (syncOnChange) {
    Blynk.syncAll();
    syncOnChange = false;
  }
  change = false;
  if (Blynk.connected()) {
    #ifdef LED1
    digitalWrite(LED1, HIGH);
    #endif
    #ifdef LED0
    digitalWrite(LED0, LOW);
    #endif
  }
  else {
    #ifdef LED0
    digitalWrite(LED0, HIGH);
    #endif
    #ifdef LED1
    digitalWrite(LED1, LOW);
    #endif
  }
  Blynk.run();
  if (leds_enable) {
    switch (effect) {
      case 0:
        leds_off();
        break;
      case 1:
        leds_on();
        break;
      case 2:
        colorWipe(strip.Color(brightness*(float)red, brightness*(float)green, brightness*(float)blue), led_speed);
        break;
      case 3:
        theaterChase(strip.Color(brightness*(float)red, brightness*(float)green, brightness*(float)blue), led_speed);
        break;
      case 4:
        theaterChaseRainbow(led_speed);
        break;
      case 5:
        rainbow(led_speed);
        break;
      case 6:
        rainbowCycle(led_speed);
        break;
    }
  }
  else {
    leds_off();
  }
  if (autoLED) {
    if (autoTime) {
      leds_enable = true;
    } else {
      leds_enable = false;
    }
  }
}

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////

void leds_off() {
  for (int i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(0, 0, 0));
  }
  strip.show();
  delay(20);
}

void leds_on() {
  for (int i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(brightness*(float)red, brightness*(float)green, brightness*(float)blue));
  }
  strip.show();
  delay(20);
}

/////////////////////////////////////////////////////////////////////////
//
//Any functions from now on are from Adafruit library with little mods.
//
/////////////////////////////////////////////////////////////////////////

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  delay(wait);
  leds_off();
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
    Blynk.run();
    if (change) {return;}
  }
  delay(wait);
  leds_off();
  delay(wait);
  for(int i=strip.numPixels(); i>=0; i--) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
    Blynk.run();
    if (change) {return;}
  }
  return;
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
    Blynk.run();
    if (change) {return;}
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
    Blynk.run();
    if (change) {return;}
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay(wait);
      Blynk.run();
      if (change) {return;}
      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
      }
      strip.show();

      delay(wait);
      Blynk.run();
      if (change) {return;}
      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Credits

Chris Hockuba

Chris Hockuba

3 projects • 5 followers
Maker, Entrepreneur, Mechanical Engineer

Comments