ESP32-Cam RGBW Light MQTT Controller
In this post the ESP32-Cam module will be used to operate a generic color LED strip using an IR LED. The actions of the ESP32-Cam module will be controlled using a MQTT broker and Node-Red. The Node-Red webUI will be provided to allow manual controls. Node-Red will also use scheduled nodes to control the lighting based on time of day.
The LED strip in this post is an inexpensive RGBW LED strip. These power strips are not logically addressable. Addressable LEDs are typically found in higher end lighting systems, such as DMX. Instead these simple LED strips are controlled with an included IR remote keypad. There are different varieties of these types of IR controlled LED strips and they don’t appear to support a set standard of operation. Because of this, it is assumed that the remote IR encoding will need to be captured and replicated.
More details about capturing and replicating IR controllable device codes can be found here, https://learn.adafruit.com/ir-sensor. The demonstrations in this post makes use of that work. Here is a photo of the RGBW Controller and IR remote keypad.
Using the sample Raw_IR.ino code from Adafruit, with the following code removed from the printpulses subroutine, provided the decoded IR stream on the serial terminal.
Serial.println("\n\r\n\rReceived: \n\rOFF \tON"); for (uint8_t i = 0; i < currentpulse; i++) { Serial.print(pulses[i][0] * RESOLUTION, DEC); Serial.print(" usec, "); Serial.print(pulses[i][1] * RESOLUTION, DEC); Serial.println(" usec"); }
This was done for each of the 40 buttons on the IR remote keypad. Each of these readings were gathered and collected into a spreadsheet to provide a visual of the IR streams. All of the buttons on the remote show a pattern using this approach. Each key is represented by colomns in the following figure.
The first 35 rows show nothing discernible between each of the keys. This might be primer data to get the controller ready to receive the actual data.
The differences start to show starting with the 36th rows through the 69th. It appears that these are 2 bytes for each key value.
Diving into the details of how the key streams are structured wasn’t necessary for this work, but it did show how well the decoding method worked at capturing the streams. Ultimately, each of these captured readings were used in their entirety for the following code.
// SPDX-FileCopyrightText: 2019 Limor Fried for Adafruit Industries // // SPDX-License-Identifier: MIT // See the full tutorial at https://learn.adafruit.com/ir-sensor/making-an-intervalometer // MIT License, attribution appreciated Limor Fried, Adafruit Industries int IRledPin = 13; // LED connected to digital pin 13 int LoopFlag = 0; unsigned long time_now = 0; // The setup() method runs once, when the sketch starts void setup() { Serial.begin(9600); Serial.println("Enter the number for your Selection"); // send action to Serial Monitor Serial.println("1 - Sunrise"); // send action to Serial Monitor Serial.println("2 - Morning"); // send action to Serial Monitor Serial.println("3 - Midday"); // send action to Serial Monitor Serial.println("4 - Evening"); // send action to Serial Monitor Serial.println("5 - Sunset"); // send action to Serial Monitor Serial.println("6 - Lighthouse"); // send action to Serial Monitor Serial.println("7 - Off Midnight"); // send action to Serial Monitor Serial.println("8 - On Noon"); // send action to Serial Monitor Serial.println("9 - End Loop"); // send action to Serial Monitor // initialize the IR digital pin as an output: pinMode(IRledPin, OUTPUT); } void loop() { if(Serial.available()) // if there is data comming { LoopFlag=0; String command = Serial.readStringUntil('\n'); // read string until meet newline character if(command == "1") { Serial.println("Sunrise Program is running"); // send action to Serial Monitor Sunrise(); } else if(command == "2") { Serial.println("Morning Program is running"); // send action to Serial Monitor MorningEvening(); } else if(command == "3") { Serial.println("Midday Program is running"); // send action to Serial Monitor Midday(); } else if(command == "4") { Serial.println("Evening Program is running"); // send action to Serial Monitor MorningEvening(); } else if(command == "5") { Serial.println("Sunset Program is running"); // send action to Serial Monitor Sunset(); } else if(command == "6") { Serial.println("Lighthouse Program is running"); // send action to Serial Monitor LoopFlag=1; Lighthouse(); } else if(command == "7") { Serial.println("System is Off"); // send action to Serial Monitor TurnOff(); } else if(command == "8") { Serial.println("System is On"); // send action to Serial Monitor TurnOn(); } else if(command == "9") { Serial.println("System is Ended"); // send action to Serial Monitor EndCycle(); } } if (LoopFlag == 1) { Lighthouse(); } } // This procedure sends a 38KHz pulse to the IRledPin // for a certain # of microseconds. We'll use this whenever we need to send codes void pulseIR(long microsecs) { // we'll count down from the number of microseconds we are told to wait cli(); // this turns off any background interrupts while (microsecs > 0) { // 38 kHz is about 13 microseconds high and 13 microseconds low digitalWrite(IRledPin, HIGH); // this takes about 3 microseconds to happen delayMicroseconds(10); // hang out for 10 microseconds, you can also change this to 9 if its not working digitalWrite(IRledPin, LOW); // this also takes about 3 microseconds delayMicroseconds(10); // hang out for 10 microseconds, you can also change this to 9 if its not working // so 26 microseconds altogether microsecs -= 26; } sei(); // this turns them back on } // Light Settings = = = = = = = = = = = = = = = = = = = = void MorningEvening() { // Mid-Day = White @ 20 and Red @ 8. TurnOnColorLEDS(); delay(10); TurnOnRedLED(); delay(10); /*** for (int fadeValue = 0 ; fadeValue <= 8; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); delay(100); } ***/ TurnOnWhiteLEDS(); delay(10); /*** for (int fadeValue = 0 ; fadeValue <= 20; fadeValue += 1) { //fader 32 steps BrightenWhiteLEDS(); delay(100); } ***/ } void Midday() { // Mid-Day = White @ 20 and Lite Blue @ 8. TurnOnLiteBlueLED(); delay(10); } void Lighthouse() { // Lighthouse = Cycles Red from 0 to 31 and back down to 0, exits if interupted in millis function. TurnOffColorLEDS(); time_now = millis(); while(millis() < time_now + 10){KeyboardInput();} TurnOffWhiteLEDS(); time_now = millis(); while(millis() < time_now + 10){KeyboardInput();} TurnOnColorLEDS(); time_now = millis(); while(millis() < time_now + 10){KeyboardInput();} TurnOnRedLED(); time_now = millis(); while(millis() < time_now + 1000){KeyboardInput();} for (int fadeValue = 0 ; fadeValue <= 30; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){KeyboardInput();} } // Hold level for 10 seconds time_now = millis(); while(millis() < time_now + 10000){KeyboardInput();} for (int fadeValue = 0 ; fadeValue <= 30; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){KeyboardInput();} } TurnOffColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){KeyboardInput();} } void TurnOff() { // Turn Off = Dim White to 0, then Red to 0 TurnOnWhiteLEDS(); time_now = millis(); while(millis() < time_now + 10){KeyboardInput();} for (int fadeValue = 0 ; fadeValue <= 31; fadeValue += 1) { //fader 32 steps DimWhiteLEDS(); time_now = millis(); while(millis() < time_now + 100){KeyboardInput();} } TurnOffWhiteLEDS(); time_now = millis(); while(millis() < time_now + 10){KeyboardInput();} TurnOnColorLEDS(); time_now = millis(); while(millis() < time_now + 10){KeyboardInput();} TurnOnRedLED(); time_now = millis(); while(millis() < time_now + 10){KeyboardInput();} for (int fadeValue = 0 ; fadeValue <= 31; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + 100){KeyboardInput();} } TurnOffColorLEDS(); time_now = millis(); while(millis() < time_now + 100){KeyboardInput();} } void TurnOn() { // Turn On = Brighten Red to 8, then White to 20 TurnOnColorLEDS(); time_now = millis(); while(millis() < time_now + 10){} TurnOnRedLED(); time_now = millis(); while(millis() < time_now + 10){} for (int fadeValue = 0 ; fadeValue <= 8; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} } TurnOnWhiteLEDS(); time_now = millis(); while(millis() < time_now + 10){} for (int fadeValue = 0 ; fadeValue <= 20; fadeValue += 1) { //fader 32 steps BrightenWhiteLEDS(); time_now = millis(); while(millis() < time_now + 100){} } } void EndCycle(){ // Preferred function when exiting the Lighthouse Loop, since it's typically ran during sleep hours } void KeyboardInput(){ // Loop Interupt for Lighthouse millis function if(Serial.available()) // if there is data comming { LoopFlag=0; } } void Sunrise() { // Red @ 0 will increase every 60 seconds until Red @ 28 // then Red @ 28 will decrease and White @ 0 will increase every 90 seconds until White @ 20 and Red @ 8. TurnOnColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} TurnOnRedLED(); time_now = millis(); while(millis() < time_now + 1000){} for (int fadeValue = 0 ; fadeValue <= 28; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){} } TurnOnWhiteLEDS(); time_now = millis(); while(millis() < time_now + 1000){} for (int fadeValue = 0 ; fadeValue <= 20; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} BrightenWhiteLEDS(); time_now = millis(); while(millis() < time_now + 1000){} } } void Sunset () { // White @ 20 with decrease and Red @ 8 with increase every 90 seconds until White @ 0 and Red @ 32 // then Red @ 32 will decrease every 60 seconds until Red @ 0. The process should take about an hour. for (int fadeValue = 0 ; fadeValue <= 21; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} DimWhiteLEDS(); time_now = millis(); while(millis() < time_now + 1000){} } TurnOffWhiteLEDS(); time_now = millis(); while(millis() < time_now + 1000){} for (int fadeValue = 0 ; fadeValue <= 31; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){} } TurnOffColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){} } // = = = = = = = = = = = = = = = = = = = = // Button IR Codes = = = = = = = = = = = = = = = = = = = = // White LED Buttons void TurnOnWhiteLEDS() { pulseIR(9180);delayMicroseconds(4600);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(40140);pulseIR(9180);delayMicroseconds(2280);pulseIR(580); } void TurnOffWhiteLEDS() { pulseIR(9200);delayMicroseconds(4580);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(540);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(540);pulseIR(660);delayMicroseconds(520);pulseIR(660);delayMicroseconds(520);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(540);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(40100);pulseIR(9220);delayMicroseconds(2240);pulseIR(620); } void BrightenWhiteLEDS() { pulseIR(9200);delayMicroseconds(4600);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(40120);pulseIR(9180);delayMicroseconds(2280); } void DimWhiteLEDS() { pulseIR(9180);delayMicroseconds(4620);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40140);pulseIR(9180);delayMicroseconds(2280);pulseIR(560); } // Color LED Buttons void TurnOnColorLEDS() { pulseIR(9180);delayMicroseconds(4600);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(40180);pulseIR(9200);delayMicroseconds(2260);pulseIR(580);delayMicroseconds(32624);pulseIR(9180);delayMicroseconds(2280);pulseIR(580); } void TurnOffColorLEDS() { pulseIR(9180);delayMicroseconds(4600);pulseIR(620);delayMicroseconds(580);pulseIR(580);delayMicroseconds(600);pulseIR(580);delayMicroseconds(600);pulseIR(580);delayMicroseconds(600);pulseIR(580);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(580);delayMicroseconds(600);pulseIR(580);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40180);pulseIR(9180);delayMicroseconds(2280);pulseIR(580);delayMicroseconds(32624);pulseIR(9200);delayMicroseconds(2260);pulseIR(580); } void BrightenColorLEDS() { pulseIR(9180);delayMicroseconds(4620);pulseIR(600);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40100);pulseIR(9200);delayMicroseconds(2260);pulseIR(600); } void DimColorLEDS() { pulseIR(9200);delayMicroseconds(4600);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40120);pulseIR(9180);delayMicroseconds(2280);pulseIR(580); } // Red void TurnOnRedLED() { pulseIR(9180);delayMicroseconds(4620);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40140);pulseIR(9180);delayMicroseconds(2280);pulseIR(580); } // LiteBlue void TurnOnLiteBlueLED() { pulseIR(9200);delayMicroseconds(4620);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(680);delayMicroseconds(500);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(40200);pulseIR(9200);delayMicroseconds(2280);pulseIR(600); } // = = = = = = = = = = = = = = = = = = = = // Footnotes
This code was loaded on an Arduino Uno as a proof of concept. The serial terminal prompts for user input and executes its subroutine after being entered. This code became the basis of the final code installed on the ESP32-Cam later on in development. The Arduino Uno was fitted with an IR LED on Pin 13 and Ground. A resistor was placed in serial on the Pin 13 side. The RGBW controller’s IR sensor was placed close to the Uno’s IR LED.
Once validated, this code was ported for use on the ESP32-Cam module. Other features such as WiFi and MQTT client support are included. Not all of the keys from the IR remote are programmed since this controller is strictly to mimic dawn, dusk, warm lighting, and mid day sunlight. This limited the keys needed to the following:
White with on, off, brighten, and dim keys.
Red and Light Blue with on, off, brighten, and dim keys.
This allows the LEDs to be adjusted along a wide color temperature range. See https://en.wikipedia.org/wiki/Color_temperature for more detials regarding this topic. Here is the code used on the ESP32-Cam module.
// Declarations and Variables #include <WiFi.h> #include <WiFiClient.h> #include <PubSubClient.h> const char* mqtt_server = "MQTT_Broker_IP"; // Put your MQTT Broker here const char* ssid = "WiFi-Network"; // Put your SSID here const char* password = "WiFi-Password"; // Put your PASSWORD here WiFiClient espClient; PubSubClient client(espClient); long lastMsg = 0; long laststats = 0; long solartime = 60000; char msg[50]; int value = 0; int up = 1; int IRledPin = 2; // LED connected to digital GPIO 2 int LoopFlag = 0; unsigned long time_now = 0; // MQTT Functions void callback(char* topic, byte* message, unsigned int length) { String messageTemp; for (int i = 0; i < length; i++) { messageTemp += (char)message[i]; } if (String(topic) == "ESP32-Cam-RGBW-Controller/LightsOff") { if(messageTemp == "TurnOff"){ LoopFlag=0; TurnOff(); } } if (String(topic) == "ESP32-Cam-RGBW-Controller/LightsOn") { if(messageTemp == "TurnOn"){ LoopFlag=0; TurnOn(); } } if (String(topic) == "ESP32-Cam-RGBW-Controller/EndCycle") { if(messageTemp == "EndCycle"){ LoopFlag=0; } } if (String(topic) == "ESP32-Cam-RGBW-Controller/Sunrise") { if(messageTemp == "Sunrise"){ LoopFlag=0; Dawn(); } } if (String(topic) == "ESP32-Cam-RGBW-Controller/MorningEvening") { if(messageTemp == "MorningEvening"){ LoopFlag=0; MorningEvening(); } } if (String(topic) == "ESP32-Cam-RGBW-Controller/Midday") { if(messageTemp == "Midday"){ LoopFlag=0; Midday(); } } if (String(topic) == "ESP32-Cam-RGBW-Controller/Sunset") { if(messageTemp == "Sunset"){ LoopFlag=0; Sunset(); } } if (String(topic) == "ESP32-Cam-RGBW-Controller/Lighthouse") { if(messageTemp == "Lighthouse"){ LoopFlag=1; Lighthouse(); } } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { // Attempt to connect if (client.connect("ESP32-Cam-RGBW-Controller")) { // Subscribe // Do you not subscribe to my methods? // # for everything, or esp32/Pump for just the pump client.subscribe("ESP32-Cam-RGBW-Controller/#"); } else { // Wait 5 seconds before retrying delay(5000); } } } // Setup Function void setup() { // initialize the IR digital pin as an output: pinMode(IRledPin, OUTPUT); client.setServer(mqtt_server, 1883); client.setCallback(callback); IPAddress ip; WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); } ip = WiFi.localIP(); } // Main Loop Function void loop() { if (!client.connected()) { reconnect(); } if (LoopFlag == 1) { Lighthouse(); } client.loop(); UpdateStats(); } void UpdateStats() { long stats = millis(); if (stats - laststats > 5000) { laststats = stats; client.publish("ESP32-Cam-RGBW-Controller/Firmware", "ESP32-Cam-RGBW-Controller_Ver-1"); String StringUptime = String(millis()); client.publish("ESP32-Cam-RGBW-Controller/Uptime", StringUptime.c_str()); String StringHWAddress = String(WiFi.macAddress()); client.publish("ESP32-Cam-RGBW-Controller/HWAddress", StringHWAddress.c_str()); String StringWifiSignal = String(WiFi.RSSI()); client.publish("ESP32-Cam-RGBW-Controller/WifiSignal",StringWifiSignal.c_str()); } } // This procedure sends a 38KHz pulse to the IRledPin // for a certain # of microseconds. We'll use this whenever we need to send codes void pulseIR(long microsecs) { // we'll count down from the number of microseconds we are told to wait cli(); // this turns off any background interrupts while (microsecs > 0) { // 38 kHz is about 13 microseconds high and 13 microseconds low digitalWrite(IRledPin, HIGH); // this takes about 3 microseconds to happen delayMicroseconds(10); // hang out for 10 microseconds, you can also change this to 9 if its not working digitalWrite(IRledPin, LOW); // this also takes about 3 microseconds delayMicroseconds(10); // hang out for 10 microseconds, you can also change this to 9 if its not working // so 26 microseconds altogether microsecs -= 26; } sei(); // this turns them back on } // Light Settings = = = = = = = = = = = = = = = = = = = = void MorningEvening() { // Mid-Day = White @ 20 and Red @ 8. TurnOnColorLEDS(); delay(10); TurnOnRedLED(); delay(10); /*** for (int fadeValue = 0 ; fadeValue <= 8; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); delay(100); } ***/ TurnOnWhiteLEDS(); delay(10); /*** for (int fadeValue = 0 ; fadeValue <= 20; fadeValue += 1) { //fader 32 steps BrightenWhiteLEDS(); delay(100); } ***/ } void Midday() { // Mid-Day = White @ 20 and Lite Blue @ 8. TurnOnLiteBlueLED(); delay(10); } void Lighthouse() { // Lighthouse = Cycles Red from 0 to 31 and back down to 0, exits if interupted in millis function. TurnOffColorLEDS(); time_now = millis(); while(millis() < time_now + 10){} TurnOffWhiteLEDS(); time_now = millis(); while(millis() < time_now + 10){} TurnOnColorLEDS(); time_now = millis(); while(millis() < time_now + 10){} TurnOnRedLED(); time_now = millis(); while(millis() < time_now + 1000){ client.loop(); } for (int fadeValue = 0 ; fadeValue <= 30; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){ client.loop(); } } // Hold level for 10 seconds time_now = millis(); while(millis() < time_now + 10000){ client.loop(); } for (int fadeValue = 0 ; fadeValue <= 30; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){ client.loop(); } } TurnOffColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){ client.loop(); } } void TurnOff() { // Turn Off = Dim White to 0, then Red to 0 TurnOnWhiteLEDS(); time_now = millis(); while(millis() < time_now + 10){} for (int fadeValue = 0 ; fadeValue <= 31; fadeValue += 1) { //fader 32 steps DimWhiteLEDS(); time_now = millis(); while(millis() < time_now + 100){} } TurnOffWhiteLEDS(); time_now = millis(); while(millis() < time_now + 10){} TurnOnColorLEDS(); time_now = millis(); while(millis() < time_now + 10){} TurnOnRedLED(); time_now = millis(); while(millis() < time_now + 10){} for (int fadeValue = 0 ; fadeValue <= 31; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} } TurnOffColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} } void TurnOn() { // Turn On = Brighten Red to 8, then White to 20 TurnOnColorLEDS(); time_now = millis(); while(millis() < time_now + 10){} TurnOnRedLED(); time_now = millis(); while(millis() < time_now + 10){} for (int fadeValue = 0 ; fadeValue <= 8; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} } TurnOnWhiteLEDS(); time_now = millis(); while(millis() < time_now + 10){} for (int fadeValue = 0 ; fadeValue <= 20; fadeValue += 1) { //fader 32 steps BrightenWhiteLEDS(); time_now = millis(); while(millis() < time_now + 100){} } } void Sunrise() { // Red @ 0 will increase every 60 seconds until Red @ 28 // then Red @ 28 will decrease and White @ 0 will increase every 90 seconds until White @ 20 and Red @ 8. TurnOnColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} TurnOnRedLED(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } for (int fadeValue = 0 ; fadeValue <= 28; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } TurnOnWhiteLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } for (int fadeValue = 0 ; fadeValue <= 20; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} BrightenWhiteLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } } void Sunset () { // White @ 20 with decrease and Red @ 8 with increase every 90 seconds until White @ 0 and Red @ 32 // then Red @ 32 will decrease every 60 seconds until Red @ 0. The process should take about an hour. for (int fadeValue = 0 ; fadeValue <= 21; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} DimWhiteLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } TurnOffWhiteLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } for (int fadeValue = 0 ; fadeValue <= 31; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } TurnOffColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){} } void Dawn() { // Red @ 0 will increase every 60 seconds until Red @ 28 // then Red @ 28 will decrease and White @ 0 will increase every 90 seconds until White @ 20 and Red @ 8. TurnOnColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} TurnOnRedLED(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } for (int fadeValue = 0 ; fadeValue <= 31; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } TurnOnWhiteLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } for (int fadeValue = 0 ; fadeValue <= 20; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } for (int fadeValue = 0 ; fadeValue <= 4; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} BrightenWhiteLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } } void Dusk () { // White @ 20 with decrease and Red @ 8 with increase every 90 seconds until White @ 0 and Red @ 32 // then Red @ 32 will decrease every 60 seconds until Red @ 0. The process should take about an hour. for (int fadeValue = 0 ; fadeValue <= 4; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + 100){} DimWhiteLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } for (int fadeValue = 0 ; fadeValue <= 20; fadeValue += 1) { //fader 32 steps BrightenColorLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } TurnOffWhiteLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } for (int fadeValue = 0 ; fadeValue <= 31; fadeValue += 1) { //fader 32 steps DimColorLEDS(); time_now = millis(); while(millis() < time_now + solartime){ client.loop(); } } TurnOffColorLEDS(); time_now = millis(); while(millis() < time_now + 1000){} } // = = = = = = = = = = = = = = = = = = = = // Button IR Codes = = = = = = = = = = = = = = = = = = = = // White LED Buttons void TurnOnWhiteLEDS() { pulseIR(9180);delayMicroseconds(4600);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(40140);pulseIR(9180);delayMicroseconds(2280);pulseIR(580); } void TurnOffWhiteLEDS() { pulseIR(9200);delayMicroseconds(4580);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(540);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(540);pulseIR(660);delayMicroseconds(520);pulseIR(660);delayMicroseconds(520);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(540);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(540);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(1700);pulseIR(640);delayMicroseconds(1680);pulseIR(640);delayMicroseconds(40100);pulseIR(9220);delayMicroseconds(2240);pulseIR(620); } void BrightenWhiteLEDS() { pulseIR(9200);delayMicroseconds(4600);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(40120);pulseIR(9180);delayMicroseconds(2280); } void DimWhiteLEDS() { pulseIR(9180);delayMicroseconds(4620);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40140);pulseIR(9180);delayMicroseconds(2280);pulseIR(560); } // Color LED Buttons void TurnOnColorLEDS() { pulseIR(9180);delayMicroseconds(4600);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(40180);pulseIR(9200);delayMicroseconds(2260);pulseIR(580);delayMicroseconds(32624);pulseIR(9180);delayMicroseconds(2280);pulseIR(580); } void TurnOffColorLEDS() { pulseIR(9180);delayMicroseconds(4600);pulseIR(620);delayMicroseconds(580);pulseIR(580);delayMicroseconds(600);pulseIR(580);delayMicroseconds(600);pulseIR(580);delayMicroseconds(600);pulseIR(580);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(580);delayMicroseconds(600);pulseIR(580);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40180);pulseIR(9180);delayMicroseconds(2280);pulseIR(580);delayMicroseconds(32624);pulseIR(9200);delayMicroseconds(2260);pulseIR(580); } void BrightenColorLEDS() { pulseIR(9180);delayMicroseconds(4620);pulseIR(600);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40100);pulseIR(9200);delayMicroseconds(2260);pulseIR(600); } void DimColorLEDS() { pulseIR(9200);delayMicroseconds(4600);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40120);pulseIR(9180);delayMicroseconds(2280);pulseIR(580); } // Red void TurnOnRedLED() { pulseIR(9180);delayMicroseconds(4620);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(40140);pulseIR(9180);delayMicroseconds(2280);pulseIR(580); } // LiteBlue void TurnOnLiteBlueLED() { pulseIR(9200);delayMicroseconds(4620);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(560);pulseIR(680);delayMicroseconds(500);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(1700);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(1740);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(1720);pulseIR(620);delayMicroseconds(560);pulseIR(620);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(1740);pulseIR(600);delayMicroseconds(580);pulseIR(600);delayMicroseconds(1720);pulseIR(600);delayMicroseconds(40200);pulseIR(9200);delayMicroseconds(2280);pulseIR(600); } // = = = = = = = = = = = = = = = = = = = = // Footnotes
The IR LED used to act as the IR remote is attached to the ESP32-Cam module’s ground and GPIO 2 pin. A resister was placed in series between the IR LED and the GPIO 2 pin. The ESP32-Cam module was stacked on the RGBW Controller with the IR LED and IR Sensor mated.
With the ESP32-Cam module powered on and joined to the network, Node-Red then becomes the process that controls the overall functions. The flows consist of several button nodes, each of which connect to a corisponding mqtt node. These button nodes appear on the WebUI and when pressed, publish to the MQTT Broker thier specific topic. The ESP32-Cam subscribes to these topics and enters in the subroutine that pertains to the topic. There are also light scheduler nodes that run at a defined time and will publish topics based on the mqtt node payload.
Having the ability to automaticlly and remotely control simple RBBW LED strips using inexpensive hardware may seem trivial. However, IR control functions can be enhanced on other devices that may prove to be more valuable than what was demonstrated here.