那与那鹰那人 发表于 2015-1-10 00:01:17

大神指点,两个相同的HMC5983的IIC问题

我用的是arduino uno r3板子,但是我想同时读取两个相同的HMC5983磁传感器的时候读数有问题,这个我实在是解决不了了。大神教教我。


头文件:

/*
HMC983.h - Header file for the HMC5883L Triple Axis Magnetometer Arduino Library.
Copyright (C) 2011 Love Electronics (loveelectronics.co.uk) / 2012 bildr.org (Arduino 1.0 compatible)

This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.

WARNING: THE HMC5883L IS NOT IDENTICAL TO THE HMC5883!
Datasheet for HMC5883L:
http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/HMC5883L_3-Axis_Digital_Compass_IC.pdf

*/

#ifndef HMC5983_h
#define HMC5983_h

#include <Arduino.h>
#include <Wire.h>



#define HMC5983_Address 0x1E
#define ConfigurationRegisterA 0x00
#define ConfigurationRegisterB 0x01
#define ModeRegister 0x02
#define DataRegisterBegin 0x03

#define Measurement_Continuous 0x00
#define Measurement_SingleShot 0x01
#define Measurement_Idle 0x03

#define ErrorCode_1 "Entered scale was not valid, valid gauss values are: 0.88, 1.3, 1.9, 2.5, 4.0, 4.7, 5.6, 8.1"
#define ErrorCode_1_Num 1

struct MagnetometerScaled
{
        float XAxis;
        float YAxis;
        float ZAxis;
};

struct MagnetometerRaw
{
        int XAxis;
        int YAxis;
        int ZAxis;
};

class HMC5983
{
        public:
          HMC5983();

          MagnetometerRaw ReadRawAxis();
          MagnetometerScaled ReadScaledAxis();

          int SetMeasurementMode(uint8_t mode);
          int SetScale(float gauss);

          char* GetErrorText(int errorCode);

        protected:
          void Write(int address, int byte);
          uint8_t* Read(int address, int length);

        private:
          float m_Scale;
};
#endif


源文件

/*
HMC5883L.cpp - Class file for the HMC5883L Triple Axis Magnetometer Arduino Library.
Copyright (C) 2011 Love Electronics (loveelectronics.co.uk)/ 2012 bildr.org (Arduino 1.0 compatible)

This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.

WARNING: THE HMC5883L IS NOT IDENTICAL TO THE HMC5883!
Datasheet for HMC5883L:
http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/HMC5883L_3-Axis_Digital_Compass_IC.pdf

*/

#include <Arduino.h>
#include "HMC5983.h"

HMC5983::HMC5983()
{
m_Scale = 0.92;
}

MagnetometerRaw HMC5983::ReadRawAxis()
{
uint8_t* buffer = Read(DataRegisterBegin, 6);
MagnetometerRaw raw = MagnetometerRaw();
raw.XAxis = (buffer << 8) | buffer;
raw.ZAxis = (buffer << 8) | buffer;
raw.YAxis = (buffer << 8) | buffer;
return raw;
}

MagnetometerScaled HMC5983::ReadScaledAxis()
{
MagnetometerRaw raw = ReadRawAxis();
MagnetometerScaled scaled = MagnetometerScaled();
scaled.XAxis = raw.XAxis * m_Scale;
scaled.ZAxis = raw.ZAxis * m_Scale;
scaled.YAxis = raw.YAxis * m_Scale;
return scaled;
}

int HMC5983::SetScale(float gauss)
{
        uint8_t regValue = 0x00;
        if(gauss == 0.88)
        {
                regValue = 0x00;
                m_Scale = 0.73;
        }
        else if(gauss == 1.3)
        {
                regValue = 0x01;
                m_Scale = 0.92;
        }
        else if(gauss == 1.9)
        {
                regValue = 0x02;
                m_Scale = 1.22;
        }
        else if(gauss == 2.5)
        {
                regValue = 0x03;
                m_Scale = 1.52;
        }
        else if(gauss == 4.0)
        {
                regValue = 0x04;
                m_Scale = 2.27;
        }
        else if(gauss == 4.7)
        {
                regValue = 0x05;
                m_Scale = 2.56;
        }
        else if(gauss == 5.6)
        {
                regValue = 0x06;
                m_Scale = 3.03;
        }
        else if(gauss == 8.1)
        {
                regValue = 0x07;
                m_Scale = 4.35;
        }
        else
                return ErrorCode_1_Num;
       
        // Setting is in the top 3 bits of the register.
        regValue = regValue << 5;
        Write(ConfigurationRegisterB, regValue);
}

int HMC5983::SetMeasurementMode(uint8_t mode)
{
        Write(ModeRegister, mode);
}

void HMC5983::Write(int address, int data)
{
Wire.beginTransmission(HMC5983_Address);
Wire.write(address);
Wire.write(data);
Wire.endTransmission();
}

uint8_t* HMC5983::Read(int address, int length)
{
Wire.beginTransmission(HMC5983_Address);
Wire.write(address);
Wire.endTransmission();

Wire.beginTransmission(HMC5983_Address);
Wire.requestFrom(HMC5983_Address, length);

uint8_t buffer;
if(Wire.available() == length)
{
          for(uint8_t i = 0; i < length; i++)
          {
                  buffer = Wire.read();
          }
}
Wire.endTransmission();

return buffer;
}

char* HMC5983::GetErrorText(int errorCode)
{
        if(ErrorCode_1_Num == 1)
                return ErrorCode_1;
       
        return "Error not defined.";
}


好像是应该改地址,但是这个我不会改,新手求教导。



这是arduino IDE编写的读一个传感器的程序


#include <Wire.h>
// Reference the HMC5883L Compass Library
#include <HMC5983.h>

// Store our compass as a variable.
HMC5983 compass;
// Record any errors that may occur in the compass.
int error = 0;
unsigned long time=millis();

// Out setup routine, here we will configure the microcontroller and compass.
void setup()
{
// Initialize the serial port.
Serial.begin(9600);

//Serial.println("Starting the I2C interface.");
Wire.begin(); // Start the I2C interface.

//Serial.println("Constructing new HMC5983");
compass = HMC5983(); // Construct a new HMC5883 compass.
   
//Serial.println("Setting scale to +/- 8.0 Ga");
//error = compass.SetScale(8.0); // Set the scale of the compass.
//if(error != 0) // If there is an error, print it out.
   // Serial.println(compass.GetErrorText(error));

//Serial.println("Setting measurement mode to continous.");
error = compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous
//if(error != 0) // If there is an error, print it out.
//Serial.println(compass.GetErrorText(error));
//Serial.println("\t\tTime,\t\tXAxis,\t\tYAxis,\t\tZAxis,\t\tTotalMagnetic,\t\tDeclination(C)\t");
   
   
}

// Our main program loop.
void loop()
{

// Retrive the raw values from the compass (not scaled).
MagnetometerRaw raw = compass.ReadRawAxis();
// Retrived the scaled values from the compass (scaled to the configured scale).
MagnetometerScaled scaled = compass.ReadScaledAxis();

// Values are accessed like so:
int MilliGauss_OnThe_XAxis = scaled.XAxis;// (or YAxis, or ZAxis)

// Calculate heading when the magnetometer is level, then correct for signs of axis.
float heading = atan2(scaled.YAxis, scaled.XAxis);
float totalmagnetic=sqrt((scaled.XAxis*scaled.XAxis)+(scaled.YAxis*scaled.YAxis)+(scaled.ZAxis*scaled.ZAxis));

// Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
// Find yours here: http://www.magnetic-declination.com/
// Mine is: 2� 37' W, which is 2.617 Degrees, or (which we need) 0.0456752665 radians, I will use 0.0457
// If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
float declinationAngle = -0.1044;
heading += declinationAngle;

// Correct for when signs are reversed.
if(heading < 0)
    heading += 2*PI;
   
// Check for wrap due to addition of declination.
if(heading > 2*PI)
    heading -= 2*PI;
   
// Convert radians to degrees for readability.
float headingDegrees = heading * 180/M_PI;

// Output the data via the serial port.
Output(time,scaled,totalmagnetic,headingDegrees);

// Normally we would delay the application by 66ms to allow the loop
// to run at 15Hz (default bandwidth for the HMC5883L).
// However since we have a long serial out (104ms at 9600) we will let
// it run at its natural speed.
// delay(66);
}

// Output the data down the serial port.
void Output(unsigned long time,MagnetometerScaled scaled, float totalmagnetic,float headingDegrees)
{
// Serial.print("\t\t");
   Serial.print((millis())/1000.f);
   Serial.print(",");
   //Serial.print("Raw:\t");
   //Serial.print(raw.XAxis);
   //Serial.print("   ");   
// Serial.print(raw.YAxis);
   //Serial.print("   ");   
   //Serial.print(raw.ZAxis);
   //Serial.print("   \tScaled:\t");
   
   Serial.print((scaled.XAxis)/100);
   Serial.print(",");
   Serial.print((scaled.YAxis)/100);
   Serial.print(",");   
   Serial.print((scaled.ZAxis)/100);
   Serial.print(",");
   Serial.println((totalmagnetic)/100);
   //Serial.print(",");
   //Serial.println(headingDegrees);
   //Serial.print("\t\t");
    //Serial.print("   \tHeading:\t");
   //Serial.print(heading);
// Serial.print(" Radians   \t");
   //Serial.println(" Degrees   \t");
   delay(500);

}

我想同时实现读两个或者更多HMC5983磁传感器,这个怎么实现,大神求指导!

mc.six 发表于 2015-4-18 19:58:43

可以参考这个代码,这是1602iic的库代码
LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows)
{
_Addr = lcd_Addr;
_cols = lcd_cols;
_rows = lcd_rows;
_backlightval = LCD_NOBACKLIGHT;
}
下面是主程序调用库的代码
LiquidCrystal_I2C lcd(0x27,16,2);// set the LCD address to 0x27 for a 16 chars and 2 line display

把你的库里的设地址的代码去掉,
这样可以在主程序定义两个地址不同的传感器。传感器应该有一个设地址的管脚,把两个传感器设成不同的地址,同一种传感器只能有两个地址。
明白否?

mc.six 发表于 2015-4-18 20:16:22




.h文件里
//#define HMC5983_Address 0x1E    //把这行注销掉
#define ConfigurationRegisterA 0x00
#define ConfigurationRegisterB 0x01
#define ModeRegister 0x02
#define DataRegisterBegin 0x03
//////////////////////////////////////////////////////////////////////

.cpp 里改成这样
HMC5983::HMC5983(uint8_t Addr)
{
m_Scale = 0.92
uint8_t HMC5983_Address   = Addr;

}
/////////////////////////////////////////////////////////////
主程序里

HMC5983 compass1(0x1E);//这个地址要查手册是多少
HMC5983 compass2(0x1F);//这个地址要查手册是多少

mc.six 发表于 2015-4-18 20:19:02

我也是个菜菜鸟,不知对不对,我个人觉得思路是对的,具体代码你再研究一下吧

那与那鹰那人 发表于 2015-4-23 08:42:38

多谢多谢,我下在试试!!!{:soso_e183:}

tsaiwn 发表于 2015-4-23 17:56:47

那与那鹰那人 发表于 2015-4-23 08:42 static/image/common/back.gif
多谢多谢,我下在试试!!!



(1)通常传感器的 IIC address 是不能改的,
   我不认为 HMC5983 的 IIC address 可以改 ??
(2)同一条 IIC bus 上不可以有重复的 IIC slave address
   所以如果你都直接连在一起是不行的 !
(3)如果你一定要两个,
   那可以 try 这样:
   各自的 VDD 各自连到 Arduino 的数字脚, 例如 pin 3 和 pin 5
   其他照你原先接,
   每次只可读取一个,
   把要读的透过 pin 3 或 pin 5 给它电力, 另一个则用 digitalWrite(pin, LOW); 关闭电力
如果是 5V,
假设要读 pin 3 那个,
就 digitalWrite(5, 0);digitalWrite(3, HIGH);
如果 HMC5983 是 3V, 则改这样:
   digitalWrite(5, 0);analogWrite(3, 185);// 大约 3.5 Volt
接着要 delay 一下, 例如 delay(1234);
然后才下达 IIC 命令
这样应该可以 :)
页: [1]
查看完整版本: 大神指点,两个相同的HMC5983的IIC问题