How to setup BASIC I2C sketch to read data from sensor?

I'm using the TLV493D-A1B6: I've attached links and a datasheet/register map at the bottom.

This is a 3D magnetic field position sensor that detects the magnetic field strength of a nearby magnetic field in the X, Y, and Z directions. I am NOT using the 2GO evaluation board. The sensor uses I2C protocol for communication.

I have this sensor all wired up, soldered correctly to a PCB with pinheadings, and ready to go on my breadboard.
Also, I am using a bidirectional logic level converter that is recommended for this sensor. I can confirm this as the I2C scanner sketch detects the sensor and prints out its expected defulat address.

Specifically, I am having trouble understanding the data sheets and how to setup Arduino using the 'Wire.h' library to communicate with the sensor over I2C to obtain the X, Y, Z RAW/decoded readings continuously.

I have tried code from this thread -> https://forum.arduino.cc/index.php?topic=419380.0
I have tried code from this dedicated tutorial for this sensor -> https://www.allaboutcircuits.com/technical-articles/tutorial-and-overview-of-infineons-3d-magnetic-2go-kit/
I have even tried code from Github for this sensor -> TLV493D-3D-Magnetic-Sensor-Arduino-Library/TLV493D.h at master · IRNAS/TLV493D-3D-Magnetic-Sensor-Arduino-Library · GitHub

Using any of the above, I will get readings of "X=-1, Y=-1, Z=-1" or it will get random readings of "255" and "0".

I've written my own code and have failed vigorously to get anything but random, clearly wrong readouts, this was my latest attempt, I chopped this code down for simplicity and clarity. I've also tried variations using the I2C.h master library, but no luck:

#include "Wire.h"       

const int tlv_addr = 0x1F; // obtained by i2c scanner; all default address of tlv sensor - 0x1F, 0x5E, or 0x3E
const int config_reg = 0x00; // I have scene this in other examples of code for this sensor, I cannot find the "configure" or "command register" address on any of its datasheets
const int lp_mode = 0x05; //Have found this on the data sheet as the low power mode command
// Note: I switched from const byte to const int for HEX assignments because I get a warning when compiling the sketch about this and I found online that this is the solution?

void setup() {
  Wire.begin();   //join I2C bus
  Serial.begin(9600); //start Serial
  while(!Serial); //wait for Serial to be available
  
  Wire.beginTransmission(tlv_addr); //initiate communication with sensor
  Wire.write(config_reg); //set pointer/access configuration register
  Wire.write(lp_mode); //from what I read, the sensor defaults to power down mode on start up, so I send the low power mode command to the configure register to activate the sensor in low power mode which should cause it to start "sensing"
  Wire.endTransmission(); //end configurations
  delay(100); //delay to allow time for sensor the update
  Serial.print("Setup Complete\n\n");
}

void loop(){
  Wire.requestFrom(tlv_addr, 3); //request the 3 raw, UN-decoded bits from the sensor's readings of X, Y, Z axes
  
  //---- Read in each byte of sensor data one by one for each axis ----//
  byte Bx = Wire.read(); //Have scene the "*" added to the beginning of the variable on a lot of code, not sure why this is necessary?
  byte By = Wire.read();
  byte Bz = Wire.read();

  //---- Print Out Sensor Axis Readings ----//
  Serial.println("X= ");
  Serial.print(Bx);       //Have also scene "&" added to the beginning of the variable on a lot of code like Serial.print(&Bx);? 
  Serial.print("\tY= ");
  Serial.print(By);
  Serial.print("\tZ= ");
  Serial.print(By);

  //Expecting something like this: 01011011
  //Getting -1 or 255 or 0 randomly?

  delay(1000); //arbitrary delay
}

And furthermore, I understand that these values needed to be decoded to make sense of the actual data, I have no idea what is going on the register map sheet and why they are shifting different bits of segments of each byte, seemingly like totally picking the bytes apart then reordering them, and then casting them as integers to get real data?

I am very new to Arduino and especially to I2C. If you could please help me understand especially what I'm missing from the data sheet, or what I'm doing wrong in the simplest of terms, I want to intuitively understand whats going on at every step so I can do this again with another I2C sensor on my own.

Thank you for your time and help!

Datasheet.pdf (800 KB)

Register Map.pdf (886 KB)

Why do you want to do this? Are you one of those people who enjoy building code from the most basic level? If not, why not just use one of the available Arduino Libraries for the chip, maybe this one?

I actually listed that same library as one I've already tried. Yes, I am one of those people who like the build it from the ground up because thats the best way I can get a full understanding of what I'm doing, but in this case I cannot get the sensor to work no matter if I use predefined libraries or try to create my own basic sketch, I've swapped out sensors and am still not getting any results with those libraries or my own code.

I'd rather build the sketch from the ground up since reading data from a sensor should be trivial and I cannot do it.

For "normal" sensors, the hardest part is to make the I2C bus work so it can be detected by the I2C Scanner. You have that already working, very nice :smiley:

When reading data from a "normal" sensor, the register address (inside the sensor) is set first. You may call it a pointer, I like to call it the "register address".
However, this sensor is not "normal" at all, and the datasheet is indeed hard to understand.

The official example code is not easy, but I think you can use it: TLV493D-A1B6-3DMagnetic-Sensor/Tlv493d.cpp at master · Infineon/TLV493D-A1B6-3DMagnetic-Sensor · GitHub.
The library by IRNAS is better, that code is straightforward. You should use that library. Click also on the "Issues" tab, there seem to be a few issues with the code.

You don't want to do the "recovery mode", assuming that the sensor is not stuck in the I2C communication ?
According to the datasheet, you should do a "I2C send reset" and read and store the sensorbitmap.
Only after that you may set the MOD1 and MOD2 registers.
You try to write to the register at register address 0. But that is reserved, that is not a configuration register.

Do you want to write the value 0x05 to register MOD1 ? but that enables the interrupt. It is in the datasheet.

The datasheet always reads 7 bytes from the sensor. I suggest you do the same.

  byte buffer[7];
  Wire.requestFrom(tlv_addr, 7); //request the 7 raw, UN-decoded bits from the sensor's readings of X, Y, Z axes
  Wire.readBytes( buffer, 7);

  //---- Print Out Sensor Axis Readings ----//
  Serial.print( "X= ");
  Serial.print( buffer[0], HEX);
  Serial.print( ", tY= ");
  Serial.print( buffer[1], HEX);
  Serial.print( ", Z= ");
  Serial.print( buffer[2], HEX);
  Serial.println();

Koepel:
You don't want to do the "recovery mode", assuming that the sensor is not stuck in the I2C communication ?
According to the datasheet, you should do a "I2C send reset" and read and store the sensorbitmap.
Only after that you may set the MOD1 and MOD2 registers.
You try to write to the register at register address 0. But that is reserved, that is not a configuration register.

Do you want to write the value 0x05 to register MOD1 ? but that enables the interrupt. It is in the datasheet.

Thank you so much for your reply, this is exactly what I'm having trouble understanding, to do things like you said, "I2C send reset," "read and store the sensorbitmap," and just knowing which register is what and what to do what has been very challenging and I can barely understand what I'm supposed to do this being the only datasheet I've tried to make sense of before.

I know all of this is in the datasheet, but the formatting and being new to this I cant see this clearly as that and I am learning as I'm going, these are new concepts to me completely.

So to confirm, I should:
First do a I2C send reset by writing the hex code to the sensor address
Second store the sensorbitmap
Then write to the mod registers

  • what is/does storing the sensor bitmap do?

  • are the mod registers the same thing as the configuration register?

  • I have heard of the interrupt but I'm not sure what it is and is it necessary?

  • If i get all the above then the sensor will start outputting the magnetic axes measurements, at least raw bytes?

Sorry about all of the questions, but thank you so much this is the most explanation for anything related to this I've received at all.

If thats too much to request, I also looked at that library and that library depends on me connecting my sensor using the A4, A5 pins for for I2C, Is there an easy way to edit that sketch so I only have to use the already dedicated SCL/SDA pins on the Arduino Uno instead?

O boy, the datasheet is not only hard to understand, it is weird as well :smiley_cat:
I don't know what went wrong when they designed this chip en wrote the datasheet. It is almost as if they outsourced the design of the chip to others that have not done such thing before. And after that more went wrong when the datasheet was translated to English.

With the "Bitmap" they mean all the bits of all the registers. Okay, it is a map of all the bits. See Figure 20 in the "Register Map.pdf".

Reading the whole sensor bitmap (all the registers) means address 0x00 up to 0x09, that are 10 bytes in total.
By storing the bitmap, they mean to store the data in variables in the sketch, they might be needed later.

The are needed when the four Write Registers are written (all four at once).
A few of the restrictions when writing the Write Registers are:
The Reserved Write Register at 0x02 should be written with Register 0x08 from the Read Registers.
The Reserved Bits of Write Register MOD2 (at 0x03) should be written with bit 0...4 from Read Register 0x09.

That is not just weird, that is totally nuts.

I strongly suggest to keep the code of the library by IRNAS close. That should be working code. That is much more efficient than trying to understand this nutty sensor with its weird datasheet.

We know. We know that you also asked it at StackExchange: arduino uno - Communicating with magnetic sensor - TLV493D-A1B6 over I2C - Arduino Stack Exchange.
What else are you expecting then what we have already written ?
We are not a datasheet-reading-service and not a sketch-writing-service.

I asked on both forums to be able to get the most help yes, I wasn't asking for anyone to write or read the datasheet for me, I was asking for help because I exhausted my options and have been stuck for awhile. I appreciate all the help really, thank you, this has been tremendous.