/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/rmt_tx.h"
#include "led_strip_encoder.h"
#define RMT_LED_STRIP_RESOLUTION_HZ 10000000 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
#define RMT_LED_STRIP_GPIO_NUM 7
#define EXAMPLE_LED_NUMBERS 16
#define EXAMPLE_CHASE_SPEED_MS 10
static const char *TAG = "example";
static uint8_t led_strip_pixels[(EXAMPLE_LED_NUMBERS) * 3];//数组来LED的RGB值 3的倍数
/**
* @brief Simple helper function, converting HSV color space to RGB color space
*
* Wiki: https://en.wikipedia.org/wiki/HSL_and_HSV
*
*/
void led_strip_hsv2rgb(uint32_t h, uint32_t s, uint32_t v, uint32_t *r, uint32_t *g, uint32_t *b)
{
h %= 360; // h -> [0,360]
uint32_t rgb_max = v * 2.55f;
uint32_t rgb_min = rgb_max * (100 - s) / 100.0f;
uint32_t i = h / 60;
uint32_t diff = h % 60;
// RGB adjustment amount by hue
uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60;
switch (i) {
case 0:
*r = rgb_max;
*g = rgb_min + rgb_adj;
*b = rgb_min;
break;
case 1:
*r = rgb_max - rgb_adj;
*g = rgb_max;
*b = rgb_min;
break;
case 2:
*r = rgb_min;
*g = rgb_max;
*b = rgb_min + rgb_adj;
break;
case 3:
*r = rgb_min;
*g = rgb_max - rgb_adj;
*b = rgb_max;
break;
case 4:
*r = rgb_min + rgb_adj;
*g = rgb_min;
*b = rgb_max;
break;
default:
*r = rgb_max;
*g = rgb_min;
*b = rgb_max - rgb_adj;
break;
}
}
void app_main(void)
{
uint32_t red = 0;
uint32_t green = 0;
uint32_t blue = 0;
uint16_t hue = 0;
uint16_t start_rgb = 0;
ESP_LOGI(TAG, "Create RMT TX channel");
rmt_channel_handle_t led_chan = NULL;
rmt_tx_channel_config_t tx_chan_config = {
.clk_src = RMT_CLK_SRC_DEFAULT, // select source clock
.gpio_num = RMT_LED_STRIP_GPIO_NUM,
.mem_block_symbols = 64, // increase the block size can make the LED less flickering
.resolution_hz = RMT_LED_STRIP_RESOLUTION_HZ,
.trans_queue_depth = 4, // set the number of transactions that can be pending in the background
};
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &led_chan));
ESP_LOGI(TAG, "Install led strip encoder");
ESP_LOGI(TAG, "Install led strip gpio is %d",RMT_LED_STRIP_GPIO_NUM);
rmt_encoder_handle_t led_encoder = NULL;
led_strip_encoder_config_t encoder_config = {
.resolution = RMT_LED_STRIP_RESOLUTION_HZ,
};
ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&encoder_config, &led_encoder));
ESP_LOGI(TAG, "Enable RMT TX channel");
ESP_ERROR_CHECK(rmt_enable(led_chan));
ESP_LOGI(TAG, "Start LED rainbow chase");
rmt_transmit_config_t tx_config = {
.loop_count = 0, // no transfer loop
};
while (1) {
for (int i = 0; i < 3; i++) {//i小于3是因为 下层循环j+=3 关系到的是led_strip_pixels[]这个数组的元素分配
//比如i=0,j取值 0,3,6,9等等,那i=1,2就j的取值就能覆盖所有example_led_number了
for (int j = i; j < EXAMPLE_LED_NUMBERS; j += 3) {//每次外层i循环进来都走一次 int j=i;
// Build RGB pixels
hue = j * 360 / EXAMPLE_LED_NUMBERS + start_rgb;
led_strip_hsv2rgb(hue, 100, 25, &red, &green, &blue);
led_strip_pixels[j * 3 + 0] = green;
led_strip_pixels[j * 3 + 1] = blue;
led_strip_pixels[j * 3 + 2] = red;
}
// Flush RGB values to LEDs
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
vTaskDelay(pdMS_TO_TICKS(EXAMPLE_CHASE_SPEED_MS));
memset(led_strip_pixels, 0, sizeof(led_strip_pixels));//用0来pixels的数据,实现的效果就是灯不亮
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
vTaskDelay(pdMS_TO_TICKS(EXAMPLE_CHASE_SPEED_MS));
}
start_rgb += 60;
}
}
参数定义:
h:色调(Hue),取值范围通常是[0, 360)。但在这里,代码通过h %= 360;确保了h的值在[0, 360)范围内。
s:饱和度(Saturation),取值范围通常是[0, 100]或[0, 1](这里假设是[0, 100])。
v:亮度(Value/Brightness),取值范围通常是[0, 100]或[0, 1](这里假设是[0, 100])。
r, g, b:这三个是指针,用于存储转换后的RGB值。
计算RGB的最大值和最小值:
rgb_max:基于亮度v计算RGB中的最大值。
rgb_min:基于亮度和饱和度计算RGB中的最小值。
计算i和diff:
i:表示h在哪个RGB扇区(总共有6个扇区)。
diff:表示h在当前扇区内的偏移量。
计算RGB调整量:
rgb_adj:基于diff和rgb_max、rgb_min的差值计算RGB的调整量。
根据i的值设置RGB值:
使用switch语句根据i的值来设置r、g、b的值。这里对应了HSV颜色空间中的6个扇区。
增加串口输入灯光延迟时间跟亮度,两个数据中间空格隔开 回车结束输入
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/rmt_tx.h"
#include "led_strip_encoder.h"
#include "driver/uart.h"
#define UART_NUM UART_NUM_0 // 假设我们使用UART0
#define BUF_SIZE 256 // 读取缓冲区大小
#define RMT_LED_STRIP_RESOLUTION_HZ 10000000 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
#define RMT_LED_STRIP_GPIO_NUM 7
#define EXAMPLE_LED_NUMBERS 16
int EXAMPLE_CHASE_SPEED_MS = 10;
int EXAMPLE_V = 25;
static const char *TAG = "example";
static uint8_t led_strip_pixels[(EXAMPLE_LED_NUMBERS) * 3];//数组来LED的RGB值 3的倍数
/**
* @brief Simple helper function, converting HSV color space to RGB color space
*
* Wiki: https://en.wikipedia.org/wiki/HSL_and_HSV
*
*/
void led_strip_hsv2rgb(uint32_t h, uint32_t s, uint32_t v, uint32_t *r, uint32_t *g, uint32_t *b)
{
h %= 360; // h -> [0,360]
uint32_t rgb_max = v * 2.55f;
uint32_t rgb_min = rgb_max * (100 - s) / 100.0f;
uint32_t i = h / 60;
uint32_t diff = h % 60;
// RGB adjustment amount by hue
uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60;
switch (i) {
case 0:
*r = rgb_max;
*g = rgb_min + rgb_adj;
*b = rgb_min;
break;
case 1:
*r = rgb_max - rgb_adj;
*g = rgb_max;
*b = rgb_min;
break;
case 2:
*r = rgb_min;
*g = rgb_max;
*b = rgb_min + rgb_adj;
break;
case 3:
*r = rgb_min;
*g = rgb_max - rgb_adj;
*b = rgb_max;
break;
case 4:
*r = rgb_min + rgb_adj;
*g = rgb_min;
*b = rgb_max;
break;
default:
*r = rgb_max;
*g = rgb_min;
*b = rgb_max - rgb_adj;
break;
}
}
// UART读取任务
void uart_read_task(void *pvParameters)
{
uint8_t data[BUF_SIZE];
size_t len;
while (1) {
// 读取UART数据
len = uart_read_bytes(UART_NUM, data, sizeof(data), 100 / portTICK_PERIOD_MS);
if (len > 0) {
// 处理接收到的数据
char *token = strtok((char *)data, " ");
if (token != NULL) {
EXAMPLE_CHASE_SPEED_MS = atoi(token);
token = strtok(NULL, " ");
}
if (token != NULL) {
EXAMPLE_V = atoi(token);
token = strtok(NULL, " ");
}
printf("\n");
memset(data, 0, BUF_SIZE);
}
}
}
void app_main(void)
{
uint32_t red = 0;
uint32_t green = 0;
uint32_t blue = 0;
uint16_t hue = 0;
uint16_t start_rgb = 0;
ESP_LOGI(TAG, "Create RMT TX channel");
rmt_channel_handle_t led_chan = NULL;
rmt_tx_channel_config_t tx_chan_config = {
.clk_src = RMT_CLK_SRC_DEFAULT, // select source clock
.gpio_num = RMT_LED_STRIP_GPIO_NUM,
.mem_block_symbols = 64, // increase the block size can make the LED less flickering
.resolution_hz = RMT_LED_STRIP_RESOLUTION_HZ,
.trans_queue_depth = 4, // set the number of transactions that can be pending in the background
};
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &led_chan));
ESP_LOGI(TAG, "Install led strip encoder");
ESP_LOGI(TAG, "Install led strip gpio is %d",RMT_LED_STRIP_GPIO_NUM);
rmt_encoder_handle_t led_encoder = NULL;
led_strip_encoder_config_t encoder_config = {
.resolution = RMT_LED_STRIP_RESOLUTION_HZ,
};
ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&encoder_config, &led_encoder));
ESP_LOGI(TAG, "Enable RMT TX channel");
ESP_ERROR_CHECK(rmt_enable(led_chan));
ESP_LOGI(TAG, "Start LED rainbow chase");
rmt_transmit_config_t tx_config = {
.loop_count = 0, // no transfer loop
};
// UART配置
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
// 设置UART参数
ESP_ERROR_CHECK(uart_param_config(UART_NUM, &uart_config));
// 安装UART驱动
ESP_ERROR_CHECK(uart_driver_install(UART_NUM, BUF_SIZE * 2, 0, 0, NULL, 0));
// 创建UART读取任务
xTaskCreate(&uart_read_task, "uart_read_task", 2048, NULL, 10, NULL);
while (1) {
for (int i = 0; i < 4; i++) {//i小于3是因为 下层循环j+=3 关系到的是led_strip_pixels[]这个数组的元素分配
//比如i=0,j取值 0,3,6,9等等,那i=1,2就j的取值就能覆盖所有example_led_number了
for (int j = i; j < EXAMPLE_LED_NUMBERS; j += 4) {//每次外层i循环进来都走一次 int j=i;
// Build RGB pixels
hue = j * 360 / EXAMPLE_LED_NUMBERS + start_rgb;
led_strip_hsv2rgb(hue, 100, EXAMPLE_V, &red, &green, &blue);
led_strip_pixels[j * 3 + 0] = green;
led_strip_pixels[j * 3 + 1] = blue;
led_strip_pixels[j * 3 + 2] = red;
}
// Flush RGB values to LEDs
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
vTaskDelay(pdMS_TO_TICKS(EXAMPLE_CHASE_SPEED_MS));
memset(led_strip_pixels, 0, sizeof(led_strip_pixels));//用0来pixels的数据,实现的效果就是灯不亮
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
vTaskDelay(pdMS_TO_TICKS(EXAMPLE_CHASE_SPEED_MS));
}
start_rgb += 60;
}
}