宠物喂食器的设计-基于涂鸦三明治三件套
宠物喂食器的设计-基于涂鸦三明治三件套
本文章允许涂鸦智能转载使用
去年疫情突发,全国很多地区封城,封小区,让原本备受宠爱的主子与铲屎官异地分离。遇到有准备的铲屎官,主子们还能勉强度日,那些没有准备的主子只能靠吃猫砂,吃垃圾度日,甚至有些小可怜被活活饿死。
疫情缓解后,为了避免这样的事件再次发生,也为了解放懒惰的铲屎官,于是自动猫砂盆,自动喂食器,自动喂水器的需求不断提升。有数据显示,疫情后自动猫砂盆增长879%,自动喂水器增长120%,自动喂食器增长也超一倍。毕竟主子是家里的老大,要吃好喝好还要拉好。
此次DIY自动投食器由涂鸦智能开展的【宠物喂食器】实战营策划,并提供了涂鸦三明治开发套件,其中包括:
涂鸦三明治 Wi-Fi MCU 通信板1
涂鸦三明治H桥直流电机驱动功能板1
涂鸦三明治直流供电电源板*1。
除此之外,用户还需要自行准备MCU控制板和电机等组件,该WiFi模组出厂默认为透传模式,只负责数据转发,不负责数据处理,所以我们只需要准备MCU用于数据处理和外设控制。
涂鸦智能平台
1.前往涂鸦智能开发平台
(https://auth.tuya.com/register_source=7b811ac2e872ccb62376ba4dfe0568eb)注册开发者账号
2.在涂鸦loT平台创建产品
3.在小家电品类里面找到【宠物喂食器】
4.使用MCU SDK方案,完善产品信息
5.产品创建后添加标准功能
6.硬件开发选项
以上步骤更加具体配置可参考涂鸦IOT平台产品创建流程(https://shimo.im/docs/HvHRgTtjUDYIvLlA/read)产品创建完成后下载开发资料,建议全部下载,其中MCU SDK的内容会根据你所选择的标准功能不同而不同,为了方便可在选择功能时尽可能多的考虑到需要配置的功能,当然,即使你一个不选,SDK也开放了各个功能的函数,只是被屏蔽,可自行放开。
功能调试
MCU对接方案通信原理图
1.WIFI模组调试
打开上一步最终下载的文件如图,接着我们打开涂鸦调试助手
将WiFi的通信板的串口1接到usb-ttl上,接到电脑,一定是串口1,串口0是查看模组本身的logo的,打开涂鸦调试助手。选择MCU模拟,此时调试助手就相当于是MCU,可以与WiFi模组通信,可用此来调试WiFi模组。选择好串口,波特率默认9600.功能点调试文件选择之前下载的json文件。初始化配置保持默认,点击开始调试。如收到以下数据说明模组与助手连接正常,可以开始调试。
此时我们下载涂鸦智能APP,注册后选择添加设备,在小家电里面找到宠物喂食器,选择2.4G的WiFi网络。输入密码。点击下一步
此时在模组调试助手点击smart配网,手机点击下一步
配网成功后会在手机APP和调试助手同时看到相应信息。连接成功后会定时发送心跳包保持连接。
至此WiFi模组配网完成,改配网信息会保存在WiFi模组内部,下次上电会自动连接该网络。如果更换网络环境需要重置后再次配网。此时可在DP CMD里面测试相关DP点的数据上报,观察有无数据的上报下发。
2.MCU调试
WiFi模组调试完成之后我们需要调试我们的主控,也就是MCU,在我这里就是STM32F103ZET6。在进行MCU调试之前我们需要先进行SDK的移植,将之前下载的SDK移植到我们的STM32项目中。
1.工程搭建
本文实在串口驱动实验的基础上搭建的,因为后面需要用到串口;
usart.h
usart.c
#include "sys.h" #include "usart.h" #include "mcu_api.h" #include "protocol.h" #include "system.h" #include "wifi.h" // //如果使用ucos,则包括下面的头文件即可. #if SYSTEM_SUPPORT_OS #include "includes.h" //ucos 使用 #endif#if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x = x; } //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0);//循环发送,直到发送完毕 USART1->DR = (u8) ch; return ch; } #endif #if EN_USART1_RX //如果使能了接收 //串口1中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误 u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART_RX_STA=0; //接收状态标记 void uart_init(u32 bound) {//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式USART_Init(USART1, &USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART1, ENABLE); //使能串口1 }void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) {/* 发送一个字节数据到USART */USART_SendData(pUSARTx,ch);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); }void USART1_IRQHandler(void) {uint8_t ucTemp;if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET){ ucTemp = USART_ReceiveData(USART1);uart_receive_input(ucTemp); } USART_ClearFlag(USART1,USART_FLAG_RXNE); }#endif写一个发送单字节函数,此函数必须,用于向WiFi模组发送数据。
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) {/* 发送一个字节数据到USART */USART_SendData(pUSARTx,ch);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); }2.移植SDK
基础工程搭建完成后将SDK放入工程,记得在keil中添加文件路径。
这个时候要是编译,会疯狂报错,主要是官方方便我们修改。
在下图的函数中填入上面写的串口单字节发送函数
3.确认protocol.h的相关宏定义
1.定义 PID。PRODUCT_KEY 为产品 PID 宏定义。PID 即产品 ID, 为每个产品的唯一标识,可在 IoT 平台的产品详情页面获取。
2.定义 Wi-Fi 模块工作模式。CONFIG_MODE 为配网方式,支持默认模式(AP 和 SmartConfig 互相切换)、安全模式、防误触模式。建议选择防误触模式。
3.定义模块工作方式(必选)
如果配网按键和 LED 接在 MCU 端,即选择模块和 MCU 配合处理工作模式(常用),保持 WIFI_CONTROL_SELF_MODE 宏定义处于被注释状态。
如果配网指示灯和按键是接在 Wi-Fi 模块上的,即选择模块自处理工作模式,开启 WIFI_CONTROL_SELF_MODE 宏定义,然后根据实际的硬件连接,将指示灯和按键所连接的 GPIO 脚位填入下面两个宏定义。
#ifdef WIFI_CONTROL_SELF_MODE //模块自处理#define WF_STATE_KEY 14 //Wi-Fi 模块状态指示按键,请根据实际 GPIO 管脚设置#define WF_RESERT_KEY 0 //Wi-Fi 模块重置按键,请根据实际 GPIO 管脚设置 #endif以上三点较为重要,其他可自行安排,都有相关介绍。
移植protocol.c文件及函数调用
走到这一步,SDK移植已经完成了,接下来将单片机的串口街道电脑进行调试。此时调试助手选择模组模拟。同时我们在protocol.c文件中将all_data_update() 函数中的所有DP点上传函数打开,默认为0。
此时MCU接到调试助手,打开串口,添加DP点文件,启动调试,便会看到所有DP点的上报
进入DP CMD添加一个开启小夜灯的指令并下发,便可看到模组成功接收,说明MCU的SDK移植成功。
一个完整的自动喂食器的MCU工程便已搭建完成,后续我们只需要解析wifi模组下发的消息,并进行相应的外设控制便可。当然,每次MCU完成动作后也要上传数据给模组。完成服务器和手机APP端的数据刷新。
3.相关功能完善
1.一键配网功能
配网有两种模式AP配网和smart配网,这里仅介绍smart类型。
配网指令有两个函数可以实现:mcu_reset_wifi() 和 mcu_set_wifi_mode()。通常在按键触发配网后,在按键处理函数中调用。mcu_reset_wifi()调用后复位 Wi-Fi 模组,复位后之前的配网信息全部清除。mcu_reset_wifi() 每调用一次,Wi-Fi 模块即在 AP 和 Smart 之间切换一次配网模式。
mcu_set_wifi_mode()参数为SMART_CONFIG和AP_CONFIG。调用后清除配网信息,进入 Smart 模式或者 AP 模式。值了在按键KEY0中断函数中调用 mcu_get_wifi_work_state() 函数主动获取 Wi-Fi 状态。根据 Wi-Fi 状态,写入相应闪灯的模式。通过switch()判断进入何种状态,状态可选参数如下:
exti.c
在外部中断函数0里面添加了mcu_reset_wifi(),复位模组,清除全部配网信息,然后调用mcu_set_wifi_mode()函数,参数添加SMART_CONFIG进入smart模式。在这用TFTLCD屏幕显示是否进入smart配网模式,还可显示其他状态。
现在将MCU与模组通过串口1连接,注意TX与RX反接并共地。按下按键,LED快闪,打开手机APP进行配网,当wifi配置完成灯会熄灭,连接上路由器之后灯会重新点亮,并保持常亮。此过程本人已测试无问题,但是过程比较长不适合贴图,会在视频中展示。
2.添加小夜灯等类似功能
配网完成了,那么怎么执行功能呢?在protocol.c中dp_download_handle()函数可以处理下发的数据。在此函数中会对下发的指令进行归类,我们找到小夜灯的处理,这里可以进行小夜灯指令的处理,处理完成之后会上报数据,用于更新APP数据。我们跳转进dp_download_light_handle()函数,此函数中有具体的处理,针对不同的开或关会进入不同的if函数。我们在对LED的端口初始化后便可以将开关灯填入。达到不同下发指令实现开关灯。开关功能类似,不赘述。
3. 添加手动喂食执行功能
这里没有使用涂鸦提供的H桥驱动板,大家要是想要用,直接上一个12V的减速电机,每分钟12转,驱动力大,速度慢,易于控制。将电机接到驱动板的U和V接线柱上,控制口PWM1和PWM2接到单片机PA2和PA3。给PA2和PA3不同的高低电平就可以实现正反转,因为电机本身速度比较慢,就不用软件进行控制速度了。而且因为场景的关系,不用控制正反两个反向,只控制正转和停止。
我在这里用的就不是涂鸦提供的了,步进电机:28BYJ-48,驱动电路:ULN2003芯片的驱动板,
motor.c
编写控制函数,参数为投喂量,通过转动时间来控制投喂量,延时时间需要与宠物的饭盒出粮口搭配,不同出粮口修改延时基数。
随后在dp_download_quick_feed_handle()函数中执行该函数,参数由mcu_get_dp_download_value()函数提供,该函数会提取手机下发的命令。
最后我还加了语音控制功能,下面的文件里有这个工程的全部文件,包括语音模块的设计,就是类似于小度小度那样的智能管家,这里就不在一一介绍了,大家自行下载,看我的演示视频吧。
文件地址:https://download.csdn.net/download/kekebb/16207490
总结
以上是生活随笔为你收集整理的宠物喂食器的设计-基于涂鸦三明治三件套的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 360天擎卸载密码_Windows安装和
- 下一篇: SIKI学院lua热更新技术