Go Down

Topic: Need some help with I2C (Read 9297 times) previous topic - next topic

tr24em

I think I have this in the right spot. Let me know if not as this is my first post.

I am fairly new Arduino I and am wanting some help with I2C. I have a lego HiTechnic Compass sensor (http://www.hitechnic.com/cgi-bin/commerce.cgi?preadd=action&key=NMC1034), that uses I2C, and I am trying to use it in a UGV that I am building. I was wondering if someone could tell me how to tell the sensor that I want the values from register 0x42 and 0x43 on the sensor. If you scroll down in the link to the Sensor Register Layout you can see what I am talking about. I modified the Master_Reader example to what I thought might work (see below). The device address is 1. The code below returns characters and numbers I thought that they might be ASCII values. But using those values pointing aprox. north it gave a value about (I did the test last night and didn't write them down) 420, east 350, south 190, and west 360. That was using the ASCII values and the formula in the link.

So I really have three questions, am I doing this correctly, if so any suggestions about what the characters are representing, and if no to the first then how should I go about this.


Any help would be great.
Thanks

Code: [Select]

/ Wire Master Reader
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Reads data from an I2C/TWI slave device
// Refer to the "Wire Slave Sender" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


/****************modified for tests*****************************/

#include <Wire.h> // libary for I2C

void setup()
{
  Wire.begin();        // start I2C
  Serial.begin(9600);  // start serial for output
 
  Serial.println("ready");
}

void loop()
{
  Serial.println("0x42");
 
  Wire.beginTransmission(1); // talk to I2C device ID 1
  Wire.write(0x42); // At 0x42 (This is what I think I need to do to get to the 0x42 location)
  Wire.requestFrom(1, 2); // Request 3 bytes from ID 1
  Wire.endTransmission(); // end transmission

  while(Wire.available()) // read the values and write them
  {
    char c = Wire.read();
    Serial.println(c);
  }
 
  Serial.println("   ");
 
  Serial.println("0x43");
 
  Wire.beginTransmission(1);  // talk to I2C device ID 1
  Wire.write(0x43); // At 0x43 (This is what I think I need to do to get to the 0x43 location)
  Wire.requestFrom(1, 1); // Request 3 bytes from ID 1
  Wire.endTransmission(); // end transmission

  while(Wire.available()) // read the values and write them
  {
    char c = Wire.read();
    Serial.println(c);
  }
 
  Serial.println("   ");

  delay(500);

}

tr24em

BTW I am using a Arduino Mega, with Arduino Sketch 1.0.1

tr24em

For anyone else that is trying/wanting to do this.

My uncle and I did some looking around and testing and have figured something out. Looking at some Arduino to Lego shield program files, they seem to do more than just have nice plugs so that you don't have to chop up your wires to connect them. So instead of trying to reverse engineer them I am just going to buy a compass sensor. Reverse engineering the shield is probably not impossible, however I am just going to spend the money for a compass rater than hours/days/week/however-long-it-takes to do so.

pylon

If you're still interested in doing this, here are a few point you might consider:

Code: [Select]
  Wire.beginTransmission(1); // talk to I2C device ID 1
  Wire.write(0x42); // At 0x42 (This is what I think I need to do to get to the 0x42 location)
  Wire.requestFrom(1, 2); // Request 3 bytes from ID 1
  Wire.endTransmission(); // end transmission


This should be that way round:

Code: [Select]
  Wire.beginTransmission(1); // talk to I2C device ID 1
  Wire.write(0x42); // At 0x42 (This is what I think I need to do to get to the 0x42 location)
  Wire.endTransmission(); // end transmission
  Wire.requestFrom(1, 2); // Request 3 bytes from ID 1


This is because Wire.endTransmission sends the characters to the device, you have to do that before you can read from the device (as you do with Wire.requestFrom()).

To check the communication I would use register 0x08 because there you know what it should return (the eight characters "HiTechnc").

The better value for you to read is probably in register 0x44 and 0x45. You directly get an integer value with the heading.

tr24em

Pylon,
Thanks for the info. I tried commenting out the Wire.write(0x42) line and requesting 1,000 bytes and the sensor would send the version #, the brand, and the sensor type to me. I then fix the code they way you suggested and asked for 1,000 bytes at register 0x08 and it gave we the brand name and sensor type. So the sensor does seem to communicate with the Arduino. I then tried at register 0x44 (same way as in the last one) and I got characters that did not show values that would make sense for a compass (like in my first post). Then I did it again at Register 0x45 and i got nothing.

pylon

You don't get characters, you get bytes. Just send the value 0x44 and request two bytes. The first byte received is the lower byte of the direction integer, the second is the higher part:

Code: [Select]
Wire.beginTransmission(1); // talk to I2C device ID 1
  Wire.write(0x44); // direction register
  Wire.endTransmission(); // end transmission
  Wire.requestFrom(1, 2); // Request 2 bytes from ID 1
  while (Wire.available() < 2);
  uint16_t lb = Wire.read();
  uint16_t val = Wire.read();
  val <<= 8;
  val |= lb;
  Serial.println(val);

tr24em

Thank you so much!!!! It now is working. I used the code you posted and it is now reading good values.

Go Up