基于涂鸦智能的宠物喂食器

一、开发计划

请看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类型为BOOL
    unsigned 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;
    else
        return 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 ---- PB13

GPIO_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类型为BOOL
    unsigned 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;
    else
        return ERROR;
}

四、过程及结果展示

哔哩哔哩:https://www.bilibili.com/video/BV1TA411K7Gk/

本文章允许涂鸦智能转载使用

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jack_Mask

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值