文章目录
- 一、宠物喂食器
- 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仿真。
感谢你的观看!