Communicating with TLE493D-W2B6 3D hall sensor

EDIT: go to a second attempt thread on this chip

Hello,

today I received TLE493D-W2B6-A3 (magnetic encoder), here is user manual with I2C registers.

I soldered it to a breakout PCB and hooked another I2C device to get pullups (5K).
Testing with 3.3V "mini" Leonardo – I2C scanner detects them fine (TLE493D at 0x44).

I tried different I2C speeds, but I always get 255 if I try to read any register.
Logic analyzer data (plenty samples):

I tied requesting 1,2,3,10,20 bytes, always "255" and always last byte gets "NACK".
I can't believe I fried the chip – I wasn't heating it that much...

My code:

#include <Wire.h>

#define TLE493D_A3 0x44 // I2C address
#define By 0x01 // Returns Y magnetic (MSB/R) value

void setup()
{
  Wire.begin();
  Wire.setClock(100000); // 10000, 100000, 400000, 1000000

}

void loop()
{

  Wire.beginTransmission(TLE493D_A3);
  Wire.write(By);
  Wire.endTransmission();
  Wire.requestFrom(TLE493D_A3, 2);

  delay(1000);

}

I used to be good at I2C, I know I'm missing something obvious... Any ideas?

Can you get 4k7 or 10k resistors as pullup resistors ? I want to rule out all problems. Perhaps the 0x44 is the other I2C device ?
Is that a 3.3V 8MHz ATmega32U4 board ?

The picture shows that it gives an acknowledge to its address. Everything seems okay. You are reading 0xFF from it. That means the register is 0xFF or it is in power down mode.

I suggest to start with the diagnostics register at 0x06.

This is the manufacturer's page for the TLE493D-W2B6 A3: https://www.infineon.com/cms/en/product/sensor/magnetic-sensors/magnetic-position-sensors/3d-magnetics/tle493d-w2b6-a3/.
Selecting on the left "Documents" and then "User Manual" shows a document for the I2C registers.
There is a lot written about power en resetting the sensor and waiting 30µs. I did not read all of that.

Have you seen this: GitHub - Infineon/TLE493D-3DMagnetic-Sensor: Library for Infineons's 3D magnetic sensor TLE493D for Arduino. ?

It's 3.3V 16MHz ATmega32U4 board ( I know, it's strange spec combo, but they are true).
It's not a resistors and address is good.

I had a suspicion that this is some sort of setup issue, but after digging more I found that this chip by default communicates differently than most devices I know – it uses 2 byte communication by default:
master have to send chip address with "read" bit at the end and after that again master should send register byte and only then wait for data. I don't think default wire lib can do that.

I've tried that library, it gives me an error when I try to upload, even with vanilla UNO, so gave up on it, tho I'll analyze it tomorrow.

I linked datasheet and user manual in my first post – I did some googling and troubleshooting myself, I'm not that lazy You know :slight_smile:

The Infineon library at github is confusing. The initialization code is spread over three files.
Have you seen this: "//TODO: tle493d-w2b6 freezes after being reset".

3Dgeo:
master should send register byte and only then wait for data.

I can not read somewhere that such a delay is needed. If that delay is needed, then the Wire library can not do it, but the Infineon code at Github uses the Wire library.

3Dgeo:
I linked datasheet and user manual in my first post – I did some googling and troubleshooting myself, I'm not that lazy You know :slight_smile:

Are you sure ? Check your links and mine, check also the URL's themself ::slight_smile:

I can not find other Arduino code for that sensor :frowning:
But you are not the only one having problems with it. This is just a few days ago: c++ - Compilation error in example for Infineons Tle493d_w2b6 sensor - Stack Overflow.

My conclusion is that you have bad luck, you have to figure it out on your own. I suggest to work on two paths. Try to make the Infineon code work, and try to wakeup the sensor. Start by reading all the registers and print them.

I soldered it to a breakout PCB

Post a picture of the PCB. Did you include the required 100 nF decoupling cap?

Koepel:
The Infineon library at github is confusing. The initialization code is spread over three files.
Have you seen this: "//TODO: tle493d-w2b6 freezes after being reset".

I think I can crack it and make my own library as long as freezing is not due to a hardware issues...

Koepel:
I can not read somewhere that such a delay is needed. If that delay is needed, then the Wire library can not do it, but the Infineon code at Github uses the Wire library.

It's not a delay, odd thing is that master have to send slave address and a "read" bit (wire lib automatically adds "write" bit if beginTransmission is called), and after "read" bit still master should write a byte instead of waiting for a byte:

Koepel:
I can not find other Arduino code for that sensor :frowning:
But you are not the only one having problems with it. This is just a few days ago: c++ - Compilation error in example for Infineons Tle493d_w2b6 sensor - Stack Overflow.

Yes, I know, I had same issues... What comes to I2C I'm usually making my own libs, tho this time it's a bit different due to "2 byte communication", but the way I see it – it's just makes things more interesting :slight_smile:

Koepel:
My conclusion is that you have bad luck, you have to figure it out on your own. I suggest to work on two paths. Try to make the Infineon code work, and try to wakeup the sensor. Start by reading all the registers and print them.

Nah, I don't see it as a bad luck, I see it as a way to improve my knowledge and coding skills.

I have to admit I'm surprised by Your effort to help me, I really appreciate it, You are awesome, thank You!

jremington:
Post a picture of the PCB. Did you include the required 100 nF decoupling cap?

Well, it's only a test, so assumed that I can get communication working without a cap, tho it's not an issue to stick one...

assumed that I can get communication working without a cap

Extremely bad assumption. ALWAYS obey the manufacturer's recommendations, if you want your projects to work.

jremington:
Extremely bad assumption. ALWAYS obey the manufacturer's recommendations, if you want your projects to work.

Of course I'll add it on a final project, but currently I'm only focus on fast and simple communication test, nothing more, so please calm your caps :wink:

It seems that your long URL's are needed. I spoke too soon, sorry for my remarks :-[

A datasheet can be bad.
The people that design the chip are probably not the same people that write the datasheet.

So we are talking about the: "User Manual: TLE493D-W2B6 Low Power 3D Hall Sensor with I2C Interface and Wake Up Function" (Infineon-TLE493D-W2B6-UM-v01-01-UserManual-v01_11-EN.pdf).
On page 20, Figure 3, there are trigger bits and a register address while in reading mode.

The picture is very clear, there is no repeated start in between. The chip does not even support a repeated start.
I think that such an extra byte breaks the normal I2C protocol.
That is not possible with the Arduino Wire library.

It is almost the same as 10-bit addresses.
https://i2c.info/i2c-bus-specification (scroll down to the bottom).
The Arduino Wire library does not support 10-bit addresses.
The address 0x44 is not in the range for extended addresses. So something is wrong and Infineon is to blame for that.

Infineon should at least have written in the datasheet that they had a bad idea and made a special 2-byte read command that is not according to the I2C specifications.

Can you read the registers with the 1-byte read command ? It seems that the PR bit has to be set to enter the 1-byte read mode.
Then the chip behaves like any other sensor, and you can still read multiple bytes.

I think that the special 2-byte read command is not needed to use the chip.
If you want to explore it, then you can alter one of the software I2C libraries.

By the way, the note about freezing has a delay in that function. Perhaps the delay is enough, perhaps it is something they are still working on.

jremington was serious with "Extremely bad assumption". You need to decouple the power. For now we are only trying to understand the datasheet. Please add a cap. When fixing one problem, you have to take extra care to avoid other problems.

@OP

Your codes of original post is incomplete -- after Wire.requestFrom() command, you have not taken out the data from the FIFO Buffer. Try the following sketch.

#include <Wire.h>

#define TLE493D_A3 0x44 // I2C address
#define By 0x01 // Returns Y magnetic (MSB/R) value

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  Wire.setClock(100000); // 10000, 100000, 400000, 1000000

}

void loop()
{

  Wire.beginTransmission(TLE493D_A3);
  Wire.write(By);
  Wire.endTransmission();
  Wire.requestFrom(TLE493D_A3, 2);

  byte x1 = Wire.read();
  x1 = x1<<8|wire.read();
  Serial.println(x1, HEX);  //Serial Monitor should show something.
   delay(1000);

}

Hi,
Have you googled

tle493d arduino library

The library has examples that may help.

Thanks.. Tom.. :slight_smile:

Koepel:
Can you read the registers with the 1-byte read command ? It seems that the PR bit has to be set to enter the 1-byte read mode.
Then the chip behaves like any other sensor, and you can still read multiple bytes.

I think that the special 2-byte read command is not needed to use the chip.

Yes, there is a way to change read commands according to standard. I will explore this today.
I always can bit bang it to test if chip works.

Koepel:
jremington was serious with "Extremely bad assumption". You need to decouple the power. For now we are only trying to understand the datasheet. Please add a cap. When fixing one problem, you have to take extra care to avoid other problems.

You know, big part of me want to prove that this is not that dam cap and wants to leave it out from this testing phase just cos :smiley:

GolamMostafa:
Your codes of original post is incomplete -- after Wire.requestFrom() command, you have not taken out the data from the FIFO Buffer. Try the following sketch.

No, I remove that part of code when I made this thread to keep it short cos I'm using logic analyzer. That part don't make any difference.

TomGeorge:
Hi,
Have you googled

tle493d arduino library

What "googled" means? What "google" is?

Just kidding, as discussed above that lib is incomplete and gives errors when uploading.

I "lizard brained" a crap out of it: :smiley:

To change it to 1 byte mode instead of 2 bytes I have to write 1bit (4th) to a MOD1 register, to do that I have to read it firs cos it contains other settings that I don't want to change, but I can't read it due to 2 byte mode...

I tried lazy way and just sent B00010000, but chip changed it's address from 0x44 to 0x35 (address resets after resetting).
Well OK, lets do this it's way, lets send instruction to 0x35...
I tried reading data from 0x35 and it seems to work – I'm getting changing data according to magnet distance.

I can add that cap now, I proved my point :smiley:

Yes, I realize I'm being lazy here, I know I should dig in to MOD1 and set it as it should be, not write "0" to other bits...

So the datasheet is probably correct. But the chip does not operate according to the I2C standard :slightly_frowning_face: What were they thinking ? :angry: If they designed something not according to a standard, then it should be something that is turned off by default.

I'm glad you have at least a start.

Talking about bad design, there is one more little thing: In C++ it is 0b00010000 and the B00010000 is defined by Arduino without a good reason. It does not seem to be a big issue, until a new Arduino user tries 'B1' as a variable name.

Koepel:
So the datasheet is probably correct. But the chip does not operate according to the I2C standard :slightly_frowning_face: What were they thinking ? :angry: If they designed something not according to a standard, then it should be something that is turned off by default.

I'm glad you have at least a start.

Yes, it is strange, and yes, it should be off by default. At least it supports standard, even if it's not default.
Anyway, there is much more to figure out, this was an easy part... :slight_smile:

Koepel:
Talking about bad design, there is one more little thing: In C++ it is 0b00010000 and the B00010000 is defined by Arduino without a good reason. It does not seem to be a big issue, until a new Arduino user tries 'B1' as a variable name.

Cheeese, how noob do You think I'm? :smiley:

OK, next task is to calculate Temp out of received data.

After a bit of digging this time I found a real mistake on datasheet:
Registers holds only 10bit temp value and in first page on datasheet it claims that temp is 10bit, but in datasheets page 13, Table 14 shows 12bit temp calculations. That's a mess up... :slight_smile:

You can fix all the errors and most of the warnings in the Infineon library (TLE493D-3DMagnetic-Sensor/src at master · Infineon/TLE493D-3DMagnetic-Sensor · GitHub) by:

  • Changing PD3 and PD0 to _PD3 and _PD0 so they don't conflict with AVR pin number defines.
  • Commenting out the two lines that reference "LED2" (which is not defined).

johnwasser:
You can fix all the errors and most of the warnings in the Infineon library (TLE493D-3DMagnetic-Sensor/src at master · Infineon/TLE493D-3DMagnetic-Sensor · GitHub) by:

  • Changing PD3 and PD0 to _PD3 and _PD0 so they don't conflict with AVR pin number defines.
  • Commenting out the two lines that reference "LED2" (which is not defined).

Thanks, I'm not arguing against that, but I need to get to know this IC cos I'm planing to implement it in commercial project, so I don't want to use poor written libraries made by others.
I don't say mine will be perfect, but at least it will be optimized for my needs and I will know how it works.

3Dgeo:
After a bit of digging this time I found a real mistake on datasheet:
Registers holds only 10bit temp value and in first page on datasheet it claims that temp is 10bit, but in datasheets page 13, Table 14 shows 12bit temp calculations. That's a mess up... :slight_smile:

In the datasheet it says: "Temperature values are based on 12 bit resolution. Please note: only bit 11 ... 2 are listed in the bitmap registers".

The registers have only bit 4 ... 11 and bit 2 ... 3. That is 10 bits resolution from the registers of a 12-bit value. You have to make bit 0 and 1 zero to make 12 bits. The temperature is a 2's complement. That means you have to check the highest bit, and extend that bit over all the higher bits.

You also have to enable the temperature.

They combine the data with this line, do the calculation with this line with these constants.

Are they ignoring negative values for the 10 bits from the registers ? I think so.

I have tested how to calculate the temperature in a sketch:

// Datasheet:
//   Table 14 shows the values for the temperature bits   : 0101001011
//   In the calculation they use a different example value: 0110101011
//   However, in the example calculation they write the second one, but use the first one !
//   I assume that is a error in the datasheet.
//
//   Using the first one:
//     0101001011 = 0 + 1024 + 0 + 256 + 0 + 0 + 32 + 0 + 8 + 4 = 1324
//     Calculation to temperature: (1324 -1180) * 0.24 + 25°C ≈ 60°C
//
//   In the source code is written that the 0.24 is in the range 0.21 to 0.27
//


// When reading the registers into bytes, register 0x03 and 0x05 are required for the temperature.
byte reg03 = 0b01010010;   // Temp (11...4)
byte reg05 = 0b11000000;   // Temp (3...2), ID, Bz (3...0)

void setup()
{
  Serial.begin( 9600);
  Serial.println( "TLE394D-W2B6 temperature");

  // Combine the registers
  
  int16_t rawT;
  rawT  = int16_t( reg03 & 0xFF) << 4;      // unused bits will become zero
  rawT |= int16_t( reg05 & 0xC0) >> 4;      // add bit 2 and 3

  Serial.print( "rawT = 0x");
  Serial.print( rawT, HEX);     // writing a negative HEX value prints too many FFFF (Arduino bug)
  Serial.print( " = 0b");
  Serial.print( rawT, BIN);
  Serial.print( " = ");
  Serial.print( rawT);
  Serial.println( " dec");

  // Extend the sign bit

  if( (rawT & 0x0800) != 0)   // or: if( bitRead( rawT, 11) == 1)  // 12-th bit is bit number 11 ?
  {
    rawT |= 0xF000;
  }

  Serial.print( "rawT with sign extend = 0x");
  Serial.print( rawT, HEX);
  Serial.print( " = ");
  Serial.print( rawT);
  Serial.println( " dec");

  float t_float = (float( rawT - 1180) * 0.24) + 25.0;

  // It is possible to do the calculation with with integers.
  // 0.24 happens to be 6/25.
  // Multiplying by 6 does not hit the limit of a signed 16 integer,
  // because the highest 4 bits were not used.
  // Is the rounding correct for negative numbers ? I don't know.
  int   t_int = ((rawT - 1180) * 6 / 25) + 25;
  int   t_int_rounded = ((((rawT - 1180) * 6) + 12) / 25) + 25;

  Serial.print( "t_float = ");
  Serial.println( t_float);
  Serial.print( "t_int = ");
  Serial.println( t_int);
  Serial.print( "t_int_rounded = ");
  Serial.println( t_int_rounded);
}

void loop() 
{
}

Thanks again for Your effort, but, temp calculation is just a practice working with the chip and I wasn't planing to use it in the end.

I have much bigger issues – it seems I can't configure this IC (properly this time), it's just crashes...
And the worst thing is than the only way to reset it in the product "on the fly" is to send specific I2C commands that wire lib does not support.

My enthusiasm is very low at this point, it's just too much effort... I'll give it one more day and after that I'm moving on.
Its I2C protocol is just too messed up and chip itself is too unstable. It's probably possible to make it work, but it would require much more time, and I rather spend it elsewhere...
I will leave it on the final PCB design cos it doesn't block its replacement and I might give it 2dn try later, but at the moment I'm just too frustrated.

To be specific – when I try to "Write" MOD2 register chip crashes:

  // MOD2
  Wire.beginTransmission(TLE493D_A3);
  Wire.write(MOD2);
  Wire.endTransmission();
  Wire.requestFrom(TLE493D_A3, 1);

  while (Wire.available())
  {
      MOD2value = Wire.read(); 
  }

  MOD2value &= 0b00011111;
  MOD2value |= PRD << 5;


  Wire.beginTransmission(TLE493D_A3);
  Wire.write(MOD2);
  Wire.write(MOD2value); // <--- this line crashes IC
  Wire.endTransmission();

Are you really reading the MOD2 register ?
I don't want to read the datasheet again, but I think with 1-byte reading mode the read data starts at register address 0.
Perhaps it is not possible to set the register address with the 1-byte reading mode.

The datasheet tells that the initial version was january 2018 (page 20, revision history). It is not an old chip, they should know better.
The last revision was updating the text for I2C reset.

On page 9: "The I2C reset feature of the sensor shall be used by the μC after Power Up".

On page 26 of the User Manual is written how to reset it.
The addresses 0xFF and 0x00 have to be written followed by a 30µs delay.

That is the part in the Infineon code that is commented out.

// mInterface.bus->begin();
// mInterface.bus->write(0xFF);
// mInterface.bus->end();

I could not find those "begin()" and "end()" functions, so I can not verify that this would be executed:

// Wire.beginTransmission(0xFF);
// Wire.endTransmission();

But it is weird to make functions "begin()" and "end()" when there is already a "Wire.begin()" and "Wire.end()" who do something totally different.

Just now, I am reading the known issues: TLE493D-3DMagnetic-Sensor/Readme.md at master · Infineon/TLE493D-3DMagnetic-Sensor · GitHub. And I scrolled through the two open Github Issues.
Wow, they really messed up.

Looking at the closed issues I found one by me. So initially they did not know how to use the Wire library.

I think you are right, and the best choice is to drop this sensor. Who knows how many more problems you will encounter.