<- Back

Beautiful update on TMAG5273

Its raining outside here so just stuck myself in the room and continued to explore better options to get accuracy without complication. The results makes me so happy, I was able to get really really good readings from the sensor, without doing advanced maths. I almost started finding algos to shape fitting algorithms from ellipsoid to a sphere, but those dramas are not required; If you refer my previous logs, I was using x,y,and x axes. X-axis is not required. CORDIC Angle is amazing!!! This is a big win for us :-)

I will be attaching 3 logs:

  1. log3.txt - sampled at 45RPM
  2. log4.txt - sampled at 5RPM
  3. log5.txt - sampled at 4RPM

Just take a look at log5.txt, it gave me goosebumps. I will still plan to make it better by using kalman filter, but sometime later during next week. And that is for getting accurate readings of 0.5 degrees at lower RPM. from the logs, I can see that it is possible.


// hey peeps I just found a better way of getting angular positions with further trials.
// this is way much easier way to get really good and accurate readings without even using kalman filter (but I will implement kalman later in the days.).

#include <Wire.h>
// I am heavily referring this code for now because
// the library is good and I am getting stable and better readings.
// just take a visit here:
// https://docs.sparkfun.com/SparkFun_Qwiic_Hall_Effect_Sensor_TMAG5273/example_angle_calculation/#hardware-connections
// and then, it has a link to:
// https://github.com/sparkfun/SparkFun_TMAG5273_Arduino_Library/blob/main/examples/Example3_AngleCalculations/Example3_AngleCalculations.ino
// this is heavenly because the MIT license lets me use the code.
// also, I recommend reading SparkFun_TMAG5273_Arduino_Library_Defs.h
// Tt has all the options to configure the sensor's registers and helps you very well.
#include "SparkFun_TMAG5273_Arduino_Library.h"

// my i2c pins
#define I2C_SDA 8
#define I2C_SCL 9

TMAG5273 sensor;

uint8_t i2cAddress = TMAG5273_I2C_ADDRESS_INITIAL;

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    delay(10);
  }

  // Esp32 supports a maximum clock speed of 800kHz, and the sensor offers a maximum clock speed of 1MHz.
  // lowest of the 2 is 800kHz. but dont wanna bottle neck it, so let me try with 600k
  bool i2cStatus = Wire.begin(I2C_SDA, I2C_SCL, 600000);  // 600kHz clock speed

  if (!i2cStatus) {
    Serial.println(F("Critical Error: I2C bus initialization failed"));
    while (1)
      ;
  }

  // Initialize the sensor instance using the remapped Wire instance
  if (sensor.begin(i2cAddress, Wire) == 1) {
    Serial.println(F("Success: TMAG5273 detected on the I2C bus!"));
  } else {
    Serial.println(F("Error: Sensor not found. Checking alternative addresses..."));

    // Fallback check if the standard library address (0x22) fails
    if (sensor.begin(0x35, Wire) == 1) {
      i2cAddress = 0x35;
      Serial.println(F("Success: Found sensor at fallback address 0x35!"));
    } else if (sensor.begin(0x44, Wire) == 1) {
      i2cAddress = 0x44;
      Serial.println(F("Success: Found sensor at fallback address 0x44!"));
    } else {
      Serial.println(F("Fatal: No TMAG5273 device responded at 0x22, 0x35, or 0x44."));
      Serial.println(F("Please double-check your connections and pull-up resistors."));
      while (1) {
        delay(1000);  // noooooo :-/
      }
    }
  }

  // Activate core sensor functions
  sensor.setTemperatureEn(true);
  // Enable the physical tracking channels for the math engine to work on
  // Enable X, Y channels. Yes!!!!! this is enough!
  // take a look at my previous log to see the pic of orientation.
  // I tried with TMAG5273_Y_Z_ENABLE as well, but the angle got warped under 180 degrees. So, using this now.
  sensor.setMagneticChannel(TMAG5273_YZY_ENABLE);
  // YZ is the only way
  sensor.setAngleEn(TMAG5273_YZ_ANGLE_CALCULATION);           // Fixes compile error
  sensor.setOperatingMode(TMAG5273_CONTINUOUS_MEASURE_MODE);  // Maintain continuous pipeline refreshing
}

void loop() {
  if (sensor.getMagneticChannel() != 0) {
    // Collect calibrated floating-point fields scaled to milliTesla
    unsigned long timestamp = micros();
    float magY = sensor.getYData();
    float magZ = sensor.getZData();
    float temp = sensor.getTemp();
    float angD = sensor.getAngleResult();
    float rpm = getRPM(timestamp, angD);


    // wooohoooo!!!! results:
    Serial.printf("{\"time\": %lu, \"By\": %.6f, \"Bz\": %.6f, \"angD\": %.4f, \"rpm\": %.2f \"Temp\": %.2f },\n",
                  timestamp, magY, magZ, angD, rpm, temp);

  } else {
    Serial.println(F("Warning: Magnetic channels reporting disabled. Check configuration registers."));
  }
}


float getRPM(unsigned long t, float angle) {
  static float prevAng = angle;
  static unsigned long revStart = t;
  static float accum = 0.0f;  // unwrapped deg this rev
  static float rpm = 0.0f;

  float d = angle - prevAng;
  prevAng = angle;
  if (d > 180.0f) {
    d -= 360.0f;
  }
  if (d < -180.0f) {
    d += 360.0f;
  }
  accum += d;

  if (fabsf(accum) >= 360.0f) {  // one full turn completed
    float secs = (t - revStart) * 1e-6f;
    if (secs > 0.0f){
      rpm = 60.0f / secs; 
    } 
    accum -= (accum > 0.0f) ? 360.0f : -360.0f;
    revStart = t;
  }
  return rpm;
}