基于涂鸦智能的宠物喂食器
- 一、开发计划
- 二、涂鸦三明治开发套件
- 涂鸦三明治 Wi-Fi MCU 通信板+喇叭
- 涂鸦三明治H桥直流电机驱动功能板
- 涂鸦三明治直流供电电源板
- MCU主控板
- 三、产品开发
- 1、产品创建
- 进入涂鸦IoT平台创建产品
- 选择对应的功能点和设备面板
- 下载SDK
- 2、MCU SDK移植
- 对串口寄存器的数据读取
- 将数据通过串口发送
- 在main.c中加入函数调用
- 3、完善DP点功能
- 所有DP点的上报
- 小夜灯下发功能
- 温湿度数据上报
- 余粮重量
- OLED显示
- 电机部分
- 手动喂食和自动喂食
- 四、过程及结果展示
一、开发计划
请看github:https://github.com/594642987/Tuya-Feed
二、涂鸦三明治开发套件
涂鸦三明治 Wi-Fi MCU 通信板+喇叭
涂鸦三明治H桥直流电机驱动功能板
涂鸦三明治直流供电电源板
MCU主控板
利用以前做的STM32F030C8T6最小系统板作为主控板(图中WBR3已坏)。
三、产品开发
1、产品创建
进入涂鸦IoT平台创建产品
涂鸦IoT平台地址:https://iot.tuya.com/
在涂鸦IOT平台找到 创建产品 -> 小家电 -> 宠物喂食器由于这里是VWXR2模组,所以通讯协议应选择Wi-Fi
选择对应的功能点和设备面板
下载SDK
2、MCU SDK移植
下载的MCU_SDK里面有以下文件
对串口寄存器的数据读取
在stm32f0xx_it.c中对在USART1_IRQHandler中加入以下代码(需要引入头文件mcu_api.h)
void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 */unsigned char value;/* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 */if((USART1->ISR & UART_FLAG_RXNE) != 0){value = USART1->RDR;extern void uart_receive_input(unsigned char value);uart_receive_input(value);}/* USER CODE END USART1_IRQn 1 */
}
ISR是USART的中断状态寄存器,UART_FLAG_RXNE(为1代表USART的读取寄存器不为空),也就是说USART接受到了数据。
RDR是USART的接收寄存器,从RDR中取出数据赋值到value
uart_receive_input(value)在mcu_api.c,将串口接受到的数据交由MCU_SDK处理
不同的芯片的中断状态寄存器和接收寄存器的名称不一样,具体需要看官方的代码。(比如航顺的中断状态寄存器是SR,接收寄存器和发送寄存器共用DR)
将数据通过串口发送
在protocol.c中找到下列函数(需要引入头文件#include “usart.h”)
/*** @brief 串口发送数据* @param[in] {value} 串口要发送的1字节数据* @return Null*/
void uart_transmit_output(unsigned char value)
{//#error "请将MCU串口发送函数填入该函数,并删除该行"HAL_UART_Transmit(&huart1, &value, 1, 1000);
/*//Example:extern void Uart_PutChar(unsigned char value);Uart_PutChar(value); //串口发送函数
*/
}
这里我们调用STM32的HAL库HAL_UART_Transmit,传入的参数含义
HAL_UART_Transmit(串口名,数据的首地址(指针),数据个数,发送超时时间)
在main.c中加入函数调用
然后可以将上述函数中的#error删掉了,基本上MCU与模组的串口通信基本完成了
3、完善DP点功能
所有DP点的上报
这里要先处理all_data_update的函数,看个人习惯,这里不打算使用
小夜灯下发功能
static unsigned char dp_download_light_handle(const unsigned char value[], unsigned short length)
{//示例:当前DP类型为BOOLunsigned char ret;//0:关/1:开unsigned char light;extern unsigned char Light_Switch;light = mcu_get_dp_download_bool(value,length);if(light == 0) {//开关关Light_Switch = 0;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);}else {//开关开Light_Switch = 1;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);}//处理完DP数据后应有反馈ret = mcu_dp_bool_update(DPID_LIGHT,light);if(ret == SUCCESS)return SUCCESS;elsereturn ERROR;
}
温湿度数据上报
将SHT30获得的数据上报
void SHT30_Update(float temperature, float humidity){if(count == 0){mcu_dp_value_update(DPID_TEMPERATURE, (uint32_t) (temperature));mcu_dp_value_update(DPID_HUMIDITY, (uint32_t) (humidity));}count++;count = count%Limit;
}
余粮重量
在HX711变化大于一定值(10)时才上报余粮重量值,否则在经过Cnt_Limit次循环后更新一下重量。
#define GapValue 213
#define Cnt_Limit 200 //通过while(1)循环次数来定时上报uint32_t HX711_Buffer;
uint32_t Weight_Maopi=0;
int32_t Pre_Weight = 0;
int32_t Weight=0;
int Cnt = 0;
void Weight_Update(void){Pre_Weight = Weight;mcu_dp_value_update(DPID_WEIGHT,(unsigned long)Weight);
}
int My_abs(int k){return k>=0? k:-k;
}
void Weight_Handle(void){if(My_abs((int)(Weight-Pre_Weight))>=10){Weight_Update();Cnt = 0;}else{Cnt++;if(Cnt>=Cnt_Limit){Weight_Update();Cnt = 0;}}
}
OLED显示
将温湿度、重量字符串进行拼接然后在OLED上显示
sprintf(ch2,"Weight = %3d(g)",(int)Weight);strcat(ch,ch2);//OLED_Clearrow(0);OLED_ShowString(0, 0, ch, strlen(ch));
电机部分
由于测试的时候不小心反接了电源加上数据线断了,只能先鸽着。
下面是电机的代码。//没有经过测试需要后面细调整
#include "motor.h"
/*----------------------------------------------------------------
IN1 ---- PB10
IN2 ---- PB11
IN3 ---- PB12
IN4 ---- PB13GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13
*/
void Motorcw(int time){HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);HAL_Delay(time);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);HAL_Delay(time);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);HAL_Delay(time);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);HAL_Delay(time);
}void Motorccw(int time){HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);HAL_Delay(time);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);HAL_Delay(time);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);HAL_Delay(time);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);HAL_Delay(time);
}void MotorStop(void){HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
}void MotorHandle(int sign, int time){unsigned char speed = 25;while(speed>=4){for(int i=0; i<10; i++){if(sign) Motorcw(time);else Motorccw(time);}speed--;}MotorStop();
}
手动喂食和自动喂食
static unsigned char dp_download_quick_feed_handle(const unsigned char value[], unsigned short length)
{//示例:当前DP类型为BOOLunsigned char ret;//0:关/1:开unsigned char quick_feed;quick_feed = mcu_get_dp_download_bool(value,length);if(quick_feed == 0) {//开关关}else {//开关开MotorHandle(1,10);//slow_feed就是将10改成30}//处理完DP数据后应有反馈ret = mcu_dp_bool_update(DPID_QUICK_FEED,quick_feed);if(ret == SUCCESS)return SUCCESS;elsereturn ERROR;
}
四、过程及结果展示
哔哩哔哩:https://www.bilibili.com/video/BV1TA411K7Gk/
本文章允许涂鸦智能转载使用