With the kick-off of Super Bowl L between the Carolina Panters and the Denver Broncos a few hours away I decided to show the ultimate team spirit and blink my NodeMCU and RGB LED in the colors of Broncos Country: orange and blue. It makes for an excellent opportunity to get some hands on experience with Pulse-Width Modulation and NodeMCU's PWM module before the big game kick-off.[^n]
A common method to 'mix' a custom color of a RGB LED is by controlling the brightness of each of the individual three colors. The brightness of a LED can be controlled by adjusting the duty cycle.
If we dim all three colors in equal amounts, the result will be white light. Red equally mixed with green will gets us yellow. From a Bronco's perspective I mix the following RGB recipe: set red fully on, and green 50% brightness and blue off will get us an orange color.
NodeMCU's PWM module provides a set of commands that do exactly this.
First we need to define the pins which are connected to the respective RGB legs respectively. A separate config.lua script contains all variables that are relevant for adjustments. See code snippet below.
-[[ config.lua | Tiest van Gool Global variables definitions for usage across various lua scripts --]] --NodeMCU Pin Definitions PIN_R = 1 --GPIO5 Red PIN_G = 2 --GPIO4 Green PIN_B = 5 --GPIO14 Blue -- Status Message print("Global variables loaded")
Controlling the brightness of the RGB LED using the PWM module is realized here. Lets examine this script a little closer. In order to accomplish the blinking I have defined 3 different routines:
- The initialization routine
rgb_initsets the RGB pins to PWN mode with the command
pwm.setup(). Once activated
pwm.start()enables detection of the waveform on the GPIOs.
- The routine
rgb_dutymixes the actual color of the LED by adjusting the duty cycles
pwm.setduty(). The parameter color is evaluated to determine what color to output. A duty value of 0 turns the pin to full brightness while 1023 is off.
- Lastly the
rgb_toggleroutine alternates the LED color from orange to blue. The parameter color is alternated and passed on to the routine
rgb_dutyfor the color adjustment.
At the end the script toggles the color value from orange (3) to blue (2) in a 2 second interval leveraging a modified Blink! script as described in this post.
--[[ pwm_blink.lua | Tiest van Gool Serves as actual init file to enable testing and debugging during initialization mode. --]] -- Load global user-defined variables' dofile("config.lua") -- Initialization routine for RGB LED pins' function rgb_init(freq, duty) -- Configure PWM (freq, 50% duty cycle[512/1023]) pwm.setup(PIN_R, freq, duty) -- Red pwm.setup(PIN_G, freq, duty) -- Green pwm.setup(PIN_B, freq, duty) -- Blue --Start the PWM on the pins (Defaults to white) pwm.start(PIN_R) pwm.start(PIN_G) pwm.start(PIN_B) end -- Routine to set color of RGB LED based on local variable -- Default set color to orange or white function rgb_duty(color) if color == 0 then -- RED COLOR pwm.setduty(PIN_R, 0) pwm.setduty(PIN_G, 1023) pwm.setduty(PIN_B, 1023) elseif color == 1 then -- GREEN COLOR pwm.setduty(PIN_R, 1023) pwm.setduty(PIN_G, 0) pwm.setduty(PIN_B, 1023) elseif color == 2 then -- BLUE COLOR pwm.setduty(PIN_R, 1023) pwm.setduty(PIN_G, 1023) pwm.setduty(PIN_B, 0) elseif color == 3 then -- ORANGE COLOR pwm.setduty(PIN_R, 0) pwm.setduty(PIN_G, 512) pwm.setduty(PIN_B, 1023) else -- WHITE COLOR pwm.setduty(PIN_R, 0) pwm.setduty(PIN_G, 0) pwm.setduty(PIN_B, 0) end end -- LED Initialization rgb_init(100, 1023) print("LED Initialized") color = 2 print("Blue color") -- Routine to toggle color of LED Orange and Blue function rgb_toggle () -- BLUE COLOR if color == 2 then print("color 2 - BLUE") color = 3 rgb_duty(color) -- Turn LED Orange -- ORANGE COLOR elseif color == 3 then print("color 3 - ORANGE") color = 2 rgb_duty(color) -- Turn LED Blue else print("color X - WHITE") color = 3 rgb_duty(color) -- Turn LED White end end -- Create interval for toggling color tmr.alarm(0, 2000, 1, rgb_toggle)
NodeMCU uses init.lua as the auto executable which is invoked upon boot-up. The script below calls the init_broncos.lua. It contains a 10 second delay to allow for cancelling the excution in the situation of an error in order to interrupt and endless loop.
--[[ init.lua | Tiest van Gool Init.lua is automatically executed on bootup of the NodeMCU. This launcher file loads the actual init_XYZ file only when everything has been tested and debugged. A 15 second delay has been added in case of error and enable abort. --]] -- Set local variable FileToExecute="pwm.lua" -- Set timer to abort initialization of actual program print("You have 15 second to enter file.remove('init.lua') to abort") tmr.alarm(0, 15000, 0, function() print("Executing: ".. FileToExecute) dofile(FileToExecute) end)
Once the scripts are uploaded onto the NodeMCU your RGB LED should be proudly blinking in the colors of the Denver Broncos: orange/blue. We've successfully mixed colors by leveraging the PWM module and duty cycles.
The Denver Broncos have won Super Bowl 50 with 24 - 10 where the defense dominated Cam and the Panthers.
[^n] Republished and modified based on my original blog post created on February 7th 2016.