2017-04-25 03:24:11 +00:00
/*
. ______ . ______ __ __ __ __ ___ __ __ . ___________ . ______ . ___ ___ . ___ . ___________ . __ ______ . __ __ .
| _ \ | _ \ | | | | | | | | / \ | | | | | | / __ \ | \ / | / \ | | | | / __ \ | \ | |
| | _ ) | | | _ ) | | | | | | | __ | | / ^ \ | | | | ` - - - | | - - - - ` | | | | | \ / | / ^ \ ` - - - | | - - - - ` | | | | | | | \ | |
| _ < | / | | | | | __ | / / _ \ \ | | | | | | | | | | | | \ / | | / / _ \ \ | | | | | | | | | . ` |
| | _ ) | | | \ \ - . | ` - - ' | | | | | / _____ \ | ` - - ' | | | | ` - - ' | | | | | / _____ \ | | | | | ` - - ' | | | \ |
| ______ / | _ | ` . __ | \ ______ / | __ | | __ | / __ / \ __ \ \ ______ / | __ | \ ______ / | __ | | __ | / __ / \ __ \ | __ | | __ | \ ______ / | __ | \ __ |
Thanks much to @ corbanmailloux for providing a great framework for implementing flash / fade with HomeAssistant https : //github.com/corbanmailloux/esp-mqtt-rgb-led
2017-04-27 04:17:00 +00:00
To use this code you will need the following dependancies :
- Support for the ESP8266 boards .
- You can add it to the board manager by going to File - > Preference and pasting http : //arduino.esp8266.com/stable/package_esp8266com_index.json into the Additional Board Managers URL field.
- Next , download the ESP8266 dependancies by going to Tools - > Board - > Board Manager and searching for ESP8266 and installing it .
- You will also need to download the follow libraries by going to Sketch - > Include Libraries - > Manage Libraries
- DHT sensor library
2017-05-02 20:21:47 +00:00
- Adafruit unified sensor
2017-04-27 04:17:00 +00:00
- PubSubClient
- ArduinoJSON
2017-04-25 03:24:11 +00:00
*/
# include <ESP8266WiFi.h>
# include <DHT.h>
# include <PubSubClient.h>
# include <ESP8266mDNS.h>
# include <WiFiUdp.h>
# include <ArduinoOTA.h>
# include <ArduinoJson.h>
/************ WIFI and MQTT INFORMATION (CHANGE THESE FOR YOUR SETUP) ******************/
# define wifi_ssid "YourSSID" //type your WIFI information inside the quotes
# define wifi_password "YourWIFIpassword"
# define mqtt_server "your.mqtt.server.ip"
# define mqtt_user "yourMQTTusername"
# define mqtt_password "yourMQTTpassword"
2017-04-27 04:06:21 +00:00
# define mqtt_port 1883
2017-04-25 03:24:11 +00:00
/************* MQTT TOPICS (change these topics as you wish) **************************/
# define light_state_topic "bruh / sensornode1"
# define light_set_topic "bruh / sensornode1 / set"
const char * on_cmd = " ON " ;
const char * off_cmd = " OFF " ;
/**************************** FOR OTA **************************************************/
# define SENSORNAME "sensornode1"
# define OTApassword "bruh"
int OTAport = 8266 ;
/**************************** PIN DEFINITIONS ********************************************/
const int redPin = D1 ;
const int greenPin = D2 ;
const int bluePin = D3 ;
# define PIRPIN D5
# define DHTPIN D7
# define DHTTYPE DHT22
# define LDRPIN A0
/**************************** SENSOR DEFINITIONS *******************************************/
float ldrValue ;
int LDR ;
float calcLDR ;
float diffLDR = 25 ;
float diffTEMP = 0.2 ;
float tempValue ;
float diffHUM = 1 ;
float humValue ;
int pirValue ;
int pirStatus ;
String motionStatus ;
char message_buff [ 100 ] ;
int calibrationTime = 0 ;
const int BUFFER_SIZE = 300 ;
# define MQTT_MAX_PACKET_SIZE 512
/******************************** GLOBALS for fade/flash *******************************/
byte red = 255 ;
byte green = 255 ;
byte blue = 255 ;
byte brightness = 255 ;
byte realRed = 0 ;
byte realGreen = 0 ;
byte realBlue = 0 ;
bool stateOn = false ;
bool startFade = false ;
unsigned long lastLoop = 0 ;
int transitionTime = 0 ;
bool inFade = false ;
int loopCount = 0 ;
int stepR , stepG , stepB ;
int redVal , grnVal , bluVal ;
bool flash = false ;
bool startFlash = false ;
int flashLength = 0 ;
unsigned long flashStartTime = 0 ;
byte flashRed = red ;
byte flashGreen = green ;
byte flashBlue = blue ;
byte flashBrightness = brightness ;
WiFiClient espClient ;
PubSubClient client ( espClient ) ;
DHT dht ( DHTPIN , DHTTYPE ) ;
/********************************** START SETUP*****************************************/
void setup ( ) {
Serial . begin ( 115200 ) ;
pinMode ( PIRPIN , INPUT ) ;
pinMode ( DHTPIN , INPUT ) ;
pinMode ( LDRPIN , INPUT ) ;
Serial . begin ( 115200 ) ;
delay ( 10 ) ;
ArduinoOTA . setPort ( OTAport ) ;
ArduinoOTA . setHostname ( SENSORNAME ) ;
ArduinoOTA . setPassword ( ( const char * ) OTApassword ) ;
Serial . print ( " calibrating sensor " ) ;
for ( int i = 0 ; i < calibrationTime ; i + + ) {
Serial . print ( " . " ) ;
delay ( 1000 ) ;
}
Serial . println ( " Starting Node named " + String ( SENSORNAME ) ) ;
setup_wifi ( ) ;
client . setServer ( mqtt_server , mqtt_port ) ;
client . setCallback ( callback ) ;
ArduinoOTA . onStart ( [ ] ( ) {
Serial . println ( " Starting " ) ;
} ) ;
ArduinoOTA . onEnd ( [ ] ( ) {
Serial . println ( " \n End " ) ;
} ) ;
ArduinoOTA . onProgress ( [ ] ( unsigned int progress , unsigned int total ) {
Serial . printf ( " Progress: %u%% \r " , ( progress / ( total / 100 ) ) ) ;
} ) ;
ArduinoOTA . onError ( [ ] ( ota_error_t error ) {
Serial . printf ( " Error[%u]: " , error ) ;
if ( error = = OTA_AUTH_ERROR ) Serial . println ( " Auth Failed " ) ;
else if ( error = = OTA_BEGIN_ERROR ) Serial . println ( " Begin Failed " ) ;
else if ( error = = OTA_CONNECT_ERROR ) Serial . println ( " Connect Failed " ) ;
else if ( error = = OTA_RECEIVE_ERROR ) Serial . println ( " Receive Failed " ) ;
else if ( error = = OTA_END_ERROR ) Serial . println ( " End Failed " ) ;
} ) ;
ArduinoOTA . begin ( ) ;
Serial . println ( " Ready " ) ;
Serial . print ( " IPess: " ) ;
Serial . println ( WiFi . localIP ( ) ) ;
}
/********************************** START SETUP WIFI*****************************************/
void setup_wifi ( ) {
delay ( 10 ) ;
Serial . println ( ) ;
Serial . print ( " Connecting to " ) ;
Serial . println ( wifi_ssid ) ;
WiFi . mode ( WIFI_STA ) ;
WiFi . begin ( wifi_ssid , wifi_password ) ;
while ( WiFi . status ( ) ! = WL_CONNECTED ) {
delay ( 500 ) ;
Serial . print ( " . " ) ;
}
Serial . println ( " " ) ;
Serial . println ( " WiFi connected " ) ;
Serial . println ( " IP address: " ) ;
Serial . println ( WiFi . localIP ( ) ) ;
}
/********************************** START CALLBACK*****************************************/
void callback ( char * topic , byte * payload , unsigned int length ) {
Serial . print ( " Message arrived [ " ) ;
Serial . print ( topic ) ;
Serial . print ( " ] " ) ;
char message [ length + 1 ] ;
for ( int i = 0 ; i < length ; i + + ) {
message [ i ] = ( char ) payload [ i ] ;
}
message [ length ] = ' \0 ' ;
Serial . println ( message ) ;
if ( ! processJson ( message ) ) {
return ;
}
if ( stateOn ) {
// Update lights
realRed = map ( red , 0 , 255 , 0 , brightness ) ;
realGreen = map ( green , 0 , 255 , 0 , brightness ) ;
realBlue = map ( blue , 0 , 255 , 0 , brightness ) ;
}
else {
realRed = 0 ;
realGreen = 0 ;
realBlue = 0 ;
}
startFade = true ;
inFade = false ; // Kill the current fade
sendState ( ) ;
}
/********************************** START PROCESS JSON*****************************************/
bool processJson ( char * message ) {
StaticJsonBuffer < BUFFER_SIZE > jsonBuffer ;
JsonObject & root = jsonBuffer . parseObject ( message ) ;
if ( ! root . success ( ) ) {
Serial . println ( " parseObject() failed " ) ;
return false ;
}
if ( root . containsKey ( " state " ) ) {
if ( strcmp ( root [ " state " ] , on_cmd ) = = 0 ) {
stateOn = true ;
}
else if ( strcmp ( root [ " state " ] , off_cmd ) = = 0 ) {
stateOn = false ;
}
}
// If "flash" is included, treat RGB and brightness differently
if ( root . containsKey ( " flash " ) ) {
flashLength = ( int ) root [ " flash " ] * 1000 ;
if ( root . containsKey ( " brightness " ) ) {
flashBrightness = root [ " brightness " ] ;
}
else {
flashBrightness = brightness ;
}
if ( root . containsKey ( " color " ) ) {
flashRed = root [ " color " ] [ " r " ] ;
flashGreen = root [ " color " ] [ " g " ] ;
flashBlue = root [ " color " ] [ " b " ] ;
}
else {
flashRed = red ;
flashGreen = green ;
flashBlue = blue ;
}
flashRed = map ( flashRed , 0 , 255 , 0 , flashBrightness ) ;
flashGreen = map ( flashGreen , 0 , 255 , 0 , flashBrightness ) ;
flashBlue = map ( flashBlue , 0 , 255 , 0 , flashBrightness ) ;
flash = true ;
startFlash = true ;
}
else { // Not flashing
flash = false ;
if ( root . containsKey ( " color " ) ) {
red = root [ " color " ] [ " r " ] ;
green = root [ " color " ] [ " g " ] ;
blue = root [ " color " ] [ " b " ] ;
}
if ( root . containsKey ( " brightness " ) ) {
brightness = root [ " brightness " ] ;
}
if ( root . containsKey ( " transition " ) ) {
transitionTime = root [ " transition " ] ;
}
else {
transitionTime = 0 ;
}
}
return true ;
}
/********************************** START SEND STATE*****************************************/
void sendState ( ) {
StaticJsonBuffer < BUFFER_SIZE > jsonBuffer ;
JsonObject & root = jsonBuffer . createObject ( ) ;
root [ " state " ] = ( stateOn ) ? on_cmd : off_cmd ;
JsonObject & color = root . createNestedObject ( " color " ) ;
color [ " r " ] = red ;
color [ " g " ] = green ;
color [ " b " ] = blue ;
root [ " brightness " ] = brightness ;
root [ " humidity " ] = ( String ) humValue ;
root [ " motion " ] = ( String ) motionStatus ;
root [ " ldr " ] = ( String ) LDR ;
root [ " temperature " ] = ( String ) tempValue ;
char buffer [ root . measureLength ( ) + 1 ] ;
root . printTo ( buffer , sizeof ( buffer ) ) ;
Serial . println ( buffer ) ;
client . publish ( light_state_topic , buffer , true ) ;
}
/********************************** START SET COLOR *****************************************/
void setColor ( int inR , int inG , int inB ) {
analogWrite ( redPin , inR ) ;
analogWrite ( greenPin , inG ) ;
analogWrite ( bluePin , inB ) ;
Serial . println ( " Setting LEDs: " ) ;
Serial . print ( " r: " ) ;
Serial . print ( inR ) ;
Serial . print ( " , g: " ) ;
Serial . print ( inG ) ;
Serial . print ( " , b: " ) ;
Serial . println ( inB ) ;
}
/********************************** START RECONNECT*****************************************/
void reconnect ( ) {
// Loop until we're reconnected
while ( ! client . connected ( ) ) {
Serial . print ( " Attempting MQTT connection... " ) ;
// Attempt to connect
if ( client . connect ( SENSORNAME , mqtt_user , mqtt_password ) ) {
Serial . println ( " connected " ) ;
client . subscribe ( light_set_topic ) ;
setColor ( 0 , 0 , 0 ) ;
sendState ( ) ;
} else {
Serial . print ( " failed, rc= " ) ;
Serial . print ( client . state ( ) ) ;
Serial . println ( " try again in 5 seconds " ) ;
// Wait 5 seconds before retrying
delay ( 5000 ) ;
}
}
}
/********************************** START CHECK SENSOR **********************************/
bool checkBoundSensor ( float newValue , float prevValue , float maxDiff ) {
return newValue < prevValue - maxDiff | | newValue > prevValue + maxDiff ;
}
/********************************** START MAIN LOOP***************************************/
void loop ( ) {
ArduinoOTA . handle ( ) ;
if ( ! client . connected ( ) ) {
reconnect ( ) ;
}
client . loop ( ) ;
if ( ! inFade ) {
float newTempValue = dht . readTemperature ( true ) ;
float newHumValue = dht . readHumidity ( ) ;
//PIR CODE
pirValue = digitalRead ( PIRPIN ) ; //read state of the
if ( pirValue = = LOW & & pirStatus ! = 1 ) {
motionStatus = " standby " ;
sendState ( ) ;
pirStatus = 1 ;
}
else if ( pirValue = = HIGH & & pirStatus ! = 2 ) {
motionStatus = " motion detected " ;
sendState ( ) ;
pirStatus = 2 ;
}
delay ( 100 ) ;
if ( checkBoundSensor ( newTempValue , tempValue , diffTEMP ) ) {
tempValue = newTempValue ;
sendState ( ) ;
}
if ( checkBoundSensor ( newHumValue , humValue , diffHUM ) ) {
humValue = newHumValue ;
sendState ( ) ;
}
int newLDR = analogRead ( LDRPIN ) ;
if ( checkBoundSensor ( newLDR , LDR , diffLDR ) ) {
LDR = newLDR ;
sendState ( ) ;
}
}
if ( flash ) {
if ( startFlash ) {
startFlash = false ;
flashStartTime = millis ( ) ;
}
if ( ( millis ( ) - flashStartTime ) < = flashLength ) {
if ( ( millis ( ) - flashStartTime ) % 1000 < = 500 ) {
setColor ( flashRed , flashGreen , flashBlue ) ;
}
else {
setColor ( 0 , 0 , 0 ) ;
// If you'd prefer the flashing to happen "on top of"
// the current color, uncomment the next line.
// setColor(realRed, realGreen, realBlue);
}
}
else {
flash = false ;
setColor ( realRed , realGreen , realBlue ) ;
}
}
if ( startFade ) {
// If we don't want to fade, skip it.
if ( transitionTime = = 0 ) {
setColor ( realRed , realGreen , realBlue ) ;
redVal = realRed ;
grnVal = realGreen ;
bluVal = realBlue ;
startFade = false ;
}
else {
loopCount = 0 ;
stepR = calculateStep ( redVal , realRed ) ;
stepG = calculateStep ( grnVal , realGreen ) ;
stepB = calculateStep ( bluVal , realBlue ) ;
inFade = true ;
}
}
if ( inFade ) {
startFade = false ;
unsigned long now = millis ( ) ;
if ( now - lastLoop > transitionTime ) {
if ( loopCount < = 1020 ) {
lastLoop = now ;
redVal = calculateVal ( stepR , redVal , loopCount ) ;
grnVal = calculateVal ( stepG , grnVal , loopCount ) ;
bluVal = calculateVal ( stepB , bluVal , loopCount ) ;
setColor ( redVal , grnVal , bluVal ) ; // Write current values to LED pins
Serial . print ( " Loop count: " ) ;
Serial . println ( loopCount ) ;
loopCount + + ;
}
else {
inFade = false ;
}
}
}
}
/**************************** START TRANSITION FADER *****************************************/
// From https://www.arduino.cc/en/Tutorial/ColorCrossfader
/* BELOW THIS LINE IS THE MATH -- YOU SHOULDN'T NEED TO CHANGE THIS FOR THE BASICS
The program works like this :
Imagine a crossfade that moves the red LED from 0 - 10 ,
the green from 0 - 5 , and the blue from 10 to 7 , in
ten steps .
We ' d want to count the 10 steps and increase or
decrease color values in evenly stepped increments .
Imagine a + indicates raising a value by 1 , and a -
equals lowering it . Our 10 step fade would look like :
1 2 3 4 5 6 7 8 9 10
R + + + + + + + + + +
G + + + + +
B - - -
The red rises from 0 to 10 in ten steps , the green from
0 - 5 in 5 steps , and the blue falls from 10 to 7 in three steps .
In the real program , the color percentages are converted to
0 - 255 values , and there are 1020 steps ( 255 * 4 ) .
To figure out how big a step there should be between one up - or
down - tick of one of the LED values , we call calculateStep ( ) ,
which calculates the absolute gap between the start and end values ,
and then divides that gap by 1020 to determine the size of the step
between adjustments in the value .
*/
int calculateStep ( int prevValue , int endValue ) {
int step = endValue - prevValue ; // What's the overall gap?
if ( step ) { // If its non-zero,
step = 1020 / step ; // divide by 1020
}
return step ;
}
/* The next function is calculateVal. When the loop value, i,
reaches the step size appropriate for one of the
colors , it increases or decreases the value of that color by 1.
( R , G , and B are each calculated separately . )
*/
int calculateVal ( int step , int val , int i ) {
if ( ( step ) & & i % step = = 0 ) { // If step is non-zero and its time to change a value,
if ( step > 0 ) { // increment the value if step is positive...
val + = 1 ;
}
else if ( step < 0 ) { // ...or decrement it if step is negative
val - = 1 ;
}
}
// Defensive driving: make sure val stays in the range 0-255
if ( val > 255 ) {
val = 255 ;
}
else if ( val < 0 ) {
val = 0 ;
}
return val ;
}
2017-04-11 01:58:45 +00:00