1206527298 发表于 2013-11-30 00:32:43

Arduino 调用GY-86模块上的MS5611芯片经验分享

本帖最后由 1206527298 于 2013-11-30 00:36 编辑

最近刚开始研究IIC的一些东西,把研究得到的成果给各位遇到同样问题的网友分享一下~

硬件:
Arduino nano
GY-86(MPU6050+5611+HMC5883)

软件:
Arduino IDE   1.0.5

资料:
MS5611中文资料:http://wenku.baidu.com/view/ccd4ef02c5da50e2524d7f9a.html

GY-86与NANO采用 IIC 总线连接,官方给出NANO的IIC总线针脚定义为: A4 为SDA,A5为SCL,根据官方给出的针脚定义连接GY-86即可。

在这里需要简述一下我所查到的IIC总线:
Arduino主从机之间的I2C通讯实验:http://www.eefocus.com/zhang700309/blog/12-01/236815_59f78.html
——————————————————————————————————————————————————————————
I2C总线定义I2C(‘intel’ -Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。在主从通信中,可以有多个I2C总线器件同时接到I2C总线上,通过地址来识别通信对象。
    I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,最高传送速率100kbps。各种被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工作,所以每个电路和模块都有唯一的地址,在信息的传输过程中,I2C总线上并接的每一模块电路既可以是主控器(或被控器),又可以是发送器(或接收器),这取决于它所要完成的功能。
http://www.eefocus.com/include/picture/500/400/data/12-01/1325733906_401d354c.jpg

——————————————————————————————————————————————————————————
根据简述可知GY-86上的各个芯片都有自己的地址(Address),主控与芯片通信必须了解地址才行。
而根据芯片资料所示:MS5611的IIC地址是:为二进制 111011Cx,其中C为芯片CSB引脚的补码值(取反)。化为十六进制就是0x77   或0x76 两种。

这是GY-86上的MS5611电路图,(此图仅供参考)


这是单独的MS5611模块图片,由图片可看到CSB引脚定义IIC地址
http://www.drotek.fr/photos/drotek%20-%20MS5611-%20arduino%20-%20I2C.jpg

我手里的这块GY-86板子,MS5611的地址就是0x76

下面是从国外论坛查到的调用MS5611的调试代码:可以在串口监视器以及其他串口接收工具上实时查看到温度、高度等数值

——————————————————————————————————————————————————————————
#include <Wire.h>
#define ADDRESS 0x77 //0x76   IIC Address

uint32_t D1 = 0;
uint32_t D2 = 0;
int64_t dT = 0;
int32_t TEMP = 0;
int64_t OFF = 0;
int64_t SENS = 0;
int32_t P = 0;
uint16_t C;

float Temperature;
float Pressure;
const float sea_press = 1013.25;

void setup() {
// Disable internal pullups, 10Kohms are on the breakout
PORTC |= (1 << 4);
PORTC |= (1 << 5);

Wire.begin();
Serial.begin(9600); //9600 changed 'cos of timing?
delay(100);
initial(ADDRESS);

}

void loop()
{
D1 = getVal(ADDRESS, 0x48); // Pressure raw
D2 = getVal(ADDRESS, 0x58);// Temperature raw

dT   = D2 - ((uint32_t)C << 8);
OFF= ((int64_t)C << 16) + ((dT * C) >> 7);
SENS = ((int32_t)C << 15) + ((dT * C) >> 8);

TEMP = (int64_t)dT * (int64_t)C / 8388608 + 2000;

if(TEMP < 2000) // if temperature lower than 20 Celsius
{
    int32_t T1    = 0;
    int64_t OFF1= 0;
    int64_t SENS1 = 0;

    T1    = pow(dT, 2) / 2147483648;
    OFF1= 5 * pow((TEMP - 2000), 2) / 2;
    SENS1 = 5 * pow((TEMP - 2000), 2) / 4;
   
    if(TEMP < -1500) // if temperature lower than -15 Celsius
    {
      OFF1= OFF1 + 7 * pow((TEMP + 1500), 2);
      SENS1 = SENS1 + 11 * pow((TEMP + 1500), 2) / 2;
    }
   
    TEMP -= T1;
    OFF -= OFF1;
    SENS -= SENS1;
}


Temperature = (float)TEMP / 100;

P= ((int64_t)D1 * SENS / 2097152 - OFF) / 32768;

Pressure = (float)P / 100;

Serial.print("   Actual TEMP= ");
Serial.print(Temperature);
Serial.print("      Actual PRESSURE= ");
Serial.print(Pressure);
Serial.println();
Serial.println();

Serial.print("   Actual ALTITUDE= ");
Serial.print(getAltitude(Pressure, Temperature));
Serial.println("m");
Serial.println();
Serial.print(" RAW Temp D2=");
Serial.print(D2);
Serial.print(" RAW Pressure D1=");
Serial.println(D1);
Serial.println();

//Serial.print(" dT=");
//Serial.println(dT); can't print int64_t size values
Serial.println();
Serial.print(" C1 = ");
Serial.println(C);
Serial.print(" C2 = ");
Serial.println(C);
Serial.print(" C3 = ");
Serial.println(C);
Serial.print(" C4 = ");
Serial.println(C);
Serial.print(" C5 = ");
Serial.println(C);
Serial.print(" C6 = ");
Serial.println(C);
//Serial.print(" C7 = ");
//Serial.println(C);
Serial.println();

delay(1000);
}
float getAltitude(float Pressure, float Temperature) {
return ((pow((sea_press / Pressure), 1/5.257) - 1.0) * (Temperature + 273.15)) / 0.0065;
}
long getVal(int address, byte code)
{
unsigned long ret = 0;
Wire.beginTransmission(address);
Wire.write(code);
Wire.endTransmission();
delay(10);
// start read sequence
Wire.beginTransmission(address);
Wire.write((byte) 0x00);
Wire.endTransmission();
Wire.beginTransmission(address);
Wire.requestFrom(address, (int)3);
if (Wire.available() >= 3)
{
    ret = Wire.read() * (unsigned long)65536 + Wire.read() * (unsigned long)256 + Wire.read();
}
else {
    ret = -1;
}
Wire.endTransmission();
return ret;
}

void initial(uint8_t address)
{

Serial.println();
Serial.println("PROM COEFFICIENTS ivan");

Wire.beginTransmission(address);
Wire.write(0x1E); // reset
Wire.endTransmission();
delay(10);


for (int i=0; i<6; i++) {

    Wire.beginTransmission(address);
    Wire.write(0xA2 + (i * 2));
    Wire.endTransmission();

    Wire.beginTransmission(address);
    Wire.requestFrom(address, (uint8_t) 6);
    delay(1);
    if(Wire.available())
    {
       C = Wire.read() << 8 | Wire.read();
    }
    else {
      Serial.println("Error reading PROM 1"); // error reading the PROM or communicating with the device
    }
    Serial.println(C);
}
Serial.println();
}

以上就是我所搜索资料研究得到的经验,希望能帮到遇到困难的各位。

leicheng 发表于 2014-1-18 18:18:14

Thanks!图中的单片机用的是pro mini~

catokko123 发表于 2014-4-4 22:24:28

国外这个代码 不知道哪里有问题,实际压力为0,实际高度为inf

catokko123 发表于 2014-4-4 22:30:31

ok,这个代码是对的,重新打开串口以后,数据正常啦

luoshayu 发表于 2014-4-4 23:17:38

刚好在弄这个东西,一直不对。看了代码后终于对了。谢谢

ml418ily 发表于 2014-5-18 16:17:39

求注释~~英文不好的孩子~伤不起~

伊芙妤 发表于 2014-7-8 15:09:59

用 ardublock 如何表达这个程序

弘毅 发表于 2014-7-8 19:44:30

伊芙妤 发表于 2014-7-8 15:09 static/image/common/back.gif
用 ardublock 如何表达这个程序

ardublock只适合逻辑很简单的东西。。。这种稍微复杂点的,就不用想了。还是用代码比较稳妥。

Momo_Seven 发表于 2014-10-6 10:17:06

对新手真的很有用啊~~~给楼主赞一个~~~

HenryXue 发表于 2016-2-5 11:19:49

学习了,非常感谢。

小小白痴 发表于 2016-7-15 14:38:58

您好!请问你知道BA5803和MS5611的防水方式吗?急求!谢谢!
页: [1]
查看完整版本: Arduino 调用GY-86模块上的MS5611芯片经验分享