getting data from a custom compass sensor

Hi!

So recently I got my hands on a couple of relatively good compass modules from china:
http://www.robotplayer.com/products/post.asp?pid=149
the page is in chinese, but with google translate I got the gist of it.
they work great with they’re own controller,
http://www.robotplayer.com/products/post.asp?pid=109
however I would like to get it to work with by arduino.
I started looking through the files for the drag and drop programming software for these controllers and I guess I found the C file that is used to get data from the compass,

#ifdef _GETCOMPASSB_
 #ifndef  _GETCOMPASSB_EXISTS_
  #define _GETCOMPASSB_EXISTS_
  #include <jmkernel.h>
  #include "I2C_Soft.h"

  #ifndef _COMPASS_
   #define _COMPASS_ unsigned long
  #endif

  unsigned int GetCompassB(_COMPASS_ which){
    struct select *information=&which;
    unsigned char ddr1=portarray[1][information->group1];
    unsigned char ddr2=portarray[1][information->group2];
    unsigned char port1=portarray[2][information->group1];
    unsigned char port2=portarray[2][information->group2];
    unsigned char pin1=portarray[0][information->group1];
    unsigned char pin2=portarray[0][information->group2];
    unsigned char bit1=information->bit1;
    unsigned char bit2=information->bit2;
    SDA_DDR=ddr2;
    SDA_PORT=port2;
    SDA_PIN=pin2;
    SDA_BIT=bit2;
    SCL_DDR=ddr1;
    SCL_PORT=port1;
    SCL_BIT=bit1;

    unsigned char low;
    unsigned char high;
    unsigned int angle;
    Soft_I2C_Start();
    Soft_I2C_Write(0x76);
    Soft_I2C_Write(0x01);
    Soft_I2C_Start();
    Soft_I2C_Write(0x77);
    high=Soft_I2C_Read(0);
    low=Soft_I2C_Read(1);
    Soft_I2C_Stop();

    if(high==1)
      angle=256+low;
    else
      if(high==0)
        angle=low;
      else
        angle=9999;
    return angle;
  }
 #endif
#endif

now my question is how would I write this for my Arduino, here is one of my (failed) attempts:

#include <Wire.h>
#include <SoftwareSerial.h>
void setup(){
  Wire.begin();                                               // Conects I2C
  Serial.begin(9600);
}
 void loop()
{
   char high, low;              
 
   int bearing;                             
   Wire.begin();
   Wire.write(0x76);           
   Wire.write(0x01);                              
   //Wire.endTransmission();
   Wire.begin();
   Wire.write(0x77);              
   high = Wire.read();           
   low = Wire.read();            
             
      if(high==1)
      {
      bearing=256+low;
      }
   
      if(high==0)
  {  
    bearing=low;
  }
  
   Serial.println(bearing);
}

Any ideas/tips on how to get this to work would be much appreciated, please forgive my ignorance if I made a dumb programming mistake.

How is the compass connected to the Arduino? It may not be a software issue.

   Wire.begin();
   Wire.write(0x76);           
   Wire.write(0x01);                              
   //Wire.endTransmission();

Nothing gets written until you do Wire.endTransmission(); so the code you posted won’t do much.

Read this, you should be more comfortable with I2C after wading through it. :slight_smile:

http://www.gammon.com.au/i2c

It is a JoinMax compass, JMP-BE-2611, http://en.robotplayer.com/products/list.asp?id=70
The price of 81 dollars seems extremely high. Is it tilt compensated ? Is the I2C connected to the sensor, or to a microcontroller inside ?

The example code uses 8-bit address, shift it to right for the Arduino Wire library. But you first have to run the i2c scanner to see if the I2C bus is working.
http://playground.arduino.cc/Main/I2cScanner

A HMC5883L breakout board costs less than 3 dollars on Ebay, inclusive shipping.

PaulS:
How is the compass connected to the Arduino? It may not be a software issue.

I'm pretty sure it's not a hardware issue, I even have the pull up resistors.

I un-commented that line, still no difference.
I read what you advised, I do understand I2C a bit better now, but I am still confused on how I can change the original code for
the custom controller to get it to work on my arduino.

Erdin:
It is a JoinMax compass, JMP-BE-2611, http://en.robotplayer.com/products/list.asp?id=70
The price of 81 dollars seems extremely high. Is it tilt compensated ? Is the I2C connected to the sensor, or to a microcontroller inside ?

The example code uses 8-bit address, shift it to right for the Arduino Wire library. But you first have to run the i2c scanner to see if the I2C bus is working.
Arduino Playground - I2cScanner

A HMC5883L breakout board costs less than 3 dollars on Ebay, inclusive shipping.

I ran it, It said: "I2C device found at address 0x3B"
and yeah, ill probably get another compass if I can't get this to work,
but I got this used, for way less, and It has quite steady/good readings in comparison with other compass sensors I have used.
So anyway 0x3B? should I try that address?

If it says 0x3B that's the address you've got to use. Where did you get 0x76 from? I couldn't see a datasheet at that link.

It was in the code I found for the custom controller in the install files for the custom software
as included in my original post:

#ifdef _GETCOMPASSB_
 #ifndef  _GETCOMPASSB_EXISTS_
  #define _GETCOMPASSB_EXISTS_
  #include <jmkernel.h>
  #include "I2C_Soft.h"

  #ifndef _COMPASS_
   #define _COMPASS_ unsigned long
  #endif

  unsigned int GetCompassB(_COMPASS_ which){
    struct select *information=&which;
    unsigned char ddr1=portarray[1][information->group1];
    unsigned char ddr2=portarray[1][information->group2];
    unsigned char port1=portarray[2][information->group1];
    unsigned char port2=portarray[2][information->group2];
    unsigned char pin1=portarray[0][information->group1];
    unsigned char pin2=portarray[0][information->group2];
    unsigned char bit1=information->bit1;
    unsigned char bit2=information->bit2;
    SDA_DDR=ddr2;
    SDA_PORT=port2;
    SDA_PIN=pin2;
    SDA_BIT=bit2;
    SCL_DDR=ddr1;
    SCL_PORT=port1;
    SCL_BIT=bit1;

    unsigned char low;
    unsigned char high;
    unsigned int angle;
    Soft_I2C_Start();
    Soft_I2C_Write(0x76);
    Soft_I2C_Write(0x01);
    Soft_I2C_Start();
    Soft_I2C_Write(0x77);
    high=Soft_I2C_Read(0);
    low=Soft_I2C_Read(1);
    Soft_I2C_Stop();

    if(high==1)
      angle=256+low;
    else
      if(high==0)
        angle=low;
      else
        angle=9999;
    return angle;
  }
 #endif
#endif

So I tried using 0x3B, still nothing,
Any other ideas?

Yes, post your current code.

#include <Wire.h>
#include <SoftwareSerial.h>
void setup(){
  Wire.begin();                                               // Conects I2C
  Serial.begin(9600);
}
 void loop()
{
   char high, low;              
 
   int bearing;                             
   Wire.begin();
   Wire.write(0x3B);           
   Wire.write(0x01);                              
   Wire.endTransmission();
   Wire.begin();
   Wire.write(0x3B);              
   high = Wire.read();           
   low = Wire.read();            
             
      if(high==1)
      {
      bearing=256+low;
      }
   
      if(high==0)
  {  
    bearing=low;
  }
  
   Serial.println(bearing);
}
   Wire.begin();
   Wire.write(0x3B);           
   Wire.write(0x01);                              
   Wire.endTransmission();
   Wire.begin();
   Wire.write(0x3B);              
   high = Wire.read();           
   low = Wire.read();

Read this again:

Your code looks nothing like the examples there.

You need Wire.beginTransmission, not Wire.begin and you also need Wire.requestFrom.

Hi,

So I sort of left this project once school started, and now I’m giving it a second try,

I did add them in my latest version, and I am really trying to understand I2C better, but I just can’t seem to figure out
how to use it on this compass sensor, Again all advise is much appreciated.

#include <Wire.h>
#include <SoftwareSerial.h>
void setup(){
  Wire.begin();                                               // Conects I2C
  Serial.begin(9600);
}
 void loop()
{
   char high, low;              
 
   int bearing;                             
   Wire.beginTransmission ();
   Wire.write(0x3B);           
   Wire.write(0x01);                              
   Wire.endTransmission();
   Wire.requestFrom(0x3B);              
   high = Wire.read();           
   low = Wire.read();            
             
      if(high==1)
      {
      bearing=256+low;
      }
   
      if(high==0)
  {  
    bearing=low;
  }
  
   Serial.println(bearing);
}

That doesn't compile, right?

See the link for how to use Wire.requestFrom: