那与那鹰那人 发表于 2015-1-10 00:02:16

关于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磁传感器,这个怎么实现,大神求指导!

Super169 发表于 2015-1-10 02:11:56

除了 0X1E 外, 可以設定其他地址嗎?如果不可以的話, 同一個 IIC bus 上, 應該不可以有兩個相同地址的設備吧.

如果可以設定其他地址, 只要改了原來的庫, 把 HMC5983_Address 改成變數, 在創建時由程式提供就可以了.

johnleeqiang 发表于 2015-1-10 06:15:56

可以查芯片手册看能不能设成其他地址,不过芯片尺寸往往很小,要模块上有引出的脚才行。还可以考虑用软件模拟出另一路IIC通道。或者外接三极管或芯片控制不同模块线路的通断。

那与那鹰那人 发表于 2015-1-10 09:32:51

Super169 发表于 2015-1-10 02:11 static/image/common/back.gif
除了 0X1E 外, 可以設定其他地址嗎?如果不可以的話, 同一個 IIC bus 上, 應該不可以有兩個相同地址的設備 ...

http://wenku.baidu.com/view/8fdb776648d7c1c708a145c5.html
这是HMC5983的资料,我不知道怎么来改地址。请你看看。

那与那鹰那人 发表于 2015-1-10 09:34:08

johnleeqiang 发表于 2015-1-10 06:15 static/image/common/back.gif
可以查芯片手册看能不能设成其他地址,不过芯片尺寸往往很小,要模块上有引出的脚才行。还可以考虑用软件模 ...


http://wenku.baidu.com/view/8fdb776648d7c1c708a145c5.html
这是HMC5983的资料,我不知道怎么来改地址。请你看看。

zoologist 发表于 2015-1-10 16:59:01

那与那鹰那人 发表于 2015-1-10 09:34 static/image/common/back.gif
http://wenku.baidu.com/view/8fdb776648d7c1c708a145c5.html
这是HMC5983的资料,我不知道怎么来改地 ...

问卖家吧,一般来说他们会留跳线给你改变地址的

Super169 发表于 2015-1-10 23:34:28

那与那鹰那人 发表于 2015-1-10 09:32 static/image/common/back.gif
http://wenku.baidu.com/view/8fdb776648d7c1c708a145c5.html
这是HMC5983的资料,我不知道怎么来改地址 ...

不是每一個模塊都有多個地址可選的, 而且同一模塊, 不同生產商也可以有不同的設計.最好還是問問賣家吧.

之前好像見過一個軟體 IIC 的庫, 可以用其他 I/O 作 SDA 及 SCL 的, 或許可以在同一系統下出現兩個獨立 IIC 線路.
但可能要對現有的庫作出很大的改動, 而且不知是否可以跟 Wire 庫共存.
页: [1]
查看完整版本: 关于IIC通讯的问题,大神求赐教!!