ESP32-Cam RGBW Light MQTT Controller

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.

Comments are closed.