{"id":4290,"date":"2023-03-28T00:00:02","date_gmt":"2023-03-28T07:00:02","guid":{"rendered":"https:\/\/www.cloudacm.com\/?p=4290"},"modified":"2023-03-19T22:15:50","modified_gmt":"2023-03-20T05:15:50","slug":"esp32-cam-rgbw-light-mqtt-controller","status":"publish","type":"post","link":"https:\/\/www.cloudacm.com\/?p=4290","title":{"rendered":"ESP32-Cam RGBW Light MQTT Controller"},"content":{"rendered":"<p>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.<\/p>\n<p>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&#8217;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.<\/p>\n<p>More details about capturing and replicating IR controllable device codes can be found here, <a href=\"https:\/\/learn.adafruit.com\/ir-sensor\">https:\/\/learn.adafruit.com\/ir-sensor<\/a>. The demonstrations in this post makes use of that work. Here is a photo of the RGBW Controller and IR remote keypad.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/RGBW-Controller-and-IR-Remote.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4292 size-full\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/RGBW-Controller-and-IR-Remote.png\" alt=\"\" width=\"740\" height=\"702\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/RGBW-Controller-and-IR-Remote.png 740w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/RGBW-Controller-and-IR-Remote-300x285.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/RGBW-Controller-and-IR-Remote-285x270.png 285w\" sizes=\"auto, (max-width: 740px) 100vw, 740px\" \/><\/a><\/p>\n<p>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.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">Serial.println(\"\\n\\r\\n\\rReceived: \\n\\rOFF \\tON\");\r\nfor (uint8_t i = 0; i &lt; currentpulse; i++) {\r\n  Serial.print(pulses[i][0] * RESOLUTION, DEC);\r\n  Serial.print(\" usec, \");\r\n  Serial.print(pulses[i][1] * RESOLUTION, DEC);\r\n  Serial.println(\" usec\");\r\n}<\/pre>\n<p>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.\u00a0 Each key is represented by colomns in the following figure.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Visual.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4294 size-large\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Visual-1024x409.png\" alt=\"\" width=\"640\" height=\"256\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Visual-1024x409.png 1024w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Visual-300x120.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Visual-768x307.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Visual-604x241.png 604w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Visual.png 1179w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>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.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-First-Bits.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4295 size-full\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-First-Bits.png\" alt=\"\" width=\"365\" height=\"651\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-First-Bits.png 365w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-First-Bits-168x300.png 168w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-First-Bits-151x270.png 151w\" sizes=\"auto, (max-width: 365px) 100vw, 365px\" \/><\/a><\/p>\n<p>The differences start to show starting with the 36th rows through the 69th. It appears that these are 2 bytes for each key value.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Last-Bits.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4296 size-full\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Last-Bits.png\" alt=\"\" width=\"357\" height=\"717\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Last-Bits.png 357w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Last-Bits-149x300.png 149w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/IR-Remote-Decoded-Last-Bits-134x270.png 134w\" sizes=\"auto, (max-width: 357px) 100vw, 357px\" \/><\/a><\/p>\n<p>Diving into the details of how the key streams are structured wasn&#8217;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.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">\/\/ SPDX-FileCopyrightText: 2019 Limor Fried for Adafruit Industries\r\n\/\/\r\n\/\/ SPDX-License-Identifier: MIT\r\n\r\n\/\/ See the full tutorial at https:\/\/learn.adafruit.com\/ir-sensor\/making-an-intervalometer\r\n\/\/ MIT License, attribution appreciated    Limor Fried, Adafruit Industries\r\n \r\nint IRledPin =  13;    \/\/ LED connected to digital pin 13\r\nint LoopFlag = 0;\r\nunsigned long time_now = 0;\r\n\r\n\/\/ The setup() method runs once, when the sketch starts\r\n \r\nvoid setup()   {                \r\n  Serial.begin(9600);\r\n  Serial.println(\"Enter the number for your Selection\"); \/\/ send action to Serial Monitor\r\n  Serial.println(\"1 - Sunrise\"); \/\/ send action to Serial Monitor\r\n  Serial.println(\"2 - Morning\"); \/\/ send action to Serial Monitor\r\n  Serial.println(\"3 - Midday\"); \/\/ send action to Serial Monitor\r\n  Serial.println(\"4 - Evening\"); \/\/ send action to Serial Monitor\r\n  Serial.println(\"5 - Sunset\"); \/\/ send action to Serial Monitor\r\n  Serial.println(\"6 - Lighthouse\"); \/\/ send action to Serial Monitor\r\n  Serial.println(\"7 - Off Midnight\"); \/\/ send action to Serial Monitor\r\n  Serial.println(\"8 - On Noon\"); \/\/ send action to Serial Monitor\r\n  Serial.println(\"9 - End Loop\"); \/\/ send action to Serial Monitor\r\n  \/\/ initialize the IR digital pin as an output:\r\n  pinMode(IRledPin, OUTPUT);    \r\n}\r\n \r\nvoid loop()                     \r\n{\r\n\r\n\r\n  if(Serial.available()) \/\/ if there is data comming\r\n  {\r\n    \r\n    LoopFlag=0;\r\n    String command = Serial.readStringUntil('\\n'); \/\/ read string until meet newline character\r\n\r\n    if(command == \"1\")\r\n    {\r\n      Serial.println(\"Sunrise Program is running\"); \/\/ send action to Serial Monitor\r\n      Sunrise();\r\n    }\r\n    else\r\n    if(command == \"2\")\r\n    {\r\n      Serial.println(\"Morning Program is running\"); \/\/ send action to Serial Monitor\r\n      MorningEvening();\r\n    }\r\n    else\r\n    if(command == \"3\")\r\n    {\r\n      Serial.println(\"Midday Program is running\"); \/\/ send action to Serial Monitor\r\n      Midday();\r\n    }\r\n    else\r\n    if(command == \"4\")\r\n    {\r\n      Serial.println(\"Evening Program is running\"); \/\/ send action to Serial Monitor\r\n      MorningEvening();\r\n    }\r\n    else\r\n    if(command == \"5\")\r\n    {\r\n      Serial.println(\"Sunset Program is running\"); \/\/ send action to Serial Monitor\r\n      Sunset();\r\n    }\r\n    else\r\n    if(command == \"6\")\r\n    {\r\n      Serial.println(\"Lighthouse Program is running\"); \/\/ send action to Serial Monitor\r\n      LoopFlag=1;\r\n      Lighthouse();\r\n    }\r\n    else\r\n    if(command == \"7\")\r\n    {\r\n      Serial.println(\"System is Off\"); \/\/ send action to Serial Monitor\r\n      TurnOff();\r\n    }\r\n    else\r\n    if(command == \"8\")\r\n    {\r\n      Serial.println(\"System is On\"); \/\/ send action to Serial Monitor\r\n      TurnOn();\r\n    }\r\n    else\r\n    if(command == \"9\")\r\n    {\r\n      Serial.println(\"System is Ended\"); \/\/ send action to Serial Monitor\r\n      EndCycle();\r\n    }\r\n  }\r\n\r\n  if (LoopFlag == 1)\r\n  {\r\n    Lighthouse();\r\n  }\r\n\r\n}\r\n \r\n\/\/ This procedure sends a 38KHz pulse to the IRledPin \r\n\/\/ for a certain # of microseconds. We'll use this whenever we need to send codes\r\nvoid pulseIR(long microsecs) {\r\n  \/\/ we'll count down from the number of microseconds we are told to wait\r\n \r\n  cli();  \/\/ this turns off any background interrupts\r\n \r\n  while (microsecs &gt; 0) {\r\n    \/\/ 38 kHz is about 13 microseconds high and 13 microseconds low\r\n   digitalWrite(IRledPin, HIGH);  \/\/ this takes about 3 microseconds to happen\r\n   delayMicroseconds(10);         \/\/ hang out for 10 microseconds, you can also change this to 9 if its not working\r\n   digitalWrite(IRledPin, LOW);   \/\/ this also takes about 3 microseconds\r\n   delayMicroseconds(10);         \/\/ hang out for 10 microseconds, you can also change this to 9 if its not working\r\n \r\n   \/\/ so 26 microseconds altogether\r\n   microsecs -= 26;\r\n  }\r\n \r\n  sei();  \/\/ this turns them back on\r\n}\r\n\r\n\r\n\r\n\r\n\/\/ Light Settings  = = = = = = = = = = = = = = = = = = = = \r\n\r\nvoid MorningEvening() {\r\n  \/\/ Mid-Day = White @ 20 and Red @ 8.\r\n\r\n  TurnOnColorLEDS();\r\n  delay(10);\r\n  TurnOnRedLED();\r\n  delay(10);\r\n\/***\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 8; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    delay(100);\r\n  }\r\n***\/\r\n  TurnOnWhiteLEDS();\r\n  delay(10);\r\n\/***\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 20; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenWhiteLEDS();\r\n    delay(100);\r\n  }\r\n***\/\r\n}\r\n\r\nvoid Midday() {\r\n  \/\/ Mid-Day = White @ 20 and Lite Blue @ 8.\r\n\r\n  TurnOnLiteBlueLED();\r\n  delay(10);\r\n\r\n}\r\n\r\nvoid Lighthouse() {\r\n  \/\/ Lighthouse = Cycles Red from 0 to 31 and back down to 0, exits if interupted in millis function.\r\n  TurnOffColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){KeyboardInput();}\r\n  TurnOffWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){KeyboardInput();}\r\n\r\n  TurnOnColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){KeyboardInput();}\r\n  TurnOnRedLED();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 1000){KeyboardInput();}\r\n\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 30; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){KeyboardInput();}\r\n  }\r\n  \r\n  \/\/ Hold level for 10 seconds\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10000){KeyboardInput();}\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 30; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){KeyboardInput();}\r\n  }\r\n  TurnOffColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){KeyboardInput();}\r\n\r\n}\r\n\r\nvoid TurnOff() {\r\n  \/\/ Turn Off = Dim White to 0, then Red to 0\r\n  TurnOnWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){KeyboardInput();}\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 31; fadeValue += 1) { \/\/fader 32 steps\r\n    DimWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){KeyboardInput();}\r\n  }\r\n  TurnOffWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){KeyboardInput();}\r\n  \r\n  TurnOnColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){KeyboardInput();}\r\n  TurnOnRedLED();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){KeyboardInput();}\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 31; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){KeyboardInput();}\r\n  }  \r\n  TurnOffColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){KeyboardInput();}\r\n\r\n}\r\n\r\nvoid TurnOn() {\r\n  \/\/ Turn On = Brighten Red to 8, then White to 20\r\n  \r\n  TurnOnColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  TurnOnRedLED();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 8; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n  } \r\n  \r\n  TurnOnWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 20; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n  }\r\n\r\n\r\n}\r\n\r\nvoid EndCycle(){\r\n  \/\/ Preferred function when exiting the Lighthouse Loop, since it's typically ran during sleep hours\r\n}\r\n\r\nvoid KeyboardInput(){\r\n  \/\/ Loop Interupt for Lighthouse millis function\r\n  if(Serial.available()) \/\/ if there is data comming\r\n  {   \r\n    LoopFlag=0;\r\n  }\r\n}\r\n\r\nvoid Sunrise() {\r\n  \/\/ Red @ 0 will increase every 60 seconds until Red @ 28\r\n  \/\/ then Red @ 28 will decrease and White @ 0 will increase every 90 seconds until White @ 20 and Red @ 8.\r\n\r\n  TurnOnColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n  TurnOnRedLED();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 1000){}\r\n\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 28; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){}\r\n  }\r\n\r\n  TurnOnWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 1000){}\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 20; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 100){}\r\n    BrightenWhiteLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){}\r\n  }\r\n}\r\n\r\nvoid Sunset () {\r\n  \/\/ White @ 20 with decrease and Red @ 8 with increase every 90 seconds until White @ 0 and Red @ 32\r\n  \/\/ then Red @ 32 will decrease every 60 seconds until Red @ 0.  The process should take about an hour.\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 21; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 100){}\r\n    DimWhiteLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){}\r\n  }\r\n  \r\n  TurnOffWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 1000){}\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 31; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){}\r\n  }\r\n \r\n  TurnOffColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 1000){}\r\n  \r\n}\r\n\r\n\r\n\/\/ = = = = = = = = = = = = = = = = = = = = \r\n\r\n\r\n\r\n\/\/ Button IR Codes  = = = = = = = = = = = = = = = = = = = = \r\n\r\n\/\/ White LED Buttons\r\nvoid TurnOnWhiteLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid TurnOffWhiteLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid BrightenWhiteLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid DimWhiteLEDS() {\r\npulseIR(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);\r\n}\r\n\r\n\r\n\/\/ Color LED Buttons\r\nvoid TurnOnColorLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid TurnOffColorLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid BrightenColorLEDS() {\r\npulseIR(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);\r\n\r\n}\r\n\r\nvoid DimColorLEDS() {\r\npulseIR(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);\r\n\r\n}\r\n\r\n\r\n\/\/ Red\r\nvoid TurnOnRedLED() {\r\npulseIR(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);\r\n}\r\n\r\n\/\/ LiteBlue\r\nvoid TurnOnLiteBlueLED() {\r\npulseIR(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);\r\n}\r\n\r\n\r\n\/\/ = = = = = = = = = = = = = = = = = = = = \r\n\r\n\r\n\r\n\r\n\r\n\/\/ Footnotes\r\n<\/pre>\n<p>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&#8217;s IR sensor was placed close to the Uno&#8217;s IR LED.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Arduino-Uno-IR-Remote.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4297 size-full\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Arduino-Uno-IR-Remote.png\" alt=\"\" width=\"384\" height=\"391\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Arduino-Uno-IR-Remote.png 384w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Arduino-Uno-IR-Remote-295x300.png 295w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Arduino-Uno-IR-Remote-265x270.png 265w\" sizes=\"auto, (max-width: 384px) 100vw, 384px\" \/><\/a><\/p>\n<p>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:<\/p>\n<p>White with on, off, brighten, and dim keys.<br \/>\nRed and Light Blue with on, off, brighten, and dim keys.<\/p>\n<p>This allows the LEDs to be adjusted along a wide color temperature range. See <a href=\"https:\/\/en.wikipedia.org\/wiki\/Color_temperature\">https:\/\/en.wikipedia.org\/wiki\/Color_temperature<\/a> for more detials regarding this topic. Here is the code used on the ESP32-Cam module.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">\/\/ Declarations and Variables\r\n\r\n#include &lt;WiFi.h&gt;\r\n#include &lt;WiFiClient.h&gt;\r\n#include &lt;PubSubClient.h&gt;\r\n\r\n\r\n\r\nconst char* mqtt_server = \"MQTT_Broker_IP\";     \/\/ Put your MQTT Broker here\r\nconst char* ssid =     \"WiFi-Network\";               \/\/ Put your SSID here\r\nconst char* password = \"WiFi-Password\";           \/\/ Put your PASSWORD here\r\n\r\nWiFiClient espClient;\r\nPubSubClient client(espClient);\r\nlong lastMsg = 0;\r\nlong laststats = 0;\r\nlong solartime = 60000;\r\nchar msg[50];\r\nint value = 0;\r\nint up = 1;\r\n\r\nint IRledPin = 2;    \/\/ LED connected to digital GPIO 2\r\nint LoopFlag = 0;\r\nunsigned long time_now = 0;\r\n\r\n\r\n\r\n\/\/ MQTT Functions\r\n\r\nvoid callback(char* topic, byte* message, unsigned int length) {\r\n  String messageTemp;\r\n  \r\n  for (int i = 0; i &lt; length; i++) {\r\n    messageTemp += (char)message[i];\r\n  }\r\n\r\n  if (String(topic) == \"ESP32-Cam-RGBW-Controller\/LightsOff\") {\r\n    if(messageTemp == \"TurnOff\"){\r\n      LoopFlag=0;\r\n      TurnOff();\r\n    }\r\n  }\r\n\r\n  if (String(topic) == \"ESP32-Cam-RGBW-Controller\/LightsOn\") {\r\n    if(messageTemp == \"TurnOn\"){\r\n      LoopFlag=0;\r\n      TurnOn();\r\n    }\r\n  }\r\n\r\n  if (String(topic) == \"ESP32-Cam-RGBW-Controller\/EndCycle\") {\r\n    if(messageTemp == \"EndCycle\"){\r\n      LoopFlag=0;\r\n    }\r\n  }\r\n\r\n  if (String(topic) == \"ESP32-Cam-RGBW-Controller\/Sunrise\") {\r\n    if(messageTemp == \"Sunrise\"){\r\n      LoopFlag=0;\r\n      Dawn();\r\n    }\r\n  }\r\n\r\n  if (String(topic) == \"ESP32-Cam-RGBW-Controller\/MorningEvening\") {\r\n    if(messageTemp == \"MorningEvening\"){\r\n      LoopFlag=0;\r\n      MorningEvening();\r\n    }\r\n  }\r\n\r\n  if (String(topic) == \"ESP32-Cam-RGBW-Controller\/Midday\") {\r\n    if(messageTemp == \"Midday\"){\r\n      LoopFlag=0;\r\n      Midday();\r\n    }\r\n  }\r\n\r\n  if (String(topic) == \"ESP32-Cam-RGBW-Controller\/Sunset\") {\r\n    if(messageTemp == \"Sunset\"){\r\n      LoopFlag=0;\r\n      Sunset();\r\n    }\r\n  }\r\n\r\n  if (String(topic) == \"ESP32-Cam-RGBW-Controller\/Lighthouse\") {\r\n    if(messageTemp == \"Lighthouse\"){\r\n      LoopFlag=1;\r\n      Lighthouse();\r\n    }\r\n  }\r\n  \r\n}\r\n\r\n\r\nvoid reconnect() {\r\n  \/\/ Loop until we're reconnected\r\n  while (!client.connected()) {\r\n    \/\/ Attempt to connect\r\n    if (client.connect(\"ESP32-Cam-RGBW-Controller\")) {\r\n      \/\/ Subscribe\r\n      \/\/ Do you not subscribe to my methods?\r\n      \/\/ # for everything, or esp32\/Pump for just the pump\r\n      client.subscribe(\"ESP32-Cam-RGBW-Controller\/#\");\r\n    } else {\r\n      \/\/ Wait 5 seconds before retrying\r\n      delay(5000);\r\n    }\r\n  }\r\n}\r\n\r\n\r\n\r\n\/\/ Setup Function\r\n\r\nvoid setup()\r\n{\r\n    \/\/ initialize the IR digital pin as an output:\r\n    pinMode(IRledPin, OUTPUT);    \r\n\r\n    client.setServer(mqtt_server, 1883);\r\n    client.setCallback(callback);\r\n   \r\n    IPAddress ip;\r\n\r\n    WiFi.mode(WIFI_STA);\r\n    WiFi.begin(ssid, password);\r\n    while (WiFi.status() != WL_CONNECTED)\r\n    {\r\n        delay(500);\r\n    }\r\n    ip = WiFi.localIP();\r\n\r\n}\r\n\r\n\/\/ Main Loop Function\r\n\r\nvoid loop()\r\n{\r\n  \r\n  if (!client.connected()) {\r\n    reconnect();\r\n  }\r\n\r\n  if (LoopFlag == 1)\r\n  {\r\n    Lighthouse();\r\n  }\r\n  \r\n  client.loop();\r\n  UpdateStats();\r\n\r\n}\r\n\r\nvoid UpdateStats()\r\n{\r\n  long stats = millis();\r\n  if (stats - laststats &gt; 5000) {\r\n    laststats = stats;\r\n\r\n    client.publish(\"ESP32-Cam-RGBW-Controller\/Firmware\", \"ESP32-Cam-RGBW-Controller_Ver-1\");     \r\n    String StringUptime = String(millis());\r\n    client.publish(\"ESP32-Cam-RGBW-Controller\/Uptime\", StringUptime.c_str());\r\n    String StringHWAddress = String(WiFi.macAddress());\r\n    client.publish(\"ESP32-Cam-RGBW-Controller\/HWAddress\", StringHWAddress.c_str());   \r\n    String StringWifiSignal = String(WiFi.RSSI());\r\n    client.publish(\"ESP32-Cam-RGBW-Controller\/WifiSignal\",StringWifiSignal.c_str());   \r\n\r\n\r\n  }\r\n}\r\n\r\n\r\n \r\n\/\/ This procedure sends a 38KHz pulse to the IRledPin \r\n\/\/ for a certain # of microseconds. We'll use this whenever we need to send codes\r\nvoid pulseIR(long microsecs) {\r\n  \/\/ we'll count down from the number of microseconds we are told to wait\r\n \r\n  cli();  \/\/ this turns off any background interrupts\r\n \r\n  while (microsecs &gt; 0) {\r\n    \/\/ 38 kHz is about 13 microseconds high and 13 microseconds low\r\n   digitalWrite(IRledPin, HIGH);  \/\/ this takes about 3 microseconds to happen\r\n   delayMicroseconds(10);         \/\/ hang out for 10 microseconds, you can also change this to 9 if its not working\r\n   digitalWrite(IRledPin, LOW);   \/\/ this also takes about 3 microseconds\r\n   delayMicroseconds(10);         \/\/ hang out for 10 microseconds, you can also change this to 9 if its not working\r\n \r\n   \/\/ so 26 microseconds altogether\r\n   microsecs -= 26;\r\n  }\r\n \r\n  sei();  \/\/ this turns them back on\r\n}\r\n\r\n\r\n\r\n\r\n\/\/ Light Settings  = = = = = = = = = = = = = = = = = = = = \r\n\r\nvoid MorningEvening() {\r\n  \/\/ Mid-Day = White @ 20 and Red @ 8.\r\n\r\n  TurnOnColorLEDS();\r\n  delay(10);\r\n  TurnOnRedLED();\r\n  delay(10);\r\n\/***\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 8; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    delay(100);\r\n  }\r\n***\/\r\n  TurnOnWhiteLEDS();\r\n  delay(10);\r\n\/***\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 20; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenWhiteLEDS();\r\n    delay(100);\r\n  }\r\n***\/\r\n}\r\n\r\nvoid Midday() {\r\n  \/\/ Mid-Day = White @ 20 and Lite Blue @ 8.\r\n\r\n  TurnOnLiteBlueLED();\r\n  delay(10);\r\n\r\n}\r\n\r\nvoid Lighthouse() {\r\n  \/\/ Lighthouse = Cycles Red from 0 to 31 and back down to 0, exits if interupted in millis function.\r\n  TurnOffColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  TurnOffWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n\r\n  TurnOnColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  \r\n  TurnOnRedLED();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 1000){\r\n      client.loop();\r\n    }\r\n\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 30; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){\r\n      client.loop();\r\n    }\r\n  }\r\n  \r\n  \/\/ Hold level for 10 seconds\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10000){\r\n      client.loop();\r\n    }\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 30; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){\r\n      client.loop();\r\n    }\r\n  }\r\n  TurnOffColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 1000){\r\n      client.loop();\r\n    }\r\n\r\n}\r\n\r\nvoid TurnOff() {\r\n  \/\/ Turn Off = Dim White to 0, then Red to 0\r\n  TurnOnWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 31; fadeValue += 1) { \/\/fader 32 steps\r\n    DimWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n  }\r\n  TurnOffWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  \r\n  TurnOnColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  TurnOnRedLED();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 31; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n  }  \r\n  TurnOffColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n\r\n}\r\n\r\nvoid TurnOn() {\r\n  \/\/ Turn On = Brighten Red to 8, then White to 20\r\n  \r\n  TurnOnColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  TurnOnRedLED();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 8; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n  } \r\n  \r\n  TurnOnWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 10){}\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 20; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n  }\r\n\r\n\r\n}\r\n\r\n\r\n\r\n\r\nvoid Sunrise() {\r\n  \/\/ Red @ 0 will increase every 60 seconds until Red @ 28\r\n  \/\/ then Red @ 28 will decrease and White @ 0 will increase every 90 seconds until White @ 20 and Red @ 8.\r\n\r\n  TurnOnColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n  TurnOnRedLED();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 28; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n\r\n  TurnOnWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 20; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 100){}\r\n    BrightenWhiteLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n}\r\n\r\nvoid Sunset () {\r\n  \/\/ White @ 20 with decrease and Red @ 8 with increase every 90 seconds until White @ 0 and Red @ 32\r\n  \/\/ then Red @ 32 will decrease every 60 seconds until Red @ 0.  The process should take about an hour.\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 21; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 100){}\r\n    DimWhiteLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n  \r\n  TurnOffWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 31; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n \r\n  TurnOffColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 1000){}\r\n  \r\n}\r\n\r\n\r\n\r\n\r\nvoid Dawn() {\r\n  \/\/ Red @ 0 will increase every 60 seconds until Red @ 28\r\n  \/\/ then Red @ 28 will decrease and White @ 0 will increase every 90 seconds until White @ 20 and Red @ 8.\r\n\r\n  TurnOnColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 100){}\r\n  TurnOnRedLED();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n\r\n  for (int fadeValue = 0 ; fadeValue &lt;= 31; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n\r\n  TurnOnWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 20; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 4; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 100){}\r\n    BrightenWhiteLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n}\r\n\r\nvoid Dusk () {\r\n  \/\/ White @ 20 with decrease and Red @ 8 with increase every 90 seconds until White @ 0 and Red @ 32\r\n  \/\/ then Red @ 32 will decrease every 60 seconds until Red @ 0.  The process should take about an hour.\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 4; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + 100){}\r\n    DimWhiteLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 20; fadeValue += 1) { \/\/fader 32 steps\r\n    BrightenColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n  \r\n  TurnOffWhiteLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  \r\n  for (int fadeValue = 0 ; fadeValue &lt;= 31; fadeValue += 1) { \/\/fader 32 steps\r\n    DimColorLEDS();\r\n    time_now = millis();\r\n    while(millis() &lt; time_now + solartime){\r\n      client.loop();\r\n      }\r\n  }\r\n \r\n  TurnOffColorLEDS();\r\n  time_now = millis();\r\n  while(millis() &lt; time_now + 1000){}\r\n  \r\n}\r\n\r\n\r\n\/\/ = = = = = = = = = = = = = = = = = = = = \r\n\r\n\r\n\r\n\/\/ Button IR Codes  = = = = = = = = = = = = = = = = = = = = \r\n\r\n\/\/ White LED Buttons\r\nvoid TurnOnWhiteLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid TurnOffWhiteLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid BrightenWhiteLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid DimWhiteLEDS() {\r\npulseIR(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);\r\n}\r\n\r\n\r\n\/\/ Color LED Buttons\r\nvoid TurnOnColorLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid TurnOffColorLEDS() {\r\npulseIR(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);\r\n}\r\n\r\nvoid BrightenColorLEDS() {\r\npulseIR(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);\r\n\r\n}\r\n\r\nvoid DimColorLEDS() {\r\npulseIR(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);\r\n\r\n}\r\n\r\n\r\n\/\/ Red\r\nvoid TurnOnRedLED() {\r\npulseIR(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);\r\n}\r\n\r\n\/\/ LiteBlue\r\nvoid TurnOnLiteBlueLED() {\r\npulseIR(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);\r\n}\r\n\r\n\r\n\/\/ = = = = = = = = = = = = = = = = = = = = \r\n\r\n\r\n\r\n\r\n\r\n\/\/ Footnotes\r\n<\/pre>\n<p>The IR LED used to act as the IR remote is attached to the ESP32-Cam module&#8217;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.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Node-Red_RGBW_LED_Buttons.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4300 size-full\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Node-Red_RGBW_LED_Buttons.png\" alt=\"\" width=\"860\" height=\"627\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Node-Red_RGBW_LED_Buttons.png 860w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Node-Red_RGBW_LED_Buttons-300x219.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Node-Red_RGBW_LED_Buttons-768x560.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2023\/03\/Node-Red_RGBW_LED_Buttons-370x270.png 370w\" sizes=\"auto, (max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8230;<\/p>\n<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.cloudacm.com\/?p=4290\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4290","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/4290","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4290"}],"version-history":[{"count":13,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/4290\/revisions"}],"predecessor-version":[{"id":4310,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/4290\/revisions\/4310"}],"wp:attachment":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4290"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4290"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4290"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}