极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12711|回复: 6

关于IIC通讯的问题,大神求赐教!!

[复制链接]
发表于 2015-1-10 00:02:16 | 显示全部楼层 |阅读模式
我用的是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-1-10 02:11:56 | 显示全部楼层
除了 0X1E 外, 可以設定其他地址嗎?  如果不可以的話, 同一個 IIC bus 上, 應該不可以有兩個相同地址的設備吧.  

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

回复 支持 反对

使用道具 举报

发表于 2015-1-10 06:15:56 | 显示全部楼层
可以查芯片手册看能不能设成其他地址,不过芯片尺寸往往很小,要模块上有引出的脚才行。还可以考虑用软件模拟出另一路IIC通道。或者外接三极管或芯片控制不同模块线路的通断。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-1-10 09:32:51 | 显示全部楼层
Super169 发表于 2015-1-10 02:11
除了 0X1E 外, 可以設定其他地址嗎?  如果不可以的話, 同一個 IIC bus 上, 應該不可以有兩個相同地址的設備 ...

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

使用道具 举报

 楼主| 发表于 2015-1-10 09:34:08 | 显示全部楼层
johnleeqiang 发表于 2015-1-10 06:15
可以查芯片手册看能不能设成其他地址,不过芯片尺寸往往很小,要模块上有引出的脚才行。还可以考虑用软件模 ...


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

使用道具 举报

发表于 2015-1-10 16:59:01 | 显示全部楼层
那与那鹰那人 发表于 2015-1-10 09:34
http://wenku.baidu.com/view/8fdb776648d7c1c708a145c5.html
这是HMC5983的资料,我不知道怎么来改地 ...

问卖家吧,一般来说他们会留跳线给你改变地址的
回复 支持 反对

使用道具 举报

发表于 2015-1-10 23:34:28 | 显示全部楼层
那与那鹰那人 发表于 2015-1-10 09:32
http://wenku.baidu.com/view/8fdb776648d7c1c708a145c5.html
这是HMC5983的资料,我不知道怎么来改地址 ...

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

之前好像見過一個軟體 IIC 的庫, 可以用其他 I/O 作 SDA 及 SCL 的, 或許可以在同一系統下出現兩個獨立 IIC 線路.
但可能要對現有的庫作出很大的改動, 而且不知是否可以跟 Wire 庫共存.
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-8 09:02 , Processed in 0.038561 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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