New to I2C, confusion with programming a magnetic sensor

I've been staring at this data sheet for my magnetic sensor for a while now, and this is my first time every using the I2C protocol. When attempting to translate the steps shown in "Example Measurement" I'm quite sure I am doing this incorrectly . . .

#include <Wire.h>
#define address 0b110000 // find the actual address, it is at 0x30, which is 0b00110000

void setup() {
  Serial.begin(9600);
  Wire.begin(address);
}


void loop() {
  int x, y, z;

  Wire.beginTransmission(address); 
  Wire.requestFrom(0b00110000, 1); // START condition?, starts with a 0 to indicate a WRITE request
  if(Wire.available() > 0) {
    Serial.println("1");
    Wire.read();
  }
  Serial.println(Wire.read());
  Wire.write(0b00000111);
  if(Wire.available() > 0) {
    Serial.println("2");
    Wire.read();
  }
  Wire.write(0b00000001); 
  if(Wire.available() > 0) {
    Serial.println("3");
    Wire.read();
  }
  Wire.requestFrom(0b00110000, 1); // write request
  if(Wire.available() > 0) {
    Serial.println("4");
    Wire.read();
  }
  Wire.write(0b00000110);
  if(Wire.available() > 0) {
    Serial.println("5");
    Wire.read();
  }
  Wire.requestFrom(0b10110000, 1); // READ request 
  if(Wire.available() > 0) {
    Serial.println("6");
    Wire.read();
  }
  // not sure what to do for the 7th cycle???
  // am I even doing the previous correct?



//  Wire.requestFrom(0b10110000, 6);
//    
//  if(Wire.available() >= 6) {
//    Serial.println("good");
//    x = Wire.read()<<8; //X msb
//    x |= Wire.read(); //X lsb
//    z = Wire.read()<<8; //Z msb
//    z |= Wire.read(); //Z lsb
//    y = Wire.read()<<8; //Y msb
//    y |= Wire.read(); //Y lsb
//  }
//
//  //Print out values of each axis
//  Serial.print("x: ");
//  Serial.print(x);
//  Serial.print("  y: ");
//  Serial.print(y);
//  Serial.print("  z: ");
//  Serial.println(z);
//  Wire.endTransmission(address);
  delay(1000);
}

I believe that the first 6 cycles are incorrect, but I'm not sure of any other way to approach this. I used this I2C scanner to scan for the address of my device, and it was found to be 0x30, which is 0b00110000. Some things I am confused about,

  • What does it mean to scan the SCL line, and how would this be done with the Wire library?
  • I'm never actually getting acknowledgements back from the device, i.e: after each requestFrom()/write(), I'm never entering the if statement afterwards.

Any help would be greatly appreciated!!!

 if(Wire.available() > 0) {
    Serial.println("1");
    Wire.read();
  }

If there is I2C data available, print a useless message, and then throw away the data read.

Serial.println(Wire.read());

Then, even though there is nothing to read, read() anyway.

I give up. What ARE you doing? If this IS supposed to do something useful, you need comments to explain that the illogical code is correct. Or, you need to fix it.

You should not be requesting data between beginTransmission() and endTransmission(), since nothing gets sent until the endTransmission() call.

Sorry, I guess I was a bit unclear of what the numbers meant in each of the println's. I am mapping each number printed out to the cycle number in the "Example Measurement" section in the data sheet.

That being said, I am still unsure about how a START/STOP conditions are sent, read/write requests and what these register number mean on the datasheet

dchin2:
I've been staring at this data sheet for my magnetic sensor for a while now, and this is my first time every using the I2C protocol. When attempting to translate the steps shown in "Example Measurement" I'm quite sure I am doing this incorrectly . . .

you code is faulty.

I2C transaction come in two flavors, Writing and Reading.

A write transaction: (edit 06/30/17, I seem to always write beginTransmission() ad beginTransaction, sorry :wink:

Wire.beginTransmission(address);
Wire.write(byteValue);
Wire.endTransmission();

A read transaction is even simpler:

Wire.requestFrom(address,number_of_bytes);
while(Wire.available()){
  uint8_t data = Wire.read();
  }

Usually with I2C devices you want to read a specific address so you must set the device's internal address pointer before you issue the read command.

// read 2 byte at offset 5 in the device at I2C address 0x30
uint8_t address=0x30;
Wire.beginTransmission(address);
Wire.write(5); // set the devices internal address pointer to 5;
Wire.endTransmission();

// now we issue a read command and ask for 2 bytes

Wire.requestFrom(address,2);
if(Wire.available()==2){ // got the two bytes
   Serial.print("success: ");
   Serial.print(Wire.read(),HEX);
   Serial.print(' ');
   Serial.println(Wire.read(),HEX);
   }
else {
   Serial.println(" Read Failed!");
  }

Now, there is an added complexity if your device requires a Re-Start between the Set address_pointer and the Read from device I2C transactions, change the Wire.endTransmission(); to Wire.endTransmission(false);

Chuck.

Just read your data sheet. Here is code to start a measurement cycle, poll until data is ready, then grab the whole array of data.

uint8_t address = 0x30;

// initiate data acquisition

Wire.beginTransmission(address);
Wire.write(7); // select control register 0
Wire.write(1); // initiate data acquisition
Wire.endTransmission(); // preform I2C transaction

// Test that data acquisition is complete

Wire.beginTransmission(address);
Wire.write(6); // select Status register, The address_pointer does not automatically increment
// when it is set to the status register
Wire.endTransmission(); // preform I2C t

bool ready=false; // data ready flag
unsigned long timeout = millis(); // a timeout counter
while(!ready&&(timeout-millis()<1000)){ // wait up to a second for a measurement to complete
  Wire.requestFrom(address,1); // get current status byte from device
  if(Wire.available()) { // got data from device)  
    uint8_t status=Wire.read();
    ready = (status & 1)==1; // is bit zero set? if so that means a measurement has completed!
    }
  }

if(ready){ // measurement completed
  Wire.beginTransmission(address);
  Wire.write(0); // set internal address pointer to zero, the Xout LSB register
  Wire.endTransmission();

  Wire.requestFrom(address,6); // get the six bytes of measurement data.

  if(Wire.available()==6){ // go the whole packet
    uint16_t x,y,z,temp;
    x=Wire.read(); // get lsb
    temp = Wire.read(); // high byte
    x = x + (temp <<8); // assemble 16bit from two 8bit values
    y=Wire.read(); // get lsb
    temp = Wire.read(); // high byte
    y = y + (temp <<8); // assemble 16bit from two 8bit values
    z=Wire.read(); // get lsb
    temp = Wire.read(); // high byte
    z = z + (temp <<8); // assemble 16bit from two 8bit values

    Serial.print("x = "); Serial.println(x,HEX);
    Serial.print("y = "); Serial.println(y,HEX);
    Serial.print("z = "); Serial.println(z,HEX);
    }
  else {
    Serial.println(" requestFrom() failed");
    }
} 
else {
  Serial.println(" Device timeout ");
}

Try it.