2. ESP32-S3 Lighting an LED
2.1 Structure of an LED
An LED (light-emitting diode) is a semiconductor light source. Its main structure includes the following parts:
- Housing: usually made of plastic or glass, used to protect the internal components.
- Light-emitting material: the most critical part of the LED, made of special semiconductor materials, such as InGaN (indium gallium nitride) or AlInGaP (aluminum indium gallium phosphide).
- Chip: the LED chip used to produce light.
- Leads: metal leads that provide electrical connection.
- Solder joints: the soldered points that connect the LED chip to the leads.
- Electrodes: responsible for connecting the semiconductor material to the external circuit, usually made of metal.
- Reflective cavity: a structure used to enhance the lighting effect by reflecting the emitted light to the front.
2.2 How an LED Emits Light
The principle of LED (light-emitting diode) emission is based on semiconductor properties. In a semiconductor, there are two types of carriers: electrons (n-type semiconductor) and holes (p-type semiconductor). When n-type and p-type semiconductor materials come into contact, a junction is formed at the interface. When an appropriate voltage is applied, holes and electrons in the junction can recombine and release energy. This energy is released in the form of photons, producing light.
2.3 Principle of an LED Driver
LED driving means providing a stable power source with appropriate current and voltage to make the LED operate and light up normally. There are two main LED driving methods: constant current and constant voltage. Constant current driving with a current limit is the most common, because LEDs are sensitive to current — a current higher than the rated value may damage the LED. Constant current driving guarantees stable current and therefore the safety of the LED. LED driving is relatively simple. You only need to connect the positive and negative terminals of the LED to the positive and negative terminals on the MCU. There are also two ways to connect an LED: current sinking and current sourcing.
- Current sinking means the LED is powered by an external source, and the current flows into our MCU. The risk is that when the external power supply changes, it may damage the MCU pin.
- Current sourcing means the MCU provides the voltage and current and outputs the current to the LED. If you use the MCU's GPIO to drive the LED directly, the drive capability is weak and may not provide enough current to drive the LED. Note that different LED colors have different forward voltages. The current must not be too large. Usually you need to connect a current-limiting resistor of about 220 ohms to 10 K ohms. The larger the current-limiting resistor, the dimmer the LED.
2.4 LED Schematic
In the schematic, the anode of the LED is connected to the 3.3 V power supply, and the cathode is connected to a current-limiting resistor and then to GPIO48. According to the LED driving principle, as long as we control the GPIO48 pin of the development board to output a low level, the LED will light up.
2.5 LED Driver Flow
2.5.1 Configure the IO Port
Two methods for configuring the IO port are provided here. Method 1: Include the header file "driver/gpio.h", and use a structure gpio_config_t to configure IO48 as output mode, with no pull-up or pull-down, and no interrupt support. The advantage of this method is that you have full flexibility: you can configure the corresponding IO port as input or output, with pull-up or pull-down, edge interrupt or level interrupt, exactly as you want.
include "driver/gpio.h"
#define LED_PIN 48
gpio_config_t led_config = {
.pin_bit_mask = (1ULL<<LED_PIN), // Configure the pin
.mode =GPIO_MODE_OUTPUT, // Output mode
.pull_up_en = GPIO_PULLUP_DISABLE, // Do not enable pull-up
.pull_down_en = GPIO_PULLDOWN_DISABLE, // Do not enable pull-down
.intr_type = GPIO_INTR_DISABLE // Do not enable pin interrupts
};
gpio_config(&led_config);2
3
4
5
6
7
8
9
10
11
The following describes the available parameters:
What are input and output?
📌 - Input refers to transferring data or signals from external devices or other sources to the target device or system (any signal coming from an external device into the development board can be called input). In computer systems, input usually means sending data or commands to the computer via external devices such as keyboards, mice, touch screens, and sensors.
- Output refers to transferring data or signals from the target device or system to external devices or other receivers (any signal sent from the development board to an external device can be called output). In computer systems, output usually means presenting data or results processed by the computer to the user or to other devices via monitors, printers, audio devices, and so on.
What are pull-up and pull-down resistors?
📌 Pull-up and pull-down resistors are components commonly used in electronic circuits to control the default state of a signal line.
- When a signal line is not connected to any power supply or ground, it is in an open-circuit state and is susceptible to external electromagnetic interference, which produces an indeterminate level. To ensure signal stability, a pull-up or pull-down resistor can be added on the signal line.
- A pull-up resistor is connected between the signal line and a high level (usually the supply voltage). When the signal line is not connected to any external device, the pull-up resistor pulls the signal line to a high level. When an external device is connected to the signal line and outputs a low level, the large current of the external device overcomes the pull-up resistor and the signal line becomes low.
- A pull-down resistor is connected between the signal line and a low level (usually ground). When the signal line is not connected to any external device, the pull-down resistor pulls the signal line to a low level. When an external device is connected to the signal line and outputs a high level, the large current of the external device overcomes the pull-down resistor and the signal line becomes high.
Method 2: This is a simpler method. First call gpio_reset_pin to initialize an IO port, then call gpio_set_direction to configure the input/output mode of this pin. Example: initialize the GPIO9 pin to output mode.
#define LED_PIN 9
gpio_reset_pin(LED_PIN); // Initialize the LED_PIN pin
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT); // Configure the pin as output mode2
3
About the functions used:
esp_err_t gpio_reset_pin(gpio_num_t gpio_num): This is a function in the ESP-IDF used to reset a GPIO port on the ESP32. It can reset the selected GPIO port to its initial state for subsequent configuration or other use. The parameter is:
gpio_num: the number of the GPIO port to reset. The return value is an enumerated value of typeesp_err_tindicating the result of the operation. If the operation succeeds, it returnsESP_OK. If the GPIO number is wrong, it returnsESP_ERR_INVALID_ARG.
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode): This is a function in the ESP-IDF used to set the direction of a GPIO port on the ESP32. It can set the selected GPIO port to input mode, output mode, or bidirectional mode. The parameters are:
gpio_num: the number of the GPIO port to set.direction: the direction to set, which can be:GPIO_MODE_INPUT: input mode;GPIO_MODE_OUTPUT: output mode;GPIO_MODE_INPUT_OUTPUT: input/output mode; The return value is an enumerated value of typeesp_err_tindicating the result of the operation. If the operation succeeds, it returnsESP_OK. If the GPIO number or the direction parameter is wrong, it returns the corresponding error code.
Let's open the gpio_reset_pin function and see what it actually does.
esp_err_t gpio_reset_pin(gpio_num_t gpio_num)
{
assert(GPIO_IS_VALID_GPIO(gpio_num));
gpio_config_t cfg = {
.pin_bit_mask = BIT64(gpio_num),
.mode = GPIO_MODE_DISABLE,
//for powersave reasons, the GPIO should not be floating, select pullup
.pull_up_en = true,
.pull_down_en = false,
.intr_type = GPIO_INTR_DISABLE,
};
gpio_config(&cfg);
return ESP_OK;
}2
3
4
5
6
7
8
9
10
11
12
13
14
As you can see, this function essentially also configures the gpio_config_t structure.
2.5.2 Controlling the IO Port
After configuring the IO port, let's look at another IO control function.
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level)This function is used in the ESP-IDF to set the level of a GPIO port on the ESP32. It can set the GPIO port to high or low. The parameters are:
gpio_num: the number of the GPIO port to set.level: the level value to set. 0 means low level, 1 means high level. The return value is an enumerated value of typeesp_err_tindicating the result of the operation. If the operation succeeds, it returnsESP_OK. If the GPIO number is wrong or the GPIO port is not configured as output mode, it returns the corresponding error code. Example:
int LED_PIN = 9;
gpio_set_level(LED_PIN, 0);// Set the LED pin to low level
gpio_set_level(LED_PIN, 1);// Set the LED pin to high level2
3
What are high and low levels?
📌 High level and low level refer to the high or low voltage state of an electrical signal in digital circuits. In digital circuits, the high and low levels of a signal usually correspond to two discrete voltage values. For example, in the TTL (Transistor-Transistor Logic) level standard, a low level (L) is usually defined as a voltage in the range 0 V to 0.8 V, and a high level (H) is usually defined as a voltage in the range 2.4 V to 5 V. In digital circuits, low and high levels are usually used to represent the two states of logic "0" and "1". In logic circuits, when a signal is at a high level, it usually represents a logic "1"; when a signal is at a low level, it represents a logic "0". This is because digital circuits have only two states (1 and 0), and a high level and a low level happen to correspond to logic "1" and "0". Note that different level standards may have different definitions and specifications. The definitions of high and low levels may vary across circuits and systems.
2.6 Lighting an LED Verification
Create a new folder named hardware where all driver code we write later will be placed. Inside hardware, create another folder named led to hold our LED .c and .h files. Inside the led folder, create two files: bsp_led.c and bsp_led.h.
How to add them in VSCode: right-click where you want to create the folder or file, and you'll see the New File option.
Add the .c and .h file path
In bsp_led.c, write the following code:
#include "bsp_led.h"
// Configure the output register
#define GPIO_OUTPUT_PIN_SEL (1ULL<<LED_PIN)
/**
* @brief LED initialization
*
*/
void LedGpioConfig(void)
{
gpio_config_t gpio_init_struct = {0};
// Configure the IO as a general-purpose IO
esp_rom_gpio_pad_select_gpio(LED_PIN);
gpio_init_struct.intr_type = GPIO_INTR_DISABLE; // Do not use interrupts
gpio_init_struct.mode = GPIO_MODE_OUTPUT; // Output mode
gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; // Enable pull-up mode
gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; // Disable pull-down mode
gpio_init_struct.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; // Use the GPIO9 output register
// Apply the configuration above to the pin
gpio_config( &gpio_init_struct );
// Set the pin to output high level; by default, do not light the LED
gpio_set_level(LED_PIN, 1);
}
/**
* @brief Turn on the LED
*
*/
void LedOn(void)
{
gpio_set_level(LED_PIN, 0);
}
/**
* @brief Turn off the LED
*
*/
void LedOff(void)
{
gpio_set_level(LED_PIN, 1);
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
In bsp_led.h, write the following code:
#ifndef _BSP_LED_H_
#define _BSP_LED_H_
#include "driver/gpio.h"
// Set the LED pin
#define LED_PIN 48
/**
* @brief LED initialization
*
*/
void LedGpioConfig(void);
/**
* @brief Turn on the LED
*
*/
void LedOn(void);
/**
* @brief Turn off the LED
*
*/
void LedOff(void);
#endif2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
In main.c, write the following code:
#include <stdio.h>
#include "hardware/led/bsp_led.h"
void app_main(void)
{
// LED initialization
LedGpioConfig();
// Set the LED to light up
LedOn();
}2
3
4
5
6
7
8
9
10
11
12
2.7 Lighting the LED Effect
The LED marked G48 on the development board will stay on after the code is downloaded.