LED Dimming Driver

The LED lights used in our project have five color options: red, green, blue, warm (WW), and cold (CW), so we need five PWM channels to control them. The target functions include turning on/off LED lights, and controlling their color, color temperature, brightness, breathing, and fading. However, since we are using the ESP32-C3-DevKitM-1 in practice, which only has R, G, and B channels, we can only change LEDs' colors but not their color temperature during development.

According to the requirements of the smart light project, the LED dimming driver is encapsulated and provided in the form of a light_driver component, which can be found at book-esp32c3-iot-projects/device_firmware/components/light_driver.

Besides, to save the status of LED lights, the project also introduces an app_storage component. Its underlayer adopts NVS, which stores key-value pairs in the main flash partition by calling APIs in esp_partition.h. The component can be found at book-esp32c3-iot-projects/device_firmware/components/app_storage.

1. light_driver component

According to the requirements of this project, the light_driver component implements functions such as initializing/deinitializing the LED dimming driver, turning on/off lights, controlling their color, brightness, color temperature, etc. Table 6.1 lists the APIs provided for the main application by the LED dimming driver in the light_driver component.

Table 6.1. APIs provided by the LED dimming driver in light_driver

APIFunction
light_driver_init()Initialize light_driver
light_driver_deinit()Deinitialize light_driver
light_driver_config()Configure fade time and blink cycle of light_driver
light_driver_set_switch()Turn on/off LED lights
light_driver_get_switch()Get the on/off status of LED lights
light_driver_set_hue()Set the Hue
light_driver_get_hue()Get the Hue
light_driver_set_saturation()Set the Saturation
light_driver_get_saturation()Get the Saturation
light_driver_set_value()Set the Value (as in HSV)
light_driver_get_value()Get the Value (as in HSV)
light_driver_set_hsv()Set the three HSV components in one call
light_driver_get_hsv()Get the three HSV components in one call
light_driver_set_lightness()Set the Lightness (as in HSL)
light_driver_get_lightness()Get the Lightness (as in HSL)
light_driver_set_hsl()Set the three HSL components in one call
light_driver_get_hsl()Get the three HSL components in one call
light_driver_set_color_temperature()Set the color temperature
light_driver_get_color_temperature()Get the color temperature
light_driver_set_brightness()Set the brightness
light_driver_get_brightness()Get the brightness
light_driver_set_ctb()Set color temperature and brightness in one call
light_driver_get_ctb()Get color temperature and brightness in one call
light_driver_set_rgb()Set the three RGB components in one call
light_driver_breath_start()Set the color of LED breathing and start breathing
light_driver_breath_stop()Stop breathing
light_driver_blink_start()Set the colour of LED blinking and start blinking
light_driver_blink_stop()Stop blinking

2. app_storage component

The app_storage component uses non-volatile storage (NVS) at its underlying layer. Table 6.2 shows the APIs provided for the main application by the app_storage component.

Table 6.2. APIs provided by the app_storage component

APIFunction
app_storage_init()Initialize app_storage
app_storage_set()Store data in key-value pair format
app_storage_get()Get key-value pairs
app_storage_erase()Erase a specific key-value pair

3. Saving LED status

When the LED lights are powered up, we may expect them to be set to the color and brightness of last use. To achieve this function, we need to save the status of the lights after each control and load the latest status when the driver is initialized. This status saving function is implemented in the light_driver component. Every time an API in the light_driver component is called to modify the LEDs' status, the new status will be saved, which will be loaded when the initialization API is called.

//Save LED status
if (app_storage_get(LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_ status_t)) ! = ESP_OK) {
    //Code Omitted
}
//Load LED status
if (app_storage_set(LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_ status_t)) ! = ESP_OK) {
    //Code Omitted
}

4. Initializing the driver

When adding the LED dimming driver to the smart light project, you need to write the code to initialize the driver in the app_main() function. To use such code, a light_driver_config_t parameter should be provided, which specifies the ESP32-C3 GPIOs used by the five PWM channels, the fade time, the breathing cycles, the PWM frequency, the clock source of the LEDC, the PWM duty resolution, etc. The driver initialization code in app_main() is defined as function app_driver_init(), and called as follows:

void app_driver_init()
{    
    //Code Omitted
    //Initialize LED dimming driver
    light_driver_config_t driver_config = {        
        .gpio_red= LIGHT_GPIO_RED,        
        .gpio_green         = LIGHT_GPIO_GREEN,        
        .gpio_blue          = LIGHT_GPIO_BLUE,        
        .gpio_cold          = LIGHT_GPIO_COLD,        
        .gpio_warm          = LIGHT_GPIO_WARM,        
        .fade_period_ms     = LIGHT_FADE_PERIOD_MS,        
        .blink_period_ms    = LIGHT_BLINK_PERIOD_MS,
        .freq_hz            = LIGHT_FREQ_HZ,
        .clk_cfg            = LEDC_USE_APB_CLK,
        .duty_resolution    = LEDC_TIMER_11_BIT,    
   };
   ESP_ERROR_CHECK(light_driver_init(&driver_config));
   //Code Omitted
}

5. Controlling LED status

After initializing the LED dimming driver, we can use the APIs provided by the light_driver component to control the LED lights. Combined with the button driver, the LED lights can be turned on/off through a button. Here, we will focus on controlling the on/off status, the color, and the color temperature.

(1) On/off status

The following API can be used to control the on/off status of the LED lights.

//Turn on the light
light_driver_set_switch(true);
//Turn off the light
light_driver_set_switch(false);

(2) Color

After initializing the LED dimming driver and turning on the lights, the color of the LEDs can be controlled based on RGB, HSL, or HSV color spaces. When using LED dimming APIs, pay attention to the parameter value range of these APIs:

  • HSV: Hue ≤ 360, Saturation ≤ 100, Value ≤ 100.
  • HSL: Hue ≤ 360, Saturation ≤ 100, Lightness ≤ 100.
  • RGB: Red ≤ 255, Green ≤ 255, Blue ≤ 255.

The following APIs are used for adjusting all three components of RGB, HSL, or HSV color space in one call. You can also adjust only one component using APIs listed in Table 6.1.

//RGB color control
light_driver_set_rgb(uint8_t red, uint8_t green, uint8_t blue);
//HSL color control
light_driver_set_hsl(uint16_t hue, uint8_t saturation, uint8_t lightness);
//HSV color control
light_driver_set_hsv(uint16_t hue, uint8_t saturation, uint8_t value);

(3) Color temperature

In addition to controlling the on/off status and color, light_driver APIs can also be used to control the color temperature (but not available for simulated lights). The following API can be used to change the color temperature and brightness:

light_driver_set_ctb(uint8_t color_temperature, uint8_t brightness);

📝 Source code

Please refer to book-esp32c3-iot-projects/device_firmware/2_light_drivers for the complete code to add the LED dimming driver and the button driver to the smart light project. You can also check the running results after compiling the code and flashing it onto the development board.