添加RGB灯
This commit is contained in:
@@ -30,6 +30,9 @@ list(APPEND srcs "utils/sb_aes.c")
|
||||
list(APPEND srcs "drivers/sertrf/sertrf.c")
|
||||
list(APPEND srcs "drivers/sertrf/device.c")
|
||||
|
||||
list(APPEND srcs "drivers/led_strip/led_strip.c")
|
||||
list(APPEND srcs "drivers/led_strip/led_strip_encoder.c")
|
||||
|
||||
if(CONFIG_BUILD_BLE)
|
||||
list(APPEND srcs "drivers/data_port/ble_spp/ble_spp_server.c")
|
||||
list(APPEND srcs "drivers/data_port/ble_spp/ble_spp_server_shell.c")
|
||||
|
||||
103
app/drivers/led_strip/led_strip.c
Normal file
103
app/drivers/led_strip/led_strip.c
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "led_strip.h"
|
||||
|
||||
rmt_channel_handle_t led_chan = NULL;
|
||||
rmt_encoder_handle_t led_encoder = NULL;
|
||||
rmt_transmit_config_t tx_config = {
|
||||
.loop_count = 0, // no transfer loop
|
||||
};
|
||||
|
||||
static uint8_t led_strip_pixels[EXAMPLE_LED_NUMBERS * 3];
|
||||
uint16_t toggle_cycle = 1000;
|
||||
static uint8_t rgb_color_index = RGB_COLOR_RAD;
|
||||
|
||||
rgb_color_t rgb_color_rad = {0,255,0,0,0};
|
||||
rgb_color_t rgb_color_green = {0,0,255,0,0};
|
||||
rgb_color_t rgb_color_blue = {0,0,0,255,0};
|
||||
|
||||
|
||||
|
||||
void led_strip_init(void)
|
||||
{
|
||||
|
||||
// ESP_LOGI(TAG, "Create RMT TX channel");
|
||||
|
||||
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");
|
||||
|
||||
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");
|
||||
|
||||
|
||||
}
|
||||
void led_strip_set_pixel(uint8_t pin, uint8_t index, uint8_t green, uint8_t blue, uint8_t red)
|
||||
{
|
||||
led_strip_pixels[0 + index * 3] = green;
|
||||
led_strip_pixels[1 + index * 3] = red;
|
||||
led_strip_pixels[2 + index * 3] = blue;
|
||||
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));
|
||||
}
|
||||
|
||||
void work_rgb_led_start(void)
|
||||
{
|
||||
led_strip_init();
|
||||
/* 创建 shell 的接收任务 _work_sh() */
|
||||
static os_work_t work_handler_rgb_led;
|
||||
os_work_create(&work_handler_rgb_led, "work-rgb-led", _work_rgb_led, NULL, OS_PRIORITY_NORMAL);
|
||||
os_work_submit(default_os_work_q_hdl, &work_handler_rgb_led, toggle_cycle * 0.5);
|
||||
|
||||
}
|
||||
|
||||
void _work_rgb_led(void *arg)
|
||||
{
|
||||
static rgb_color_t* expression;
|
||||
switch (rgb_color_index)
|
||||
{
|
||||
case RGB_COLOR_RAD:
|
||||
expression = &rgb_color_rad;
|
||||
break;
|
||||
case RGB_COLOR_GREEN:
|
||||
expression = &rgb_color_green;
|
||||
break;
|
||||
case RGB_COLOR_BLUE:
|
||||
expression = &rgb_color_blue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rgb_toggle(expression);
|
||||
os_work_later(toggle_cycle * 0.5);
|
||||
}
|
||||
void rgb_update_cyle(uint16_t cyle)
|
||||
{
|
||||
toggle_cycle = cyle;
|
||||
}
|
||||
void rgb_toggle(rgb_color_t* rgb_color)
|
||||
{
|
||||
if(rgb_color->toggle_flag == 0)
|
||||
led_strip_set_pixel(0,rgb_color->index,rgb_color->green,rgb_color->blue,rgb_color->red);
|
||||
else
|
||||
led_strip_set_pixel(0,rgb_color->index,0,0,0);
|
||||
|
||||
rgb_color->toggle_flag = !rgb_color->toggle_flag;
|
||||
}
|
||||
|
||||
void rgb_color_change(uint8_t index, uint8_t color)
|
||||
{
|
||||
rgb_color_index = color;
|
||||
}
|
||||
48
app/drivers/led_strip/led_strip.h
Normal file
48
app/drivers/led_strip/led_strip.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "led_strip_encoder.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/rmt_tx.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "os/os.h"
|
||||
#include "../../config/board_config.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 g_cfg_board->rgb_led_pin
|
||||
#define RMT_LED_STRIP_GPIO_NUM 8
|
||||
|
||||
#define EXAMPLE_LED_NUMBERS 2
|
||||
#define EXAMPLE_CHASE_SPEED_MS 10
|
||||
|
||||
// static const char *TAG = "example";
|
||||
|
||||
extern rmt_channel_handle_t led_chan;
|
||||
extern rmt_encoder_handle_t led_encoder;
|
||||
extern rmt_transmit_config_t tx_config;
|
||||
|
||||
|
||||
typedef struct rgb_color_s
|
||||
{
|
||||
uint8_t index;
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
uint8_t toggle_flag;
|
||||
}rgb_color_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RGB_COLOR_RAD = 0,
|
||||
RGB_COLOR_GREEN,
|
||||
RGB_COLOR_BLUE,
|
||||
}RGB_COLOR;
|
||||
|
||||
void led_strip_init(void);
|
||||
void led_strip_set_pixel(uint8_t pin, uint8_t index, uint8_t green, uint8_t blue, uint8_t red);
|
||||
void work_rgb_led_start(void);
|
||||
void _work_rgb_led(void *arg);
|
||||
void rgb_update_cyle(uint16_t cyle);
|
||||
void rgb_toggle(rgb_color_t* rgb_color);
|
||||
void rgb_color_change(uint8_t index, uint8_t color);
|
||||
125
app/drivers/led_strip/led_strip_encoder.c
Normal file
125
app/drivers/led_strip/led_strip_encoder.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "led_strip_encoder.h"
|
||||
|
||||
static const char *TAG = "led_encoder";
|
||||
|
||||
typedef struct {
|
||||
rmt_encoder_t base;
|
||||
rmt_encoder_t *bytes_encoder;
|
||||
rmt_encoder_t *copy_encoder;
|
||||
int state;
|
||||
rmt_symbol_word_t reset_code;
|
||||
} rmt_led_strip_encoder_t;
|
||||
|
||||
|
||||
static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
|
||||
{
|
||||
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
||||
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
|
||||
rmt_encode_state_t session_state = RMT_ENCODING_RESET;
|
||||
rmt_encode_state_t state = RMT_ENCODING_RESET;
|
||||
size_t encoded_symbols = 0;
|
||||
switch (led_encoder->state) {
|
||||
case 0: // send RGB data
|
||||
encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state);
|
||||
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||
led_encoder->state = 1; // switch to next state when current encoding session finished
|
||||
}
|
||||
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||
state |= RMT_ENCODING_MEM_FULL;
|
||||
goto out; // yield if there's no free space for encoding artifacts
|
||||
}
|
||||
// fall-through
|
||||
case 1: // send reset code
|
||||
encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code,
|
||||
sizeof(led_encoder->reset_code), &session_state);
|
||||
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||
led_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session
|
||||
state |= RMT_ENCODING_COMPLETE;
|
||||
}
|
||||
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||
state |= RMT_ENCODING_MEM_FULL;
|
||||
goto out; // yield if there's no free space for encoding artifacts
|
||||
}
|
||||
}
|
||||
out:
|
||||
*ret_state = state;
|
||||
return encoded_symbols;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder)
|
||||
{
|
||||
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||
rmt_del_encoder(led_encoder->copy_encoder);
|
||||
free(led_encoder);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder)
|
||||
{
|
||||
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_encoder_reset(led_encoder->bytes_encoder);
|
||||
rmt_encoder_reset(led_encoder->copy_encoder);
|
||||
led_encoder->state = RMT_ENCODING_RESET;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
rmt_led_strip_encoder_t *led_encoder = NULL;
|
||||
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
led_encoder = rmt_alloc_encoder_mem(sizeof(rmt_led_strip_encoder_t));
|
||||
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder");
|
||||
led_encoder->base.encode = rmt_encode_led_strip;
|
||||
led_encoder->base.del = rmt_del_led_strip_encoder;
|
||||
led_encoder->base.reset = rmt_led_strip_encoder_reset;
|
||||
// different led strip might have its own timing requirements, following parameter is for WS2812
|
||||
rmt_bytes_encoder_config_t bytes_encoder_config = {
|
||||
.bit0 = {
|
||||
.level0 = 1,
|
||||
.duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us
|
||||
.level1 = 0,
|
||||
.duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us
|
||||
},
|
||||
.bit1 = {
|
||||
.level0 = 1,
|
||||
.duration0 = 0.9 * config->resolution / 1000000, // T1H=0.9us
|
||||
.level1 = 0,
|
||||
.duration1 = 0.3 * config->resolution / 1000000, // T1L=0.3us
|
||||
},
|
||||
.flags.msb_first = 1 // WS2812 transfer bit order: G7...G0R7...R0B7...B0
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, TAG, "create bytes encoder failed");
|
||||
rmt_copy_encoder_config_t copy_encoder_config = {};
|
||||
ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, TAG, "create copy encoder failed");
|
||||
|
||||
uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us
|
||||
led_encoder->reset_code = (rmt_symbol_word_t) {
|
||||
.level0 = 0,
|
||||
.duration0 = reset_ticks,
|
||||
.level1 = 0,
|
||||
.duration1 = reset_ticks,
|
||||
};
|
||||
*ret_encoder = &led_encoder->base;
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (led_encoder) {
|
||||
if (led_encoder->bytes_encoder) {
|
||||
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||
}
|
||||
if (led_encoder->copy_encoder) {
|
||||
rmt_del_encoder(led_encoder->copy_encoder);
|
||||
}
|
||||
free(led_encoder);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
36
app/drivers/led_strip/led_strip_encoder.h
Normal file
36
app/drivers/led_strip/led_strip_encoder.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "driver/rmt_encoder.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Type of led strip encoder configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t resolution; /*!< Encoder resolution, in Hz */
|
||||
} led_strip_encoder_config_t;
|
||||
|
||||
/**
|
||||
* @brief Create RMT encoder for encoding LED strip pixels into RMT symbols
|
||||
*
|
||||
* @param[in] config Encoder configuration
|
||||
* @param[out] ret_encoder Returned encoder handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG for any invalid arguments
|
||||
* - ESP_ERR_NO_MEM out of memory when creating led strip encoder
|
||||
* - ESP_OK if creating encoder successfully
|
||||
*/
|
||||
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
100
app/drivers/led_strip/led_strip_shell.c
Normal file
100
app/drivers/led_strip/led_strip_shell.c
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "led_strip_shell.h"
|
||||
#include "../pin_io/pin_io.h"
|
||||
|
||||
static int32_t s_value = 0;
|
||||
|
||||
SH_CMD_FN(set);
|
||||
SH_CMD_FN(start);
|
||||
SH_CMD_FN(clr);
|
||||
|
||||
//设置子命令
|
||||
SH_DEF_SUB_CMD(
|
||||
sub_led,
|
||||
SH_SETUP_CMD("set", "点亮灯珠 <引脚号> <灯珠号> [红] [绿] [蓝]", set, NULL), //
|
||||
SH_SETUP_CMD("start", "开启按键检测 1:初始化 2:检测", start, NULL), //
|
||||
SH_SETUP_CMD("clr", "熄灭全部灯珠 <引脚号>", clr, NULL), //
|
||||
|
||||
);
|
||||
//设置主命令
|
||||
SH_DEF_CMD(
|
||||
_register_cmd,
|
||||
SH_SETUP_CMD("led", "操作灯带驱动", NULL, sub_led), //
|
||||
);
|
||||
//设置存储解析到的数据
|
||||
static int _set_value(const char *argv[]) { return SET_VAR(&s_value, 0, 0x100); }
|
||||
|
||||
void led_strip_shell_register(void)
|
||||
{
|
||||
sh_register_cmd(&_register_cmd);
|
||||
}
|
||||
|
||||
void led_strip_shell_unregister(void)
|
||||
{
|
||||
|
||||
}
|
||||
SH_CMD_FN(set)
|
||||
{
|
||||
uint32_t pin = 0, index = 0, red = 0, green = 0, blue = 0;
|
||||
if (argc < 5)
|
||||
{
|
||||
sh_echo(sh_hdl, "输入少于 5 个参数\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc >= 1 && _set_value(&argv[0]))
|
||||
return -1;
|
||||
pin = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
if (argc >= 2 && _set_value(&argv[1]))
|
||||
return -1;
|
||||
index = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
if (argc >= 3 && _set_value(&argv[2]))
|
||||
return -1;
|
||||
red = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
if (argc >= 4 && _set_value(&argv[3]))
|
||||
return -1;
|
||||
green = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
if (argc >= 5 && _set_value(&argv[4]))
|
||||
return -1;
|
||||
blue = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
led_strip_set_pixel(pin,index,green,red,blue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SH_CMD_FN(start)
|
||||
{
|
||||
static uint32_t start_flag;
|
||||
if (argc < 1)
|
||||
{
|
||||
sh_echo(sh_hdl, "输入少于 1 个参数\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc >= 1 && _set_value(&argv[0]))
|
||||
return -1;
|
||||
start_flag = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
if (start_flag == 1)
|
||||
{
|
||||
// pin_cfg_input(&g_cfg_board->key_reset);
|
||||
}
|
||||
else if (start_flag == 2)
|
||||
{
|
||||
// bool data_flag = pin_get_valid(&g_cfg_board->key_reset);
|
||||
// sh_echo(sh_hdl, "数据 %d\r\n", data_flag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
SH_CMD_FN(clr)
|
||||
{
|
||||
if (argc < 1)
|
||||
{
|
||||
sh_echo(sh_hdl, "输入少于 1 个参数\r\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
8
app/drivers/led_strip/led_strip_shell.h
Normal file
8
app/drivers/led_strip/led_strip_shell.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "led_strip.h"
|
||||
#include "shell/sh.h"
|
||||
#include "sh_vset.h"
|
||||
|
||||
void led_strip_shell_register(void);
|
||||
void led_strip_shell_register(void);
|
||||
@@ -10,7 +10,8 @@ void sertrf_init(void)
|
||||
{
|
||||
SYS_LOG_WRN("device init error");
|
||||
}
|
||||
|
||||
//RGB灯
|
||||
work_rgb_led_start();
|
||||
sertrf_start();
|
||||
}
|
||||
void sertrf_start(void)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include "../led_strip/led_strip.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user