sparkfun / SparkFun_TMAG5273_Arduino_Library

Communicates with the TMAG5273 over I2C to quickly integrate a Hall-effect sensor into your project.
Other
11 stars 6 forks source link

Inconsistent X/Y axis magnetic field readings, incorrect temperature reading #5

Open asfarley opened 12 months ago

asfarley commented 12 months ago

I am using:

Steps to reproduce

Run BasicReadings code. Observe that Z-axis readings are consistent/make sense based on magnet presence, but X/Y axis readings seem to just be jumping around without any relationship to field strength.

Also, the temperature reading is indicating -266C. It's about 21C here.

Expected behavior

I expect a close-to-0 reading on magnetic axes when they're not exposed to a magnet. I expect a temperature reading around 21C.

Here's what I'm seeing from the Serial Monitor:

-266.31 C (0.94, -0.47, -0.03) mT -266.31 C (0.94, -0.66, -0.03) mT -266.31 C (0.51, -0.70, -0.02) mT -266.31 C (0.70, -0.66, -0.02) mT -266.31 C (0.94, -0.35, -0.02) mT -266.31 C (0.27, -0.82, -0.02) mT -266.31 C (0.86, -0.39, 0.00) mT -266.31 C (0.86, -0.86, -0.03) mT -266.31 C (0.43, -0.35, -0.03) mT -266.31 C (0.94, -0.47, -0.02) mT -266.31 C

I'll do some lower-level debugging and post the results here.

asfarley commented 12 months ago

The code in getTemp() uses a slightly different method for getting the MSB/LSB values from the device, I'm not sure why.

The code only refers to the MSB register:

float TMAG5273::getTemp()
{
    // Variable to store full temperature value
    int16_t temp = 0;
    uint8_t databuffer[2];
    // Read in the MSB and LSB registers
    readRegisters(TMAG5273_REG_T_MSB_RESULT, databuffer, 2);
    // Combines the two in one register where the MSB is shifted to the correct location
    temp = (databuffer[0] << 8) | (databuffer[1]);
    // Formula for correct output value
    float tempOut = TMAG5273_TSENSE_T0 + (((float)temp - TMAG5273_TADC_T0) / (TMAG5273_TADC_RES));

    return tempOut;
}

Whereas the code for e.g. GetZData reads MSB and LSB explicitly:

float TMAG5273::getZData()
{
    int8_t zLSB = 0;
    int8_t zMSB = 0;

    zLSB = readRegister(TMAG5273_REG_Z_LSB_RESULT);
    zMSB = readRegister(TMAG5273_REG_Z_MSB_RESULT);

    // Variable to store full X data
    int16_t zData = 0;
    // Combines the two in one register where the MSB is shifted to the correct location
    zData = zLSB + (zMSB << 8); 

    // Reads to see if the range is set to 40mT or 80mT
    uint8_t rangeValZ = getZAxisRange();
    uint8_t range = 0;
    if (rangeValZ == 0)
    {
        range = 40;
    }
    else if (rangeValZ == 1)
    {
        range = 80;
    }

    // div = (2^16) / 2    (as per the datasheet equation 10)
    // 16-bit data format equation
    float div = 32768;
    float zOut = (range * zData) / div;

    return zOut;
}

I tried modifying getTemp to use the same approach, and now I'm getting a more sensible value (33C) although this is quite a bit higher than I expected unless the IC is self-heating by 13C.

The values I'm seeing for MSB and LSB are around 70 and 64 respectively. The LSB is moving around the amount I would expect (by the lower 1-2 bits) so it looks believable.

asfarley commented 12 months ago

Here's the exact Arduino sketch code I'm using for completeness:

//#include <SoftwareWire.h>
#include <Wire.h>            // Used to establish serial communication on the I2C bus
#include "SparkFun_TMAG5273_Arduino_Library.h" // Used to send and recieve specific information from our sensor

// I2C default address
#define TMAG5273_I2C_ADDRESS_INITIAL 0X35 // I2C ADDRESS (7 MBS BITS - TMAG5273A1)
#define TMAG5273_I2C_ADDRESS_WRITE 0X6A // I2C WRITE ADDRESS (8-bit)
#define TMAG5273_I2C_ADDRESS_READ 0X6B // I2C READ ADDRESS (8-bit)

TMAG5273 sensor; // Initialize hall-effect sensor
// I2C default address
uint8_t i2cAddress = TMAG5273_I2C_ADDRESS_INITIAL;

void setup() {

  //myWire.begin();
  Wire.begin();
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(A0, OUTPUT);
  pinMode(6, INPUT);
  pinMode(12, INPUT);

  delay(1000);  
  // If begin is successful (0), then start example
  if(sensor.begin(i2cAddress, Wire) == 1)
  {
    Serial.println("Begin");
  }
  else // Otherwise, infinite loop
  {
    Serial.println("Device failed to setup - Freezing code.");
    while(1); // Runs forever
  }
}

void loop() {

  ReadMagnetometer();

  // put your main code here, to run repeatedly:
  // int j3 = digitalRead(6);
  // int j4 = digitalRead(12);
  // Serial.print("J3:");
  // Serial.println(j3);
  // Serial.print("J4:");
  // Serial.println(j4);
  //Serial.println("PF7:ON");
  digitalWrite(A0, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(1000);                      // wait for a second
  //Serial.println("PF7:OFF");
  digitalWrite(A0, LOW);   // turn the LED off by making the voltage LOW
  delay(1000);  
  //Serial.println("Hello from ThrottleController");
}

void ReadMagnetometer()
{
   // Checks if mag channels are on - turns on in setup
    if(sensor.getMagneticChannel() != 0) 
    {
      sensor.setTemperatureEn(true);

      float magX = sensor.getXData();
      float magY = sensor.getYData();
      float magZ = sensor.getZData();
      float temp = sensor.getTemp();

      Serial.print("(");
      Serial.print(magX);
      Serial.print(", ");
      Serial.print(magY);
      Serial.print(", ");
      Serial.print(magZ);
      Serial.println(") mT");
      Serial.print(temp);
      Serial.println(" C");
    }
    else
    {
      // If there is an issue, stop the magnetic readings and restart sensor/example
      Serial.println("Mag Channels disabled, stopping..");
    }
}
asfarley commented 12 months ago

Here's a schematic of my circuit, although (since the IC seems to be responding) I think this is probably a software issue rather than hardware.

https://imgur.com/a/QunX3ba

asfarley commented 12 months ago

I noticed a couple of things I don't understand:

I'm reading through the data sheet to check the code against the specs. The device returns 2s-complement values, so the final result interpreted as one 16-bit number should be interpreted as signed. According to the Arduino website, the Atmega-based devices use 16-bit 2s complement for integers.

It doesn't seem correct to me to sum together 2 signed values which each are one byte of a 2s-complement value. I also can't see anything in the datasheet indicating why the x-channel would need to be reversed.

asfarley commented 12 months ago

I had success modifying the 2s-complement conversion routine in the library. It's interesting to me that there was another report of a similar issue, and it seemed to be fixed then. Is there some MCU dependency here? The other user was using an ESP8266.

MadisonC-SparkFun commented 12 months ago

Hi @asfarley ,

As for the X-Channel sign, it should be a negative number. If you look at Equation 10 on page 22 of the datasheet, all of the signs need to be flipped to be multiplied by (-1). The Y and Z channels will be corrected to match in the next release of this library.

For the temperature function confusion, this uses the readRegisters() function, not readRegister(). This function reads both the MSB and the LSB registers by reading one register, and then the next, combining them.

As for the issues that you are seeing with inconsistent readings of the temperature functionality, that issue was fixed in the previous update as you had mentioned. I have been testing with your code trying to recreate the issue that you have been seeing, but been having no luck. I'm going to continue with this throughout the day but wanted to give an update for the time being. I do not believe that it is an MCU dependency, but that will also be taken into consideration when testing. Thanks!

asfarley commented 12 months ago

@MadisonC-SparkFun Thanks for following up. Are there any differences between my hardware/software setup and yours?

MadisonC-SparkFun commented 12 months ago

As for my testing environment, I have been using the following:

MadisonC-SparkFun commented 12 months ago

My temperature readings with each device are consistently reading around 24-25C in my environment (which is reading a tad high, but I do keep my office quite warm with a heater so it would make sense for my case).

asfarley commented 12 months ago

Is the interrupt pin tied to ground on your TMAG?

Are you able to test with a Leonardo/ Atmega32u4?

Interesting re: temperature readings. 24-25C seems more believable than 30C.

I've been getting sensible/apparently correct magnetic readings after locally makes some changes to this library. My changes required a different method of 2s-complement conversion compared to what is in 1.0.3.

I'll post back here after doing some detailed testing on the changes I introduced.

MadisonC-SparkFun commented 12 months ago

The interrupt is tied high to 3.3V

As for the other boards, I will get my hands on those and report back with how those test 👍

MadisonC-SparkFun commented 12 months ago

Hi @asfarley , after doing some more testing, I have been unable to recreate the issue that you have been seeing. Since this is not being tested on a SparkFun product, there are a lot of variables that could be playing into this issue. At this point, I'm going to refer you to the SparkFun Forums for further questions and technical help. I am going to keep this issue open to see if any other users have come across this. https://forum.sparkfun.com/

joemcmanus commented 8 months ago

I have the same results on a Sparkfun Pro Micro C https://www.sparkfun.com/products/15795 and Sparkfun 3D Linear Hall Effect Sensor https://www.sparkfun.com/products/23880 . I read -266C. I'll tinker around and see if I can help.

-Joe

MadisonC-SparkFun commented 8 months ago

Hi @joemcmanus, after some testing on my end with the Pro Micro C I am unable to recreate this result. I'm going to point you in the direction of our forums for further questions and technical help. https://forum.sparkfun.com/

WenjingLi2036 commented 6 months ago

I am using

After running the Example 1. Basic Reading from TMAG5273 Library. I got the results shown in the following figure.

Serial information

I felt like all three-axis magnetic readings didn't make sense. I also tested with some PM, the reading will never be larger than 1mT.

For more information, I also attached my PCB board. my PCB board

I would appreciate it very much if someone could give me some hints on how to debug this project. Thanks!

jmole commented 6 months ago

I'm also having this issue with the Pro Micro C Qwiic and the TMAG5273 sensor. Exactly the same boards as Joe in #issuecomment-1991918332

Oscilloscope shows that the data from the mag sensor looks correct, I suspect there is an issue with the conversion to floating point on the ATMEGA32U4 chip.

jmole commented 6 months ago

Yep, returning the values directly as int16 solves the problem. Not familiar with using floating point on ATMega chips (not am I interested in doing so), so I don't have a real "fix" for this, but you can use this patch to test. int16.patch

The change to uint8_t came from PR #8 which should also be merged, since it doesn't make sense to store multibyte I2C data in an int8_t.

asfarley commented 6 months ago

I was able to get it working for myself on the ATMega, here's my fork:

https://github.com/asfarley/SparkFun_TMAG5273_Arduino_Library.git

yutong-he commented 3 months ago

@WenjingLi2036 Hi May I know if you solve this problem? I met the same problem recently.