Arduino Project Hub
Project showcase

Wifi Death Lamp

IKEA PS 2014 Pendant Lamp Modification

  • 19,674 views
  • 3 comments
  • 49 respects

Components and supplies

About this project

When you first see the IKEA PS 2014 Pendant lamp, It's hard not to think of Star Wars Death Star.

I wanted to create a IoT (Internet Of Things) connected Wifi Death Lamp. I searched the net for projects and found one project that inspired me the most http://davidbliss.com/2014/11/18/transforming-sphere-lamp/ I also added a Ultrasonic Sensor from this project https://youtu.be/95-dtNbKG6Q/

I aquired the parts and started the assembling. 

  • This project is work in progress. Currently I am finalizing and testing the software.


Proof of concept

Testing the stepper motor (Arduino Uno + Arduino Stepper Motor Shield r3)

Testing the stepper motor (Arduino Uno + Arduino Stepper Motor Shield r3)
Testing the NeoPixels (Particle (Spark) Core)

Schematics

Wiring diagram
Wiring diagram, see how to connect the parts
Wifideathlamp bb
Schematic draft
Hand drawn project sketch
Death%20lamp%20projektskiss%20001

Code

Particle photon test code (works with Particle Core aswell)C/C++
Test code for controlling the NeoPixels + Stepper with your hand (gestures).
// This #include statement was automatically added by the Spark IDE.
#include "neopixel/neopixel.h"

// This #include statement was automatically added by the Spark IDE.
#include "application.h"
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D2
#define PIXEL_COUNT 114
#define PIXEL_TYPE WS2812B

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

int led0 = D7; // This one is the built-in tiny one to the right of the USB jack
int motortrigg = D6; // Stepper-trigger to ARDUINO -> PIN2 INPUT trigg Arduino/MotorShield
int trigger = D3; // TRIGG
int echo = D4; //ECHO
int ping = 0; //loop couter
int showType = 0; //led show start

unsigned long triggerTarget;

uint8_t value = 1;

void setup() {
    pinMode(motortrigg, OUTPUT);
    pinMode(trigger, OUTPUT);
    pinMode(echo, INPUT);
    pinMode(led0, OUTPUT);
    digitalWrite(trigger, LOW);
    digitalWrite(motortrigg, LOW);
    strip.begin();
    strip.show(); // Initialize all pixels to 'off'
  
    showType = value;
    startShow(showType); // Set last shownumber from EEPROM
}

void loop() {
    
    digitalWrite(led0, LOW);    // Turn OFF the LED pin

    // Pull the trigger pin high for roughly 10uS then pull it low and wait another 10uS.
    triggerTarget = micros();
    while (micros() < triggerTarget + 10) {
        digitalWrite(trigger, HIGH);
    }
    while (micros() < triggerTarget + 20) {
        digitalWrite(trigger, LOW);
    }

    // Read the return echo then convert it to in and cm.
    unsigned long sonar = pulseIn(echo, HIGH);
    //float in = sonar / 148;
    int cm = sonar / 58;

    if (cm >= 8 && cm <= 10){  digitalWrite(led0, HIGH); // // Internal led
                    digitalWrite(motortrigg, HIGH);   // Trigger stepper on PARTICLE CORE PIN D6 -> PIN D2 ARDUINO + MOTOR SHIELD
                    delay(50);
                    digitalWrite(motortrigg, LOW);
                    digitalWrite(led0, LOW);
         
    }
    //if (cm < 35){ digitalWrite(led2, HIGH);   // LED on object closer than x cm
    if (cm >= 15 && cm <=30 ){ digitalWrite(led0, HIGH);   // Internal led on
                // NEOPIXELS light em up!
                //colorAll(strip.Color(255, 20, 0), 5); // Orangeish!!
                showType++;
                if (showType > 9) //Number of SHOWS
                    showType=0;
                    startShow(showType);
    }
       
    // Bump the ping counter.
    ping++;

}

//--- functions
unsigned long pulseIn(uint8_t pin, uint8_t state) {
    
    GPIO_TypeDef* portMask = (PIN_MAP[pin].gpio_peripheral); // Cache the target's peripheral mask to speed up the loops.
    uint16_t pinMask = (PIN_MAP[pin].gpio_pin); // Cache the target's GPIO pin mask to speed up the loops.
    unsigned long pulseCount = 0; // Initialize the pulseCount variable now to save time.
    unsigned long loopCount = 0; // Initialize the loopCount variable now to save time.
    unsigned long loopMax = 20000000; // Roughly just under 10 seconds timeout to maintain the Spark Cloud connection.
      // Wait for the pin to enter target state while keeping track of the timeout.
    while (GPIO_ReadInputDataBit(portMask, pinMask) != state) {
        if (loopCount++ == loopMax) {
            return 0;
        }
    }
    
    // Iterate the pulseCount variable each time through the loop to measure the pulse length; we also still keep track of the timeout.
    while (GPIO_ReadInputDataBit(portMask, pinMask) == state) {
        if (loopCount++ == loopMax) {
            return 0;
        }
        pulseCount++;
    }
    
    // Return the pulse time in microseconds by multiplying the pulseCount variable with the time it takes to run once through the loop.
    return pulseCount * 0.405; // Calculated the pulseCount++ loop to be about 0.405uS in length.
}

//---- NEOPIXEL functions
void colorAll(uint32_t c, uint8_t wait) {
  uint16_t i;
  
  for(i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
  }
  strip.show();
  delay(wait);
}


void startShow(int i) {
  switch(i){
    case 0: value = 0; 
            colorWipe(strip.Color(0, 0, 0), 2);    // Black/off
            break;
    case 1: value = 1;
           
            colorWipe(strip.Color(255, 45, 0), 2);  // Orange
            break;
    case 2: value = 2;
            colorWipe(strip.Color(0, 255, 0), 2);  // Green
            break;
    case 3: value = 3;
            colorWipe(strip.Color(255, 255, 255), 2);  // White
            break;
    case 4: value = 4;
            theaterChase(strip.Color(0, 255, 0), 5); // Green
            break;
    case 5: value = 5;
            theaterChase(strip.Color(255,   0,   0), 5); // Red
            break;
    case 6: value = 6;
            theaterChase(strip.Color(  0,   0, 255), 5); // Blue
            break;
    case 7: value = 7;
            lightTop(0,255,255,5);
            break;
    case 8: value = 8;
            lightBottom(0,255,255,5);
            break;
    case 9: value = 9;
          
            wave(255,0,128);
            break;
  }
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
      delay(wait);
  }
}

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

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

//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);
     
      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);
       
        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);
  } else if(WheelPos < 170) {
    WheelPos -= 85;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
}

//------------------- cut in functions

void wave(int r,int g,int b){
  for(uint8_t i=0; i<99; i++) { 
    setThreePixels(i, r, g, b);
    strip.show();
    delay(10);
  }
  for(uint8_t i=0; i<45; i++){
    setThreePixels(strip.numPixels()-i, r, g, b);
    strip.show();
    delay(10);
  }
}

void lightTop(int r,int g,int b, uint8_t wait){   
  for(uint8_t i=0; i<45; i++) { 
    strip.setPixelColor(i/1.875, r, g, b);
    strip.setPixelColor(24+i, r, g, b);  
    strip.setPixelColor(114-i, 0, 0, 0); 
    strip.show();
    delay(wait);  
  }
}

void lightBottom(int r,int g,int b, uint8_t wait){    
  for(uint8_t i=0; i<45; i++) {
    strip.setPixelColor(i/1.875, 0, 0, 0);
    strip.setPixelColor(24+i, 0, 0, 0);  
    strip.setPixelColor(114-i, r, g, b); 
    strip.show();  
    delay(wait);  
  }
}

void setThreePixels(int LED,int r,int g,int b) {
   strip.setPixelColor(LED, r, g, b);
   if (LED>0) strip.setPixelColor(LED-1, r, g, b);
   if (LED<strip.numPixels()-1)strip.setPixelColor(LED+1, r, g, b);
}
Arduino stepper motor codeC/C++
Stepper motor code for Arduino + Motor shield. Stepper has three states/positions (fully open/semi-open/fully closed). The current position is also stored in the EEPROM (to know postiion when power off/on).
#include <EEPROM.h> // position 0-220 stored in position 0 
#include <Stepper.h>
const int stepsPerRevolution = 200;  
Stepper myStepper(stepsPerRevolution, 12,13);     
 
// give the motor control pins names:
const uint8_t pwmA = 3;
const uint8_t pwmB = 11;
const uint8_t brakeA = 9;
const uint8_t brakeB = 8;
const uint8_t dirA = 12;
const uint8_t dirB = 13;

uint16_t currentPosition = 0;   // 0 - 2200; set by position from smartthings; 0 is closed/furthest from motor 

//button toggle switch
int button = 2; //button pin, connect to +3.3V as button, otherwise ground through resistor
int press = 0;
int toggle = 0; // 0-3; Switch case loop


void setup() {
   //Serial.begin(9600); //debug
  // read values out of memory
  //EEPROM.write(1, toggle);
  currentPosition = EEPROM.read(0)*10;// Read current position
  //toggle = EEPROM.read(1);// 0-3; Switch case loop stored in EEPROM (when power off)
  //Serial.print("EEPROM Position: ");
  //Serial.print(EEPROM.read(0)*10);
  //Serial.print(" Toggle: ");
  //Serial.print(toggle);
  
  // set the PWM and brake pins so that the direction pins  // can be used to control the motor:
  pinMode(pwmA, OUTPUT);
  pinMode(pwmB, OUTPUT);
  pinMode(brakeA, OUTPUT);
  pinMode(brakeB, OUTPUT);
   
  // turn on POWER (turn to low to release the motor and avoid heating)
  digitalWrite(pwmA, HIGH);
  digitalWrite(pwmB, HIGH);
   
  // turn off BRAKES
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
     
  // 150 is max speed unloaded
  // at 150, there is not enough torque to open the lamp, lowering speed overcomes this.
  myStepper.setSpeed(110); 
  
  // turn off POWER (to release the motor and avoid heating)
  digitalWrite(pwmA, LOW);
  digitalWrite(pwmB, LOW);
 
 //button toggle switch stuff
 // pinMode(10, OUTPUT); //LED on pin 10 "Debug led"
  pinMode(button, INPUT); //arduino monitor pin state
  digitalWrite(2, LOW); //enable pullups to make pin 5 high --- PULL DOWN!!! earth natural state
}

void loop() {
  
  press = digitalRead(button);
  if (press == HIGH)
  {
    switch(toggle){
      case 0: //digitalWrite(10, LOW);   // set the LED on
              //Stepper
              digitalWrite(pwmA, HIGH);
              digitalWrite(pwmB, HIGH);
              digitalWrite(brakeA, LOW);
              digitalWrite(brakeB, LOW);
              digitalWrite(dirA, HIGH);
              digitalWrite(dirB, HIGH);
              setPosition("0"); //MAX step 0-106 
              digitalWrite(pwmA, LOW);
              digitalWrite(pwmB, LOW);
              digitalWrite(brakeA, HIGH);
              digitalWrite(brakeB, HIGH);
              digitalWrite(dirA, LOW);
              digitalWrite(dirB, LOW);
              //stepper slut
              toggle++;
             //EEPROM.write(1, toggle);// Store current switch-case in EEPROM
              break;
        case 1: //digitalWrite(10, HIGH);   // set the LED on
              //Stepper
              digitalWrite(pwmA, HIGH);
              digitalWrite(pwmB, HIGH);
              digitalWrite(brakeA, LOW);
              digitalWrite(brakeB, LOW);
              digitalWrite(dirA, HIGH);
              digitalWrite(dirB, HIGH);
              setPosition("50"); //MAX step 0-106 
              digitalWrite(pwmA, LOW);
              digitalWrite(pwmB, LOW);
              digitalWrite(brakeA, HIGH);
              digitalWrite(brakeB, HIGH);
              digitalWrite(dirA, LOW);
              digitalWrite(dirB, LOW);
              //stepper slut
              toggle++;
              //EEPROM.write(1, toggle);// Store current switch-case in EEPROM
              break;
       case 2: //digitalWrite(10, HIGH);   // set the LED on
              //Stepper
              digitalWrite(pwmA, HIGH);
              digitalWrite(pwmB, HIGH);
              digitalWrite(brakeA, LOW);
              digitalWrite(brakeB, LOW);
              digitalWrite(dirA, HIGH);
              digitalWrite(dirB, HIGH);
              setPosition("102"); //MAX step 0-106 | Currently 102
              digitalWrite(pwmA, LOW);
              digitalWrite(pwmB, LOW);
              digitalWrite(brakeA, HIGH);
              digitalWrite(brakeB, HIGH);
              digitalWrite(dirA, LOW);
              digitalWrite(dirB, LOW);
              //stepper slut
              toggle++;
              //EEPROM.write(1, toggle);// Store current switch-case in EEPROM
              break;
        case 3: //digitalWrite(10, HIGH);   // set the LED on
              //Stepper
              digitalWrite(pwmA, HIGH);
              digitalWrite(pwmB, HIGH);
              digitalWrite(brakeA, LOW);
              digitalWrite(brakeB, LOW);
              digitalWrite(dirA, HIGH);
              digitalWrite(dirB, HIGH);
              setPosition("50"); //MAX step 0-106 
              digitalWrite(pwmA, LOW);
              digitalWrite(pwmB, LOW);
              digitalWrite(brakeA, HIGH);
              digitalWrite(brakeB, HIGH);
              digitalWrite(dirA, LOW);
              digitalWrite(dirB, LOW);
              //stepper slut
              toggle = 0;
              //EEPROM.write(1, toggle);// Store current switch-case in EEPROM
              break;
          } 
      delay(50);  //delay for debounce
} //End of if statement
} //End of main loop

void setPosition (String targetPosition) {
  uint16_t targetMapped = map(targetPosition.toInt(), 0, 99, 0, 220);
  targetMapped = targetMapped*10; // since we save value 0-220 we want an increment of 10
  uint16_t deltaPosition = targetMapped - currentPosition;
    
  // TODO: add a saftey to be sure current position will be 0-2200;
  currentPosition += deltaPosition;
 
  EEPROM.write(0, currentPosition/10);
  //Serial.print(" New position:");
  //Serial.print(EEPROM.read(0)); //DEBUG - print latest position
  
  digitalWrite(pwmA, HIGH);
  digitalWrite(pwmB, HIGH);
  delay(250);
  myStepper.step(deltaPosition);  
  digitalWrite(pwmA, LOW);
  digitalWrite(pwmB, LOW);
}
davidbliss/spherelamp/spherelamp.ino
Code for stepper motor (Arduino)
technobly/SparkCore-NeoPixel
For litting WS2812B/Neopixels with Particle (Spark) Core
Ultrasonic Sensor Spark Core Code
Function used for the Ultrasonic Sensor HC-SR04 (function pulseIn) - connected to the Particle (Spark) Core

Comments

Author

Photo
Jhn S
  • 1 project
  • 6 followers

Additional contributors

Published on

November 15, 2015

Members who respect this project

Avatar?size=thumbAvatar?size=thumbAvatar?size=thumbAvatar?size=thumbAvatar?size=thumbAvatar?size=thumbAvatar?size=thumbAvatar?size=thumb

and 41 others

See similar projects
you might like

Similar projects you might like

The Magic Display With Arduino - The Mind Reader

Project tutorial by LAGSILVA

  • 1,084 views
  • 2 comments
  • 4 respects

Very First Hands On Arduino - Voice Activated LED

Project tutorial by Liren Yeo

  • 411 views
  • 0 comments
  • 5 respects

Get Connected! WiFi Registration Using AP Mode!

Project tutorial by Brian Carbonette

  • 1,051 views
  • 0 comments
  • 15 respects

The Soldering Iron Controller for Hakko T12 Tips

Project tutorial by Alexander

  • 8,156 views
  • 4 comments
  • 26 respects

Voltmeter Using Arduino

by Team Next Tech Lab

  • 2,853 views
  • 8 comments
  • 44 respects

Prank Your Friends with Talking Darth Vader

Project tutorial by Chathuranga Liyanage

  • 173 views
  • 0 comments
  • 1 respect
Add projectSign up / Login