回答

收藏

《2023 DigiKey 汽车应用创意挑战赛》--智能车载氛围灯

#竞赛 #竞赛 1859 人阅读 | 0 人回复 | 2024-01-29

本帖最后由 walker2048 于 2024-1-30 11:47 编辑

一、项目名称

车载氛围灯
二、项目概述:

项目,旨在为车辆内部营造一个独特的氛围。通过ESP32和触摸屏,RGB LED灯条,可以在车内创造出多彩的灯光效果。这些灯光可以实现各种模式和效果,如渐变、闪烁、呼吸等。通过连接麦克风,采样麦克风数据,灯光可以根据音乐的节奏和音量进行调整,实现与音乐的同步效果。此外,还可以通过触摸屏来控制灯光的开关、颜色和模式等。

三、作品实物图




四、演示视频

视频.zip (29.3 MB, 下载次数: 8)


五、代码

5.1 触屏驱动移植代码
  1. #include "cst816.h"

  2. #include <driver/i2c.h>
  3. #include <esp_log.h>
  4. #ifdef LV_LVGL_H_INCLUDE_SIMPLE
  5. #include <lvgl.h>
  6. #else
  7. #include <lvgl/lvgl.h>
  8. #endif

  9. #include "../lvgl_i2c_conf.h"
  10. #include "tp_i2c.h"

  11. #define TAG "CST816T"

  12. static cst816t_status_t cst816t_status;
  13. uint8_t cst816t_read_len(uint16_t reg_addr, uint8_t *data, uint8_t len) {
  14.   uint8_t res = 0;
  15.   res = i2c_master_write_read_device(TOUCH_I2C_PORT, CST816T_ADDR, ?_addr, 1,
  16.                                      data, len, 1000 / portTICK_PERIOD_MS);

  17.   return res;
  18. }

  19. uint8_t cst816t_chipId(void) { return 0; }
  20. static esp_err_t cst816t_get_touch_points_num(uint8_t *touch_points_num) {
  21.   uint8_t res = 0;
  22.   res = cst816t_read_len(0x02, touch_points_num, 1);
  23.   return res;
  24. }

  25. esp_err_t cst816t_read_pos(uint8_t *touch_points_num, uint16_t *x,
  26.                            uint16_t *y) {
  27.   uint8_t data[4];

  28.   cst816t_get_touch_points_num(touch_points_num);
  29.   if (0 == *touch_points_num) {
  30.     *x = 0;
  31.     *y = 0;
  32.     return 1;
  33.   } else {
  34.     cst816t_read_len(0x03, data, 4);

  35.     *x = ((data[0] & 0x0f) << 8) | data[1];
  36.     *y = ((data[2] & 0x0f) << 8) | data[3];
  37.   }

  38.   return ESP_OK;
  39. }

  40. esp_err_t cst816t_i2c_read(uint8_t slave_addr, uint16_t register_addr,
  41.                            uint8_t *data_buf, uint8_t len) {
  42.   i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();

  43.   i2c_master_start(i2c_cmd);
  44.   i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true);
  45.   i2c_master_write_byte(i2c_cmd, register_addr, I2C_MASTER_ACK);

  46.   i2c_master_start(i2c_cmd);
  47.   i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_READ, true);

  48.   i2c_master_read_byte(i2c_cmd, data_buf, I2C_MASTER_NACK);
  49.   i2c_master_stop(i2c_cmd);
  50.   esp_err_t ret =
  51.       i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_PERIOD_MS);
  52.   i2c_cmd_link_delete(i2c_cmd);
  53.   return ret;
  54. }

  55. esp_err_t cst816t_i2c_write8(uint8_t slave_addr, uint16_t register_addr,
  56.                              uint8_t data) {
  57.   i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();

  58.   i2c_master_start(i2c_cmd);
  59.   i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true);
  60.   i2c_master_write_byte(i2c_cmd, register_addr, I2C_MASTER_ACK);

  61.   i2c_master_start(i2c_cmd);
  62.   i2c_master_write_byte(i2c_cmd, data, true);

  63.   i2c_master_stop(i2c_cmd);
  64.   esp_err_t ret =
  65.       i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_PERIOD_MS);
  66.   i2c_cmd_link_delete(i2c_cmd);
  67.   return ret;
  68. }

  69. void cst816t_init(uint16_t dev_addr) {
  70.   if (!cst816t_status.inited) {
  71.     cst816t_status.i2c_dev_addr = dev_addr;
  72.     uint8_t data_buf[10];
  73.     esp_err_t ret;

  74.     ESP_LOGI(TAG, "Checking for CST816T Touch Controller ");

  75.     if ((ret = cst816t_i2c_read(dev_addr, 0x15, &data_buf, 1) != ESP_OK)) {
  76.       vTaskDelay(pdMS_TO_TICKS(10));
  77.       ESP_LOGE(TAG, "Error reading from device: %s",
  78.                esp_err_to_name(ret)); // Only show error the first time
  79.                                       // return;
  80.     }
  81.     if ((ret = cst816t_i2c_read(dev_addr, 0xa7, &data_buf, 1) != ESP_OK)) {
  82.       ESP_LOGE(TAG, "Error reading from device: %s",
  83.                esp_err_to_name(ret)); // Only show error the first time
  84.       ESP_LOGE(TAG, "device ID: %02x", data_buf[0]);
  85.       // return;
  86.     }

  87.     cst816t_status.inited = true;
  88.   }
  89. }

  90. bool cst816t_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {

  91.   uint8_t touch_points_num = 0;
  92.   uint16_t x = 0;
  93.   uint16_t y = 0;

  94.   cst816t_read_pos(&touch_points_num, &x, &y);

  95. #if CONFIG_LV_TOUCH_INVERT_X
  96.   x = LV_HOR_RES_MAX - x;
  97. #endif
  98. #if 1
  99.   y = 280 - y;
  100. #endif
  101. #if 1
  102.   int16_t swap_buf = x;
  103.   x = y;
  104.   y = swap_buf;
  105. #endif

  106.   data->point.x = x;
  107.   data->point.y = y;
  108.   if (touch_points_num > 0) {
  109.     data->state = LV_INDEV_STATE_PR;
  110.     ESP_LOGI(TAG, "X=%u Y=%u", data->point.x, data->point.y);
  111.     ESP_LOGV(TAG, "X=%u Y=%u", data->point.x, data->point.y);
  112.   } else {
  113.     data->state = LV_INDEV_STATE_REL;
  114.   }

  115.   return false;
  116. }
复制代码
5.2 测试用的LVGL代码
  1. /* LVGL Example project
  2. *
  3. * Basic project to test LVGL on ESP32 based projects.
  4. *
  5. * This example code is in the Public Domain (or CC0 licensed, at your option.)
  6. *
  7. * Unless required by applicable law or agreed to in writing, this
  8. * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  9. * CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. #include <stdbool.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>

  15. #include "freertos/FreeRTOS.h"
  16. #include "freertos/task.h"
  17. #include "esp_freertos_hooks.h"
  18. #include "freertos/semphr.h"
  19. #include "esp_timer.h"
  20. #include "esp_system.h"
  21. #include "driver/gpio.h"

  22. /* Littlevgl specific */
  23. #ifdef LV_LVGL_H_INCLUDE_SIMPLE
  24. #include "lvgl.h"
  25. #else
  26. #include "lvgl/lvgl.h"
  27. #endif

  28. #include "lvgl_helpers.h"

  29. #ifndef CONFIG_LV_TFT_DISPLAY_MONOCHROME
  30.     #if defined CONFIG_LV_USE_DEMO_WIDGETS
  31.         #include "lv_examples/src/lv_demo_widgets/lv_demo_widgets.h"
  32.     #elif defined CONFIG_LV_USE_DEMO_KEYPAD_AND_ENCODER
  33.         #include "lv_examples/src/lv_demo_keypad_encoder/lv_demo_keypad_encoder.h"
  34.     #elif defined CONFIG_LV_USE_DEMO_BENCHMARK
  35.         #include "lv_examples/src/lv_demo_benchmark/lv_demo_benchmark.h"
  36.     #elif defined CONFIG_LV_USE_DEMO_STRESS
  37.         #include "lv_examples/src/lv_demo_stress/lv_demo_stress.h"
  38.     #else
  39.         #error "No demo application selected."
  40.     #endif
  41. #endif

  42. /*********************
  43. *      DEFINES
  44. *********************/
  45. #define TAG "demo"
  46. #define LV_TICK_PERIOD_MS 1

  47. /**********************
  48. *  STATIC PROTOTYPES
  49. **********************/
  50. static void lv_tick_task(void *arg);
  51. static void guiTask(void *pvParameter);
  52. static void create_demo_application(void);

  53. /**********************
  54. *  STATIC VARIABLES
  55. **********************/

  56. static void event_handler(lv_obj_t *obj, lv_event_t event) {
  57.   if (event == LV_EVENT_VALUE_CHANGED) {
  58.     int n = lv_dropdown_get_selected(obj);
  59.     printf("num: %d\n", n);
  60.   }
  61. }

  62. void lv_sport(void) {
  63.   /*Create a normal drop down list*/
  64.   // lv_obj_t *ddlist = lv_dropdown_create(lv_scr_act(), NULL);
  65.   //   lv_dropdown_set_options(ddlist, "1\n2\n3\n4");

  66.   // lv_obj_align(ddlist, NULL, LV_ALIGN_IN_TOP_MID, 0, 20);
  67.   // lv_obj_set_event_cb(ddlist, event_handler);

  68.   /*Create a Tab view object*/

  69.   lv_obj_t *tabview;
  70.   tabview = lv_tabview_create(lv_scr_act(), NULL);

  71.   /*Add 3 tabs (the tabs are page (lv_page) and can be scrolled*/
  72.   lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "计划健身");

  73.   /*Add content to the tabs*/
  74.   lv_obj_t *dr_sport = lv_dropdown_create(tab1, NULL);
  75.   lv_obj_set_width(
  76.       dr_sport,
  77.       lv_obj_get_width_grid(tab1, 3, 1));
  78.   lv_dropdown_set_options(dr_sport, "Rainbow\n"
  79.                                     "Comet\n"
  80.                                     "Sparkle");
  81.   lv_obj_align(dr_sport, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 10);
  82. }

  83. /**********************
  84. *   APPLICATION MAIN
  85. **********************/
  86. void app_main() {

  87.     /* If you want to use a task to create the graphic, you NEED to create a Pinned task
  88.      * Otherwise there can be problem such as memory corruption and so on.
  89.      * NOTE: When not using Wi-Fi nor Bluetooth you can pin the guiTask to core 0 */
  90.     xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 0, NULL, 1);
  91. }

  92. /* Creates a semaphore to handle concurrent call to lvgl stuff
  93. * If you wish to call *any* lvgl function from other threads/tasks
  94. * you should lock on the very same semaphore! */
  95. SemaphoreHandle_t xGuiSemaphore;

  96. static void guiTask(void *pvParameter) {

  97.     (void) pvParameter;
  98.     xGuiSemaphore = xSemaphoreCreateMutex();

  99.     lv_init();

  100.     /* Initialize SPI or I2C bus used by the drivers */
  101.     lvgl_driver_init();

  102.     lv_color_t* buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
  103.     assert(buf1 != NULL);

  104.     /* Use double buffered when not working with monochrome displays */
  105. #ifndef CONFIG_LV_TFT_DISPLAY_MONOCHROME
  106.     lv_color_t* buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
  107.     assert(buf2 != NULL);
  108. #else
  109.     static lv_color_t *buf2 = NULL;
  110. #endif

  111.     static lv_disp_buf_t disp_buf;

  112.     uint32_t size_in_px = DISP_BUF_SIZE;

  113. #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820         \
  114.     || defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A    \
  115.     || defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D     \
  116.     || defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306

  117.     /* Actual size in pixels, not bytes. */
  118.     size_in_px *= 8;
  119. #endif

  120.     /* Initialize the working buffer depending on the selected display.
  121.      * NOTE: buf2 == NULL when using monochrome displays. */
  122.     lv_disp_buf_init(&disp_buf, buf1, buf2, size_in_px);

  123.     lv_disp_drv_t disp_drv;
  124.     lv_disp_drv_init(&disp_drv);
  125.     disp_drv.flush_cb = disp_driver_flush;

  126. #if defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT || defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT_INVERTED
  127.     disp_drv.rotated = 1;
  128. #endif

  129.     /* When using a monochrome display we need to register the callbacks:
  130.      * - rounder_cb
  131.      * - set_px_cb */
  132. #ifdef CONFIG_LV_TFT_DISPLAY_MONOCHROME
  133.     disp_drv.rounder_cb = disp_driver_rounder;
  134.     disp_drv.set_px_cb = disp_driver_set_px;
  135. #endif

  136.     disp_drv.buffer = &disp_buf;
  137.     lv_disp_drv_register(&disp_drv);

  138.     /* Register an input device when enabled on the menuconfig */
  139. #if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE
  140.     lv_indev_drv_t indev_drv;
  141.     lv_indev_drv_init(&indev_drv);
  142.     indev_drv.read_cb = touch_driver_read;
  143.     indev_drv.type = LV_INDEV_TYPE_POINTER;
  144.     lv_indev_drv_register(&indev_drv);
  145. #endif

  146.     /* Create and start a periodic timer interrupt to call lv_tick_inc */
  147.     const esp_timer_create_args_t periodic_timer_args = {
  148.         .callback = &lv_tick_task,
  149.         .name = "periodic_gui"
  150.     };
  151.     esp_timer_handle_t periodic_timer;
  152.     ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
  153.     ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS * 1000));

  154.     /* Create the demo application */
  155.     lv_sport();

  156.     while (1) {
  157.         /* Delay 1 tick (assumes FreeRTOS tick is 10ms */
  158.         vTaskDelay(pdMS_TO_TICKS(10));

  159.         /* Try to take the semaphore, call lvgl related function on success */
  160.         if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY)) {
  161.             lv_task_handler();
  162.             xSemaphoreGive(xGuiSemaphore);
  163.        }
  164.     }

  165.     /* A task should NEVER return */
  166.     free(buf1);
  167. #ifndef CONFIG_LV_TFT_DISPLAY_MONOCHROME
  168.     free(buf2);
  169. #endif
  170.     vTaskDelete(NULL);
  171. }

  172. static void lv_tick_task(void *arg) {
  173.     (void) arg;

  174.     lv_tick_inc(LV_TICK_PERIOD_MS);
  175. }
复制代码
5.3 测试RGB灯的Python代码
  1. # SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
  2. # SPDX-License-Identifier: MIT

  3. """
  4. This example repeatedly displays all available animations, at a five second interval.

  5. For NeoPixel FeatherWing. Update pixel_pin and pixel_num to match your wiring if using
  6. a different form of NeoPixels.

  7. This example does not work on SAMD21 (M0) boards.
  8. """
  9. import board
  10. import neopixel

  11. from adafruit_led_animation.animation.blink import Blink
  12. from adafruit_led_animation.animation.comet import Comet
  13. from adafruit_led_animation.animation.sparkle import Sparkle
  14. from adafruit_led_animation.animation.rainbow import Rainbow
  15. from adafruit_led_animation.color import PURPLE, WHITE, AMBER, JADE, MAGENTA, ORANGE

  16. # Update to match the pin connected to your NeoPixels
  17. pixel_pin = board.D6
  18. # Update to match the number of NeoPixels you have connected
  19. pixel_num = 16

  20. pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.5, auto_write=False)

  21. blink = Blink(pixels, speed=0.5, color=JADE)
  22. colorcycle = ColorCycle(pixels, speed=0.4, colors=[MAGENTA, ORANGE])
  23. comet = Comet(pixels, speed=0.01, color=PURPLE, tail_length=10, bounce=True)
  24. sparkle = Sparkle(pixels, speed=0.1, color=PURPLE, num_sparkles=10)
  25. rainbow = Rainbow(pixels, speed=0.1, period=2)

  26. animations = AnimationSequence(
  27.     comet,
  28.     blink,
  29.     sparkle,
  30.     rainbow,
  31.     advance_interval=5,
  32.     auto_clear=True,
  33. )

  34. while True:
  35.     animations.animate()
复制代码
由于时间的原因,做完板子就没多少时间完成项目工程了,所以只能简单设计了个LVGL界面,移植触屏驱动,并且使用CircuitPython进行测试WS2812,实现一些简单的LED动画。
六、文档
文档.zip (1.35 MB, 下载次数: 5)



分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条