51单片机积雪融化系统使用51单片机作为系统主控,借助HX711检测积雪厚度,同时集成了LCD显示模块显示实时温度等,系统通过积雪厚度驱动改变加热片的功率进行一个融雪操作,同时集成了按键模块,可以手动调节加热/自动模式,加热强度等。
一、硬件设计
51单片机积雪融化系统使用洞洞板进行焊接,电路简单,这边不多做阐述。
二、软件设计
1、HX711
sbit HX711_DOUT = P2^0; //声明P2^1口接HX711数据线
sbit HX711_SCK = P2^1; //声明P2^0口接HX711时钟线
//****************************************************
//延时函数
//****************************************************
void Delay__hx711_us(void)
{
_nop_();
_nop_();
}
//****************************************************
//读取HX711
//****************************************************
unsigned long HX711_Read(void) //增益128
{
unsigned long count;
unsigned char i;
HX711_DOUT=1;
Delay__hx711_us();
HX711_SCK=0;
count=0;
while(HX711_DOUT);
for(i=0;i<24;i++)
{
HX711_SCK=1;
count=count<<1;
HX711_SCK=0;
if(HX711_DOUT)
count++;
}
HX711_SCK=1;
count=count^0x800000;//第25个脉冲下降沿来时,转换数据
Delay__hx711_us();
HX711_SCK=0;
return(count);
}
//转化重量函数
long Get_Weight()
{
HX711_Buffer = HX711_Read(); ///读取此时的传感器输出值
Weight_Shiwu = HX711_Buffer; ///将传感器的输出值储存
Weight_Shiwu = Weight_Shiwu - Weight_Maopi; //获取实物的AD采样数值。
Weight_Shiwu = (long)((float)Weight_Shiwu/GapValue); //AD值转换为重量(g)
return Weight_Shiwu;
}
2、DS18B20
#include <REGX52.H>
#include "OneWire.h"
#define DS18B20_SKIP_ROM 0xcc
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCERATCHPAD 0xbe
void DS18B20_ConvertT()
{
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_CONVERT_T);
}
float DS18B20_ReadT()
{
unsigned char TLSB,TMSB;
int Temp;
float T;
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_READ_SCERATCHPAD);
TLSB=OneWire_ReceiveByte();
TMSB=OneWire_ReceiveByte();
Temp=(TMSB<<8)|TLSB;
T=Temp/16.0;
return T;
}
#include <REGX52.H>
sbit OneWire_DQ=P2^3;
unsigned char OneWire_Init()
{
unsigned char i;
unsigned char AckBit;
OneWire_DQ=1;
OneWire_DQ=0;
i = 247;while (--i); //delay 500us
OneWire_DQ=1;
i = 32;while (--i); //delay 70us
AckBit=OneWire_DQ;
i = 247;while (--i); //delay 500us
return AckBit;
}
void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
OneWire_DQ=0;
i=4;while(--i); //delay 10us
OneWire_DQ=Bit;
i=24;while(--i); //delay 50us
OneWire_DQ=1;
}
unsigned char OneWire_ReceiveBit()
{
unsigned char i;
unsigned char Bit;
OneWire_DQ=0;
i=2;while(--i); //delay 5us
OneWire_DQ=1;
i=2;while(--i); //dealy 5us
Bit=OneWire_DQ;
i=24;while(--i); //delay 50us
return Bit;
}
void OneWire_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
OneWire_SendBit(Byte&(0x01<<i));
}
}
unsigned char OneWire_ReceiveByte()
{
unsigned char i;
unsigned char Byte=0x00;
for(i=0;i<8;i++)
{
if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
}
return Byte;
}
3、主程序
#include <REGX52.H>
#include "intrins.h"
#include "LCD1602.H"
#include "delay.h"
#include "DS18B20.h"
#include "KEY.h"
#include "Timer0.h"
//定义加热片引脚
sbit warm = P2^2;
unsigned char mode=0;
unsigned char runMode=0;
unsigned char Counter=0;
unsigned char Compare=0;
float tem=0;
unsigned char keyNum=0;
char warm_grade=0;
unsigned char flag=0;
//加热片加热阈值
char warm_th=35;
//HX711有关参数
long HX711_Buffer = 0;
long Weight_Maopi = 0, Weight_Shiwu = 0;
#define GapValue 440 ///该值需校准 每个传感器都有所不同
sbit HX711_DOUT = P2^0; //声明P2^1口接HX711数据线
sbit HX711_SCK = P2^1; //声明P2^0口接HX711时钟线
//****************************************************
//延时函数
//****************************************************
void Delay__hx711_us(void)
{
_nop_();
_nop_();
}
//****************************************************
//读取HX711
//****************************************************
unsigned long HX711_Read(void) //增益128
{
unsigned long count;
unsigned char i;
HX711_DOUT=1;
Delay__hx711_us();
HX711_SCK=0;
count=0;
while(HX711_DOUT);
for(i=0;i<24;i++)
{
HX711_SCK=1;
count=count<<1;
HX711_SCK=0;
if(HX711_DOUT)
count++;
}
HX711_SCK=1;
count=count^0x800000;//第25个脉冲下降沿来时,转换数据
Delay__hx711_us();
HX711_SCK=0;
return(count);
}
//转化重量函数
long Get_Weight()
{
HX711_Buffer = HX711_Read(); ///读取此时的传感器输出值
Weight_Shiwu = HX711_Buffer; ///将传感器的输出值储存
Weight_Shiwu = Weight_Shiwu - Weight_Maopi; //获取实物的AD采样数值。
Weight_Shiwu = (long)((float)Weight_Shiwu/GapValue); //AD值转换为重量(g)
return Weight_Shiwu;
}
//定义重量变量
unsigned long weight=0;
void main()
{
//LCD初始化
LCD_Init();
//初始化转换一遍温度
DS18B20_ConvertT();
tem = DS18B20_ReadT();
//等待转化完成
delay(1000);
//初始获取一遍HX711的置
Weight_Maopi = HX711_Read();
//定时器初始化
Timer0_Init();
while(1)
{
//获取按键值
keyNum = KEY();
//按键1按下,进行模式切换
if(keyNum==1){
mode++;
mode%=2;
LCD_Clear();
warm_grade=0;
}
//按键4按下,手动自动模式切换
if(keyNum == 4){
runMode++;
runMode%=2;
warm_grade=0;
}
//默认模式
if(mode == 0){
if(runMode==0){
//判断是否达到加热条件
if(tem < warm_th){
//通过总量进行挡位调节
if(weight < 200){
warm_grade=0;
}
else if(weight >= 200 && weight <400){
warm_grade=1;
}
else if(weight >= 400 && weight <600){
warm_grade=2;
}
else if(weight >= 600){
warm_grade=3;
}
}
//显示自动模式
LCD_ShowString(2, 13, "Auto");
}
else if(runMode==1){
//显示手动模式
LCD_ShowString(2, 13, "Hand");
//进行加热挡位的调节,减挡
if(keyNum==2){
warm_grade--;
if(warm_grade<0)warm_grade=3;
}
//进行加热挡位的调节,加挡
else if(keyNum==3){
warm_grade++;
warm_grade%=4;
}
}
//显示加热等级
LCD_ShowNum(1, 15, warm_grade, 1);
//显示温度
LCD_ShowString(1,1,"Tempe:");
LCD_ShowNum(1, 8, tem, 2);
//显示重量
LCD_ShowNum(2, 1, weight, 4);
LCD_ShowString(2,5,"g");
}
else if(mode == 1){
//显示加热阈值
LCD_ShowString(1,1,"warm_th:");
LCD_ShowNum(1, 12, warm_th, 2);
//加热阈值减
if(keyNum==2){
warm_th--;
if(warm_th<-50)warm_th=-50;
}
//加热阈值加
else if(keyNum==3){
warm_th++;
if(warm_th>=50)warm_th=50;
}
}
//通过加热阈值调整PWM占空比
if(warm_grade==0)Compare=0;
if(warm_grade==1)Compare=1;
if(warm_grade==2)Compare=2;
if(warm_grade==3)Compare=3;
}
}
//定时器中断函数
void Timer0_Routine() interrupt 1
{
static unsigned char Tcnt=0;
TL0 = 0x00; //设置定时初始值
TH0 = 0x94; //设置定时初始值
//生成PWM波,控制加热挡位
Counter++;
Counter%=4;
if(Counter<Compare)
{
warm= 0;
}
else
{
warm = 1;
}
//转化温度
DS18B20_ConvertT();
tem = DS18B20_ReadT();
//定时获取重量,500ms
if(++Tcnt >= 16){
Tcnt=0;
weight = Get_Weight();
}
}
三、项目演示
1、默认状态
默认状态下,LCD显示温度、重量、加热等级、自动模式
2、自动模式
自动模式下,加热等级,随着积雪重量的增加而增加,如下:
3、手动模式
手动模式下,可以通过按键修改加热等级
四、项目总结
本次项目是一个通过积雪重量进行加热等级的控制,一般而言,重量越中,加热等级越大,同时系统可以手动控制。详情参考我的bilibili: