// 微型气象站
// 光照度传感器(I2C)、温湿度传感器(One Wire)、地磁气压温度传感器(I2C)、锂电池保护模块、太阳能锂电池充电模块、时钟日历芯片、EEPROM储存芯片、无线口透传模块
// MCU:ATmega328P
// 电压:锂电3.7V,可直接使用5V外接电源,但不可与锂电一同使用,太阳能充电输入电压4.35~6V
//实测电流(锂电池):
//MCU运行,未在测量,无线模块开启:31.9mA
//MCU休眠,无线模块休眠,传感器闲置:450uA
////加载外部库//////////////////////////////////////////////
#include <Wire.h> //I2C库(Arduino自带库)
#include <I2C.h> //I2C库(Arduino自编库)
////测试用按钮、LED//////////////////////////////////////////////
#define Test_Button_Pin 3 //测试按钮针脚位
#define Test_LED_Pin 15 //测试LED针脚位
////电压//////////////////////////////////////////////
#define Voltage_Pin 20 //电压值读取针脚位,A6
#define Voltage_Read() (500*1.1*analogRead(Voltage_Pin)/1023) //读取电压值并计算终值,100倍于原值,选择片内1.1V基准电压源
//分压电阻精度误差调整系数*分压电阻比例(75K+300K,最高检测电压5.5V)*标准电压值*检测读数/1023 + 输入二极管压降(实测0.224-0.336V)
unsigned int Voltage_Result = 0; //电压值,100倍于原值
////风向、风速//////////////////////////////////////////////
// #define Wind_direction_Pin1 0 //风向传感器1(线性霍尔传感器)针脚位
// #define Wind_direction_Pin2 1 //风向传感器2(线性霍尔传感器)针脚位
// #define Wind_speed_Pin 2 //风速传感器 (开关霍尔传感器)针脚位
unsigned int Wind_direction_Result = 0; //风速(转/分)
unsigned int Wind_speed_Result = 0; //风向,0-359度(正东向为0度)
////BH1751FVI光照度芯片//////////////////////////////////////////////
#define I2C_Address_BH1751FVI 0x23 //BH1751FVI芯片I2C地址转换为7位地址
unsigned char BH1751FVI_Mode = 0x11; //测量模式
/*
0x10 连续高分辨率模式
在1lx 分辨率下开始测量,测量时间一般为120ms,最大180ms
0x11 连续高分辨率模式2
在0.5lx 分辨率下开始测量,测量时间一般为120ms
0x13 连续低分辨率模式
在41lx 分辨率下开始测量,测量时间一般为16ms,最大24ms
0x20 一次高分辨率模式
在1lx 分辨率下开始测量,测量时间一般为120ms,测量后自动设置为断电模式
0x21 一次高分辨率模式2
在0.5lx 分辨率下开始测量,测量时间一般为120ms,测量后自动设置为断电模式
0x23 一次低分辨率模式
在41lx 分辨率下开始测量,测量时间一般为16ms,测量后自动设置为断电模式
*/
unsigned int BH1751FVI_Result = 0; //测量结果
//箱内外光照度:箱内 - 297Lx;箱外 - 6175Lx;相差95.19%
////BMP085气压计//////////////////////////////////////////////
#define I2C_Address_BMP085 0x77 //BMP085气压计芯片I2C地址
const unsigned char REG_BMP085_Command = 0xF4; //测量控制寄存器地址
const unsigned char Param_BMP085_Close = 0x00; //将芯片设置到断电状态
const unsigned char Param_BMP085_Open = 0x01; //将芯片设置到通电状态,等待测量指令
// const unsigned char Param_BMP085_Rest = 0x01; //重置数字寄存器
const unsigned char Param_BMP085_Temperature = 0x2E; //温度,4.5ms
// const unsigned char Param_BMP085_Pressure0 = 0x34; //低精度气压,4.5ms
// const unsigned char Param_BMP085_Pressure1 = 0x74; //中精度气压,7.5ms
// const unsigned char Param_BMP085_Pressure2 = 0xB4; //高精度气压,13.5ms
// const unsigned char Param_BMP085_Pressure3 = 0xF4; //最高精度气压,25.5ms
const unsigned char REG_BMP085_MSB = 0xF6; //测量值寄存器高位
// const unsigned char REG_BMP085_LSB = 0xF7; //测量值寄存器低位
// const unsigned char REG_BMP085_XLSB = 0xF8; //测量值寄存器低位
#define OSS 3 //气压采样精度设置,低精度到高精度 0~3
//校准值
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
//b5用于计算BMP085_read_Temperature(),它也同时用于BMP085_read_Pressure()
//所以BMP085_read_Temperature()必须放在BMP085_read_Pressure()之前
long b5;
int BMP085_Temperature = 0; //温度值,10倍于原值
unsigned long BMP085_Pressure = 0; //气压值(Pa)
////HMC5883L数字罗盘//////////////////////////////////////////////
#define I2C_Address_HMC5883L 0x1E //HMC5883L数字罗盘芯片I2C地址
const unsigned char REG_HMC5883L_SetA = 0x00; //配置寄存器A地址
const unsigned char REG_HMC5883L_SetB = 0x01; //配置寄存器B地址
const unsigned char REG_HMC5883L_Mode = 0x02; //模式寄存器地址
const unsigned char REG_HMC5883L_X = 0x03; //X轴数据寄存器MSB地址
// const unsigned char REG_HMC5883L_Z = 0x05; //Z轴数据寄存器MSB地址
// const unsigned char REG_HMC5883L_Y = 0x07; //Y轴数据寄存器MSB地址
// const unsigned char REG_HMC5883L_Status = 0x09; //状态寄存器地址
// const unsigned char REG_HMC5883L_IDA = 0x10; //识别寄存器A地址
// const unsigned char REG_HMC5883L_IDB = 0x11; //识别寄存器B地址
// const unsigned char REG_HMC5883L_IDC = 0x12; //识别寄存器C地址
const int HMC5883L_Declination = -4; //磁偏角修正值
unsigned int HMC5883L_Result = 0; //测量结果
////AM2302温湿度计//////////////////////////////////////////////
#define AM2302_Pin 9 //针脚位
unsigned int AM2302_Humidity = 0; //湿度,10倍于原值
int AM2302_Temperature = 0; //温度,10倍于原值
////AM2321温湿度计//////////////////////////////////////////////
#define I2C_Address_AM2321 0x5C //AM2321温湿度计I2C地址
const unsigned char Param_AM2321_Read = 0x03; //读寄存器命令
const unsigned char REG_AM2321_Humidity_MSB = 0x00; //湿度寄存器高位
const unsigned char REG_AM2321_Humidity_LSB = 0x01; //湿度寄存器低位
const unsigned char REG_AM2321_Temperature_MSB = 0x02; //温度寄存器高位
const unsigned char REG_AM2321_Temperature_LSB = 0x03; //温度寄存器低位
unsigned int AM2321_Humidity = 0; //湿度,10倍于原值
int AM2321_Temperature = 0; //温度,10倍于原值
////EEPROM储存芯片//////////////////////////////////////////////
#define I2C_Address_EEPROM 0x53 //EEPROM储存芯片I2C地址
// unsigned int DATA_EEPROM_TotalKB = 32; //芯片总容量,AT24C256 - 32Kbyte
unsigned int DATA_EEPROM_TotalKB = 64; //芯片总容量,AT24C512 - 64Kbyte
unsigned int DATA_EEPROM_DataUsed = 0; //已使用数据个数
const unsigned char DATA_EEPROM_DataLength = 24; //每个数据长度,24字节
const unsigned int DATA_EEPROM_DataFirst = 0x20; //首个数据地址
const unsigned int REG_EEPROM_TotalKB = 0x00; //EEPROM芯片总容量(Kbyte),2字节
// const unsigned int REG_EEPROM_DataLength = 0x02; //每个数据长度(Byte),1字节
const unsigned int REG_EEPROM_DataUsed = 0x03; //已使用数据个数,2字节
// const unsigned int REG_EEPROM_DataFirst = 0x05; //首个数据地址,2字节
const unsigned int REG_EEPROM_LastPowerOn = 0x07; //最后开机时间,6字节
////PCF8563时钟芯片//////////////////////////////////////////////
#include <Rtc_Pcf8563.h> //PCF8563库,I2C地址:0x51
Rtc_Pcf8563 PCF8563;
#define PCF8563_Pin 2 //PCF8563时钟芯片报警中断脚
// #define I2C_Address_PCF8563 0x51 //PCF8563时钟芯片I2C地址
// #define REG_PCF8563_Year 0x08 //年
// #define REG_PCF8563_Month 0x07 //月
// #define REG_PCF8563_Week 0x06 //周
// #define REG_PCF8563_Day 0x05 //日
// #define REG_PCF8563_Hour 0x04 //时
// #define REG_PCF8563_Minute 0x03 //分
// #define REG_PCF8563_Second 0x02 //秒
// #define REG_PCF8563_Alarm_Week 0x0C //报警-周
// #define REG_PCF8563_Alarm_Day 0x0B //报警-日
// #define REG_PCF8563_Alarm_Hour 0x0A //报警-时
// #define REG_PCF8563_Alarm_Minute 0x09 //报警-分
// #define REG_PCF8563_Control_1 0x00 //控制状态1
// #define REG_PCF8563_Control_2 0x01 //控制状态2
// #define REG_PCF8563_Frequency 0x0D //频率寄存器
// #define REG_PCF8563_Timer_1 0x0E //定时器1寄存器
// #define REG_PCF8563_Timer_2 0x0F //定时器倒计数寄存器
// unsigned char Time_year, Time_month, Time_day, Time_hour, Time_minute, Time_sec;
////模块电源MOS开关//////////////////////////////////////////////
#define PowerSwitch_Pin_EEPROM 8 //EEPROM电源开关 针脚位
#define PowerSwitch_Pin_Sensor 7 //传感器电源开关 针脚位
// #define PowerSwitch_Pin_Radio 6 //无线模块电源开关 针脚位
#define PowerSwitch_Pin_Radio 10 //无线模块电源开关 针脚位
#define Open_EEPROM() {digitalWrite(PowerSwitch_Pin_EEPROM,HIGH);delay(10);} //开EEPROM电源开关
#define Close_EEPROM() {delay(10);digitalWrite(PowerSwitch_Pin_EEPROM,LOW);} //关EEPROM电源开关
#define Open_Sensor() {digitalWrite(PowerSwitch_Pin_Sensor,HIGH);delay(1000);} //开传感器电源开关
#define Close_Sensor() {digitalWrite(PowerSwitch_Pin_Sensor,LOW);} //关传感器电源开关
#define Open_Radio() {digitalWrite(PowerSwitch_Pin_Radio,HIGH);delay(2000);} //开无线数传模块电源开关
#define Close_Radio() {if(!PowerSwitch_Radio_Enable){delay(1000);digitalWrite(PowerSwitch_Pin_Radio,LOW);}} //关无线数传模块电源开关
bool NoSleep = 0; //是否强制不进入休眠模式
bool PowerSwitch_Radio_Enable = 0; //是否强制无线模块电源一直开着
//串口部分////////////////////////////////////////////////
String comdata = ""; //串口读取数据值
unsigned int CommandVal = 0; //串口命令值,0表示没有命令
//串口命令值
#define Command_EEPROM_AllAndEccAndClear 0x01 //传输所有数据(带CRC校验)
#define Command_EEPROM_AllNoEccAndClear 0x02 //无确认传输所有数据
#define Command_EEPROM_AllNoEccNoClear 0x03 //无确认传输所有数据,不清除EEPROM数据
#define Command_EEPROM_AllNoEccNoClearFormat 0x04 //无确认传输所有数据,不清除EEPROM数据,间隔1.5s,用于向LCD传输数据
#define Command_EEPROM_LastNoEccNoClearFormat 0x05 //无确认传输最后一个数据,不清除EEPROM数据,格式化回传数据
#define Command_ReadImmediately 0x06 //读当前数据并传输
#define Command_CurrentTime 0x07 //传输当前时间
#define Command_SetTime 0x08 //设置当前时间
// #define Command_EEPROM_LastPowerOn 0x09 //读最后开机时间
#define Command_EEPROM_Information 0x0A //传输当前EEPROM信息
#define Command_EEPROM_TotalKB 0x0B //设置EEPROM芯片总容量(KByte)
#define Command_EEPROM_Clear 0x0C //清空EEPROM中所有数据(将已使用数据个数写0)
#define Command_PowerSwitch_Radio_OPEN 0x0D //强制开启无线模块电源
#define Command_NoSleep 0x0E //强制不进入休眠模式
#define Command_EEPROM_WritePresent 0x0F //将当前数据写入EEPROM
//////////////////////////////////////////////////
volatile bool IntTime = 0; //判断是否产生时间中断
volatile bool IntButton = 0; //判断是否按下按钮
//外部中断0////////////////////////////////////////////////
void Int_time() //时钟唤醒中断
{
SMCR &= ~(1<<SE); //停止休眠
detachInterrupt(0); //禁止再次接收时钟中断
IntTime = 1; //告知程序已经在时钟唤醒中断内
}
//外部中断1////////////////////////////////////////////////
void Int_button() //按钮中断
{
SMCR &= ~(1<<SE); //停止休眠
detachInterrupt(1); //禁止再次接收时钟中断
IntButton = 1; //按钮按下
}
void setup()
{
//针脚位设置
pinMode(PCF8563_Pin, INPUT); //时钟芯片中断 针脚位
pinMode(Test_Button_Pin, INPUT); //测试用按钮 针脚位
pinMode(Test_LED_Pin, OUTPUT); //测试用灯 针脚位
// pinMode(Wind_speed_Pin, OUTPUT); //风速霍尔传感器 针脚位
pinMode(PowerSwitch_Pin_EEPROM, OUTPUT); //EEPROM芯片 电源开关 针脚位
pinMode(PowerSwitch_Pin_Sensor, OUTPUT); //传感器 电源开关 针脚位
pinMode(PowerSwitch_Pin_Radio, OUTPUT); //无线模块 电源开关 针脚位
//电压检测设置
analogReference(INTERNAL); //选择片内1.1V基准电压源
//MCU休眠设置
SMCR = 0x04; //休眠模式 - 掉电模式
Serial.begin(9600); //串口波特率设置
Wire.begin(); //开启I2C总线
Open_Radio(); //打开无线模块
//时钟芯片首次定时唤醒时间设置
PCF8563.getDate(); //获取当前日期
PCF8563.getTime(); //获取当前时间
PCF8563.setAlarm((PCF8563.getMinute()<30?30:0), 99, 99, 99); //分、时、日、周,设置为99时此位无效
//写入EEPROM首数据
// EEP.write(I2C_Address_EEPROM, REG_EEPROM_TotalKB, DATA_EEPROM_TotalKB); //EEPROM芯片总容量(Kbyte)
// EEP.write(I2C_Address_EEPROM, REG_EEPROM_DataLength, DATA_EEPROM_DataLength); //每个数据长度(Byte)
// EEP.write(I2C_Address_EEPROM, REG_EEPROM_DataFirst, DATA_EEPROM_DataFirst); //首个数据地址
// delay(10); //EEPROM读写转换周期
//读出现在芯片的已使用数据个数
DATA_EEPROM_DataUsed = I2C.read(I2C_Address_EEPROM, REG_EEPROM_DataUsed, 2); //已使用数据个数
delay(10); //EEPROM读写转换周期
//EEPROM写最后开机时间
EEP.write(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn, (unsigned char)PCF8563.getYear()); //年
EEP.write(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+1, (unsigned char)PCF8563.getMonth()); //月
EEP.write(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+2, (unsigned char)PCF8563.getDay()); //日
EEP.write(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+3, (unsigned char)PCF8563.getHour()); //时
EEP.write(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+4, (unsigned char)PCF8563.getMinute()); //分
EEP.write(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+5, (unsigned char)PCF8563.getSecond()); //秒
//开机校准方向
// Test_init();
// delay(1000);
//外部中断
attachInterrupt(1, Int_button, LOW); //按钮中断(此设置一定要在开机校准方向后)
attachInterrupt(0, Int_time, FALLING); //时钟芯片中断
digitalWrite(Test_LED_Pin, 1); //打开测试灯
delay(100); //延时
digitalWrite(Test_LED_Pin, 0); //关闭测试灯
}
void loop()
{
unsigned long _time = millis(); //用于超时
while(1)
{
//串口读取
if(Serial.available() > 0)
{
while(Serial.available() > 0) //当串口有信息传入,读取之
{
comdata += char(Serial.read());
delay(2);
}
if(comdata.length() > 0)
{
//串口命令格式:头字($*)+ 命令数(2位数字);例:$*01
if(comdata.substring(0,2) == "$*") CommandVal = (comdata.substring(2,4)).toInt(); //命令头字
comdata = ""; //清空变量
}
if(CommandVal) //如果有命令
{
Wireless(CommandVal);
CommandVal = 0; //清空命令值
}
_time = millis(); //重新开始超时循环
}
if(IntTime) //时钟中断发生
{
//打开无线模块电源
Open_Radio();
//读取传感器数据
Serial.print(PCF8563.formatDate(2)); Serial.print(' '); Serial.print(PCF8563.formatTime()); Serial.print(' '); Serial.println("Reading sensor..."); Serial.println();
Sensor_Read();
//串口输出当前数据
Serial.print("&*");
Serial.print(PCF8563.formatDate(2)); Serial.print(','); Serial.print(PCF8563.formatTime(2)); Serial.print(',');
Serial.print(Voltage_Result); Serial.print(',');
Serial.print(AM2321_Temperature); Serial.print(',');
Serial.print(AM2321_Humidity); Serial.print(',');
Serial.print(BMP085_Pressure); Serial.print(',');
Serial.print(BH1751FVI_Result); Serial.print(',');
Serial.print(HMC5883L_Result); Serial.println(';'); Serial.println();
//把数据存入EEPROM
EEPROM_Write();
Serial.print(PCF8563.formatDate(2)); Serial.print(' '); Serial.print(PCF8563.formatTime()); Serial.print(' '); Serial.println("EEPROM write OK."); Serial.println();
//设置时钟芯片下次定时时间
PCF8563.setAlarm((PCF8563.getMinute()<30?30:0), 99, 99, 99); //设置时钟芯片唤醒时间,分、时、日、周,设置为99时此位无效
IntTime = 0; //告知程序已经出了时钟唤醒中断
attachInterrupt(0, Int_time, FALLING); //重新打开时钟芯片中断
_time = millis(); //重新开始超时循环
}
if(IntButton) //按钮被按下
{
Open_Radio(); //打开无线模块电源
if(!NoSleep) //进入无休眠、无线模块强制打开状态
{
NoSleep = 1; //打开强制无休眠模式
PowerSwitch_Radio_Enable = 1; //打开强制开启无线模块模式
Serial.println("No sleep.");
Serial.println();
digitalWrite(Test_LED_Pin, 1); //打开测试灯
delay(50); //延时去毛刺,同时用于闪灯
digitalWrite(Test_LED_Pin, 0); //关闭测试灯
delay(100);
digitalWrite(Test_LED_Pin, 1); //打开测试灯
delay(50); //延时去毛刺,同时用于闪灯
digitalWrite(Test_LED_Pin, 0); //关闭测试灯
}
else //进入正常状态
{
NoSleep = 0; //关闭强制无休眠模式
PowerSwitch_Radio_Enable = 0; //关闭强制开启无线模块模式
Serial.println("Sleep mode.");
Serial.println();
digitalWrite(Test_LED_Pin, 1); //打开测试灯
delay(100); //延时去毛刺,同时用于闪灯
digitalWrite(Test_LED_Pin, 0); //关闭测试灯
delay(500);
}
IntButton = 0; //按钮复位
attachInterrupt(1, Int_button, FALLING); //再次打开中断
_time = millis(); //重新开始超时循环
}
if((millis() - _time) > 30000) break; //超时设置,30s内无串口命令则跳出循环进入休眠模式
}
//启动MCU休眠模式,直到被外部中断唤醒(时钟芯片或串口读取到数据)
if(!NoSleep)
{
Serial.print(PCF8563.formatDate(2)); Serial.print(' '); Serial.print(PCF8563.formatTime()); Serial.print(' '); Serial.println("Sleep."); Serial.println();
PowerSwitch_Radio_Enable = 0; //关闭强制开启无线模块模式
Close_Radio(); //关闭无线模块
SMCR |= (1<<SE); //开启休眠模式
__asm__ __volatile__ ("SLEEP"); //进入休眠模式
}
}
////串口输入模块//////////////////////////////////////////////
String Wait_Input()
{
bool _Judge = 0; //判断是否完成输入
String _comdata = ""; //串口输入临时变量
while(_Judge == 0) //判断输入完成后退出循环
{
while(Serial.available() > 0) //等待串口输入
{
_comdata += char(Serial.read());
delay(2);
}
if(_comdata.length() > 0) _Judge = 1; //将判断字设为true退出循环
}
return _comdata;
}
//串口输出当前数据
void Print_CurrentData()
{
//注意:需确保串口无线数传模块已经开启
Serial.print(PCF8563.formatDate(2)); Serial.print(' '); Serial.println(PCF8563.formatTime(2));
Serial.print("Vol: "); Serial.print(float(Voltage_Result)/100); Serial.println(" V");
Serial.print("Tem: "); Serial.print(float(AM2321_Temperature)/10); Serial.println(" ^C");
Serial.print("Hum: "); Serial.print(float(AM2321_Humidity)/10); Serial.println(" %RH");
Serial.print("Pre: "); Serial.print(BMP085_Pressure); Serial.println(" Pa");
Serial.print("Lig: "); Serial.print(BH1751FVI_Result); Serial.println(" lx");
Serial.print("Geo: "); Serial.print(HMC5883L_Result); Serial.println(" ^");
Serial.println();
}
////开机校准方向//////////////////////////////////////////////
/* void Test_init()
{
int _x, _y, _z;
HMC5883L_init(); //配置HMC5883L
Serial.print(PCF8563.formatDate(2)); Serial.print(' '); Serial.println(PCF8563.formatTime());
Serial.println("Set dir.");
Serial.println();
unsigned long _time = millis(); //用于超时
while(1)
{
//读取地磁方向
I2C.write(I2C_Address_HMC5883L, REG_HMC5883L_X); //发送测量命令
delay(10); //等待转换结果
//接收6个字节
Wire.beginTransmission(I2C_Address_HMC5883L);
Wire.requestFrom(I2C_Address_HMC5883L, 6);
_x += Wire.read()<<8 | Wire.read(); //X轴数据
_z += Wire.read()<<8 | Wire.read(); //Z轴数据
_y += Wire.read()<<8 | Wire.read(); //Y轴数据
Wire.endTransmission();
//计算地磁方向
HMC5883L_Result = ((atan2(_y, _x) + M_PI) * 180 / M_PI);
//纠正磁偏角
HMC5883L_Result -= HMC5883L_Declination;
if(HMC5883L_Result < 0) HMC5883L_Result = 360 - HMC5883L_Result;
else if(HMC5883L_Result > 359) HMC5883L_Result -= 360;
//判断是否在90度方向
if(HMC5883L_Result%90 == 0) digitalWrite(Test_LED_Pin, 0); //如果地磁在4个90度方向,关闭测试LED
else digitalWrite(Test_LED_Pin, 1); //否则打开测试LED
//判断是否按下按钮
if(!digitalRead(Test_Button_Pin)) //按下测试按钮后退出
{
digitalWrite(Test_LED_Pin, 0); //关闭测试灯
Serial.println("Dir set OK.");
Serial.println();
break;
}
//判断是否超时
if(millis() - _time > 30000) //如果操作时间大于30s,超时退出
{
digitalWrite(Test_LED_Pin, 0);
Serial.println("Dir set OT.");
Serial.println();
break;
}
}
I2C.write(I2C_Address_HMC5883L, REG_HMC5883L_Mode, (unsigned char)0x01); //将HMC5883L芯片设置到闲置模式
} */
////读取传感器//////////////////////////////////////////////
void Sensor_Read()
{
Open_Sensor(); //打开传感器电源
delay(2000);
HMC5883L_init(); //配置HMC5883L
BMP085_init(); //读取BMP085的校准值
PCF8563.getDate(); //获取当前日期
PCF8563.getTime(); //获取当前时间
AM2321_Read(); //温、湿度值
BMP085_read_Temperature(); //温度(读大气压之前必须读此温度值,作为大气压校准)
BMP085_read_Pressure(); //大气压
BH1751FVI_Read(); //光照度
HMC5883L_Read(); //地磁方向
Voltage_Result = Voltage_Read(); //电压
Close_Sensor(); //关闭传感器电源
}
////数据写入EEPROM//////////////////////////////////////////////
void EEPROM_Write()
{
Open_EEPROM(); //打开EEPROM电源
delay(10);
//写入地址=数据首地址 + 每个数据长度 * 当前已使用数据个数
DATA_EEPROM_DataUsed = I2C.read(I2C_Address_EEPROM, REG_EEPROM_DataUsed, 2); //再次核对已使用数据个数
delay(10); //EEPROM读写周期
unsigned int writeAdd = DATA_EEPROM_DataFirst + DATA_EEPROM_DataLength * DATA_EEPROM_DataUsed;
//写入EEPROM
EEP.write(I2C_Address_EEPROM, writeAdd, (unsigned char)PCF8563.getYear()); //年
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+1, (unsigned char)PCF8563.getMonth()); //月
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+2, (unsigned char)PCF8563.getDay()); //日
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+3, (unsigned char)PCF8563.getHour()); //时
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+4, (unsigned char)PCF8563.getMinute()); //分
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+5, Voltage_Result); //电压
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+7, AM2321_Temperature); //温度
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+9, AM2321_Humidity); //湿度
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+11, BMP085_Pressure); //大气压
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+15, BH1751FVI_Result); //光照度
delay(10); //EEPROM写周期
EEP.write(I2C_Address_EEPROM, writeAdd+17, HMC5883L_Result); //地磁方向
delay(10); //EEPROM写周期
DATA_EEPROM_DataUsed++; //已使用数据个数增一位
EEP.write(I2C_Address_EEPROM, REG_EEPROM_DataUsed, DATA_EEPROM_DataUsed); //已使用数据个数写入EEPROM
delay(10); //EEPROM读写周期
//校验EEPROM写入数据(未写)
Close_EEPROM(); //关闭EEPROM电源
}
////读取EEPROM数据//////////////////////////////////////////////
void EEPROM_Read(unsigned int num, bool crc, bool clear, bool format)
{
//如果EEPROM中没有数据
if(DATA_EEPROM_DataUsed == 0)
{
Serial.println("EEPROM no data."); //传输出错信息
Serial.println();
return;
}
String _date, _time;
unsigned char _tmp;
//读取地址 = 数据首地址 + 每个数据长度 * (需要读取的位数 - 1)
unsigned int ReadAdd = DATA_EEPROM_DataFirst + DATA_EEPROM_DataLength * (num - 1);
//读EEPROM内容
_date = "20" + (String)I2C.read(I2C_Address_EEPROM, ReadAdd, 1); //年
_tmp = I2C.read(I2C_Address_EEPROM, ReadAdd+1, 1);
if(_tmp < 10) _date = _date + "-0" + (String)_tmp; //月
else _date = _date + '-' + (String)_tmp;
_tmp = I2C.read(I2C_Address_EEPROM, ReadAdd+2, 1);
if(_tmp < 10) _date = _date + "-0" + (String)_tmp; //日
else _date = _date + '-' + (String)_tmp;
_tmp = I2C.read(I2C_Address_EEPROM, ReadAdd+3, 1);
if(_tmp < 10) _time = '0' + (String)_tmp; //时
else _time = (String)_tmp;
_tmp = I2C.read(I2C_Address_EEPROM, ReadAdd+4, 1);
if(_tmp < 10) _time = _time + ":0" + (String)_tmp; //分
else _time = _time + ':' + (String)_tmp;
Voltage_Result = I2C.read(I2C_Address_EEPROM, ReadAdd+5, 2); //电压
AM2321_Temperature = (int)I2C.read(I2C_Address_EEPROM, ReadAdd+7, 2); //温度(需转换为int类型)
AM2321_Humidity = I2C.read(I2C_Address_EEPROM, ReadAdd+9, 2); //湿度
BMP085_Pressure = I2C.read(I2C_Address_EEPROM, ReadAdd+11, 4); //大气压
BH1751FVI_Result = I2C.read(I2C_Address_EEPROM, ReadAdd+15, 2); //光照度
HMC5883L_Result = I2C.read(I2C_Address_EEPROM, ReadAdd+17, 2); //地磁方向
//已使用数据个数减一位
if(clear)
{
delay(10); //EEPROM读写转换周期
DATA_EEPROM_DataUsed--;
I2C.write(I2C_Address_EEPROM, REG_EEPROM_DataUsed, DATA_EEPROM_DataUsed); //写入EEPROM
delay(10); //EEPROM写周期
}
//无线发送数据
if(format) //发送格式化数据
{
Serial.print(_date); Serial.print(' '); Serial.println(_time);
Serial.print("Vol: "); Serial.print(float(Voltage_Result)/100); Serial.println(" V");
Serial.print("Tem: "); Serial.print(float(AM2321_Temperature)/10); Serial.println(" ^C");
Serial.print("Hum: "); Serial.print(float(AM2321_Humidity)/10); Serial.println(" %RH");
Serial.print("Pre: "); Serial.print(BMP085_Pressure); Serial.println(" Pa");
Serial.print("Lig: "); Serial.print(BH1751FVI_Result); Serial.println(" lx");
Serial.print("Geo: "); Serial.print(HMC5883L_Result); Serial.println(" ^");
Serial.println();
}
else //发送打包数据
{
Serial.print("&*");
Serial.print(_date); Serial.print(',');
Serial.print(_time); Serial.print(',');
// Serial.print(float(Voltage_Result)/100); Serial.print(',');
// Serial.print(float(AM2321_Temperature)/10); Serial.print(',');
// Serial.print(float(AM2321_Humidity)/10); Serial.print(',');
Serial.print(Voltage_Result); Serial.print(',');
Serial.print(AM2321_Temperature); Serial.print(',');
Serial.print(AM2321_Humidity); Serial.print(',');
Serial.print(BMP085_Pressure); Serial.print(',');
Serial.print(BH1751FVI_Result); Serial.print(',');
Serial.print(HMC5883L_Result); Serial.println(';');
// if(_date == PCF8563.formatDate(2)) delay(1500); //用于向LCD传输数据
Serial.println();
//加CRC校验值
// if(crc)
// {
// unsigned char _CRC = 0;
// for(unsigned char i = 0; i < SendString.length(); i++) _CRC |= SendString.charAt(i);
// SendString += (String)_CRC;
// }
}
}
////无线传输数据//////////////////////////////////////////////
void Wireless(unsigned char command)
{
//从最后一个数据开始回传,每传完一个数据就把EEPROM中的此位数据清除掉(仅减少一位数据位)
//命令:
// 1 - 传输所有数据(带CRC校验)
// 2 - 无确认传输所有数据
// 3 - 无确认传输所有数据,不清除EEPROM数据
// 4 - 无确认传输所有数据,不清除EEPROM数据,间隔1.5s,用于向LCD传输数据
// 5 - 无确认传输最后一个数据,不清除EEPROM数据,格式化回传数据
// 6 - 读当前数据并传输
// 7 - 传输当前时间
// 8 - 设置当前时间
// 9 - 读最后开机时间 - 未用
// 10 - 传输当前EEPROM信息
// 11 - 设置EEPROM芯片总容量(KByte)
// 12 - 清空EEPROM中所有数据(将已使用数据个数写0)
// 13 - 强制开启无线模块电源
// 14 - 强制不进入休眠模式
// 15 - 将当前数据写入EEPROM
Open_EEPROM(); //打开EEPROM电源
if(command == Command_EEPROM_AllAndEccAndClear) //传输所有数据(带CRC校验),每传完一个数据要求回传确认信息
{
for(unsigned int i = DATA_EEPROM_DataUsed; i >=1 ; i--) //循环读取、发送
{
EEPROM_Read(i, 1, 1, 0);
//等待回传
unsigned long _time = millis();
String comval = "";
while(1)
{
while(Serial.available() > 0) //当串口有信息传入,读取之
{
comval += char(Serial.read());
delay(2);
}
if(comval == "Next") break;
else if (comval == "Again")
{
DATA_EEPROM_DataUsed++; //已使用数据个数重新增一位
EEP.write(I2C_Address_EEPROM, REG_EEPROM_DataUsed, DATA_EEPROM_DataUsed); //写入EEPROM
delay(10); //EEPROM写周期
i++;
break;
}
if ((millis() - _time) > 2000) //超时2s直接结束
{
DATA_EEPROM_DataUsed++; //已使用数据个数重新增一位
EEP.write(I2C_Address_EEPROM, REG_EEPROM_DataUsed, DATA_EEPROM_DataUsed); //写入EEPROM
delay(10); //EEPROM写周期
i++;
Close_EEPROM(); //关闭EEPROM电源
return;
}
}
}
}
else if(command == Command_EEPROM_AllNoEccAndClear) //无确认传输所有数据
{
for(unsigned int i = DATA_EEPROM_DataUsed; i >=1 ; i--)
{
EEPROM_Read(i, 0, 1, 0);
delay(100); //间隔时间
}
}
else if(command == Command_EEPROM_AllNoEccNoClear) //无确认传输所有数据,不清除EEPROM数据
{
for(unsigned int i = DATA_EEPROM_DataUsed; i >=1 ; i--)
{
EEPROM_Read(i, 0, 0, 0);
delay(100); //间隔时间
}
}
else if(command == Command_EEPROM_AllNoEccNoClearFormat) //无确认传输所有数据,不清除EEPROM数据,间隔1.5s,用于向LCD传输数据
{
for(unsigned int i = DATA_EEPROM_DataUsed; i >=1 ; i--)
{
EEPROM_Read(i, 0, 0, 0);
delay(1500); //间隔时间
}
}
else if(command == Command_EEPROM_LastNoEccNoClearFormat) //无确认传输最后一个数据,不清除EEPROM数据
{
EEPROM_Read(DATA_EEPROM_DataUsed, 0, 0, 1);
}
else if(command == Command_ReadImmediately) //如果是要求传输当前传感器数据
{
Serial.println("Reading sensor...");
Serial.println();
Sensor_Read(); //读取当前数据
Print_CurrentData(); //串口输出当前数据
}
else if(command == Command_CurrentTime) //如果是要求传输当前时间
{
Serial.print(PCF8563.formatDate(2)); Serial.print(' '); Serial.println(PCF8563.formatTime());
// Serial.print(' '); Serial.print("Alarm: "); Serial.println(PCF8563.formatAlarmTime());
Serial.println();
}
else if(command == Command_SetTime) //如果是要求设置当前时间,输入格式为:“年月日周时分秒”,连续14个数字,如13011603234500
{
Serial.println("Input time :"); //输入提示符
String comdata = Wait_Input(); //等待串口输入
//设置时钟芯片时间值
PCF8563.setDate((comdata.substring(4,6)).toInt(), (comdata.substring(6,8)).toInt(), (comdata.substring(2,4)).toInt(), 0, (comdata.substring(0,2)).toInt()); //设置日期:日、周、月、世纪、年
PCF8563.setTime(comdata.substring(8,10).toInt(), comdata.substring(10,12).toInt(), comdata.substring(12,14).toInt()); //设置时间:时、分、秒
//设置时钟芯片下次定时时间
PCF8563.setAlarm((PCF8563.getMinute()<30?30:0), 99, 99, 99); //设置时钟芯片唤醒时间,分、时、日、周,设置为99时此位无效
Serial.print("Time set to : "); Serial.print(PCF8563.formatDate(2)); Serial.print(' '); Serial.println(PCF8563.formatTime());
Serial.println();
}
// else if(command == Command_EEPROM_LastPowerOn) //读取最后开机时间(会死机)
// {
// String _date, _time;
// _date = (String)I2C.read(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn, 1); //年
// _date = _date + '-' + (String)I2C.read(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+1, 1); //月
// _date = _date + '-' + (String)I2C.read(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+2, 1); //日
// _time = (String)I2C.read(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+3, 1); //时
// _time = _time + ':' + (String)I2C.read(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+4, 1); //分
// _time = _time + ':' + (String)I2C.read(I2C_Address_EEPROM, REG_EEPROM_LastPowerOn+5, 1); //秒
// Serial.print("Last poweron : ");
// Serial.print(_date); Serial.print(' '); Serial.println(_time);
// Serial.println();
// }
else if(command == Command_EEPROM_Information) //传输当前EEPROM信息
{
Serial.print("EEPROM: "); Serial.print(DATA_EEPROM_TotalKB = I2C.read(I2C_Address_EEPROM, REG_EEPROM_TotalKB, 2)); Serial.println(" Kbyte"); //EEPROM芯片总容量(Kbyte),同时更新变量数据
Serial.print("Data used: "); Serial.println(DATA_EEPROM_DataUsed = I2C.read(I2C_Address_EEPROM, REG_EEPROM_DataUsed, 2)); //已使用数据个数,同时更新变量数据
Serial.print("Data remain: "); Serial.println((DATA_EEPROM_TotalKB*1024 - DATA_EEPROM_DataFirst - DATA_EEPROM_DataUsed * DATA_EEPROM_DataLength) /DATA_EEPROM_DataLength); //剩余可使用数据个数=(芯片总容量-首个数据地址-已使用数据个数*每个数据长度)/每个数据长度
Serial.println();
}
else if(command == Command_EEPROM_TotalKB) //设置EEPROM总容量(KByte)
{
Serial.println("Input EEPROM size (KByte)."); //输入提示符
String comdata = Wait_Input(); //等待串口输入
EEP.write(I2C_Address_EEPROM, REG_EEPROM_TotalKB, (unsigned int)comdata.toInt());
delay(10); //EEPROM读写转换周期
Serial.print("EEPROM size set to ");
Serial.print(DATA_EEPROM_TotalKB = I2C.read(I2C_Address_EEPROM, REG_EEPROM_TotalKB, 2)); //同时向变量赋值
Serial.println(" KByte.");
Serial.println();
}
else if(command == Command_EEPROM_Clear) //清空EEPROM中所有数据
{
DATA_EEPROM_DataUsed = 0;
EEP.write(I2C_Address_EEPROM, REG_EEPROM_DataUsed, (unsigned int)0); //清零已使用数据个数
delay(10);
Serial.println("EEPROM clear.");
Serial.println();
}
else if(command == Command_PowerSwitch_Radio_OPEN) //强制开启无线模块电源
{
PowerSwitch_Radio_Enable = !PowerSwitch_Radio_Enable;
if(PowerSwitch_Radio_Enable) Serial.println("Radio open.");
else Serial.println("Radio close.");
Serial.println();
}
else if(command == Command_NoSleep) //强制开启无线模块电源
{
NoSleep = !NoSleep;
if(NoSleep) Serial.println("Sleep disenable.");
else Serial.println("Sleep enable.");
Serial.println();
}
else if(command == Command_EEPROM_WritePresent) //将当前数据写入EEPROM
{
EEPROM_Write();
Serial.println("EEPROM write OK.");
Serial.println();
}
Close_EEPROM(); //关闭EEPROM电源
}
////光照度 读取//////////////////////////////////////////////
void BH1751FVI_Read()
{
unsigned long _Result = 0;
//发送测量命令
I2C.write(I2C_Address_BH1751FVI, BH1751FVI_Mode); //发送测量模式命令
for(unsigned char i = 0; i < 15; i++)
{
//读取数据
delay(130); //等待转换结果
_Result += I2C.read(I2C_Address_BH1751FVI, 2); //回传测量结果,2个字节
}
BH1751FVI_Result = _Result/15; //计算平均值
//关闭BH1751FVI芯片
I2C.write(I2C_Address_BH1751FVI, Param_BMP085_Close); //发送关闭命令
//计算最终值
unsigned int tmp = 0;
for(unsigned char i = 0; i < 16; i++) tmp += pow(2*((BH1751FVI_Result>>i)&1), i);
//返回测量结果
BH1751FVI_Result = tmp/1.2;
}
////气压值 读取//////////////////////////////////////////////
//读校准值
void BMP085_init()
{
ac1 = (int)I2C.read(I2C_Address_BMP085, (unsigned char)0xAA, 2);
ac2 = (int)I2C.read(I2C_Address_BMP085, (unsigned char)0xAC, 2);
ac3 = (int)I2C.read(I2C_Address_BMP085, (unsigned char)0xAE, 2);
ac4 = I2C.read(I2C_Address_BMP085, (unsigned char)0xB0, 2);
ac5 = I2C.read(I2C_Address_BMP085, (unsigned char)0xB2, 2);
ac6 = I2C.read(I2C_Address_BMP085, (unsigned char)0xB4, 2);
b1 = (int)I2C.read(I2C_Address_BMP085, (unsigned char)0xB6, 2);
b2 = (int)I2C.read(I2C_Address_BMP085, (unsigned char)0xB8, 2);
mb = (int)I2C.read(I2C_Address_BMP085, (unsigned char)0xBA, 2);
mc = (int)I2C.read(I2C_Address_BMP085, (unsigned char)0xBC, 2);
md = (int)I2C.read(I2C_Address_BMP085, (unsigned char)0xBE, 2);
}
//读取温度(返回真实值的10倍)
void BMP085_read_Temperature()
{
unsigned int ut;
unsigned long ut_clac = 0;
for(unsigned char i = 0; i < 3; i++)
{
//读取未补偿的温度值(每秒一次)
I2C.write(I2C_Address_BMP085, REG_BMP085_Command, Param_BMP085_Temperature); //请求读取温度
delay(5); //至少等待4.5ms
//从测量值寄存器读取两个字节
ut_clac += I2C.read(I2C_Address_BMP085, REG_BMP085_MSB, 2);
delay(1000);
}
ut = ut_clac/3; //计算平均值
//计算温度值
b5 = ((((long)ut - (long)ac6)*(long)ac5) >> 15) + (((long)mc << 11)/(((((long)ut - (long)ac6)*(long)ac5) >> 15) + md));
BMP085_Temperature = ((b5 + 8)>>4);
}
//读取气压(Pa)
void BMP085_read_Pressure()
{
unsigned long up, up_clac = 0, b4;
long b3, p;
for(unsigned char i = 0; i < 64; i++)
{
//读取未补偿的压力值(最多每秒128次)
I2C.write(I2C_Address_BMP085, REG_BMP085_Command, (unsigned char)(0x34 + (OSS<<6))); //写请求读取气压
//等待转换,延迟时间依赖于OSS
delay(2 + (3<<OSS));
//读取测量值寄存器
I2C.write(I2C_Address_BMP085, REG_BMP085_MSB);
Wire.beginTransmission(I2C_Address_BMP085);
Wire.requestFrom(I2C_Address_BMP085, 3);
up_clac += (((unsigned long) Wire.read() << 16) | ((unsigned long) Wire.read() << 8) | (unsigned long) Wire.read()) >> (8-OSS);
Wire.endTransmission();
delay(10);
}
up = up_clac/64; //计算平均值
//计算气压值
b3 = (ac4 * (unsigned long)((((((ac3 * (b5-4000))>>13) + (((b5-4000) * (((b5-4000) * (b5-4000))>>12))>>16)) + 2)>>2) + 32768))>>15;
b4 = ((unsigned long)(up - ((((((long)ac1)*4 + (((b2 * ((b5-4000) * (b5-4000))>>12)>>11) + ((ac2 * (b5-4000))>>11)))<<OSS) + 2)>>2)) * (50000>>OSS));
if(b4 < 0x80000000) p = (b4<<1)/b3;
else p = (b4/b3)<<1;
BMP085_Pressure = p + ((((((p>>8) * (p>>8)) * 3038)>>16) + ((-7357 * p)>>16) + 3791)>>4);
}
////地磁方向 读取 (没有校准过程)//////////////////////////////////////////////
void HMC5883L_init()
{
I2C.write(I2C_Address_HMC5883L, REG_HMC5883L_SetA, (unsigned char)0x78); //配置寄存器A,平均采样数8、输出速率75Hz
I2C.write(I2C_Address_HMC5883L, REG_HMC5883L_SetB, (unsigned char)0x20); //配置寄存器B,增益1090高斯
I2C.write(I2C_Address_HMC5883L, REG_HMC5883L_Mode, (unsigned char)0x00); //模式寄存器,连续测量模式
}
void HMC5883L_Read()
{
int _x, _y, _z;
long x_clac = 0, y_clac = 0, z_clac = 0;
for(unsigned char i = 0; i < 15; i++)
{
//发送测量命令
I2C.write(I2C_Address_HMC5883L, REG_HMC5883L_X);
delay(10); //等待转换结果
//接收6个字节
Wire.beginTransmission(I2C_Address_HMC5883L);
Wire.requestFrom(I2C_Address_HMC5883L, 6);
x_clac += Wire.read()<<8 | Wire.read(); //X轴数据
z_clac += Wire.read()<<8 | Wire.read(); //Z轴数据
y_clac += Wire.read()<<8 | Wire.read(); //Y轴数据
Wire.endTransmission();
delay(50);
}
_x = x_clac/15;
_y = y_clac/15;
_z = z_clac/15;
//计算地磁方向
HMC5883L_Result = ((atan2(_y, _x) + M_PI) * 180 / M_PI);
//纠正磁偏角
HMC5883L_Result -= HMC5883L_Declination;
if(HMC5883L_Result < 0) HMC5883L_Result = 360 - HMC5883L_Result;
else if(HMC5883L_Result > 359) HMC5883L_Result -= 360;
//将HMC5883L芯片设置到闲置模式
I2C.write(I2C_Address_HMC5883L, REG_HMC5883L_Mode, (unsigned char)0x01);
}
////AM2302 温湿度 读取//////////////////////////////////////////////
void AM2302_Read() //读取AM2302数据值
{
//注意:两次读取间隔至少2s,长时间未读取的话,第一次值不能用,因为读到的是上一次读取完后模块自己读的值
unsigned char CRC;
unsigned int CRC_tmp;
long Temperature_clac = 0;
unsigned long Humidity_clac = 0;
for(unsigned char i = 0; i < 6; i++)
{
AM2302_Temperature = 0;
AM2302_Humidity = 0;
CRC = 0; //CRC校验值(读取出来的)
pinMode(AM2302_Pin, OUTPUT); //设置为输出状态
digitalWrite(AM2302_Pin, LOW); //输出低电平
delay(18);
pinMode(AM2302_Pin, INPUT); //设置为输入状态
if(pulseIn(AM2302_Pin, HIGH)); //等待80us高电平,80ms或50ms的低电平不管它
//读取数据
for(char i = 15; i >= 0; i--) //读16bit的湿度值
{
if(pulseIn(AM2302_Pin, HIGH) > 60) bitSet(AM2302_Humidity, i); //读取26us或70us高电平
}
for(char i = 15; i >= 0; i--) //读16bit的温度值
{
if(pulseIn(AM2302_Pin, HIGH) > 60) bitSet(AM2302_Temperature, i); //读取26us或70us高电平
}
for(char i = 7; i >= 0; i--) //读8bit的CRC值
{
if(pulseIn(AM2302_Pin, HIGH) > 60) bitSet(CRC, i); //读取26us或70us高电平
}
if(i == 0) goto breakfirst; //去掉第一次的值
//校验CRC
CRC_tmp = 0; //CRC校验计算值
for(char i = 15; i >= 0; i--)
{
CRC_tmp = (AM2302_Humidity >> 8) + (AM2302_Humidity & 0x00FF) + (AM2302_Temperature >> 8) + (AM2302_Temperature & 0x00FF);
}
//修正负温度
if(AM2302_Temperature < 0) AM2302_Temperature = -(AM2302_Temperature&0x7FFF);
if((CRC_tmp & 0x00FF) == CRC) //注:校验计算值可能会超出8位,但CRC读取值只有8位,故将8位以上的数据值过滤掉
{
Temperature_clac += AM2302_Temperature;
Humidity_clac += AM2302_Humidity;
}
else i--;
breakfirst:
delay(2000);
}
AM2302_Temperature = Temperature_clac/5;
AM2302_Humidity = Humidity_clac/5;
}
////AM2321 温湿度 读取//////////////////////////////////////////////
void AM2321_Read() //读取AM2321数据值,2次间隔2s以上,本处不做CRC检验
{
long Temperature_clac = 0;
unsigned long Humidity_clac = 0;
for(unsigned char i = 0; i < 6; i++)
{
//唤醒传感器
Wire.beginTransmission(I2C_Address_AM2321);
delay(3);
Wire.endTransmission();
//发送读取温、湿度命令
Wire.beginTransmission(I2C_Address_AM2321);
Wire.write(Param_AM2321_Read);
Wire.write(REG_AM2321_Humidity_MSB);
Wire.write(4);
Wire.endTransmission();
//等待数据准备好
delay(2);
//回传数据
Wire.requestFrom(I2C_Address_AM2321, 7);
delayMicroseconds(30); //等待30us
Wire.read();
Wire.read();
AM2321_Humidity = (Wire.read()<<8) | Wire.read();
AM2321_Temperature = (Wire.read()<<8) | Wire.read();
Wire.read();
Wire.endTransmission();
//修正负温度
if(AM2321_Temperature < 0) AM2321_Temperature = -(AM2321_Temperature&0x7FFF);
if(i > 0) //舍弃第一次读取的数值
{
Temperature_clac += AM2321_Temperature;
Humidity_clac += AM2321_Humidity;
}
delay(2000);
}
AM2321_Temperature = Temperature_clac/5;
AM2321_Humidity = Humidity_clac/5;
}