MS5611气压计数据采集(模拟IIC)/温度采集/相对高度求解

1、 MS5611气压计属性

1.1 基础属性

MS5611使用24位ADC,可以采集温度和气压,并且温度可以用来补偿气压,MS5611在出厂时进行了校准,校准的6个系数存储在PROM寄存器中, PROM寄存器起始地址0XA0, 从0xA0到0XAE, 一共16字节, 一共16*8 = 128位,其中每两个字节为一个系数:
第一个系数: 制造商定的,我们不用在意
第二到第七个系数:我们需要读取,后面用于气压计算
第八个系数:CRC

1.2 5个命令(COMMANDS)


分别是:
1、复位
2、读取PROM
3、D1转换, 其实就是设置读取气压的一些参数,然后MS5611会返回24字节(下文会说明)
4、D2转换,其实就是设置读取温度的一些参数
5、读取ADC中的数据

1.3 SPI和IIC接口

IIC模式:PS拉高
SPI模式:PS拉低
本实验用的是模拟IIC读取数据
IIC模式中CSB拉低时, IIC从设备地址为0111 0111, CSB拉高时,IIC设备地址为0111 0110

2、 温度气压读取

IIC开始、结束、等待ack、读取发送函数等(参考匿名)

#define MS5611_ADDR             0x77   //0xee //
#define CMD_RESET               0x1E // ADC reset command
#define CMD_ADC_READ            0x00 // ADC read command
#define CMD_ADC_CONV            0x40 // ADC conversion command
#define CMD_ADC_D1              0x00 // ADC D1 conversion
#define CMD_ADC_D2              0x10 // ADC D2 conversion
#define CMD_ADC_256             0x00 // ADC OSR=256
#define CMD_ADC_512             0x02 // ADC OSR=512
#define CMD_ADC_1024            0x04 // ADC OSR=1024
#define CMD_ADC_2048            0x06 // ADC OSR=2048
#define CMD_ADC_4096            0x08 // ADC OSR=4096
#define CMD_PROM_RD             0xA0 // Prom read command
#define PROM_NB                 8
#define MS5611_OSR              0x08    //CMD_ADC_4096//开始信号
int I2c_Soft_Start()
{MS5611_IIC_SDA = 1;MS5611_IIC_SCL = 1;delay_us(4);if(!MS5611_READ_SDA)return 0;  //SDA线为低电平则总线忙,退出MS5611_IIC_SDA = 0;delay_us(4);if(MS5611_READ_SDA) return 0;  //SDA线为高电平则总线出错,退出MS5611_IIC_SDA = 0;delay_us(4);return 1; }
//结束信号
void I2c_Soft_Stop()
{MS5611_IIC_SCL = 0;delay_us(4);MS5611_IIC_SDA = 0;delay_us(4);MS5611_IIC_SCL = 1;delay_us(4);MS5611_IIC_SDA = 1;delay_us(4);
}
//应答
void I2c_Soft_Ask()
{MS5611_IIC_SCL = 0;delay_us(4);MS5611_IIC_SDA = 0;delay_us(4);MS5611_IIC_SCL = 1;delay_us(4);MS5611_IIC_SCL = 0;delay_us(4);
}
//非应答
void I2c_Soft_NoAsk()
{MS5611_IIC_SCL = 0;delay_us(4);MS5611_IIC_SDA = 1;delay_us(4);MS5611_IIC_SCL = 1;delay_us(4);MS5611_IIC_SCL = 0;delay_us(4);
}
// 等待回复
int I2c_Soft_WaitAsk(void)   //返回为:=1无ASK,=0有ASK
{u8 ErrTime = 0;MS5611_IIC_SCL = 0;delay_us(4);MS5611_IIC_SDA = 1;           delay_us(4);MS5611_IIC_SCL = 1;delay_us(4);while(MS5611_READ_SDA){ErrTime++;if(ErrTime>50){I2c_Soft_Stop();return 1;}}MS5611_IIC_SCL = 0;delay_us(4);return 0;
}// IIC发送一个字节
void I2c_Soft_SendByte(u8 SendByte) //数据从高位到低位//
{u8 i=8;while(i--){MS5611_IIC_SCL = 0;delay_us(4);if(SendByte&0x80)MS5611_IIC_SDA = 1;  else MS5611_IIC_SDA = 0;   SendByte<<=1;delay_us(4);MS5611_IIC_SCL = 1;delay_us(4);}MS5611_IIC_SCL = 0;
}  //读1个字节,ack=1时,发送ACK,ack=0,发送NACK
u8 I2c_Soft_ReadByte(u8 ask)  //数据从高位到低位//
{ u8 i=8;u8 ReceiveByte=0;MS5611_IIC_SDA = 1;                while(i--){ReceiveByte<<=1;      MS5611_IIC_SCL = 0;delay_us(4);MS5611_IIC_SCL = 1;delay_us(4);    if(MS5611_READ_SDA){ReceiveByte|=0x01;}}MS5611_IIC_SCL = 0;if (ask)I2c_Soft_Ask();elseI2c_Soft_NoAsk();  return ReceiveByte;
} // IIC写一个字节数据
u8 IIC_Write_1Byte(u8 SlaveAddress,u8 REG_Address,u8 REG_data)
{I2c_Soft_Start();I2c_Soft_SendByte(SlaveAddress<<1);   if(I2c_Soft_WaitAsk()){I2c_Soft_Stop();return 1;}I2c_Soft_SendByte(REG_Address);       I2c_Soft_WaitAsk();    I2c_Soft_SendByte(REG_data);I2c_Soft_WaitAsk();   I2c_Soft_Stop(); return 0;
}// IIC读1字节数据
u8 IIC_Read_1Byte(u8 SlaveAddress,u8 REG_Address,u8 *REG_data)
{           I2c_Soft_Start();I2c_Soft_SendByte(SlaveAddress<<1); if(I2c_Soft_WaitAsk()){I2c_Soft_Stop();return 1;}I2c_Soft_SendByte(REG_Address);     I2c_Soft_WaitAsk();I2c_Soft_Start();I2c_Soft_SendByte(SlaveAddress<<1 | 0x01);I2c_Soft_WaitAsk();*REG_data= I2c_Soft_ReadByte(0);I2c_Soft_Stop();return 0;
}   

2.1 第一步:初始化MS5611

初始化包括:
1、复位
2、读取PROM中的6个关键系数

// 复位
void MS5611_Reset(void)
{// MS5611_ADDR:0x77    CMD_RESET:0x1EIIC_Write_1Byte(MS5611_ADDR, CMD_RESET, 1);
}
u8 MS5611_Read_Prom(void)
{uint8_t rxbuf[2] = { 0, 0 };u8 check = 0;u8 i;for (i = 0; i < PROM_NB; i++){check += IIC_Read_nByte(MS5611_ADDR, CMD_PROM_RD + i * 2, 2, rxbuf); // send PROM READ commandms5611_prom[i] = rxbuf[0] << 8 | rxbuf[1];}if(check == PROM_NB)return 1;elsereturn 0;
}

2.2 第二步:获取温度数据


首先发送Convert D1命令,进行相应的配置,再发送ADC Read命令,然后MS5611会返回24位的温度数据, 这时候再去读取这些温度数据。

// 写入数据
void MS5611_Start_T(void)
{//CMD_ADC_CONV + CMD_ADC_D2 + MS5611_OSR = 0x48IIC_Write_1Byte(MS5611_ADDR, CMD_ADC_CONV + CMD_ADC_D2 + MS5611_OSR, 1); // D2 (temperature) conversion start!
}
// 读取24位温度数据
void MS5611_Read_Adc_T(void)
{IIC_Read_nByte( MS5611_ADDR, CMD_ADC_READ, 3, t_rxbuf ); // read ADC
}

2.3 第三步:获取气压数据


首先发送Convert D2命令,进行相应的配置,然后再发送ADC Read命令, 然后MS5611会返回24位的气压数据, 这时候再去读取这些气压数据。

// 写入数据
void MS5611_Start_P(void)
{CMD_ADC_CONV + CMD_ADC_D1 + MS5611_OSR = 0x58IIC_Write_1Byte(MS5611_ADDR, CMD_ADC_CONV + CMD_ADC_D1 + MS5611_OSR, 1); // D1 (pressure) conversion start!
}
// 读取24位气压数据
void MS5611_Read_Adc_P(void)
{IIC_Read_nByte(MS5611_ADDR, CMD_ADC_READ, 3, p_rxbuf); // read ADC
}

3、温度补偿气压


绝对高度(海拔)的求解公式:
H= 44300*(1- (P/P0)^(1/5.256) )
H为高度
P0为标准大气压(≈101Kpa)
P为读取的气压 (注意单位得和P0相同)

相对高度(例如飞机起飞前和飞行中的高度差)的求解
这里提供一个思路:
MS5611开机上电一段时间后,读取静止100组数据并转换成海拔,取个平均,这个海拔高度就相当于基准海拔,如果你把MS5611拿高或者拿低, 此时的海拔与基准海拔相见就是相对高度。
ps:求相对高度的时候,可以对此时的海拔高度数据进行一个滑动窗滤波,这样求出的相对高度比较平滑。

void MS5611_BaroAltCalculate(void)
{float height = 0;int64_t off2 = 0, sens2 = 0, delt = 0, f = 0, f2 = 0;int32_t temperature = 0, pressure = 0, T2 = 0;int32_t dT = 0;int64_t off =0, sens =0;static int num = 0;static int cnt = 0;double ms5611SumDat = 0.0;ms5611_ut = (t_rxbuf[0] << 16) | (t_rxbuf[1] << 8) | t_rxbuf[2]; // 读取的原始温度值ms5611_up = (p_rxbuf[0] << 16) | (p_rxbuf[1] << 8) | p_rxbuf[2]; // 读取的原始气压值dT = ms5611_ut - ((uint32_t)ms5611_prom[5] << 8);off = ((uint64_t)ms5611_prom[2] << 16) + (((int64_t)dT * ms5611_prom[4]) >> 7);sens = ((uint64_t)ms5611_prom[1] << 15) + (((int64_t)dT * ms5611_prom[3]) >> 8);// 实际温度: 2007:20.07 ℃temperature = 2000 + (((int64_t)dT * ms5611_prom[6]) >> 23); if (temperature < 2000) { T2 = (dT*dT)>>31;delt = temperature - 2000;delt = delt * delt;off2 = (5 * delt) >> 1;sens2 = (5 * delt) >> 2;if (temperature < -1500) { delt = temperature + 1500;delt = delt * delt;off2  += 7 * delt;sens2 += (11 * delt) >> 1;}}temperature -= T2;off  -= off2; sens -= sens2;ms5611Data.temperature = (double)temperature / 100.0;  // ℃// 温度补偿后的气压  100009 = 1000.09 mbar = 100009 Papressure = (((ms5611_up * sens ) >> 21) - off) >> 15; // mbarms5611Data.pressure = (double)pressure / 100.0;height = (double)((1.0f - pow((double)pressure / 101325.0f, 0.190295f)) * 44330.0f); // meterms5611Data.height = height;// 求相对高度// 上电100个数据后if(num > 100) {if(cnt < MS5611_WIN_FILTER){alt[cnt] = ms5611Data.height;cnt++;}else{ms5611SumDat = 0.0;for(int i=0; i<MS5611_WIN_FILTER-1; i++){alt[i] = alt[i+1];ms5611SumDat += alt[i];}alt[cnt-1] = ms5611Data.height;ms5611SumDat += alt[cnt-1];ms5611CurAlt = ms5611SumDat/MS5611_WIN_FILTER; // 当前100组数据的高度平均if(baroCalOk == true){ms5611CurAlt -= ms5611StartAlt; // 当前相对高度}}num = 100;}num++;
}

4、总结

MS5611主要是用于计算高度,比如可以用于四旋翼的定高等。
MS5611求海拔高度的时候,由于受温度,气流等各种因素的影响,最终的结果并不理想,
例如下面是我静止采集的30分钟左右的数据,可以明显看到高度是飘的。
最后30分钟左右是我把ms5611拿上拿下来测试的, 所以出现了上图中的波动。

MS5611气压计数据采集(模拟IIC)/温度采集/相对高度求解相关推荐

  1. STM32F407单片机移植MS5611气压计(基于IIC)---同时解决温度低于20度时计算得到的大气压错误的问题

    最近一个工程项目需要使用MS5611气压计,就花时间研究了一下,发现网上很多都是基于STM32F103单片机的MS5611气压计源程序,当移植到STM32F407时发现采集的大气压力和温度值不对,同时 ...

  2. STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出

    文章目录 前言 一.I2C总线通信协议 1.I2C总线 2.工作原理 3.I2C特点 4.I2C模式选择 5.软件I2C和硬件I2C 二.串口输出温湿度传感器的数据 1.核心代码分析 2.硬件实操连接 ...

  3. STM32基于软件模拟IIC进行AHT21B温湿度采集

    STM32基于软件模拟IIC进行AHT21B温湿度采集 一. IIC简介 1.1 IIC简介 1.2 实现方式 1.3 实现方式对比 二. AHT21B简介 2.1 简介 2.2 产品特点 2.3 外 ...

  4. MS5611气压计IIC源程序

    前段工程项目需要测量大气压力,网上搜集了MS5611气压计这方面的资料,并完全参考了相关网友的程序. 1.MYIIC.h #ifndef __MYIIC_H #define __MYIIC_H #in ...

  5. 基于正点原子STM32F103精英板IIC实验的MS5611气压计的使用

    MS5611是一款气压计,能够提供高精度的气压值与温度值,这次做项目正好需要用到这款传感器,包括之前也没好好学习用过IIC,所以写下博客记录一下. 如果有需要使用的朋友可以去https://downl ...

  6. labview串口数据采集并显示_一种NB-IoT冶金节点温度采集与远程监测系统的设计...

    大型高炉出铁量大,冶金生产环境恶劣,导致铁水沟侵蚀日益严重,需人工定期对冶金沟道部分进行温测,其准确度不高,生产成本高,安全保障低[1].为了能够对高炉冶金沟道进行全方位测温,掌握铁水沟道的温度和腐蚀 ...

  7. 包含几通道数据_温度采集,无处不测!「数据采集」

    Measurement Computing (MCC) 提供多种温度数据采集产品.低成本数据采集方案,例如USB-TEMP单模块即可提供热电偶.RTD和热敏电阻输入通道.独立式无线数据采集设备和数据记 ...

  8. Proteus 8086模拟温度采集 使用LM35温度传感器

    一.思路 使用LM35温度传感器进行温度采集,将采集到的电压值(模拟量)经过ADC0808芯片转换成数字信号经数据总线传入8086的寄存器中. 二.8086接线方式 8086的接线方式如上图所示.74 ...

  9. 多路温度采集计算机网络监测设计,多路温度信号测量与监测,数据采集 温度采集模块...

    原标题:多路温度信号测量与监测,数据采集 温度采集模块 5路热电阻温度信号转RS-485/232,温度采集转换模块 WJ25 产品特点: ● 5路温度信号采集,隔离转换 RS-485/232输出 ● ...

  10. MS5611气压计 I2C驱动代码 STM32

    文章目录 前言 通信接口:IIC 一,MS5611的5种命令 RESET : 重启芯片 READ PROM: D1,D2 CONVERSION READ ADC RESULT: 二,实现代码 1 初始 ...

最新文章

  1. 2022-2028年中国消防报警行业市场前瞻与投资战略规划分析报告
  2. 学习 Spring Boot:(二十九)Spring Boot Junit 单元测试
  3. opensource项目_推出“什么是开放式教育?” Opensource.com上的资源
  4. python 百分比输出_获取Linux系统负荷百分比的python脚本
  5. git 修改commit_结合IDEA与命令行,解决常用git操作与特殊情况的最佳实践
  6. Java解析中文数字字符串
  7. 很多的Adobe Dreamweaver CS5序列号
  8. Servlet常用依赖
  9. 前复权 后复权和不复权是什么意思
  10. 写给大学男同胞几条择偶建议
  11. 大学想选择计算机专业,零基础如何快速学习编程?都是经验之谈
  12. delphi 调用浏览器内核_深入理解浏览器原理
  13. Android 学习网站
  14. 智能制造系统解决方案和智能工厂发展趋势
  15. java技术栈 高清视频
  16. im2col函数实现超级详细解释
  17. 葫芦娃手游服务器未响应,葫芦娃充值没反应 充值元宝未到账解决办法
  18. atcoder AtCoder Beginner Contest 210 D - National Railway(dp)
  19. CAD专用卸载工具,完美彻底卸载清除干净cad各种残留注册表和文件。
  20. vulnhub Monitoring: 1

热门文章

  1. jquery 仿天猫加入购物车,小图标慢慢上升消失
  2. IOS代理协议与委托
  3. win10 搭建PHP + Apache + MySQL运行环境
  4. 宏基服务器 安装系统,宏基Acer笔记本重装系统win7图文安装教程
  5. 软件需求分析的五个步骤_建立满足用户需求的云的5个步骤
  6. 身高预测_大部分都很准哦
  7. Python 程序设计(第3版)
  8. 上行PHR余量提升优化思路
  9. 搞事情 | 众编程语言齐聚密谋:如何推翻java的统治地位!
  10. 移动心理测评系统:心理健康评估、抑郁筛查、心理学量表