一、 简介
1.1 硬件介绍
ESP32-S3 SoC 芯片支持以下功能:
- 2.4 GHz Wi-Fi
- 低功耗蓝牙
- 高性能 Xtensa® 32 位 LX7 双核处理器
- 运行 RISC-V 或 FSM 内核的超低功耗协处理器
- 多种外设
- 内置安全硬件
- USB OTG 接口
- USB 串口/JTAG 控制
1.2 官方资料
1.3 开发环境
软件:IDF 5.1.1
硬件:ESP32-S3-LCD-EV-Board-MB 开发板
1.4 WS2812介绍
WS2812是一种智能控制LED灯源,集成了控制电路和RGB芯片在一个5050封装组件中。它的主要特点和技术规格如下:
- 集成设计:WS2812将控制电路和RGB芯片集成在同一个封装中,大大简化了电路设计和安装过程
- 信号重塑电路:内置信号重塑电路,可以保证波形在每次传递到下一个驱动器时不会发生失真累积
- 电源丢失重置电路:内置的电源丢失重置电路确保了在电源失效的情况下灯具能够正确重置
- 颜色和亮度:每个像素可以在三原色中实现256级亮度控制,总共可以显示16777216种颜色。扫描频率不低于400Hz/s
- 串联传输信号:通过单线串联端口传输信号,任意两点之间的距离超过5米时,信号传输不需要增加电路
- 刷新率:在30fps的刷新率下,低速模式下的串联数量不少于512点,高速模式不少于1024点
- 数据传输速率:以800Kbps的速率发送数据
- 一致性和性价比:灯光的颜色具有很高的一致性,并且成本效益高
- 应用范围:广泛应用于全彩模块、柔性灯条、室内/室外LED不规则屏幕等LED装饰照明
- 电气特性:功率供应电压为6.0~7.0V。LED的红、绿、蓝三色分别在1.8-2.2V、3.0-3.2V、3.2-3.4V的电压下工作
- 数据传输方式:采用单NZR通信模式。在上电复位后,第一个像素接收来自控制器的24位数据,然后传递到下一个像素
引脚定义
符号 | 功能描述 |
---|---|
VDD | Power supply LED |
DOUT | Control data signal output |
VSS | Ground |
DIN | Control data signal input |
数据传输时间(TH+TL=1.25us±600ns)
T0H | 0 code, high voltage time | 0.35us | ±150ns |
T1H | 1 code, high voltage time | 0.7us | ±150ns |
T0H | 0 code, low voltage time | 0.8us | ±150ns |
T1H | 1 code, low voltage time | 0.6us | ±150ns |
RES | low voltage time | Above 50us |
时序图
数据传输方法
24bit数据结构
应用电路
WS2812是一颗数字LED灯珠,采用单总线通讯,每颗灯珠支持24bit的颜色控制,也即RGB888,信号线通过DIN输入,经过一颗灯珠之后,信号线上前24bit数据会被该灯珠锁存,之后将剩下的数据信号整形之后通过DOUT输出
二、点亮一颗WS2812
2.1 引脚确认
我使用的是ESP32-S3-LCD-EV-Board-MB
开发版
查看乐鑫官网上的开发板原理图可知WS2812的控制引脚为IO4
2.2组件添加
前往乐鑫组件管理器搜索ws2812
找到led_strip组件,在当前工程目录下使用以下命令添加组件
idf.py add-dependency "espressif/led_strip^2.5.3"
2.3添加代码
此时将main.c文件修改为以下内容
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "led_strip.h"
static const char *TAG = "HK";
// GPIO assignment
#define LED_STRIP_BLINK_GPIO 4
// Numbers of the LED in the strip
#define LED_STRIP_LED_NUMBERS 1
// 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000)
led_strip_handle_t configure_led(void)
{
// LED strip general initialization, according to your led board design
led_strip_config_t strip_config = {
.strip_gpio_num = LED_STRIP_BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = LED_STRIP_LED_NUMBERS, // The number of LEDs in the strip,
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal
};
// LED strip backend configuration: RMT
led_strip_rmt_config_t rmt_config = {
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
.rmt_channel = 0,
#else
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.resolution_hz = LED_STRIP_RMT_RES_HZ, // RMT counter clock frequency
.flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3
#endif
};
// LED Strip object handle
led_strip_handle_t led_strip;
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
ESP_LOGI(TAG, "Created LED strip object with RMT backend");
return led_strip;
}
void app_main(void)
{
ESP_LOGI(TAG,"ws2812 start");
led_strip_handle_t led_strip = configure_led();
bool led_on_off = false;
// 设置亮度为 50%
uint8_t brightness = 50; // 百分比
uint8_t red = (0 * brightness) / 100;
uint8_t green = (0 * brightness) / 100;
uint8_t blue = (139 * brightness) / 100;
while (1)
{
ESP_LOGI(TAG,"ws2812 test");
if (led_on_off) {
/* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) {
ESP_ERROR_CHECK(led_strip_set_pixel(led_strip, i, red, green, blue));
}
/* Refresh the strip to send data */
ESP_ERROR_CHECK(led_strip_refresh(led_strip));
ESP_LOGI(TAG, "LED ON!");
} else {
/* Set all LED off to clear all pixels */
ESP_ERROR_CHECK(led_strip_clear(led_strip));
ESP_LOGI(TAG, "LED OFF!");
}
led_on_off = !led_on_off;
vTaskDelay(pdMS_TO_TICKS(500));
}
}
2.4 实验现象
查看开发板led灯闪烁
三、代码讲解
3.1初始化
在configure_led函数中初始化led控制引脚与rmt
led_strip_handle_t configure_led(void)
{
// LED strip general initialization, according to your led board design
led_strip_config_t strip_config = {
.strip_gpio_num = LED_STRIP_BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = LED_STRIP_LED_NUMBERS, // The number of LEDs in the strip,
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal
};
// LED strip backend configuration: RMT
led_strip_rmt_config_t rmt_config = {
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
.rmt_channel = 0,
#else
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.resolution_hz = LED_STRIP_RMT_RES_HZ, // RMT counter clock frequency
.flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3
#endif
};
// LED Strip object handle
led_strip_handle_t led_strip;
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
ESP_LOGI(TAG, "Created LED strip object with RMT backend");
return led_strip;
}
3.2 亮度控制
对于数字 LED,我们可以通过调整发送到 LED 的 RGB 值来控制亮度。降低 RGB 值将降低亮度。
// 设置亮度为 50%
uint8_t brightness = 50; // 百分比
uint8_t red = (255 * brightness) / 100;
uint8_t green = (255 * brightness) / 100;
uint8_t blue = (255 * brightness) / 100;
led_strip_set_pixel(strip, 0, red, green, blue);
led_strip_flush(strip);
3.3 刷新RGB灯数据
将设置好的RGB值传递给led_strip_set_pixel()函数
led_strip_set_pixel
函数通常用于控制 LED 灯带中单个 LED 的颜色。这个函数是 ESP-IDF 中 LED 控制库的一部分,用于设置指定 LED 灯的颜色。
led_strip_flush
函数来更新 LED 灯带,以显示新颜色。
led_strip_clear
函数来清除led灯带,以关闭灯光
在一下这段代码中,在while循环里使用led_strip_set_pixel函数设置WS2812的颜色,使用led_strip_clear函数清除所有像素,每隔500ms重复一次操作
// 设置亮度为 50%
uint8_t brightness = 50; // 百分比
uint8_t red = (0 * brightness) / 100;
uint8_t green = (0 * brightness) / 100;
uint8_t blue = (139 * brightness) / 100;
while (1)
{
ESP_LOGI(TAG,"ws2812 test");
if (led_on_off) {
/* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) {
ESP_ERROR_CHECK(led_strip_set_pixel(led_strip, i, red, green, blue));
}
/* Refresh the strip to send data */
ESP_ERROR_CHECK(led_strip_refresh(led_strip));
ESP_LOGI(TAG, "LED ON!");
} else {
/* Set all LED off to clear all pixels */
ESP_ERROR_CHECK(led_strip_clear(led_strip));
ESP_LOGI(TAG, "LED OFF!");
}
led_on_off = !led_on_off;
vTaskDelay(pdMS_TO_TICKS(500));
}
四、代码地址
Github仓库:ws2812