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
/ 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);
}
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.
If you're still interested in doing this, here are a few point you might consider:
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:
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.
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.
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:
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);