FastBond2阶段2- 基于ESP32的智能门廊灯的实现
esp32 对门廊灯多彩效果的控制,实现远程对灯具的控制。重点实现多彩led的点亮效果
标签
ESP32
FastBond第二季
悠悠兹有
更新2023-11-08
1432

 项目介绍

   非常感谢电子森林的fastbond活动。

    本次我要设计的产品是智能门廊效果灯。

    设计这个产品的原因是由于我恶劣条件的租房环境。加班回家开门满眼深深的黑,拖鞋放钥匙需要摸索一阵,不太方便。

    于是想设计本次产品,首先要点亮几个led。再加一点特效,显得有点科技感。为了增加交互感,增加网络控制灯效功能。

    选择了ws2812bled,一根线控制所有的led。

    按照datasheet手册,数据发送速度可达800Kbps,那能够串在一根线上的led数量就相当可观了。

    目前已经实现了网络连接,tcp客户端,和ws2812bled控制的三个模块。能够通过tcp服务端下发一些灯效控制指令,来实现不同的灯效,目前实现的灯效是数字0到9。

    目前打板了个样板,计划焊接几个样品,送朋友作为一个小礼物。因为具有网络控制功能,可以实现两个人呼唤对方的小工具。想念对方的时候,点亮一个灯效,做个小玩意还是挺不错的。

项目结构

   项目结构如下

FnymtxhRXTRZaqZyB1VqrzHaqfJf

esp32模组启动wifi无线模块,连接路由器,这里使用的是官网的esptouch协议配网。

创建tcp客户端,用于连接tcp服务器。服务器接收到板子,并下发控制命令,用于设置led灯板的灯效。

对led的控制使用了rmt控制器,用于灯效的控制数据编码并通过leddta发送编码,控制led灯珠的颜色。

目前实现灯效:

 数字显示

通过tcp服务器发送数值字符到esp里面,判断第一个字符是数字几,展示数字字符在led面板上。

原理图讲解

    原理图主分为两个模块: ws2812b灯板和esp32控制系统。

1. ws2812b灯板

安排了36个led,通过一根线穿起来。

FjJzZ3y4RnAhZ5NvcjQOBgO2LiJt

通过一个mos管作为电源的开关,用一个esp32引脚控制开关的通断。leddata作为控制led的数据入口。

FgcsC7fpui7a1_sp8jHs0CcSawH7

2.esp32控制系统

   esp32的外围设计了两个按钮和一个led。

   用在功能实现的初期测试esp32是否好用。

FoxJqnUDrC-QRo9Cint3G9-85Yji

  boot引脚使用排针设计,按上短接帽,用于进入一级boot。

FpqJGZo-GuuBHsu6CpqVJcq9O33T

 en引脚设计了轻触按键,用于进入下载模式。用于我们通过uart串口下载程序。

FqKo9UEMs_Z9V9PlPjXi1KvE_O-3

esp32开发流程

   命令讲解:

 配置编译条目

设置编译的目标芯片类型
idf.py set-target esp32
idf.py menuconfig

编译
idf.py build

烧写
idf.py -p COM14 [-b BAUD] flash
idf.py -p COM14  flash

这里浪费了两天时间,如下图所示,已经可以正常进入下载状态。

FhJ8e-jDGhkHLcbz-DHcBBrLty8k

strapping引脚的电平也是正确的,但是一直出现错误:

A fatal error occurred: Failed to connect to ESP32: No serial data received 

偶尔有一次竟然成功,没有触发条件。所以没有得到成功烧写的方法。

后来拔了串口的电源,再次插上就成功了,大概就是官方的文档所说,启动的上电时序有问题吧。

测试场景1:点灯

首先看一下原理图,引脚27

FpIjwydyfFq3LxcWCAelYAZDqwVT

所以配置27引脚就能控制灯了。

FmPixUXA_D6ECebuIsrVPoVyuCHZ

使用idf.py munuconfig 配置blink引脚号为27,所以就能让led闪烁了。

测试场景2: 按钮的使用

   本项目还会使用到按钮,下面来使用按键的按键事件获取。

首先看原理图。

FnRWU_l0I8aqvFyJwItY34W8nnp_

可以看到使用的引脚是 io22 和io23,先测试引脚22.

首先使用idf.py menuconfig 配置 GPIO_INPUT_IO_0使用的引脚number为22。

拿来官方的通用gpio例程,修改开启中断。代码如下

/* GPIO Example

   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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

/**
 * Brief:
 * This test code shows how to configure gpio and how to use gpio interrupt.
 *
 * GPIO status:
 * GPIO18: output (ESP32C2/ESP32H2 uses GPIO8 as the second output pin)
 * GPIO19: output (ESP32C2/ESP32H2 uses GPIO9 as the second output pin)
 * GPIO4:  input, pulled up, interrupt from rising edge and falling edge
 * GPIO5:  input, pulled up, interrupt from rising edge.
 *
 * Note. These are the default GPIO pins to be used in the example. You can
 * change IO pins in menuconfig.
 *
 * Test:
 * Connect GPIO18(8) with GPIO4
 * Connect GPIO19(9) with GPIO5
 * Generate pulses on GPIO18(8)/19(9), that triggers interrupt on GPIO4/5
 *
 */

#define GPIO_OUTPUT_IO_0    CONFIG_GPIO_OUTPUT_0
#define GPIO_OUTPUT_PIN_SEL  (1ULL<<GPIO_OUTPUT_IO_0) 
/*
 * Let's say, GPIO_OUTPUT_IO_0=18, GPIO_OUTPUT_IO_1=19
 * In binary representation,
 * 1ULL<<GPIO_OUTPUT_IO_0 is equal to 0000000000000000000001000000000000000000 and
 * 1ULL<<GPIO_OUTPUT_IO_1 is equal to 0000000000000000000010000000000000000000
 * GPIO_OUTPUT_PIN_SEL                0000000000000000000011000000000000000000
 * */
#define GPIO_INPUT_IO_0     CONFIG_GPIO_INPUT_0
#define GPIO_INPUT_PIN_SEL  (1ULL<<GPIO_INPUT_IO_0)
/*
 * Let's say, GPIO_INPUT_IO_0=4, GPIO_INPUT_IO_1=5
 * In binary representation,
 * 1ULL<<GPIO_INPUT_IO_0 is equal to 0000000000000000000000000000000000010000 and
 * 1ULL<<GPIO_INPUT_IO_1 is equal to 0000000000000000000000000000000000100000
 * GPIO_INPUT_PIN_SEL                0000000000000000000000000000000000110000
 * */

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}


void app_main(void)
{
    //zero-initialize the config structure.
    gpio_config_t io_conf = {};


    //interrupt of rising edge
    io_conf.intr_type = GPIO_INTR_POSEDGE;
    //bit mask of the pins, use GPIO4/5 here
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
    //set as input mode
    io_conf.mode = GPIO_MODE_INPUT;
    //enable pull-up mode
    io_conf.pull_up_en = 1;
    gpio_config(&io_conf);

    //change gpio interrupt type for one pin
    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);


    //install gpio isr service
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    //hook isr handler for specific gpio pin
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);


    printf("Minimum free heap size: %"PRIu32" bytes\n", esp_get_minimum_free_heap_size());

    int cnt = 0;
    while (1) {
        printf("cnt: %d\n", cnt++);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
    }
}

烧录进板子中。

打开串口,效果如下

FhJ8e-jDGhkHLcbz-DHcBBrLty8k

测试场景3: wifi启用以及连接一个tcp服务器

 使用的官方的实例:

                                    esp-idf-v5.1.1\examples\wifi\smart_config

                                    esp-idf-v5.1.1\examples\protocols\sockets\tcp_client

 

Fo_d6LLHp-m8K4OxB5q0jaDHiKDCFpKL19mU9Ad3DDbtY_DbT5KryP2q

例程smart_config 使用了官方的 esptouch协议发送WiFi账号密码,还挺好用。手机下载官方的esptouch app,截图如下:

FnRdqgzwSvQVpe8eZkmW2ceoWjHz

强烈推荐感受一下,方便快捷。

实现的方案大概是使用无线协议的广播,通过app把账号密码广播出来,esp模块会接收此条广播,解析账号密码,并尝试连接账号密码。

------

下面来点一个ws2812b灯,使用官方的例程。

官方例程使用了rmt设备来驱动ws2812b。

路径如下:esp-idf-v5.1.1\examples\peripherals\rmt\led_strip。

点灯效果如下:

 代码讲解

   wifi连接路由器

初始化wifi
static void initialise_wifi(void)
{
    ESP_ERROR_CHECK(esp_netif_init());
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );

    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );

    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_start() );
}
wifi的事件回调
static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
;;;;
}

获取到WiFi连接到路由器后,创建tcp客户端
static void smartconfig_example_task(void * parm)
{
.......
    while (1) {
........................
			initTcp();
.....................
    }
}

连接到tcp服务器,创建读取服务器数据无限循环任务,读取到数据后截取第一个字符,判断字符数值并显示到led面板。

0-9 字符显示取模
char numstr[10][20]= {
	{0,1,2,3,4,7,8,11,12,15,16,17,18,19,0},
	{1,2,4,6,10,14,16,17,18,19,0},
	{0,1,2,3,7,8,9,10,11,12,16,17,18,19,0},
	{0,1,2,3,7,8,9,10,11,15,16,17,18,19,0},
	{0,2,4,6,8,9,10,11,14,18,0},
	{0,1,2,3,4,8,9,10,11,15,16,17,18,19,0},
	{0,1,2,3,4,8,9,10,11,12,15,16,17,18,19,0},
	{0,1,2,3,4,7,11,15,19,0},
	{0,1,2,3,4,7,8,9,10,11,12,15,16,17,18,19,0},
	{0,1,2,3,4,7,8,9,10,11,15,19,0}
};

读取tcp服务器数据,并解析
void vTask1( void *pvParameters )
{    /* 任务函数的主体一般都是无限循环 */
	int len =0;
	char rx_buffer[128];
	if(!sock) {
		ESP_LOGI(TAG, "Socket created, fail");
		goto endL;
	}
	for( ;; )
	{
		memset(rx_buffer,0,128);
		len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
		if (len < 0) {
			ESP_LOGE(TAG, "recv failed: errno %d", errno);
			break;
		}
		ESP_LOGI(TAG, "------------%s-----------------", rx_buffer);
		showNum(rx_buffer[0]);
		ESP_LOGI(TAG, "T1----------------\r\n");
		vTaskDelay(pdMS_TO_TICKS(2000));
    }
endL:
	vTaskDelete(NULL);
}

疑难杂症

   开发期间,遇到一些问题。

    烧写esp32,卡了好久。esp32能够正确进入download模式,就是接收不到esp32的数据,一直下载不成功。解决办法是,换了个串口工具。

    期间用了一款hub,然后板子不停的重启。后来查询才知道 esp32会检测失压异常,然后重启。解决办法是,扔掉hub,直接连接到电脑上。

  

 总结报告

 这次活动让我受益匪浅。电子森林的活动真的很用心。学习了很多知识,非常感谢电子森林提供的学习平台。比自己瞎头乱学有用的多,方向也定了,使劲去研究学习,时间久了,总能成大佬的。

希望电子森林出一款基于Linux的学习项目。linux能够设计的项目比较多,电子森林出一个项目范围,有个学习的方向,学习起来会高效的多。

再次感谢电子森林。

 

软硬件
电路图
附件下载
WS2812B-show.7z
原理图文件、PCB文件
led2812_strip.7z
ws2812灯效代码
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号