使用Arduino Wire Library读取温湿度传感器AM2321#
AM2321是采用I2C总线或单总线通讯的国产温湿度传感器。在AM2321手册中,当采用I2C通讯时,手册指定了多处需要主机等待的时间间隔,包括:
(1)唤醒传感器时,从机不回复ACK,但主机主要等待800us~3ms再发送STOP信号;
(2)主机发送读/写指令后,需等待至少1.5ms再发送读取时序;
(3)读返回数据时,主机发送I2C地址后,需等待至少30us以上才能发送下一个串行时钟。
由于Arduino标准库Wire中的函数不支持指定(1)和(3)中的等待间隔,因此在之前的日志中,采用关闭I2C并采用bit-banging的方式唤醒传感器。
然而,就我手头的传感器测试发现,即使(3)的等待时间降低到10us左右(即100kHz速率正常通讯),并且将(1)改成“发送STOP信号后等待800us”,器件也是可以正常工作的。
这样的话,利用Wire库自带的函数,就可以实现对AM2321的操作。我利用手头的传感器分别在5V和3.3V供电下测试,都可以正常读写。
测试代码#
/*
Measurement of temperature and humidity using the AM2321 sensor
Attention:
Use functions in Wire library to wake up the sensor.
Although the sequence is different with the datasheet, it indeed works.
Connection:
AM2321 UNO
VDD <---------> 5V
GND <---------> GND
SCL <---------> SCL(A5)
SDA <---------> SDA(A4)
*/
#include <Wire.h>
#define ADDRESS_AM2321 0x5C //not 0xB8
#define SDA_PIN A4
#define SCL_PIN A5
byte fuctionCode = 0;
byte dataLength = 0;
byte humiHigh = 0;
byte humiLow = 0;
byte tempHigh = 0;
byte tempLow = 0;
byte crcHigh = 0;
byte crcLow = 0;
int humidity = 0;
int temperature = 0;
unsigned int crcCode = 0;
void setup()
{
Wire.begin();
Serial.begin(115200);
}
void loop()
{
//step 1. wake up the sensor
Wire.beginTransmission(ADDRESS_AM2321);
Wire.endTransmission();
delayMicroseconds(800);
//step 2. send command
Wire.beginTransmission(ADDRESS_AM2321);
Wire.write(0x03);
Wire.write(0x00);
Wire.write(0x04);
Wire.endTransmission();
delayMicroseconds(1500);
//step 3. read data
Wire.requestFrom(ADDRESS_AM2321, 8);
fuctionCode = Wire.read();
dataLength = Wire.read();
humiHigh = Wire.read();
humiLow = Wire.read();
tempHigh = Wire.read();
tempLow = Wire.read();
crcLow = Wire.read();
crcHigh = Wire.read();
//get the result
humidity = (humiHigh<<8) | humiLow;
temperature = (tempHigh<<8) | tempLow;
crcCode = (crcHigh<<8) | crcLow;
Serial.print(temperature/10.0, 1); Serial.println(" `C");
Serial.print(humidity/10.0, 1); Serial.println(" \%RH");
CheckCRC();
delay(4000);
}
void CheckCRC() //from the datesheet
{
byte backValues[] = {fuctionCode, dataLength, humiHigh, \
humiLow, tempHigh, tempLow};
unsigned int crc = 0xFFFF;
int i;
int len = 6;
int j = 0;
while (len--)
{
crc ^= backValues[j];
j++;
for (i=0; i<8; i++)
{
if (crc & 0x01)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
if (crc == crcCode)
{
Serial.println("CRC checked.");
}
else
{
Serial.println("CRC Error!");
}
}
器件介绍、电路连接可参见之前的日志。