极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15162|回复: 5

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

[复制链接]
发表于 2015-1-10 00:01:17 | 显示全部楼层 |阅读模式
我用的是arduino uno r3板子,但是我想同时读取两个相同的HMC5983磁传感器的时候读数有问题,这个我实在是解决不了了。大神教教我。

[pre lang="arduino" line="4" file="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[/code]


源文件

/*
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[0] << 8) | buffer[1];
  raw.ZAxis = (buffer[2] << 8) | buffer[3];
  raw.YAxis = (buffer[4] << 8) | buffer[5];
  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[length];
  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&#65533; 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磁传感器,这个怎么实现,大神求指导!

回复

使用道具 举报

发表于 2015-4-18 19:58:43 | 显示全部楼层
可以参考这个代码,这是1602iic的库代码
LiquidCrystal_I2C:iquidCrystal_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

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

使用道具 举报

发表于 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);//这个地址要查手册是多少
回复 支持 反对

使用道具 举报

发表于 2015-4-18 20:19:02 | 显示全部楼层
我也是个菜菜鸟,不知对不对,我个人觉得思路是对的,具体代码你再研究一下吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-23 08:42:38 | 显示全部楼层
多谢多谢,我下在试试!!!{:soso_e183:}
回复 支持 反对

使用道具 举报

发表于 2015-4-23 17:56:47 | 显示全部楼层
那与那鹰那人 发表于 2015-4-23 08:42
多谢多谢,我下在试试!!!



(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 命令
这样应该可以
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-5-17 15:01 , Processed in 0.042190 second(s), 20 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表