|
|
本帖最后由 walker2048 于 2024-1-30 11:47 编辑
一、项目名称:
车载氛围灯
二、项目概述:
项目,旨在为车辆内部营造一个独特的氛围。通过ESP32和触摸屏,RGB LED灯条,可以在车内创造出多彩的灯光效果。这些灯光可以实现各种模式和效果,如渐变、闪烁、呼吸等。通过连接麦克风,采样麦克风数据,灯光可以根据音乐的节奏和音量进行调整,实现与音乐的同步效果。此外,还可以通过触摸屏来控制灯光的开关、颜色和模式等。
三、作品实物图
四、演示视频
五、代码
5.1 触屏驱动移植代码
- #include "cst816.h"
- #include <driver/i2c.h>
- #include <esp_log.h>
- #ifdef LV_LVGL_H_INCLUDE_SIMPLE
- #include <lvgl.h>
- #else
- #include <lvgl/lvgl.h>
- #endif
- #include "../lvgl_i2c_conf.h"
- #include "tp_i2c.h"
- #define TAG "CST816T"
- static cst816t_status_t cst816t_status;
- uint8_t cst816t_read_len(uint16_t reg_addr, uint8_t *data, uint8_t len) {
- uint8_t res = 0;
- res = i2c_master_write_read_device(TOUCH_I2C_PORT, CST816T_ADDR, ?_addr, 1,
- data, len, 1000 / portTICK_PERIOD_MS);
- return res;
- }
- uint8_t cst816t_chipId(void) { return 0; }
- static esp_err_t cst816t_get_touch_points_num(uint8_t *touch_points_num) {
- uint8_t res = 0;
- res = cst816t_read_len(0x02, touch_points_num, 1);
- return res;
- }
- esp_err_t cst816t_read_pos(uint8_t *touch_points_num, uint16_t *x,
- uint16_t *y) {
- uint8_t data[4];
- cst816t_get_touch_points_num(touch_points_num);
- if (0 == *touch_points_num) {
- *x = 0;
- *y = 0;
- return 1;
- } else {
- cst816t_read_len(0x03, data, 4);
- *x = ((data[0] & 0x0f) << 8) | data[1];
- *y = ((data[2] & 0x0f) << 8) | data[3];
- }
- return ESP_OK;
- }
- esp_err_t cst816t_i2c_read(uint8_t slave_addr, uint16_t register_addr,
- uint8_t *data_buf, uint8_t len) {
- i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
- i2c_master_start(i2c_cmd);
- i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true);
- i2c_master_write_byte(i2c_cmd, register_addr, I2C_MASTER_ACK);
- i2c_master_start(i2c_cmd);
- i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_READ, true);
- i2c_master_read_byte(i2c_cmd, data_buf, I2C_MASTER_NACK);
- i2c_master_stop(i2c_cmd);
- esp_err_t ret =
- i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_PERIOD_MS);
- i2c_cmd_link_delete(i2c_cmd);
- return ret;
- }
- esp_err_t cst816t_i2c_write8(uint8_t slave_addr, uint16_t register_addr,
- uint8_t data) {
- i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
- i2c_master_start(i2c_cmd);
- i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true);
- i2c_master_write_byte(i2c_cmd, register_addr, I2C_MASTER_ACK);
- i2c_master_start(i2c_cmd);
- i2c_master_write_byte(i2c_cmd, data, true);
- i2c_master_stop(i2c_cmd);
- esp_err_t ret =
- i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_PERIOD_MS);
- i2c_cmd_link_delete(i2c_cmd);
- return ret;
- }
- void cst816t_init(uint16_t dev_addr) {
- if (!cst816t_status.inited) {
- cst816t_status.i2c_dev_addr = dev_addr;
- uint8_t data_buf[10];
- esp_err_t ret;
- ESP_LOGI(TAG, "Checking for CST816T Touch Controller ");
- if ((ret = cst816t_i2c_read(dev_addr, 0x15, &data_buf, 1) != ESP_OK)) {
- vTaskDelay(pdMS_TO_TICKS(10));
- ESP_LOGE(TAG, "Error reading from device: %s",
- esp_err_to_name(ret)); // Only show error the first time
- // return;
- }
- if ((ret = cst816t_i2c_read(dev_addr, 0xa7, &data_buf, 1) != ESP_OK)) {
- ESP_LOGE(TAG, "Error reading from device: %s",
- esp_err_to_name(ret)); // Only show error the first time
- ESP_LOGE(TAG, "device ID: %02x", data_buf[0]);
- // return;
- }
- cst816t_status.inited = true;
- }
- }
- bool cst816t_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
- uint8_t touch_points_num = 0;
- uint16_t x = 0;
- uint16_t y = 0;
- cst816t_read_pos(&touch_points_num, &x, &y);
- #if CONFIG_LV_TOUCH_INVERT_X
- x = LV_HOR_RES_MAX - x;
- #endif
- #if 1
- y = 280 - y;
- #endif
- #if 1
- int16_t swap_buf = x;
- x = y;
- y = swap_buf;
- #endif
- data->point.x = x;
- data->point.y = y;
- if (touch_points_num > 0) {
- data->state = LV_INDEV_STATE_PR;
- ESP_LOGI(TAG, "X=%u Y=%u", data->point.x, data->point.y);
- ESP_LOGV(TAG, "X=%u Y=%u", data->point.x, data->point.y);
- } else {
- data->state = LV_INDEV_STATE_REL;
- }
- return false;
- }
复制代码 5.2 测试用的LVGL代码
- /* LVGL Example project
- *
- * Basic project to test LVGL on ESP32 based projects.
- *
- * This example code is in the Public Domain (or CC0 licensed, at your option.)
- *
- * Unless required by applicable law or agreed to in writing, this
- * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied.
- */
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "esp_freertos_hooks.h"
- #include "freertos/semphr.h"
- #include "esp_timer.h"
- #include "esp_system.h"
- #include "driver/gpio.h"
- /* Littlevgl specific */
- #ifdef LV_LVGL_H_INCLUDE_SIMPLE
- #include "lvgl.h"
- #else
- #include "lvgl/lvgl.h"
- #endif
- #include "lvgl_helpers.h"
- #ifndef CONFIG_LV_TFT_DISPLAY_MONOCHROME
- #if defined CONFIG_LV_USE_DEMO_WIDGETS
- #include "lv_examples/src/lv_demo_widgets/lv_demo_widgets.h"
- #elif defined CONFIG_LV_USE_DEMO_KEYPAD_AND_ENCODER
- #include "lv_examples/src/lv_demo_keypad_encoder/lv_demo_keypad_encoder.h"
- #elif defined CONFIG_LV_USE_DEMO_BENCHMARK
- #include "lv_examples/src/lv_demo_benchmark/lv_demo_benchmark.h"
- #elif defined CONFIG_LV_USE_DEMO_STRESS
- #include "lv_examples/src/lv_demo_stress/lv_demo_stress.h"
- #else
- #error "No demo application selected."
- #endif
- #endif
- /*********************
- * DEFINES
- *********************/
- #define TAG "demo"
- #define LV_TICK_PERIOD_MS 1
- /**********************
- * STATIC PROTOTYPES
- **********************/
- static void lv_tick_task(void *arg);
- static void guiTask(void *pvParameter);
- static void create_demo_application(void);
- /**********************
- * STATIC VARIABLES
- **********************/
- static void event_handler(lv_obj_t *obj, lv_event_t event) {
- if (event == LV_EVENT_VALUE_CHANGED) {
- int n = lv_dropdown_get_selected(obj);
- printf("num: %d\n", n);
- }
- }
- void lv_sport(void) {
- /*Create a normal drop down list*/
- // lv_obj_t *ddlist = lv_dropdown_create(lv_scr_act(), NULL);
- // lv_dropdown_set_options(ddlist, "1\n2\n3\n4");
- // lv_obj_align(ddlist, NULL, LV_ALIGN_IN_TOP_MID, 0, 20);
- // lv_obj_set_event_cb(ddlist, event_handler);
- /*Create a Tab view object*/
- lv_obj_t *tabview;
- tabview = lv_tabview_create(lv_scr_act(), NULL);
- /*Add 3 tabs (the tabs are page (lv_page) and can be scrolled*/
- lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "计划健身");
- /*Add content to the tabs*/
- lv_obj_t *dr_sport = lv_dropdown_create(tab1, NULL);
- lv_obj_set_width(
- dr_sport,
- lv_obj_get_width_grid(tab1, 3, 1));
- lv_dropdown_set_options(dr_sport, "Rainbow\n"
- "Comet\n"
- "Sparkle");
- lv_obj_align(dr_sport, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 10);
- }
- /**********************
- * APPLICATION MAIN
- **********************/
- void app_main() {
- /* If you want to use a task to create the graphic, you NEED to create a Pinned task
- * Otherwise there can be problem such as memory corruption and so on.
- * NOTE: When not using Wi-Fi nor Bluetooth you can pin the guiTask to core 0 */
- xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 0, NULL, 1);
- }
- /* Creates a semaphore to handle concurrent call to lvgl stuff
- * If you wish to call *any* lvgl function from other threads/tasks
- * you should lock on the very same semaphore! */
- SemaphoreHandle_t xGuiSemaphore;
- static void guiTask(void *pvParameter) {
- (void) pvParameter;
- xGuiSemaphore = xSemaphoreCreateMutex();
- lv_init();
- /* Initialize SPI or I2C bus used by the drivers */
- lvgl_driver_init();
- lv_color_t* buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
- assert(buf1 != NULL);
- /* Use double buffered when not working with monochrome displays */
- #ifndef CONFIG_LV_TFT_DISPLAY_MONOCHROME
- lv_color_t* buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
- assert(buf2 != NULL);
- #else
- static lv_color_t *buf2 = NULL;
- #endif
- static lv_disp_buf_t disp_buf;
- uint32_t size_in_px = DISP_BUF_SIZE;
- #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820 \
- || defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A \
- || defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D \
- || defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
- /* Actual size in pixels, not bytes. */
- size_in_px *= 8;
- #endif
- /* Initialize the working buffer depending on the selected display.
- * NOTE: buf2 == NULL when using monochrome displays. */
- lv_disp_buf_init(&disp_buf, buf1, buf2, size_in_px);
- lv_disp_drv_t disp_drv;
- lv_disp_drv_init(&disp_drv);
- disp_drv.flush_cb = disp_driver_flush;
- #if defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT || defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT_INVERTED
- disp_drv.rotated = 1;
- #endif
- /* When using a monochrome display we need to register the callbacks:
- * - rounder_cb
- * - set_px_cb */
- #ifdef CONFIG_LV_TFT_DISPLAY_MONOCHROME
- disp_drv.rounder_cb = disp_driver_rounder;
- disp_drv.set_px_cb = disp_driver_set_px;
- #endif
- disp_drv.buffer = &disp_buf;
- lv_disp_drv_register(&disp_drv);
- /* Register an input device when enabled on the menuconfig */
- #if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE
- lv_indev_drv_t indev_drv;
- lv_indev_drv_init(&indev_drv);
- indev_drv.read_cb = touch_driver_read;
- indev_drv.type = LV_INDEV_TYPE_POINTER;
- lv_indev_drv_register(&indev_drv);
- #endif
- /* Create and start a periodic timer interrupt to call lv_tick_inc */
- const esp_timer_create_args_t periodic_timer_args = {
- .callback = &lv_tick_task,
- .name = "periodic_gui"
- };
- esp_timer_handle_t periodic_timer;
- ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
- ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS * 1000));
- /* Create the demo application */
- lv_sport();
- while (1) {
- /* Delay 1 tick (assumes FreeRTOS tick is 10ms */
- vTaskDelay(pdMS_TO_TICKS(10));
- /* Try to take the semaphore, call lvgl related function on success */
- if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY)) {
- lv_task_handler();
- xSemaphoreGive(xGuiSemaphore);
- }
- }
- /* A task should NEVER return */
- free(buf1);
- #ifndef CONFIG_LV_TFT_DISPLAY_MONOCHROME
- free(buf2);
- #endif
- vTaskDelete(NULL);
- }
- static void lv_tick_task(void *arg) {
- (void) arg;
- lv_tick_inc(LV_TICK_PERIOD_MS);
- }
复制代码 5.3 测试RGB灯的Python代码
- # SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
- # SPDX-License-Identifier: MIT
- """
- This example repeatedly displays all available animations, at a five second interval.
- For NeoPixel FeatherWing. Update pixel_pin and pixel_num to match your wiring if using
- a different form of NeoPixels.
- This example does not work on SAMD21 (M0) boards.
- """
- import board
- import neopixel
- from adafruit_led_animation.animation.blink import Blink
- from adafruit_led_animation.animation.comet import Comet
- from adafruit_led_animation.animation.sparkle import Sparkle
- from adafruit_led_animation.animation.rainbow import Rainbow
- from adafruit_led_animation.color import PURPLE, WHITE, AMBER, JADE, MAGENTA, ORANGE
- # Update to match the pin connected to your NeoPixels
- pixel_pin = board.D6
- # Update to match the number of NeoPixels you have connected
- pixel_num = 16
- pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.5, auto_write=False)
- blink = Blink(pixels, speed=0.5, color=JADE)
- colorcycle = ColorCycle(pixels, speed=0.4, colors=[MAGENTA, ORANGE])
- comet = Comet(pixels, speed=0.01, color=PURPLE, tail_length=10, bounce=True)
- sparkle = Sparkle(pixels, speed=0.1, color=PURPLE, num_sparkles=10)
- rainbow = Rainbow(pixels, speed=0.1, period=2)
- animations = AnimationSequence(
- comet,
- blink,
- sparkle,
- rainbow,
- advance_interval=5,
- auto_clear=True,
- )
- while True:
- animations.animate()
复制代码 由于时间的原因,做完板子就没多少时间完成项目工程了,所以只能简单设计了个LVGL界面,移植触屏驱动,并且使用CircuitPython进行测试WS2812,实现一些简单的LED动画。
六、文档
|
|