丄帝De咗臂 发表于 2015-8-31 17:57:57

温度报警器

本帖最后由 丄帝De咗臂 于 2015-8-31 17:57 编辑

【简介】本项目中我们使用四位数码管、温度传感器和蜂鸣器,通过Arduino程序制作温度报警器,使温度超过30度时自动报警。最后完成图如下


【器材】Arduino Nano,四位数码管,蜂鸣器,LM35温度传感器,面包板,导线若干。
【原理】电路原理图如下


【接线】接线示意图如下


【程序】代码程序如下
/*
功能:显示0-70℃范围室内温度,分辨0.5℃
采用红色超高亮度共阳的4位数码管,以及输出平衡程序代码,使得数码管之间亮度基本平衡
温度计随着电源电压波动会产生较大误差,按照USB口输出电池电压4.7V设计;如果脱机使用3节5号电池供电,电压4.0-4.5V,这时温度显示会偏高
*/
//把部分模拟口改成数字口:A0~A5对应D15~D19
int a = 15;//设置A1口连接数码管a段
int b = 19;//设置A5口连接数码b段
int c = 7;//设置D7口连接数码管c段
int d = 5;//设置D5口连接数码管d段
int e = 4;//设置D4口连接数码管e段
int f = 16;//设置A2口连接数码管f段
int g = 8;//设置D8口连接数码管g段
int dp = 6;//设置D6口连接数码管dp段
int tempPin = 7;//lm35信号端连接A7
int d1 = 14;//设置A0口连接第一个数码管公共阴极
int d2 = 17;//设置A3口连接第二个数码管公共阴极
int d3 = 18;//设置A4口连接第三个数码管公共阴极
int d4 = 9;//设置D9口连接第四个数码管公共阴极
//设置变量
int n = 0;//设置温度的变量
int del = 2; //此处数值对各位数码管之间的亮度进行微调,越大该位数码管越亮
unsigned long m=0;//设置一个消除数码管频繁闪亮的计时器变量

//以下用数组给数码管的管脚赋值,程序很简洁
byte segs = { a, b, c, d, e, f, g };//将除了小数点外的7段笔划作为一个数组
byte seven_seg_digits = { { 1,1,1,1,1,1,0 },//设置数码管显示0的数组
                               { 0,1,1,0,0,0,0 },//设置数码管显示1的数组
                               { 1,1,0,1,1,0,1 },//设置数码管显示2的数组
                               { 1,1,1,1,0,0,1 },//设置数码管显示3的数组
                               { 0,1,1,0,0,1,1 },//设置数码管显示4的数组
                               { 1,0,1,1,0,1,1 },//设置数码管显示5的数组
                               { 1,0,1,1,1,1,1 },//设置数码管显示6的数组
                               { 1,1,1,0,0,0,0 },//设置数码管显示7的数组
                               { 1,1,1,1,1,1,1 },//设置数码管显示8的数组
                               { 1,1,1,1,0,1,1 }//设置数码管显示9的数组
                               };
/****************************初始化设置函数****************************/
void setup()
{
pinMode(d1, OUTPUT); //设置引脚为输出状态
pinMode(d2, OUTPUT); //同上
pinMode(d3, OUTPUT); //同上
pinMode(d4, OUTPUT); //同上
pinMode(a, OUTPUT); //同上
pinMode(b, OUTPUT);// 同上
pinMode(c, OUTPUT);// 同上
pinMode(d, OUTPUT);// 同上
pinMode(e, OUTPUT);// 同上
pinMode(f, OUTPUT);// 同上
pinMode(g, OUTPUT);// 同上
pinMode(dp, OUTPUT);// 同上
pinMode(11, OUTPUT);//设置蜂鸣器输出状态
digitalWrite(11, LOW);//蜂鸣器关闭
Serial.begin(9600);//设置模拟口的采样频率
}
/***************************主程序(循环)******************************/
void loop()//运行程序
{
//float tempval= (3.5* analogRead(tempPin))*1000/1024;//将温度传感器获得的电压模拟量赋值给变量temval
//从模拟口A0输入温度传感器LM35的温度转换电压,0℃:0V,+1℃:+10mV
//float tempval=analogRead(tempPin)* 4.88;//5V电压,是理想的电源电压
float tempval=analogRead(tempPin)* 4.6;//4.7V,是电脑USB口输出的实测电压
//float tempval=analogRead(tempPin)* 4.0;//4.1V,3节5号电池电压
//float tempval=map(10*analogRead(tempPin),0,460,0,220);//数值区间影射函数,把一个区间的数值,线性地影射到另一个区间;这里把模拟输出采集的数值0-300(应该是0-200左右),影射到0℃-100℃,因为有一位小数,故乘以10
if (m%30==0) n=int(tempval); //设定温度的刷新时间为0.3秒,也可消除数码管闪烁的语句
/*数码管闪烁的原因是因为采样速率高达9600,所以温度数值变化很快,而数据处理产生近似值不是连续的,导致显示数值经常闪烁,影响读数。
如果用延时方法,则数码管的最右边数字特别亮,其他数字亮度很低,所以采用自设的计时器“m”,用求余数除法,过30个计时单位才采集一次显示温度数值,有效地消除了闪烁现象,并且不影响程序的正常运行*/
      if (n>300)digitalWrite(11, HIGH);//大于30度时,蜂鸣器报警
      if (n<=300)digitalWrite(11, LOW);//小于30度时,蜂鸣器停止鸣叫
//以下显示温度的数值,可显示xxx.x℃
clearLEDs();//数码管数字显示清屏
delay(del);//延时2ms(为什么是2ms)
lightSegments(n/1000%10);//显示百位数值
//如果到100度,这位数码管点亮
pickDigit((n/1000%10>0));//如果不到100度,则这位数码管熄灭

clearLEDs();//数码管数字显示清屏
delay(del);//延时2sm
pickDigit(2); //点亮第二个数码管
lightSegments(n/100%10);//显示十位数值
delay(del+2);//延时增加50%,以增加这个数码管的亮度

clearLEDs();//数码管数字显示清屏
pickDigit(3);//左边第三个数码管点亮
lightSegments(n/10%10);//显示个位数值
dispDec(3);//这个数码管要有小数点(哪个?)
delay(del+2);//这个数码管增加亮度

clearLEDs();//数码管数字显示清屏
delay(del);//这个数码管亮度减弱
pickDigit(4);//点亮左边第四个数码管
lightSegments(n%10);//显示十分位数值
delay(del-1);//这个数码管减少亮度
m++;//消除数码管闪烁的计时器变量

//发送到串口监视窗口,以便观察变量数值
Serial.println(analogRead(tempPin));//串口调试器显示A7引脚读取数值      
Serial.println(n);//串口调试器显示温度数值
}
/*实测结果表明,这个温度计受电源电压的影响较大,原因是LM35自带稳压,工作电压:4V-20V,输出电压稳定;当电池电压降低后,这个稳定的电压在模拟口的输出数值就会增大,导致误差;此外,由于模拟口的分别率只有1024级,温度数值的误差也大*/
/*****************************打开数码管子函数**************************/
void pickDigit(int x)//定义pickDigit(x),轮流打开4位数码管中的一个
{
digitalWrite(d1, LOW);//共阳极数码管,LOW则关闭
digitalWrite(d2, LOW);//共阳极数码管,LOW则关闭
digitalWrite(d3, LOW);//共阳极数码管,LOW则关闭
digitalWrite(d4, LOW);//共阳极数码管,LOW则关闭
switch(x)
{
case 1:
    digitalWrite(d1, HIGH); //打开最左边的高位数码管,即数码管的百位
    break;
case 2:
    digitalWrite(d2, HIGH); //打开最左边的高位数码管,即数码管的十位
    break;
case 3:
    digitalWrite(d3, HIGH); //打开最左边的高位数码管,即数码管的个位
    break;
case 4:// default: //打开最左边的高位数码管,十分位
digitalWrite(d4, (m%100>=30)); //用余数的区间产生数字闪烁,周期大概是1秒,30%的时间熄灭
//这样便于观察结果,特别是温度保持不变的时候,给人以设备正常运行的感觉
//这个方法也可用在时钟里,可产生闪烁的效果,通过模的数值和条件的改变,得到各种闪烁效果
    break;
}
}
/*****************************点亮小数点子函数*************************/
void dispDec(int x)
{
digitalWrite(dp, LOW);//点亮小数点
}
/******************************清屏子函数******************************/
void clearLEDs()
{
    for (int i = 0; i < 7; i++) //变量i在0到6直接变化
{
    digitalWrite(segs, HIGH);//共阳数码管,笔画段高电平熄灭
   }
    digitalWrite(dp, HIGH);//小数点熄灭
}
/***********************点亮对应数字的数码管*************************/
void lightSegments(int x) //数码管显示数字子函数
{
for (int i = 0; i < 7; i++) //变量在0到6之间变化
{
digitalWrite(segs, 1-seven_seg_digits);//由于笔画字段是按照共阴级数码管编写的,这里要用算术转换成共阳极数码管的输出结果
}
}
【效果】最终效果图如下




大连林海 发表于 2015-8-31 18:12:27

这可以好多应用

丄帝De咗臂 发表于 2015-8-31 18:22:54

大连林海 发表于 2015-8-31 18:12
这可以好多应用

什么应用,开开脑洞洞

大连林海 发表于 2015-8-31 19:48:25

丄帝De咗臂 发表于 2015-8-31 18:22
什么应用,开开脑洞洞

让陈老师给你大写不同的壳子

丄帝De咗臂 发表于 2015-8-31 21:00:10

大连林海 发表于 2015-8-31 19:48
让陈老师给你大写不同的壳子

不错的想法,但是打什么样子的呢

大连林海 发表于 2015-8-31 21:11:07

丄帝De咗臂 发表于 2015-8-31 21:00
不错的想法,但是打什么样子的呢

滚动的 奔跑的 飞的 剩下的靠你了

20060606 发表于 2020-8-22 19:16:33

电路图被df标识挡住了,建议以后df不要再加这个标识了
页: [1]
查看完整版本: 温度报警器