Hackster is hosting Hackster Holidays, Finale: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Tuesday!Stream Hackster Holidays, Finale on Tuesday!
Published

IoT Smart Bulb

A light bulb with a Particle Photon connected to a DHT22 temperature/humidity sensor with Neopixels to light up.

IntermediateFull instructions provided3 hours12,965
IoT Smart Bulb

Things used in this project

Hardware components

Photon
Particle Photon
×1
DHT22 Temperature Sensor
DHT22 Temperature Sensor
×1
Adafruit Neopixel Ring (RGBW 12 pixels)
×1

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE
Freeboard.io

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Hot glue gun (generic)
Hot glue gun (generic)

Story

Read more

Schematics

Circuit

Wire it up according to the schematic

Code

Photon Sketch

C/C++
Change the define dweetFeedName to a value you can remember. Keep the quotes though. Also change the delay value if you would like.
#include "neopixel/neopixel.h"
#include "ProbeCube_DHT/ProbeCube_DHT.h"
#include "application.h"
#include "HttpClient/HttpClient.h"

#define DHTPIN 5     // what the DHT is connected to

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11		// DHT 11 
#define DHTTYPE DHT22		// DHT 22 (AM2302)
//#define DHTTYPE DHT21		// DHT 21 (AM2301)

#define PIXEL_PIN D6
#define PIXEL_COUNT 12
#define PIXEL_TYPE SK6812RGBW
#define BRIGHTNESS 255 // 0 - 255

#define dweetFeedName "HacksterChallenge" //Your dweet.io feed name. Choose anything you can remember. NO SIGNUP OR CONFIGURATION REQUIRED.
#define DELAYTIME 3000 //The feed update interval. Must be greater than 3 seconds (3000)

//Class to extract values from httpFunction
class ledCommand {
  String argument;
public:
  void extractValues(String);
  String getCommandName (void) {
    return argument.substring(argument.indexOf("#cmd=") + 5, argument.indexOf("#red="));
  }
  int green (void) {
    return (argument.substring(argument.indexOf("#red=") + 5, argument.indexOf("#green="))).toInt();
  }
  int red (void) {
    return (argument.substring(argument.indexOf("#green=") + 7, argument.indexOf("#blue="))).toInt();
  }
  int blue (void) {
    return (argument.substring(argument.indexOf("#blue=") + 6, argument.indexOf("#white="))).toInt();
  }
  int white(void) {
    return (argument.substring(argument.indexOf("#white=") + 7, argument.indexOf("?"))).toInt();
  }
};
//
void ledCommand::extractValues (String stringPassed){
  argument = stringPassed;
}

unsigned int nextTime = 0;    // Next time to contact the server
HttpClient http;

// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
    //  { "Content-Type", "application/json" },
    //  { "Accept" , "application/json" },
    { "Accept" , "*/*"},
    { NULL, NULL } // NOTE: Always terminate headers will NULL
};

http_request_t request;
http_response_t response;

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

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);

int animation = 0; 

void rainbowAnimation() {
  // Assume the rainbow cycles every 2.56 seconds so there's a
  // 10 millisecond delay every color change.
  int n = (millis()/10) % 256;
  lightPixels(Wheel(n));
}

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

void lightPixels(uint32_t color) {
  for (int i=0; i<PIXEL_COUNT; ++i) {
    strip.setPixelColor(i, color);
  }
  strip.show();
}

void setup() {
    Particle.function("led", handleLed);
    Particle.variable("bulb", 1);
    Serial.begin(9600);
    dht.begin();
    pinMode(A5, INPUT);
    pinMode(A4, INPUT);
    strip.begin();
    strip.setBrightness(BRIGHTNESS);
}

int redColor,greenColor,blueColor,whiteColor = 0;

int handleLed(String args) {
  ledCommand command;
  command.extractValues(args);
  //command.red/green/blue/getCommandName
  Particle.publish("execCommand", command.getCommandName());
  if(command.getCommandName().equals("R")) {
    animation = 1;
    Particle.publish("Rainbow","ON");
  }
  else {
       Particle.publish("Rainbow","OFF");
    animation = 0;
    for(int i = 0; i < PIXEL_COUNT; i++) {
        strip.setPixelColor(i, strip.Color(command.red(),command.green(),command.blue(),command.white()));
        strip.show();
        delay(250);
    }
  }
  return 1;
}

void loop() {
    if (animation == 1) {
        rainbowAnimation();
    }
    else {
    }
    float h = dht.getHumidity();
	float f = dht.getTempFarenheit();
	float hi = dht.getHeatIndex();
	float dp = dht.getDewPoint();
    request.hostname = "www.dweet.io";
    request.port = 80;
    request.path = "/dweet/for/" + String(dweetFeedName) + "?humidity=" + String(round(h)) + "&temperature=" + String(round(f)) + "&dewPoint=" + String(round(dp)) + "&heatIndex=" + String(round(hi));
    http.get(request, response, headers);
}

Test Sketch

C/C++
Do not edit, pin numbers and pixel settings are correct
/*
 * This is a RGB+W NeoPixel example, see extra-examples.cpp for a version
 * with more explantory documentation, example routines, how to
 * hook up your pixels and all of the pixel types that are supported.
 *
 */

/* ======================= includes ================================= */

#include "application.h"
#include "neopixel/neopixel.h" // use for Build IDE
// #include "neopixel.h" // use for local build

/* ======================= prototypes =============================== */

uint32_t Wheel(byte WheelPos);
uint8_t red(uint32_t c);
uint8_t green(uint32_t c);
uint8_t blue(uint32_t c);
void colorWipe(uint32_t c, uint8_t wait);
void pulseWhite(uint8_t wait);
void rainbowFade2White(uint8_t wait, int rainbowLoops, int whiteLoops);
void whiteOverRainbow(uint8_t wait, uint8_t whiteSpeed, uint8_t whiteLength);
void fullWhite();
void rainbowCycle(uint8_t wait);
void rainbow(uint8_t wait);

/* ======================= rgbw-strandtest.cpp ====================== */

SYSTEM_MODE(AUTOMATIC);

// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D6
#define PIXEL_COUNT 12
#define PIXEL_TYPE SK6812RGBW
#define BRIGHTNESS 255 // 0 - 255

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

int gamma[] = {
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
    1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
    2,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,
    5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9, 10,
   10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
   17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
   25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
   37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
   51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
   69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
   90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
  115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
  144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
  177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
  215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };

void setup() {
  strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  // Some example procedures showing how to display to the pixels:
  // Do not run more than 15 seconds of these, or the b/g tasks
  // will be blocked.
  // --------------------------------------------------------------
  colorWipe(strip.Color(255, 0, 0), 50); // Red
  colorWipe(strip.Color(0, 255, 0), 50); // Green
  colorWipe(strip.Color(0, 0, 255), 50); // Blue
  colorWipe(strip.Color(0, 0, 0, 255), 50); // White

  whiteOverRainbow(20,75,5);

  pulseWhite(5);

  // fullWhite();
  // delay(2000);

  rainbowFade2White(3,3,1);
}

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

uint8_t red(uint32_t c) {
  return (c >> 8);
}
uint8_t green(uint32_t c) {
  return (c >> 16);
}
uint8_t blue(uint32_t c) {
  return (c);
}

// 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 pulseWhite(uint8_t wait) {
  for(int j = 0; j < 256 ; j++) {
    for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
    }
    delay(wait);
    strip.show();
  }

  for(int j = 255; j >= 0 ; j--){
    for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
    }
    delay(wait);
    strip.show();
  }
}


void rainbowFade2White(uint8_t wait, int rainbowLoops, int whiteLoops) {
  float fadeMax = 100.0;
  int fadeVal = 0;
  uint32_t wheelVal;
  int redVal, greenVal, blueVal;

  for(int k = 0 ; k < rainbowLoops ; k ++) {
    for(int j=0; j<256; j++) { // 5 cycles of all colors on wheel
      for(int i=0; i< strip.numPixels(); i++) {
        wheelVal = Wheel(((i * 256 / strip.numPixels()) + j) & 255);

        redVal = red(wheelVal) * float(fadeVal/fadeMax);
        greenVal = green(wheelVal) * float(fadeVal/fadeMax);
        blueVal = blue(wheelVal) * float(fadeVal/fadeMax);

        strip.setPixelColor( i, strip.Color( redVal, greenVal, blueVal ) );
      }

      // First loop, fade in!
      if(k == 0 && fadeVal < fadeMax-1) {
        fadeVal++;
      }
      // Last loop, fade out!
      else if(k == rainbowLoops - 1 && j > 255 - fadeMax ) {
        fadeVal--;
      }

      strip.show();
      delay(wait);
    }
  }

  delay(500);

  for(int k = 0 ; k < whiteLoops ; k ++) {
    for(int j = 0; j < 256 ; j++) {
      for(uint16_t i=0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
      }
      strip.show();
    }

    delay(2000);
    for(int j = 255; j >= 0 ; j--) {
      for(uint16_t i=0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
      }
      strip.show();
    }
  }

  delay(500);
}

void whiteOverRainbow(uint8_t wait, uint8_t whiteSpeed, uint8_t whiteLength ) {

  if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;

  int head = whiteLength - 1;
  int tail = 0;
  int loops = 3;
  int loopNum = 0;
  static unsigned long lastTime = 0;

  while(true) {
    for(int j=0; j<256; j++) {
      for(uint16_t i=0; i<strip.numPixels(); i++) {
        if( (i >= tail && i <= head)
          || (tail > head && i >= tail)
          || (tail > head && i <= head) ) {
          strip.setPixelColor(i, strip.Color(0,0,0, 255 ) );
        } else {
          strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
        }
      }

      if(millis() - lastTime > whiteSpeed) {
        head++;
        tail++;
        if(head == strip.numPixels()) {
          loopNum++;
        }
        lastTime = millis();
      }

      if(loopNum == loops) return;

      head %= strip.numPixels();
      tail %= strip.numPixels();
      strip.show();
      delay(wait);
    }
  }

}

void fullWhite() {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(0,0,0, 255 ) );
  }
  strip.show();
}

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

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

Credits

Comments