智能热水器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

641 lines
15 KiB

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "wifi.h"
#include "lcd1602.h"
#include "adc.h"
#include "timer.h"
#include "string.h"
#include "ds18b20.h"
#include "Lcd_Driver.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DS1302.h"
#include "oled.h"
#include "key.h"
// 0 - 加热模式 (手动启动/设定时间自动启动)
// 1 - 杀菌模式
// 2 - 保温模式
// 用户数据的结构体
struct UserInfo{
float water_temp;
int now_tager_temp;
int water_target_temp;
int model; // 模块 0-加热模式 1-杀菌模式 2-保温模式
struct timing SetTimer; // 设定时间
u8 TimerFlag;
u8 HotFlag;
u8 Heating_state;
u8 Water_pump;
float water_level;
u16 setLevel;
};
struct RegulatoryTasks
{
int hour;
int min;
int sec;
u8 flag;
float temp;
};
struct UserInfo userInfo;
struct timing nowTime;
u8 Settime[6]={0x22,0x03,0x27,0x22,0x34,0x00}; // 设置时间 22年 03月 27日 22:34:00
int setModel = 0;
int change = 0;
// 函数声明
int getValue(void);
int getFirstIndexes(const char str);
int getLastIndexes(const char str);
u8 getTimerResult(void);
struct timing getTimer(void);
void Sys_Init(void);
void DisplayTask(void);
void TaskProcessing(void);
void DataProcessing(void);
/**
* @description: main函数
* @param {*}
* @return {*}
*/
int main(void)
{
Sys_Init();
delay_ms(1000);
BEEP = 1;
while(1)
{
TaskProcessing();
DataProcessing();
DS1302_Readtime();
DisplayTask();
delay_ms(200);
}
}
/**
* @description: 系统初始化
* @param {*}
* @return {*}
*/
void Sys_Init(void)
{
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
Model_Init();
LED_Init();
DS18B20_Init();
Adc_Init(); // 水位模块
OLED_Init();
Key4x4_GPIO_Config();
DS1302_init(Settime);
DS1302_SetTime(Settime);
OLED_Clear();
}
/**
* @description: 显示
* @param {*}
* @return {*}
*/
void DisplayTask(void)
{
char str[30];
if(setModel == 0){
sprintf(str,"%2d-%2d %2d:%2d:%2d", nowTime.mon, nowTime.day, nowTime.hour, nowTime.min, nowTime.sec);
OLED_ShowString(0, 0, str, 16);
sprintf(str,"%0.2fC %dC %0.2fcm %d", userInfo.water_temp, userInfo.now_tager_temp,userInfo.water_level, userInfo.setLevel);
OLED_ShowString(0, 2, str, 16);
}else{
sprintf(str,"%2dC Level:%d %d", userInfo.water_target_temp,userInfo.setLevel, change);
OLED_ShowString(0, 0, str, 16);
sprintf(str,"%2d-%2d-%2d %2d:%2d:%2d T:%d,H:%d", userInfo.SetTimer.year,userInfo.SetTimer.mon, userInfo.SetTimer.day, userInfo.SetTimer.hour, userInfo.SetTimer.min, userInfo.SetTimer.sec, userInfo.TimerFlag, userInfo.HotFlag);
OLED_ShowString(0, 2, str, 16);
}
};
/**
* @description: 报警
* @param {*}
* @return {*}
*/
void Warning(){
BEEP = 0;
delay_ms(100);
BEEP = 1;
}
/**
* @description: 加热水 目标温度
* @param {*}
* @return {*}
*/
int HeatWaterTask(int target_temp)
{
static struct RegulatoryTasks task;
int result;
userInfo.now_tager_temp = target_temp;
// 定时加热开启后的监管任务,如5分钟内温度变化在2摄氏度内,则中断加热
if(task.flag && userInfo.Heating_state){
if(task.hour == nowTime.hour && task.min == nowTime.min && task.sec == nowTime.sec){
// 温度无变化,关闭加热
if(fabs(task.temp - userInfo.water_temp) <= 2){
HOT = 0;
task.flag = 0;
printf("No change in temperature, Turn off heating\r\n");
}
}
}
// 时间生效时为自动模式,否则为手动模式
if(userInfo.TimerFlag){
result = getTimerResult();
if(result && task.flag == 0){
printf("Time to heat up!\r\n");
Warning();
HOT = 1;
task.flag = 1;
task.hour = nowTime.hour;
task.min = nowTime.min;
task.sec = nowTime.sec;
task.temp = userInfo.water_temp;
// 过五分钟
task.min += 1;
if(task.min > 59){
task.min = task.min - 60;
task.hour += 1;
if(task.hour > 23) task.hour = task.hour - 24;
}
}else if(result == 0 && task.flag == 0){ // 时间未到默认关闭
HOT = 0;
}
else if(!userInfo.Heating_state) task.flag = 0;
}else{
task.flag = 0;
// 时间不生效时默认由HotFlag控制是否加热
HOT = userInfo.HotFlag;
}
// 判断水位过低、或温度达到
if(userInfo.water_level < 1 || userInfo.water_temp == target_temp) {
HOT = 0;
task.flag = 0;
if(userInfo.water_level < 1) return 1;
if(userInfo.water_temp >= target_temp) return 2;
}
return 0;
}
/**
* @description: 更改水位 0-低水位 1-中水位 2-高水位
* @param {*}
* @return {*}
*/
void ChageWaterLevelTask()
{
double WaterH = 2, WaterL = 1.0;
if(userInfo.setLevel == 1) WaterH = 3, WaterL = 2;
else if(userInfo.setLevel == 2) WaterH = 4, WaterL = 3;
// 加水
if(userInfo.water_level < WaterL){
// 启动水泵
MOTOR = 1;
}else if(userInfo.water_level >= WaterL && userInfo.water_level < WaterH){
// 关闭水泵
MOTOR = 0;
}else if(userInfo.water_level > WaterH){
// 黄灯闪烁
LED_YELLOW = 1;
delay_ms(100);
LED_YELLOW = 0;
MOTOR = 0;
}
if(userInfo.water_level < 1 && userInfo.Heating_state){
LED_RED = 1;
BEEP = 0;
delay_ms(100);
LED_RED = 0;
BEEP = 1;
}
}
/**
* @description: 加热模式 (控制水位、自动模式(定时加热水、不可手动开关热水功能)、手动模块(手动开关热水功能))
* @param {*}
* @return {*}
*/
void HeatingModeTask()
{
// 温度达到进入保温模式
if(HeatWaterTask(userInfo.water_target_temp) == 2){
printf("The temperature reached:%d", userInfo.water_target_temp);
BEEP = 0;
delay_ms(100);
BEEP = 1;
userInfo.model = 2;
}
}
/**
* @description: 杀菌模式 (加热到80度, 在降温到设定的温度)
* @param {*}
* @return {*}
*/
void SterilizationModeTask()
{
static u8 flag = 0;
if(flag == 0){
if(HeatWaterTask(30) == 2){
printf("The temperature reached:%d", 80);
BEEP = 0;
delay_ms(100);
BEEP = 1;
userInfo.now_tager_temp = userInfo.water_target_temp;
userInfo.model = 2;
flag = 1;
}
}else{
// 关闭加热
userInfo.TimerFlag = 0;
userInfo.HotFlag = 0;
// 温度达到进入保温模式
if(HeatWaterTask(userInfo.water_target_temp) == 2) {
printf("The temperature reached:%d", userInfo.water_target_temp);
BEEP = 0;
delay_ms(100);
BEEP = 1;
userInfo.model = 2;
}
}
}
/**
* @description: 保温模式
* @param {*}
* @return {*}
*/
void HeatPreservationModetask()
{
if(userInfo.water_temp <= (userInfo.water_target_temp - 1)) {
userInfo.TimerFlag = 0;
userInfo.HotFlag = 1;
// 切换为加热模式
userInfo.model = 0;
}
}
/**
* @description: 改变值
* @param {int} Value
* @return {*}
*/
void ChangeValue(int Value){
if(setModel != 1) return;
switch(change){
case 0:
if(userInfo.water_target_temp < 10){
userInfo.water_target_temp = userInfo.water_target_temp * 10 + Value;
}
break;
case 1:
userInfo.setLevel = Value;
if(userInfo.setLevel >= 3) userInfo.setLevel = 2;
break;
case 2:
if(userInfo.SetTimer.year < 10){
userInfo.SetTimer.year = userInfo.SetTimer.year * 10 + Value;
}
break;
case 3:
if(userInfo.SetTimer.mon < 10){
userInfo.SetTimer.mon = userInfo.SetTimer.mon * 10 + Value;
if(userInfo.SetTimer.mon > 12) userInfo.SetTimer.mon = 12;
}
break;
case 4:
if(userInfo.SetTimer.day < 10){
userInfo.SetTimer.day = userInfo.SetTimer.day* 10 + Value;
if(userInfo.SetTimer.day > 31) userInfo.SetTimer.day = 31;
}
break;
case 5:
if(userInfo.SetTimer.hour < 10){
userInfo.SetTimer.hour = userInfo.SetTimer.hour * 10 + Value;
if(userInfo.SetTimer.hour > 23) userInfo.SetTimer.hour = 23;
}
break;
case 6:
if(userInfo.SetTimer.min < 10){
userInfo.SetTimer.min = userInfo.SetTimer.min * 10 + Value;
if(userInfo.SetTimer.min > 59) userInfo.SetTimer.min = 59;
}
break;
case 7:
if(userInfo.SetTimer.sec < 10){
userInfo.SetTimer.sec = userInfo.SetTimer.sec * 10 + Value;
if(userInfo.SetTimer.sec > 59) userInfo.SetTimer.sec = 59;
}
break;
}
}
/**
* @description: 删除键 *
* @param {*}
* @return {*}
*/
void DeleteValue()
{
if(setModel != 1) return;
switch(change){
case 0:
userInfo.setLevel /= 10;
break;
case 1:
userInfo.water_target_temp /= 10;
break;
case 2:
userInfo.SetTimer.year /= 10;
break;
case 3:
userInfo.SetTimer.mon /= 10;
break;
case 4:
userInfo.SetTimer.day /= 10;
break;
case 5:
userInfo.SetTimer.hour /= 10;
break;
case 6:
userInfo.SetTimer.min /= 10;
break;
case 7:
userInfo.SetTimer.sec /= 10;
break;
}
}
/**
* @description: 按键处理
* @param {*}
* @return {*}
*/
void keyHandling(){
int key = 16;
key = Key_Scan();
switch (key)
{
case 12:
if(setModel == 0) setModel = 1;
else setModel = 0;
OLED_Clear();
break;
case 13:
change++;
if(change >= 8) change = 0;
break;
case 14:
if(userInfo.HotFlag == 0) userInfo.HotFlag = 1;
else userInfo.HotFlag = 0;
break;
case 15:
if(userInfo.TimerFlag == 0) userInfo.TimerFlag = 1;
else userInfo.TimerFlag = 0;
break;
case 11:
DeleteValue();
break;
default:
if(!setModel || key == 16) break;
if(key < 10) ChangeValue(key);
break;
}
}
/**
* @description: 任务处理
* @param {*}
* @return {*}
*/
void TaskProcessing()
{
float temp;
u16 num;
keyHandling();
if(setModel == 0){
// 获取数据
// 获取水温
userInfo.water_temp = DS18B20_Get_Temp() / 10;
num = Get_Adc_Average(ADC_Channel_1,10);
temp = (float)num * (4.0 / 4096); // 以最高水位10cm来算
userInfo.water_level = temp;
// 获取加热棒状态
userInfo.Heating_state = HOT;
// 处于加热模式 定时生效
if(userInfo.model == 0) HeatingModeTask();
else if(userInfo.model == 1) SterilizationModeTask();
else if(userInfo.model == 2) HeatPreservationModetask();
ChageWaterLevelTask();
}
}
/**
* @description: 判断时间是否到达
* @param {*}
* @return {*}
*/
u8 getTimerResult(void)
{
u8 result = 1;
// 不考虑年
//if(userInfo.SetTimer.year != nowTime.year) result = 0;
if(userInfo.SetTimer.mon != nowTime.mon) result = 0;
else if(userInfo.SetTimer.day != nowTime.day) result = 0;
else if(userInfo.SetTimer.hour != nowTime.hour) result = 0;
else if(userInfo.SetTimer.min != nowTime.min) result = 0;
else if(userInfo.SetTimer.sec != nowTime.sec) result = 0;
return result;
}
/**
* @description: 解析数据
* @param {*}
* @return {*}
*/
int getValue(void)
{
int target1 = 0, target2 = 0,i = 0;
int result = 0;
target1 = (char *)strstr((const char *)USART_RX_BUF, "(") - (char *)USART_RX_BUF;
target2 = (char *)strstr((const char *)USART_RX_BUF, ")") - (char *)USART_RX_BUF;
result = 0;
for(i = target1 + 1; i < target2; i++){
result = result * 10 + (*(USART_RX_BUF + i) - 0x30);
}
return result;
}
/**
* @description: 获取字符出现的第一个索引
* @param {char} str
* @return {*}
*/
int getFirstIndexes(const char str){
int i = 0;
int length = USART_RX_STA & 0x3fff;
for(i = 0; i < length; i++){
if(str == USART_RX_BUF[i]) return i;
}
return 0;
}
/**
* @description: 获取字符出现的最后一个索引
* @param {char} str
* @return {*}
*/
int getLastIndexes(const char str){
int result = 0, i = 0;
int length = USART_RX_STA & 0x3fff;
for(i = 0; i < length; i++){
if(str == USART_RX_BUF[i]) result = i;
}
return result;
}
/**
* @description: 解析Timer
* @param {*}
* @return {*}
*/
struct timing getTimer()
{
struct timing timer;
int target1 = 0, target2 = 0,i = 0 , result = 0;
target1 = (char *)strstr((const char *)USART_RX_BUF, "(") - (char *)USART_RX_BUF;
target2 = getFirstIndexes('-');
for(i = target1 + 1; i < target2; i++){
result = result * 10 + (*(USART_RX_BUF + i) - 0x30);
}
timer.year = result;
result = 0;
target1 = getFirstIndexes('-');
target2 = getLastIndexes('-');
for(i = target1 + 1; i < target2; i++){
result = result * 10 + (*(USART_RX_BUF + i) - 0x30);
}
timer.mon = result;
result = 0;
target1 = getLastIndexes('-');
target2 = getFirstIndexes(' ');
for(i = target1 + 1; i < target2; i++){
result = result * 10 + (*(USART_RX_BUF + i) - 0x30);
}
timer.day = result;
result = 0;
target1 = getFirstIndexes(' ');
target2 = getFirstIndexes(':');
for(i = target1 + 1; i < target2; i++){
result = result * 10 + (*(USART_RX_BUF + i) - 0x30);
}
timer.hour = result;
result = 0;
target1 = getFirstIndexes(':');
target2 = getLastIndexes(':');
for(i = target1 + 1; i < target2; i++){
result = result * 10 + (*(USART_RX_BUF + i) - 0x30);
}
timer.min = result;
result = 0;
target1 = getLastIndexes(':');
target2 = getLastIndexes(')');
for(i = target1 + 1; i < target2; i++){
result = result * 10 + (*(USART_RX_BUF + i) - 0x30);
}
timer.sec = result;
return timer;
}
/**
* @description: 接收数据
* @param {*}
* @return {*}
*/
void DataProcessing(void)
{
// 接受到数据
if(USART_RX_STA & 0x8000){
// 模式切换
if(strstr((const char*)USART_RX_BUF, "model") != NULL){
userInfo.model++;
if(userInfo.model >= 2) userInfo.model = 0;
if(userInfo.model == 0) printf("The heating mode\r\n");
else if(userInfo.model == 1) printf("Sterilization mode\r\n");
}
if(strstr((const char*)USART_RX_BUF, "getModel") != NULL){
if(userInfo.model == 0) printf("The heating mode\r\n");
else if(userInfo.model == 1) printf("Sterilization mode\r\n");
else printf("Heat preservation mode\r\n");
}
if(strstr((const char*)USART_RX_BUF, "setTargetTemp") != NULL){
userInfo.water_target_temp = getValue();
printf("setTargetTemp OK!\r\n");
}
if(strstr((const char*)USART_RX_BUF, "setTimer") != NULL){
userInfo.SetTimer = getTimer();
printf("setTimer OK!\r\n");
}
if(strstr((const char*)USART_RX_BUF, "setLevel") != NULL){
userInfo.setLevel = getValue();
if(userInfo.setLevel >= 3) userInfo.setLevel = 2;
printf("setLevel OK!\r\n");
}
if(strstr((const char*)USART_RX_BUF, "TimerFlag") != NULL){
if(userInfo.TimerFlag == 0) userInfo.TimerFlag = 1;
else userInfo.TimerFlag = 0;
if(userInfo.TimerFlag == 0) printf("Close Timer!\r\n");
else printf("Open Timer!\r\n");
}
if(strstr((const char*)USART_RX_BUF, "HotFlag") != NULL){
if(userInfo.HotFlag == 0) userInfo.HotFlag = 1;
else userInfo.HotFlag = 0;
if(userInfo.HotFlag == 0) printf("Close Hot!\r\n");
else printf("Open Hot!\r\n");
}
if(strstr((const char*)USART_RX_BUF, "getInfo") != NULL){
printf("Water_temp:%0.1f℃, target:%d℃, setTemp:%d ℃, water_level:%0.2fcm, TimerFlag:%d , HotFlag:%d\r\n", userInfo.water_temp, userInfo.now_tager_temp,userInfo.water_target_temp, userInfo.water_level, userInfo.TimerFlag, userInfo.HotFlag);
}
if(strstr((const char*)USART_RX_BUF, "getTime") != NULL){
printf("Time: 20%d-%d-%d %d:%d:%d\r\n", nowTime.year, nowTime.mon, nowTime.day, nowTime.hour, nowTime.min, nowTime.sec);
}
if(strstr((const char*)USART_RX_BUF, "getTimer") != NULL){
printf("Timer: %d-%d-%d %d:%d:%d\r\n", userInfo.SetTimer.year, userInfo.SetTimer.mon, userInfo.SetTimer.day, userInfo.SetTimer.hour, userInfo.SetTimer.min, userInfo.SetTimer.sec);
}
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
USART_RX_STA = 0x00;
}
}