Here is the code. Ignore anything that has to do with fading lights on/off, I haven’t finished designing a plan for that yet.
/* ****************************************************
****************************************************
Library Includes
****************************************************
****************************************************
*/
#include <CircularBuffer.hpp>
#include "arduino_secrets.h"
#include "thingProperties.h"
#include <Adafruit_NeoPixel.h>
#include <BH1750.h>
/* ****************************************************
****************************************************
Arduino Pinout Information
****************************************************
****************************************************
*/
const int LIMIT_SWITCH_UPPER = 3;
const int LIMIT_SWITCH_LOWER = 4;
const int ENABLE_PIN = 5;
const int OPEN_PIN = 6;
const int CLOSE_PIN = 7;
const int PIR_MIDDLE_SENSOR_PIN = 8;
const int PIR_LOWER_SENSOR_PIN = 9;
const int PIR_UPPER_SENSOR_PIN = 10;
const int NEOPIXEL_PIN_UPPERS = 11;
const int NEOPIXEL_PIN_LOWERS = 12;
/* ****************************************************
****************************************************
Ambient Light Sensor Stuff
****************************************************
****************************************************
BH1750 lightMeter(0x23);
float luxFromSensor = 0.0;
const long AMBIENT_LIGHT_CHECK_INTERVAL = 180000; //
/* ****************************************************
****************************************************
NeoPixel Stuff
****************************************************
****************************************************
*/
const int TOTAL_PIXELS_IN_UPPERS = 376;
const int TOTAL_PIXELS_IN_LOWERS = 282;
const int TOTAL_STAIR_STEPS_UPPERS = 8;
const int TOTAL_STAIR_STEPS_LOWERS = 6;
const int PIXELS_PER_STRIP = 47;
int PixelBrightnessLevel = 255; // Default to full bright
// Declaration of the variables which will be used to set colors of the NeoPixel strips
int redColorLevel = 0;
int greenColorLevel = 0;
int blueColorLevel = 0;
// Predetermined Color Switches Used In Code
const int LED_COLOR_OFF = 0;
const int LED_COLOR_RED = 1;
const int LED_COLOR_GREEN = 2;
const int LED_COLOR_BLUE = 3;
const int LED_COLOR_PURPLE = 4;
const int LED_COLOR_CHRISTMAS = 5;
const int LED_COLOR_WHITE = 6;
// Declare the NeoPixel strip
Adafruit_NeoPixel NeoPixel_Strip_Uppers(TOTAL_PIXELS_IN_UPPERS, NEOPIXEL_PIN_UPPERS, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel NeoPixel_Strip_Lowers(TOTAL_PIXELS_IN_LOWERS, NEOPIXEL_PIN_LOWERS, NEO_GRB + NEO_KHZ800);
/* ****************************************************
****************************************************
Stair Step Effects Stuff
****************************************************
****************************************************
*/
const int TRED_DELAY = 175; // Delay, in milliseconds, between treads as they light up
const unsigned long WALKING_DELAY = 15000UL; // This is how long the lights stay on after being triggered.
//const int RESET_DELAY = 3000; // I don't even know if this is necessary, but I do it anyway. See code.
const unsigned long SAFETY_DELAY = 180000UL; // If the lights are on for three minutes solid, I'm going to shut them down.
int StepsCurrentState = 0; // Will be off (0) or on (1)
const int STEPS_ON = 1;
const int STEPS_OFF = 0;
const unsigned long CLOUD_UPDATE_INTERVAL = 1000UL; // 1s
/* ****************************************************
****************************************************
Miscellaneous Stuff
****************************************************
****************************************************
*/
const int DIRECTION_UP = 1; // Specifies LED strips should turn on from bottom to top
const int DIRECTION_DOWN = 2; // Specifies LED strips should turn on from top to bottom
const int DIRECTION_BOTH = 3; // Specifies both staircases will have LED strips that turn on from the bottom up for the top group, and top down for the lower group.
int LastTriggeredDirection = 0;
unsigned long previousAmbientLightMillis = 0; // Holds the previous milliseconds value from the Arduino clock for governing the start time of certain tasks/functions
unsigned long PreviousLightsTimeoutMillis = 0;
unsigned long previousSafetyTimeoutMillis = 0;
unsigned long previousCloudMillis = 0;
bool DEBUG_SWITCH = false; // Set this to true if you want debug statements in serial monitor
bool FADE_STEPS = false; // True = fade the steps on and off. False just turns them on and off.
const int LOWER_STEPS = 2;
const int UPPER_STEPS = 1;
bool AccessDoor_CanReceiveCommand = false; // Default to false so we ignore access door commands until we're ready to receive them after boot up.
// Door Actions declarations
const int ACTION_CLOSE = 1;
const int ACTION_OPEN = 2;
const int ACTION_UNKNOWN = 3;
// Limit switch states
const int LIMIT_SWITCH_OPEN = 1;
const int LIMIT_SWITCH_CLOSED = 2;
int UpperLimitSwitchState = 0;
int LowerLimitSwitchState = 0;
/***********************************************************************************
** P O W E R O N / S E T U P **
************************************************************************************/
void setup() {
// Initialize H-Bridge pin modes
pinMode(ENABLE_PIN, OUTPUT); digitalWrite(ENABLE_PIN, LOW);
pinMode(OPEN_PIN, OUTPUT); digitalWrite(OPEN_PIN, LOW);
pinMode(CLOSE_PIN, OUTPUT); digitalWrite(CLOSE_PIN, LOW);
// Initialize linit switch pins
pinMode(LIMIT_SWITCH_UPPER, INPUT_PULLUP);
pinMode(LIMIT_SWITCH_LOWER, INPUT_PULLUP);
// Setup digital pins appropriately
pinMode(PIR_UPPER_SENSOR_PIN, INPUT); // This is the motion sensor on the upper level
pinMode(PIR_MIDDLE_SENSOR_PIN, INPUT); // This is the motion sensor in the DMZ landing
pinMode(PIR_LOWER_SENSOR_PIN, INPUT); // This is the motion sensor on the lower level
// NeoPixel Strip Initiatlization
NeoPixel_Strip_Uppers.begin();
NeoPixel_Strip_Lowers.begin();
NeoPixel_Strip_Uppers.show();
NeoPixel_Strip_Lowers.show();
// Defined in thingProperties.h
initProperties();
// Connect to Arduino IoT Cloud
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
/*
The following function allows you to obtain more information
related to the state of network and IoT Cloud connection and errors.
The higher number the more granular information you’ll get.
The default is 0 (only errors).
Maximum is 4
*/
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
// Setup our Serial Monitor if we're debugging on a computer
if (DEBUG_SWITCH) {
// Initialize serial and wait for port to open:
Serial.begin(115200);
while (!Serial);
Serial.println(" ");
Serial.println("***** DEBUG MODE *****");
}
// Initialalization the ambient light sensor
Wire.begin();
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
if (DEBUG_SWITCH) {
Serial.println("Successfully initialized Ambient Light Sensor");
}
// Set our initial brightness level for Arduino startup
SetBrightnessBasedOnAmbientLight();
if (DEBUG_SWITCH) {
Serial.print("Calculated lux as: ");
Serial.println(luxFromSensor);
Serial.println(" ");
Serial.println(" ");
Serial.println(" ");
Serial.println(" ");
Serial.println(" ");
}
} else {
// We had an error. By setting this boolean switch to false, we'll know how to
// default the LED strip brightness later on.
if (DEBUG_SWITCH) {
Serial.println("Error initializing Ambient Light Sensor");
}
}
// Set this variable to true to begin accepting
// commands from the IoT cloud (Alexa in my case!)
AccessDoor_CanReceiveCommand = true;
}
/***********************************************************************************
** M A I N L O O P **
************************************************************************************/
void loop() {
// Get the current millis (current time metric) so we can use it in
// our various "timers"
unsigned long currentMillis = millis();
// Check for a command from the cloud.
if (currentMillis - previousCloudMillis >= CLOUD_UPDATE_INTERVAL) {
previousCloudMillis += CLOUD_UPDATE_INTERVAL; // preserve schedule
ArduinoCloud.update();
}
// Set the color we want to use for the LED strips
SetLEDColorVariables(LED_COLOR_WHITE);
// If the lights are on, we need to check and see if the light timeout
// threshold has been exceeded. If so, we need to turn the lights off.
switch (StepsCurrentState) {
// See if lights are on
case STEPS_ON:
// Lights are on.
if (currentMillis - PreviousLightsTimeoutMillis >= WALKING_DELAY) {
// Turn the lights off
StepRoutine (STEPS_OFF, LastTriggeredDirection);
StepsCurrentState = STEPS_OFF;
}
// Lights are on. This is a safety measure to make sure something strange isn't
// happening to one of the sensors and keeping the lights on indefinitely.
if (currentMillis - previousSafetyTimeoutMillis >= SAFETY_DELAY) {
// Turn the lights off
StepRoutine (STEPS_OFF, LastTriggeredDirection);
StepsCurrentState = STEPS_OFF;
delay(5000);
}
break;
}
// Check timer loop for the Ambient Light interval.
if (currentMillis - previousAmbientLightMillis >= AMBIENT_LIGHT_CHECK_INTERVAL) {
if (DEBUG_SWITCH) {
Serial.println("In main loop, getting ready to measure lux.");
}
// Enough time has passed. We need to measure ambient light. So save
// this new current time (milli's) in our previous milli's variable.
previousAmbientLightMillis = currentMillis;
SetBrightnessBasedOnAmbientLight();
if (DEBUG_SWITCH) {
Serial.print("Calculated lux as: ");
Serial.println(luxFromSensor);
Serial.println(" ");
Serial.println(" ");
Serial.println(" ");
Serial.println(" ");
Serial.println(" ");
}
}
// Check for motion on the lower level PIR sensor
if (digitalRead(PIR_UPPER_SENSOR_PIN) == HIGH) { // the PIR sensor will put 5 volts on the signal port when it detects movement.
if (DEBUG_SWITCH) {
Serial.println("Received a sensor reading from PIR_UPPER_SENSOR");
}
// The upper motion sensor was triggered; regardless if the lights are on
// or off, setting PreviousLightsTimeoutMillis to currentMillis sets the
// timer if the lights are off, and re-sets the the timer (extends it) if
// the lights are already on.
PreviousLightsTimeoutMillis = currentMillis;
previousSafetyTimeoutMillis = currentMillis;
// If the steps are off, let's light them up.
if (StepsCurrentState == STEPS_OFF) {
StepRoutine(STEPS_ON, DIRECTION_DOWN);
StepsCurrentState = STEPS_ON;
}
}
// Check for motion on the lower level PIR sensor
if (digitalRead(PIR_LOWER_SENSOR_PIN) == HIGH) { // the PIR sensor will put 5 volts on the signal port when it detects movement.
if (DEBUG_SWITCH) {
Serial.println("Received a sensor reading from PIR_LOWER_SENSOR");
}
// The lower motion sensor was triggered; regardless if the lights are on
// or off, setting PreviousLightsTimeoutMillis to currentMillis sets the
// timer if the lights are off, and re-sets the the timer (extends it) if
// the lights are already on.
PreviousLightsTimeoutMillis = currentMillis;
previousSafetyTimeoutMillis = currentMillis;
// If the steps are off, let's light them up.
if (StepsCurrentState == STEPS_OFF) {
StepRoutine(STEPS_ON, DIRECTION_UP);
StepsCurrentState = STEPS_ON;
}
}
// Check for motion on the middle level PIR sensor
if (digitalRead(PIR_MIDDLE_SENSOR_PIN) == HIGH) { // the PIR sensor will put 5 volts on the signal port when it detects movement.
if (DEBUG_SWITCH) {
Serial.println("Received a sensor reading from PIR_MIDDLE_SENSOR");
}
// The middle motion sensor was triggered; regardless if the lights are on
// or off, setting PreviousLightsTimeoutMillis to currentMillis sets the
// timer if the lights are off, and re-sets the the timer (extends it) if
// the lights are already on.
PreviousLightsTimeoutMillis = currentMillis;
previousSafetyTimeoutMillis = currentMillis;
// If the steps are off, let's light them up.
if (StepsCurrentState == STEPS_OFF) {
StepRoutine(STEPS_ON, DIRECTION_BOTH);
StepsCurrentState = STEPS_ON;
}
}
}
/* *****************************************************************
*****************************************************************
This routine launches whenever the Arduino IoT Cloud tells
the LEDDoorMode switch to go on or off. I interpret "on"
as a way to signal to open the hidden access panel door.
And "off" is a signal to close the hidden access panel door.
*****************************************************************
*****************************************************************
*/
void onLEDDoorModeChange() {
if (DEBUG_SWITCH) {
Serial.println("Received change from Arduino IoT");
delay(1000);
}
// Make sure we are ready to receive commands
if (AccessDoor_CanReceiveCommand == true) {
if (DEBUG_SWITCH) {
Serial.println("Can receive command");
delay(1000);
}
// Check for "true" which is the "on" state for a CloudSwitch
// and I interpret this as the command to open the door.
if (LEDDoorMode) {
if (DEBUG_SWITCH) {
Serial.println("Received command to open the door");
}
// First, check the upper limit switch to make sure the door is closed.
// If it is, then we can open it.
if (isLimitSwitchClosed(LIMIT_SWITCH_UPPER)) {
if (DEBUG_SWITCH) {
Serial.println("Upper switch is closed, so we should open the door. Sending commands to run motor");
}
// We're going to ingore any random incoming commands
// from the IoT cloud so it doesn't confuse what
// we're doing here.
AccessDoor_CanReceiveCommand == false;
// Turn on the motor to open the access panel door.
digitalWrite(OPEN_PIN, HIGH);
digitalWrite(CLOSE_PIN, LOW);
digitalWrite(ENABLE_PIN, HIGH);
if (DEBUG_SWITCH) {
Serial.println("Motor is running. Waiting for lower limit switch to close");
}
// The motor should be running and the door lowering. Monitor the
// lower limit switch (go into a loop) so we know when to turn off the motor.
while (digitalRead(LIMIT_SWITCH_LOWER) == HIGH) {
delay(50); // Small delay to prevent overwhelming the processor
}
if (DEBUG_SWITCH) {
Serial.println("Lower limit switch is closed. Sending command to stop motor.");
}
// The lower limit switch has closed, we're out of the loop, and
// we can turn off the motor. Send the commands to do so now.
digitalWrite(OPEN_PIN, HIGH);
digitalWrite(CLOSE_PIN, HIGH);
digitalWrite(ENABLE_PIN, LOW);
}
} else {
// Since the LEDDoorMode variable wasn't true, it must be false which
// is the "off" state for a CloudSwitch and I interpret this as the
// command to close the door.
if (DEBUG_SWITCH) {
Serial.println("Received command to close the door");
}
// First, check the lower limit switch to make sure the door is open.
// If it is, then we can close it.
if (isLimitSwitchClosed(LIMIT_SWITCH_LOWER)) {
if (DEBUG_SWITCH) {
Serial.println("Lower switch is closed, so we should close the door. Sending commands to run motor");
}
// We're going to ingore any random incoming commands
// from the IoT cloud so it doesn't confuse what
// we're doing here.
AccessDoor_CanReceiveCommand == false;
// Turn on the motor to close the access panel door.
digitalWrite(OPEN_PIN, LOW);
digitalWrite(CLOSE_PIN, HIGH);
digitalWrite(ENABLE_PIN, HIGH);
if (DEBUG_SWITCH) {
Serial.println("Motor is running. Waiting for upper limit switch to close");
}
// The motor should be running and the door raising. Monitor the
// upper limit switch (go into a loop) so we know when to turn off the motor.
while (digitalRead(LIMIT_SWITCH_UPPER) == HIGH) {
delay(50); // Small delay to prevent overwhelming the processor
}
if (DEBUG_SWITCH) {
Serial.println("Upper limit switch is closed. Sending command to stop motor.");
}
// The upper limit switch has closed, we're out of the loop, and
// we can turn off the motor. Send the commands to do so now.
digitalWrite(OPEN_PIN, HIGH);
digitalWrite(CLOSE_PIN, HIGH);
digitalWrite(ENABLE_PIN, LOW);
}
}
}
// Reset this variable so we can process more command changes
// from Alexa
AccessDoor_CanReceiveCommand == true;
}
/* *****************************************************************
*****************************************************************
Simple function to determine if the provided limit switch
is closed.
*****************************************************************
*****************************************************************
*/
bool isLimitSwitchClosed(int pin) {
return digitalRead(pin) == LOW;
}
/* *****************************************************************
*****************************************************************
This routine provides the main programming logic for
activating the LED strips. It's called when any one of
the three triggers are activated
*****************************************************************
*****************************************************************
*/
void StepRoutine(int intAction, int intDirection) {
switch (intAction) {
case STEPS_ON:
// Prep work. Clear out any pending changes to the LED strips and
// set them to off.
NeoPixel_Strip_Uppers.clear();
NeoPixel_Strip_Uppers.show();
NeoPixel_Strip_Lowers.clear();
NeoPixel_Strip_Lowers.show();
// Set the direction into our last triggered direction variable so
// we know later which direction to turn them off.
LastTriggeredDirection = intDirection;
// Check to see what direction we'll be lighting 'em up.
switch (intDirection) {
// Going up from the bottom step all the way to the top
case DIRECTION_UP:
// First, loop through the bottom set of steps
for (int j = (TOTAL_STAIR_STEPS_LOWERS); j > 0; j--) {
// Determine if we should fade the steps or not, then call the routine.
if (FADE_STEPS) {
FadeOn(j, LOWER_STEPS);
} else {
LightUpStep (j, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
}
}
// Now, loop through the top set of steps
for (int i = (TOTAL_STAIR_STEPS_UPPERS); i > 0; i--) {
if (FADE_STEPS) {
FadeOn(i, UPPER_STEPS);
} else {
LightUpStep (i, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
delay(TRED_DELAY);
}
}
break;
case DIRECTION_DOWN:
// Loop through the top set of steps
for (int i = (1); i <= TOTAL_STAIR_STEPS_UPPERS; i++) {
if (FADE_STEPS) {
FadeOn(i, UPPER_STEPS);
} else {
LightUpStep (i, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
delay(TRED_DELAY);
}
}
// Now, loop through the bottom set of steps
for (int k = (1); k <= TOTAL_STAIR_STEPS_LOWERS; k++) {
if (FADE_STEPS) {
FadeOn(k, LOWER_STEPS);
} else {
LightUpStep (k, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
}
}
break;
case DIRECTION_BOTH:
if (FADE_STEPS) {
FadeOn(8, UPPER_STEPS);
FadeOn(1, LOWER_STEPS);
FadeOn(7, UPPER_STEPS);
FadeOn(2, LOWER_STEPS);
FadeOn(6, UPPER_STEPS);
FadeOn(3, LOWER_STEPS);
FadeOn(5, UPPER_STEPS);
FadeOn(4, LOWER_STEPS);
FadeOn(4, UPPER_STEPS);
FadeOn(5, LOWER_STEPS);
FadeOn(3, UPPER_STEPS);
FadeOn(6, LOWER_STEPS);
FadeOn(2, UPPER_STEPS);
FadeOn(1, UPPER_STEPS);
} else {
LightUpStep (8, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (1, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (7, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (2, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (6, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (3, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (5, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (4, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (4, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (5, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (3, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (6, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (2, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
delay(TRED_DELAY);
LightUpStep (1, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
}
break;
}
break;
case STEPS_OFF:
// We have to clear all of the colors to have the effect of turning the colors off.
SetLEDColorVariables(LED_COLOR_OFF);
// We check what the LastTriggeredDirection was to ensure we turn the lights
// off in the same direction we turned them on.
switch (LastTriggeredDirection) {
case DIRECTION_UP:
// To turn off, we'll turn them off in the same direction we turned them on.
for (int k = (TOTAL_STAIR_STEPS_LOWERS); k > 0; k--) { // iterate over all the relays
if (FADE_STEPS) {
FadeOff(k, LOWER_STEPS);
} else {
LightUpStep (k, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
}
}
// Now turn off the uppers
for (int l = (TOTAL_STAIR_STEPS_UPPERS); l > 0; l--) { // iterate over all the relays
if (FADE_STEPS) {
FadeOff(l, UPPER_STEPS);
} else {
LightUpStep (l, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
delay(TRED_DELAY);
}
}
break;
case DIRECTION_DOWN:
// Turn off the steps for the top set of steps
for (int j = (1); j <= TOTAL_STAIR_STEPS_UPPERS; j++) {
if (FADE_STEPS) {
FadeOff(j, UPPER_STEPS);
} else {
LightUpStep (j, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
delay(TRED_DELAY);
}
}
// And now loop through the lowers
for (int l = (1); l <= TOTAL_STAIR_STEPS_LOWERS; l++) {
// The next commented line should be uncommented if you want the steps
// to just turn off without any fade-out effect.
if (FADE_STEPS) {
FadeOff(l, LOWER_STEPS);
} else {
LightUpStep (l, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
}
}
break;
case DIRECTION_BOTH:
if (FADE_STEPS) {
FadeOff(8, UPPER_STEPS);
FadeOff(1, LOWER_STEPS);
FadeOff(7, UPPER_STEPS);
FadeOff(2, LOWER_STEPS);
FadeOff(6, UPPER_STEPS);
FadeOff(3, LOWER_STEPS);
FadeOff(5, UPPER_STEPS);
FadeOff(4, LOWER_STEPS);
FadeOff(4, UPPER_STEPS);
FadeOff(5, LOWER_STEPS);
FadeOff(3, UPPER_STEPS);
FadeOff(6, LOWER_STEPS);
FadeOff(2, UPPER_STEPS);
FadeOff(1, UPPER_STEPS);
} else {
LightUpStep (8, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (1, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (7, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (2, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (6, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (3, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (5, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (4, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (4, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (5, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (3, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
LightUpStep (6, NeoPixel_Strip_Lowers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), LOWER_STEPS);
delay(TRED_DELAY);
LightUpStep (2, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
delay(TRED_DELAY);
LightUpStep (1, NeoPixel_Strip_Uppers.Color((PixelBrightnessLevel*redColorLevel/255) , (PixelBrightnessLevel*greenColorLevel/255), (PixelBrightnessLevel*blueColorLevel/255)), UPPER_STEPS);
}
break;
}
// Clear out the NeoPixel strip object, and incorporate a built-in hold so things
// don't immediately start back up.
NeoPixel_Strip_Uppers.clear();
NeoPixel_Strip_Uppers.show();
NeoPixel_Strip_Lowers.clear();
NeoPixel_Strip_Lowers.show();
// TESTING ONLY!!! Taking this out as it might be causing issues with millis
//delay(RESET_DELAY); // Blocking delay after we turn lights off.
// Set the color we want to use for the LED strips
SetLEDColorVariables(LED_COLOR_WHITE);
break;
break;
}
}
/* *****************************************************************
*****************************************************************
This routine assumes that all pixels on the strip are the same
color. It will thus sample the first pixel on the strip to
get the current color the routine needs to act upon. Code is
based upon someone else's suggestion for how to fade a strip
from whatever the current color is to black (off.)
*****************************************************************
*****************************************************************
*/
void FadeOff(int thestep, int thegroup) {
uint8_t r, g, b;
uint32_t oldColor;
// Find the first pixel for the strip we need to fade
int BeginPixelNumber = (thestep -1) * PIXELS_PER_STRIP;
switch (thegroup) {
case UPPER_STEPS:
// Uppers
// Loop 53 times (suggested from the post I read) to get the colors close to 0
for(int j=1; j<43; j++) {
// Now get the current color on the strip.
oldColor = NeoPixel_Strip_Uppers.getPixelColor(BeginPixelNumber);
r = (oldColor & 0x00ff0000UL) >> 16;
g = (oldColor & 0x0000ff00UL) >> 8;
b = (oldColor & 0x000000ffUL);
r=(r<=10)? 0 : (int) r-(r*26/256);
g=(g<=10)? 0 : (int) g-(g*26/256);
b=(b<=10)? 0 : (int) b-(b*26/256);
NeoPixel_Strip_Uppers.fill(NeoPixel_Strip_Uppers.Color(r, g, b), BeginPixelNumber, PIXELS_PER_STRIP);
NeoPixel_Strip_Uppers.show();
}
break;
case LOWER_STEPS:
// Lowers
// Loop 53 times (suggested from the post I read) to get the colors close to 0
for(int j=1; j<43; j++) {
// Now get the current color on the strip.
oldColor = NeoPixel_Strip_Lowers.getPixelColor(BeginPixelNumber);
r = (oldColor & 0x00ff0000UL) >> 16;
g = (oldColor & 0x0000ff00UL) >> 8;
b = (oldColor & 0x000000ffUL);
r=(r<=10)? 0 : (int) r-(r*26/256);
g=(g<=10)? 0 : (int) g-(g*26/256);
b=(b<=10)? 0 : (int) b-(b*26/256);
NeoPixel_Strip_Lowers.fill(NeoPixel_Strip_Lowers.Color(r, g, b), BeginPixelNumber, PIXELS_PER_STRIP);
NeoPixel_Strip_Lowers.show();
}
break;
}
}
/* *****************************************************************
*****************************************************************
This routine assumes a black (off) section of pixels
representing a step. It will then fade them on up to the
appropriate color (brightness) over a stated number of
customizable iterations.
*****************************************************************
*****************************************************************
*/
void FadeOn(int thestep, int thegroup) {
float intTempBrightness = 0.0;
// The number of times to incrementally fade on a group of
// pixels. Change this to your liking.
int intMaxLoopTries = 26; // was 35
// Find the first pixel for the strip we need to fade
int BeginPixelNumber = (thestep -1) * PIXELS_PER_STRIP;
switch (thegroup) {
case UPPER_STEPS:
// Uppers
// Loop the appropriate number of times
for(int i = 0; i <= intMaxLoopTries; i++) {
intTempBrightness = intTempBrightness + (PixelBrightnessLevel / intMaxLoopTries);
NeoPixel_Strip_Uppers.fill(NeoPixel_Strip_Uppers.Color(redColorLevel * intTempBrightness / 255,greenColorLevel * intTempBrightness / 255, blueColorLevel * intTempBrightness / 255), BeginPixelNumber, PIXELS_PER_STRIP);
NeoPixel_Strip_Uppers.show();
}
break;
case LOWER_STEPS:
// Lowers
// Loop the appropriate number of times
for(int i = 0; i <= intMaxLoopTries; i++) {
intTempBrightness = intTempBrightness + (PixelBrightnessLevel / intMaxLoopTries);
NeoPixel_Strip_Lowers.fill(NeoPixel_Strip_Lowers.Color(redColorLevel * intTempBrightness / 255,greenColorLevel * intTempBrightness / 255, blueColorLevel * intTempBrightness / 255), BeginPixelNumber, PIXELS_PER_STRIP);
NeoPixel_Strip_Lowers.show();
}
break;
}
}
/* *****************************************************************
*****************************************************************
Just a simple routine to easily reset our thjree main color
variables so I didn't have to have all of that coded
separately in various parts of this sketch.
*****************************************************************
*****************************************************************
*/
void SetLEDColorVariables(int colorSwitch) {
// Set the color variables appropriately based on colorSwitch
switch (colorSwitch) {
case LED_COLOR_OFF:
redColorLevel = 0;
greenColorLevel = 0;
blueColorLevel = 0;
break;
case LED_COLOR_BLUE:
redColorLevel = 0;
greenColorLevel = 0;
blueColorLevel = 255;
break;
case LED_COLOR_WHITE:
redColorLevel = 255;
greenColorLevel = 255;
blueColorLevel = 255;
break;
}
}
/* *****************************************************************
*****************************************************************
This function lights up (or turns off) a step within the
appropriate range (given the stair number) and uses a
particular color.
*****************************************************************
*****************************************************************
*/
void LightUpStep (int thestep, uint32_t thecolor, int thegroup) {
int BeginPixelNumber = (thestep -1) * PIXELS_PER_STRIP;
switch (thegroup) {
case UPPER_STEPS:
// Uppers
NeoPixel_Strip_Uppers.fill(thecolor, BeginPixelNumber, PIXELS_PER_STRIP);
NeoPixel_Strip_Uppers.show();
break;
case LOWER_STEPS:
// Lowers
NeoPixel_Strip_Lowers.fill(thecolor, BeginPixelNumber, PIXELS_PER_STRIP);
NeoPixel_Strip_Lowers.show();
break;
}
}
void SetBrightnessBasedOnAmbientLight () {
// Get the ambient light from the sensor
luxFromSensor = lightMeter.readLightLevel();
// We need to determine what brightness level we'll use for the LED strips based on ambient light. Note
// that the lux readings from the ambient light sensor are numbers but have absolutely nothing to do
// with the 0-255 brightness value that NeoPixel strips need.
switch (int(luxFromSensor)) {
default:
PixelBrightnessLevel = 255; // defaults to full bright
if (DEBUG_SWITCH) {
Serial.println("4 out of 4: Full bright");
}
break;
case 131 ... 190:
PixelBrightnessLevel = 235;
if (DEBUG_SWITCH) {
Serial.println("3 out of 4: Medium High");
}
break;
case 41 ... 130:
PixelBrightnessLevel = 200;
if (DEBUG_SWITCH) {
Serial.println("2 out of 4: Medium Low");
}
break;
case 0 ... 40:
PixelBrightnessLevel = 36; // Anything less than 35 causes the lights to not light up. This bug needs fixed.
if (DEBUG_SWITCH) {
Serial.println("1 out of 4: Low");
}
break;
}
}