文章目录
- 一、宠物喂食器
- 1.题目要求
- 2.思路
- 2.1 OLED显示汉字
- 2.2 DS1302模块
- 2.3 液位传感器
- 2.4 压力传感器和步进电机驱动
- 3.仿真图
- 3.1 未仿真时
- 3.2 开始仿真,OLED初始界面显示实时时间
- 3.3 通过设置按键进入模式选择和喂食时间设置
- 3.4 进入喂食时间设置
- 3.5 设置好喂食时间,这里的时间指的是仿真内的时间,而非显现实时间
- 3.6 到达喂食时间,电机转动,模拟喂食
- 3.7 通过压力传感器模拟食物超过78g,大于设置阈值75g关闭电机
- 3.8 通过返回按键返回上一次的操作界面
- 3.9 通过液位模拟器模拟水位28%,低于30%阈值,开启水泵进行加水
- 3.10 通过液位模拟器模拟水位34%,高于30%阈值,关闭水泵
- 3.11 通过往上按键进入模式选择
- 3.12 模式选择界面
- 3.13 选择手动喂食模式,手动喂食模式下设置喂食时间,电机不转动(这里不演示)
- 4.仿真程序
- 4.1 程序说明
- 4.2 主函数
- 4.3 OLED显示函数
- 4.4 DS1302获取实时时间函数
- 二、总结
一、宠物喂食器
1.题目要求
基于STM32F103C8单片机做一个自动宠物喂食器,主要特点可以在自动喂食模式下通过按键设置喂食时间,待喂食时间达到,驱动步进电机转动模拟喂食;其中自动模式下,还有个液位传感器能够检测水位,低于一定水位需要开启水泵加水,而压力传感器则检测食物重量,达到一定重量,要关闭电机。而手动喂食模式电机不转动。
额外功能:DS1302时钟模块显示实时时间,OLED显示。
2.思路
2.1 OLED显示汉字
OLED要显示中文,这需要用到取模软件,如下所示:
参数设置为:
2.2 DS1302模块
这里晶振可以不画,仿真里面不影响
2.3 液位传感器
仿真里面没有液位传感器,这里用滑动变阻器代码,通过改变滑阻的阻值,输出不同的电压值来检测。而水泵的驱动则是NPN驱动继电器的电路,当PUMP为低电平时,继电器不闭合,水泵不工作,当PUMP为高电平时,继电器闭合,水泵工作。
2.4 压力传感器和步进电机驱动
这里的压力传感器用的是mpx4115,步进电机用ULN2003芯片驱动。
3.仿真图
3.1 未仿真时
3.2 开始仿真,OLED初始界面显示实时时间
3.3 通过设置按键进入模式选择和喂食时间设置
3.4 进入喂食时间设置
3.5 设置好喂食时间,这里的时间指的是仿真内的时间,而非显现实时间
3.6 到达喂食时间,电机转动,模拟喂食
3.7 通过压力传感器模拟食物超过78g,大于设置阈值75g关闭电机
3.8 通过返回按键返回上一次的操作界面
3.9 通过液位模拟器模拟水位28%,低于30%阈值,开启水泵进行加水
3.10 通过液位模拟器模拟水位34%,高于30%阈值,关闭水泵
3.11 通过往上按键进入模式选择
3.12 模式选择界面
3.13 选择手动喂食模式,手动喂食模式下设置喂食时间,电机不转动(这里不演示)
4.仿真程序
4.1 程序说明
主控芯片:STM32F103C8
HICK:64MHZ
Systick: 1ms
测试Led:PC13
模拟wifi模块(Uart1):9600(PA9:tx1,PA10:rx1)
OLED显示屏:SCL(PB10),SDA(PB11)
液位传感器:FLUID(PA0)
压力传感器:STRESS(PA1)
水泵:PUMP(PB0)
时钟DS1302:
RST(PB7)
SCLK(PB5)
IO(PB6)
KEY按键:
KEY1(PA2)
KEY2(PA3)
KEY3(PA4)
KEY4(PA5)
KEY5(PA6)
KEY6(PA7)
KEY7(PA8)
MOTOR电机:
IN1(PB12)
IN2(PB13)
IN3(PB14)
IN4(PB15)
4.2 主函数
/* Includes ------------------------------------------------------------------*/
#include "Drv_UserSystem.h"
/**
* @brief main function.
* @param none
* @retval none
*/
int main(void)
{
UserSystemInit();//用户配置初始化
while (1)
{
if (stSysTime.flg._10ms + TEN_MILLISECOND < Time_millis()) //10ms
{
stSysTime.flg._10ms = Time_millis();
Key_Scan();//按键扫描
}
if (stSysTime.flg._50ms + FIFTY_MILLISECOND < Time_millis()) //50ms
{
stSysTime.flg._50ms = Time_millis();
OLED_Handel();//OLED显示
}
if (stSysTime.flg._100ms + BEST_MILLISECOND < Time_millis()) //100ms
{
stSysTime.flg._100ms = Time_millis();
Receive_data_Handel();//数据接收判断
Led_Flicker();//灯光闪烁
ADC_Scan(); //液体/压力检测
IWDG_ReloadCounter();//清开门狗
}
if (stSysTime.flg._1s + THOUSAND_MILLISECOND < Time_millis()) //1s
{
stSysTime.flg._1s = Time_millis();
Pet_feeding_countdown();
Read_RTC();//DS1302读取当前时间
}
}
}
4.3 OLED显示函数
/*******************************************************************************
* 函数名:OLED_Handel
* 描述 :OLED显示
* 输入 :void
* 输出 :void
* 调用 :内部调用
* 备注 :50ms
*******************************************************************************/
void OLED_Handel(void)
{
if(Display_interface == 0)
{
if(Back_clear_flag)
{
Back_clear_flag = 0;
OLED_Clear();
}
OLED_ShowNum(1,1,Year,2);
OLED_Show_Character(1,2,23,16);//年
OLED_ShowNum(1,5,Month,2);
OLED_Show_Character(1,4,24,16);//月
OLED_ShowNum(1,9,Day,2);
OLED_Show_Character(1,6,25,16);//日
OLED_ShowNum(2,1,Hour,2);
OLED_Show_Character(2,2,26,16);//时
OLED_ShowNum(2,5,Minute,2);
OLED_Show_Character(2,4,27,16);//分
OLED_ShowNum(2,9,Second,2);
OLED_Show_Character(2,6,28,16);//秒
OLED_Show_Character(3,1,29,16);//星
OLED_Show_Character(3,2,30,16);//期
OLED_ShowNum(3,5,Week,1);
}
else if(Display_interface == 1)
{
if(Back_clear_flag)
{
Back_clear_flag = 0;
OLED_Clear();
}
OLED_Show_Character(1,1,5,16);//模
OLED_Show_Character(1,2,6,16);//式
OLED_Show_Character(1,3,7,16);//选
OLED_Show_Character(1,4,8,16);//择
OLED_Show_Character(2,1,11,16);//喂
OLED_Show_Character(2,2,12,16);//食
OLED_Show_Character(2,3,13,16);//时
OLED_Show_Character(2,4,14,16);//间
if(key_Line == 1)
{
if(clear_flag)
{
clear_flag = 0;
OLED_Part_Clear(2,13,16);
}
OLED_Show_Character(1,8,21,16);//←
}
else if(key_Line == 0)
{
if(clear_flag)
{
clear_flag = 0;
OLED_Part_Clear(1,13,16);
}
OLED_Show_Character(2,8,21,16);//←
}
}
else if(Display_interface == 2)//模式选择
{
if(Back_clear_flag)
{
Back_clear_flag = 0;
OLED_Clear();
}
OLED_Show_Character(1,1,19,16);//自
OLED_Show_Character(1,2,20,16);//动
OLED_Show_Character(1,3,17,16);//喂
OLED_Show_Character(1,4,18,16);//食
OLED_Show_Character(2,1,15,16);//手
OLED_Show_Character(2,2,16,16);//动
OLED_Show_Character(2,3,17,16);//喂
OLED_Show_Character(2,4,18,16);//食
if(key_Line == 1)
{
if(clear_flag)
{
clear_flag = 0;
OLED_Part_Clear(2,13,16);
}
OLED_Show_Character(1,8,21,16);//←
}
else if(key_Line == 0)
{
if(clear_flag)
{
clear_flag = 0;
OLED_Part_Clear(1,13,16);
}
OLED_Show_Character(2,8,21,16);//←
}
}
else if(Display_interface == 3)//喂食时间设置
{
if(Back_clear_flag)
{
Back_clear_flag = 0;
OLED_Clear();
}
OLED_ShowNum(2,3,Minute_tens,1);
OLED_ShowNum(2,4,Minute_ones,1);
OLED_ShowString(2,5,":");//:
OLED_ShowNum(2,6,Second_tens,1);
OLED_ShowNum(2,7,Second_ones,1);
if(key_Column == 0)
{
if(clear_flag)
{
clear_flag = 0;
OLED_Part_Clear(3,1,16);
}
OLED_ShowString(3,7,"^");//^
}
else if(key_Column == 1)
{
if(clear_flag)
{
clear_flag = 0;
OLED_Part_Clear(3,1,16);
}
OLED_ShowString(3,6,"^");//^
}
else if(key_Column == 2)
{
if(clear_flag)
{
clear_flag = 0;
OLED_Part_Clear(3,1,16);
}
OLED_ShowString(3,4,"^");//^
}
else if(key_Column == 3)
{
if(clear_flag)
{
clear_flag = 0;
OLED_Part_Clear(3,1,16);
}
OLED_ShowString(3,3,"^");//^
}
}
}
4.4 DS1302获取实时时间函数
/*******************************************************************************
* 函数名:Read_RTC
* 描述 :读RTC
* 输入 :void
* 输出 :void
* 调用 :内部调用
* 备注 :
*******************************************************************************/
void Read_RTC(void)
{
static uint8_t time_count = 0;
// 获取时间数据
Second = Read_Clock(0X81);
Minute = Read_Clock(0X83);
Hour = Read_Clock(0X85);
Day = Read_Clock(0X87);
Month = Read_Clock(0X89);
Week = Read_Clock(0X8B);
Week = Week - 1;
Year = Read_Clock(0X8D);
if(++time_count > 2)
{
time_count = 0;
// 输出时间数据
printf("时间:%d年%d月%d日 %d时%d分%d秒 星期%d \r\n", Year, Month, Day, Hour, Minute, Second, Week);
}
}
二、总结
今天主要讲了基于STM32的自动宠物喂食器的Proteus仿真。
感谢你的观看!