在线温度计:Arduino与温度传感器的完美结合
立即解锁
发布时间: 2025-08-26 00:22:34 阅读量: 2 订阅数: 34 


实用Arduino:开源硬件的酷炫项目
### 在线温度计:Arduino 与温度传感器的完美结合
#### 1. 项目概述
Arduino 是数据采集和记录系统的理想组件,尤其是在家庭自动化领域,温度传感器的应用十分广泛。通过将 Arduino 与多个 DS18B20 温度传感器相结合,我们可以在家庭或办公室的各个角落安装传感器,并通过网页浏览器实时获取温度报告。这些读数还可以随时间记录和绘图,帮助我们了解家庭供暖或制冷系统的效果,以及在气候条件变化时家庭温度的保持情况。此外,这些信息还可以作为控制系统的反馈,用于控制主动加热或冷却设备,或者触发伺服电机或线性执行器来打开和关闭窗户及被动通风系统。
#### 2. 所需部件
| 部件名称 | 数量 |
| --- | --- |
| Arduino Duemilanove、Arduino Pro、Seeeduino 或等效型号 | 1 |
| Seeed Studio 以太网扩展板或 nuElectronics 以太网扩展板(带原型开发板) | 1 |
| DS18B20 Dallas 1 - 线温度传感器(注意:非 DS18S20) | 6 |
| 4K7 1/4W 电阻 | 6 |
| PCB 安装 3 针公接头 | 6 |
| 引线安装 3 针母接头 | 6 |
| 双绞线电缆或报警电缆(至少 3 根导体) | 适量 |
源代码可从 www.practicalarduino.com/projects/online - thermometer 下载。
#### 3. 以太网扩展板选择
在众多 Arduino 以太网适配器中,我们选择了 Seeed Studio 以太网扩展板。原因在于其设计者意识到,大多数为 Arduino 添加以太网功能的用户还希望添加其他自定义部件。其他以太网扩展板通常会浪费大量的扩展板面积,而 Seeed Studio 扩展板将以太网电路集中在板的一端,剩余空间则提供了一个原型开发区域,并且将所有 Arduino I/O 引脚引出到边缘的焊盘上,方便用户使用。
然而,该扩展板也有一些不足之处。它基于 NuElectronics 以太网扩展板的设计,需要使用 NuElectronics 的 etherShield 库。与官方 Arduino 以太网库不同,etherShield 库会暴露大量 TCP/IP 的细节,使得 Arduino 程序难以理解。此外,常见的下载版本(v1.0)在区分大小写的文件系统(如大多数 Linux 机器)上存在 bug,不过可以从 Practical Arduino 网站下载更新版本(v1.1)。
该项目的示例代码仅适用于 Seeed Studio 和 NuElectronics 扩展板,不适用于基于“官方”设计的以太网扩展板。但修改后的适用于官方扩展板的代码也可从 Practical Arduino 网站下载。如果使用其他扩展板,可能需要在以太网扩展板上再安装一个原型开发板来组装项目。
#### 4. 扩展板设置
- **安装 PCB 插头**:为了方便测试扩展板,我们使用插头和插座来连接外部设备,如 DS18B20 温度传感器。我们在原型上使用了 3 针 PCB 安装接头,因为它们价格便宜,占用扩展板空间小,并且只能以一种方式插入,避免了传感器插反的问题。Seeed Studio 以太网扩展板有足够的空间安装六个接头,甚至可以安装多达 10 个。需要注意的是,Arduino 的模拟输入引脚(0 - 5)也可以作为数字 I/O 引脚使用,对应数字引脚 14 - 19。例如,要将模拟引脚 3 用作数字输入,可以使用以下代码:
```cpp
pinMode(17, INPUT);
```
- **连接 +5V 和 GND**:在扩展板上焊接好接头后,使用单芯电缆将所有 +5V 连接在一起,然后连接到扩展板的 +5V 引脚。同样,将所有接地连接在一起,然后连接到扩展板的 GND 引脚。
- **连接数据线**:使用单芯电缆将每个接头的中心(数据)引脚连接到对应的数字 I/O 线。具体分配如下:
| 传感器 | 数字 I/O 引脚 |
| --- | --- |
| 传感器 A | 3 |
| 传感器 B | 4 |
| 传感器 C | 5 |
| 传感器 D | 6 |
| 传感器 E | 7 |
| 传感器 F | 8 |
由于引脚 0 和 1 用于与主机的串行连接(USB),引脚 2 被以太网扩展板用于与 Arduino 通信,因此我们从数字引脚 3 开始连接。
#### 5. 传感器组装
- **测试传感器组装**:为了在实验台上测试系统,我们将一个 DS18B20 直接安装到一个接头上,然后将其插入扩展板。每个 DS18B20 需要在数据和 +5V 引脚之间连接一个 4k7 电阻。安装时要注意引脚方向,确保传感器正确对齐扩展板上的引脚分配。
- **长引线传感器组装**:对于需要安装在远处的传感器,可以使用各种类型的电线,如双绞线电缆或立体声屏蔽电缆。但要注意,长距离的屏蔽电缆可能会产生电容,干扰数字数据传输。我们还将 4k7 电阻安装在接头的背面,这样另一端只需要连接传感器本身即可。如果传感器要安装在恶劣环境中,可以在引线和连接点上涂抹硅胶,但要确保大部分传感器主体暴露在外,以便快速感知环境温度变化。
#### 6. 程序加载
该项目的示例程序将 Arduino 作为一个简单的 Web 服务器运行,响应网页请求并返回包含当前传感器读数的页面。不过,在深入了解代码细节之前,需要注意一些限制:
- **响应大小限制**:由于该程序基于 etherShield 库,不支持数据包分段,因此返回的网页必须适合单个数据包,否则将无法正常工作。示例程序将 TCP 缓冲区限制为 500 字节,但你可以尝试其他值。
- **路由限制**:etherShield 库没有提供指定网关或子网掩码的功能,因此没有路由概念。无法在程序中配置网关地址并发起与外部网络主机的 TCP/IP 连接,但如果网关进行源 NAT(网络地址转换),Arduino 可以响应来自外部网络的请求。
以下是示例程序的部分代码:
```cpp
#include "etherShield.h"
// 修改以下两行以适应你的本地网络配置。MAC 和 IP 地址在你的局域网中必须唯一:
static uint8_t myMac[6] = {0x54,0x55,0x58,0x10,0x00,0x24};
static uint8_t myIp[4] = {192,168,1,15};
static char baseurl[] = "http://192.168.1.15/";
static uint16_t myPort = 80; // Listen port for tcp/www (range 1-254)
// Set up variables for the TCP/IP buffer
#define BUFFER_SIZE 500
static uint8_t buf[BUFFER_SIZE+1];
#define STR_BUFFER_SIZE 22
static char strbuf[STR_BUFFER_SIZE+1];
// Create an instance of the EtherShield object named "es"
EtherShield es=EtherShield();
// Prepare the web page by writing the data to the TCP send buffer
uint16_t print_webpage(uint8_t *buf);
int8_t analyse_cmd(char *str);
// Specify data pins for connected DS18B20 temperature sensors
#define SENSOR_A 3
#define SENSOR_B 4
#define SENSOR_C 5
#define SENSOR_D 6
#define SENSOR_E 7
#define SENSOR_F 8
void setup()
{
/*initialize enc28j60*/
es.ES_enc28j60Init(myMac);
// Change clkout from 6.25MHz to 12.5MHz
es.ES_enc28j60clkout(2);
delay(10);
/* Magjack leds configuration, see enc28j60 datasheet, page 11 */
// LEDA=green LEDB=yellow
// 0x880 is PHLCON LEDB=on, LEDA=on
es.ES_enc28j60PhyWrite(PHLCON, 0x880);
delay(500);
// 0x990 is PHLCON LEDB=off, LEDA=off
es.ES_enc28j60PhyWrite(PHLCON, 0x990);
delay(500);
// 0x880 is PHLCON LEDB=on, LEDA=on
es.ES_enc28j60PhyWrite(PHLCON, 0x880);
delay(500);
// 0x990 is PHLCON LEDB=off, LEDA=off
es.ES_enc28j60PhyWrite(PHLCON, 0x990);
delay(500);
// 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
es.ES_enc28j60PhyWrite(PHLCON, 0x476);
delay(100);
//init the ethernet/ip layer:
es.ES_init_ip_arp_udp_tcp(myMac, myIp, myPort);
// Set up the data pins for communication with DS18B20 sensors
digitalWrite(SENSOR_A, LOW);
pinMode(SENSOR_A, INPUT);
digitalWrite(SENSOR_B, LOW);
pinMode(SENSOR_B, INPUT);
digitalWrite(SENSOR_C, LOW);
pinMode(SENSOR_C, INPUT);
digitalWrite(SENSOR_D, LOW);
pinMode(SENSOR_D, INPUT);
digitalWrite(SENSOR_E, LOW);
pinMode(SENSOR_E, INPUT);
digitalWrite(SENSOR_F, LOW);
pinMode(SENSOR_F, INPUT);
}
void loop(){
uint16_t plen, dat_p;
int8_t cmd;
plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);
/*plen will ne unequal to zero if there is a valid packet (without crc error) */
if(plen!=0) {
// arp is broadcast if unknown but a host may also verify the mac address by sending it to a unicast address.
if (es.ES_eth_type_is_arp_and_my_ip (buf,plen)) {
es.ES_make_arp_answer_from_request (buf);
return;
}
// check if ip packets are for us:
if (es.ES_eth_type_is_ip_and_my_ip (buf,plen) == 0) {
return;
}
if (buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V) {
es.ES_make_echo_reply_from_request (buf,plen);
return;
}
// tcp port www start, compare only the lower byte
if (buf[IP_PROTO_P] == IP_PROTO_TCP_V && buf[TCP_DST_PORT_H_P] == 0 && buf[TCP_DST_PORT_L_P] == myPort) {
if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V) {
es.ES_make_tcp_synack_from_syn (buf); // make_tcp_synack_from_syn does already send the syn,ack
return;
}
if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V) {
es.ES_init_len_info (buf); // init some data structures
dat_p = es.ES_get_tcp_data_pointer();
if (dat_p==0) { // we can possibly have no data, just ack:
if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V) {
es.ES_make_tcp_ack_from_any (buf);
}
return;
}
if (strncmp ("GET ", (char *) & (buf[dat_p]), 4) != 0) {
// head, post, and other methods for possible status codes see:
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
plen = es.ES_fill_tcp_data_p (buf,0,PSTR ("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>"));
goto SENDTCP;
}
if (strncmp("/ ", (char *) & (buf[dat_p+4]), 2) == 0){
plen = print_webpage (buf);
goto SENDTCP;
}
cmd = analyse_cmd ((char *) & (buf[dat_p+5]));
if (cmd == 1){
pl
```
0
0
复制全文
相关推荐









