這是本人在大一的時候做的第一個小東西。也是當時大一寫的第一篇博客。近日重溫舊時光,來此修改。
它的用途:很多时候需要喝温水,然而刚接出来的开水往往很烫,不适合饮用。所以我们会选择把它晾在一边,忙别的事,忙着忙着就把水忘了,等到喝水的时候,它已经不是我们想要的温度了。这个水温监控器就是用来防止这样的现象,用户可以自己来设定温度,当水温比这个温度低的时候,它的蜂鸣器就会响,也就是提醒用户喝水。
它主要由四部分组成:
arduino uno不必赘述。
lcd1602液晶屏也很好在arduino上操作,具体可以参考arduino
官方例程。
LCD硬件电路如图:
值得说明的是,电位计是非常重要的,我一开始使用定值电阻,背光率難以调节到合適情況。
重点就在于如何实现温度传感器测温,这里我选择的是DS18B20,达拉斯公司推出的单总线温度传感器,易于操作而且经典。
它的硬件电路很简单:
写程序伊始,我参考的是一本讲arduino的教程,上面用到了两个头文件,分别是OneWire.h和DallasTemperature.h,结果就是,最初的尝试都没有成功。
在编译的时候,DallasTemperature.c会導致報错,百度后,把Wprogram.h改成arduino.h或者在其下面加一段关于arduino.h的代码,编译不再出错,但是测温会显示一个神奇的数字,127度。这说明DS18B20根本没有测温。
由於教程中使用老版本IDE,懷疑换一个旧版本会不会好,于是去下载了0022版本,结果仍是失望。
最後打开例程中Onewire的文件夹,发现了一个例程,DS18x20_Temperature。它是用来串口显示温度的,拿它来试了一下,在串口监视器成功地顯示温度。
然而在proteus里,仿真的结果仍是127度,所以抱着试一试的想法,在面包板上试了一下,直接在LCD显示出了实时温度。可见,proteus其实还有待改进,且Arduino的老教程也沒有太大看的意義。
以下是目前为止的原理图:
關於仿真,arduino在proteus里有专门的库,且CSDN上就有資源。
克服傳感器后,只剩下蜂鸣器和按键控制。原理图如图:
需要注意的就是按键控制时,电路用了硬件消抖,程序里就不要再有软件消抖了,我过去试过这样做,按键会不起作用的。
至此,这个智能水温监控器就基本做完了,以下是代码:
#include <LiquidCrystal.h>
#include <OneWire.h>
LiquidCrystal lcd(12,11,5,4,3,2);
OneWire ds(10); // on pin 10
int beep = 9;
int add = 7;
int minus = 6;
float controline = 25;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
lcd.begin(16,2);
lcd.print("Hello world");
pinMode(beep, OUTPUT);
pinMode(add,INPUT);
pinMode(minus,INPUT);
}
void loop() {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
if ( !ds.search(addr)) {
ds.reset_search();
delay(250);
return;
}
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
if (OneWire::crc8(addr, 7) != addr[7]) {
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
// convert the data to actual temperature
unsigned int raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// count remain gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
if(digitalRead(add) == HIGH) controline += 1;
if(digitalRead(minus)==HIGH) controline -= 1;
if(celsius < controline) digitalWrite(beep,LOW);
else digitalWrite(beep,HIGH);
lcd.setCursor(0,0);
lcd.print("Temp = ");
lcd.print(celsius);
lcd.print(" C");
lcd.setCursor(0,1);
lcd.print("Setting: ");
lcd.print(controline);
}
原理圖如下。(画的有些难看)