Using AS5600 library to identify the Position and velocity of two DC motors using arduino Nano and I2C multiplexer

Hello

I have small and big problems with the AS5600 library. I am kinda confused about how to use it to my advantage; for my project, I have attached two AS5600 hall magnet sensors to two DC motors, which are being controlled by a FLysky controller, and my job is to read the rpm and position of the dc motors since I am using two of these sensors that need I2C connection so I am reading data using the TCA9548A multiplexer
so here is the main objective I have successfully connected my sensors and read data through a multiplexer, but the problem I am can not identify the forward and reverse position of DC motors and need to use the AS5600 library to my advantage to be able to identify forward and reverse position and RPM of the DC motor
I am at that point where I need someone's help and thoughts on my code to see where I am doing something wrong and make sure my RPM values make sense, but when I run, my code numbers are all over the place. For example, when I go two revolutions forward, the code shows 2 rev perfect right, but for reverse, the motors will turn 4 times in reverse, and my serial monitor will show -2 rev .

#include <Wire.h>
#include "AS5600.h"

#define TCAADDR 0x70  // I2C address of the TCA9548A multiplexer

// Create sensor objects for the two motors
AS5600L sensor1;  // Sensor for Motor 1
AS5600L sensor2;  // Sensor for Motor 2

// Multiplexer channels
int I2CA = 6;  // Sensor 1 channel
int I2CB = 7;  // Sensor 2 channel

// Timing variables for high resolution measurements
unsigned long lastTimeMicros = 0;
const unsigned long measurementIntervalMicros = 100000UL;  // 200 ms update interval

// Variables to store last cumulative position (raw counts)
long lastCP1 = 0;
long lastCP2 = 0;

// Constants
const float COUNTS_PER_REV = 4096.0;  // AS5600 resolution

// Function to select the multiplexer channel
void TCA9548(int bus) {
  if (bus < 0 || bus > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << bus);
  Wire.endTransmission();
  delay(1);  // Short delay for switching
}

void setup() {
  Serial.begin(115200);
  while (!Serial) { ; }
  Serial.println("Setup initializing...");
  Wire.begin();

  // --- Sensor 1 Setup & Calibration ---
  TCA9548(I2CA);
  sensor1.begin(4);
  sensor1.setDirection(AS5600_CLOCK_WISE);
  sensor1.setAddress(0x36);
  if (!sensor1.isConnected()) {
    Serial.println("Sensor 1 not detected!");
    while (1);
  }
  delay(2000);  // Allow sensor to stabilize
  lastCP1 = sensor1.getCumulativePosition();
  Serial.print("Sensor 1 initial cumulative position: ");
  Serial.println(lastCP1);

  // --- Sensor 2 Setup & Calibration ---
  TCA9548(I2CB);
  sensor2.begin(4);
  sensor2.setDirection(AS5600_CLOCK_WISE);
  sensor2.setAddress(0x36);
  if (!sensor2.isConnected()) {
    Serial.println("Sensor 2 not detected!");
    while (1);
  }
  delay(2000);  // Allow sensor to stabilize
  lastCP2 = sensor2.getCumulativePosition();
  Serial.print("Sensor 2 initial cumulative position: ");
  Serial.println(lastCP2);

  // Initialize timing
  lastTimeMicros = micros();
  Serial.println("Setup done.");
}

void loop() {
  unsigned long currentMicros = micros();

  // Update at the defined interval
  if (currentMicros - lastTimeMicros >= measurementIntervalMicros) {
    // Calculate time difference in seconds
    float dt = (currentMicros - lastTimeMicros) / 1000000.0;
    lastTimeMicros = currentMicros;

    // ----- Sensor 1 Update -----
    TCA9548(I2CA);
    long cp1 = sensor1.getCumulativePosition();  // Raw cumulative counts
    long dCP1 = cp1 - lastCP1;                     // Change in counts since last update
    lastCP1 = cp1;
    // Convert raw counts to revolutions
    float rev1 = cp1 / COUNTS_PER_REV;
    float dRev1 = dCP1 / COUNTS_PER_REV;
    // Calculate RPM: (change in rev / dt) * 60
    float rpm1 = (dRev1 / dt) * 60.0;

    // ----- Sensor 2 Update -----
    TCA9548(I2CB);
    long cp2 = sensor2.getCumulativePosition();
    long dCP2 = cp2 - lastCP2;
    lastCP2 = cp2;
    float rev2 =sensor2.getRevolutions();
    float dRev2 = dCP2 / COUNTS_PER_REV;
    float rpm2 = (dRev2 / dt) * 60.0;

    // ----- Debug Output -----
    Serial.print("Sensor 1 - Raw CP: ");
    Serial.print(cp1);
    Serial.print(" , Rev: ");
    Serial.print(rev1, 3);
    Serial.print(" , RPM: ");
    Serial.println(rpm1, 3);

    Serial.print("Sensor 2 - Raw CP: ");
    Serial.print(cp2);
    Serial.print(" , Rev: ");
    Serial.print(rev2, 3);
    Serial.print(" , RPM: ");
    Serial.println(rpm2, 3);

    delay(100);
  }
}

this results from the serial monitor                                                                                         
Sensor 1 - Raw CP: -779 , Rev: -0.190 , RPM: 10.728
Sensor 2 - Raw CP: 10979 , Rev: 2.000 , RPM: 0.000
Sensor 1 - Raw CP: -685 , Rev: -0.167 , RPM: 13.076
Sensor 2 - Raw CP: 10979 , Rev: 2.000 , RPM: 0.000
Sensor 1 - Raw CP: -859 , Rev: -0.210 , RPM: -24.256
Sensor 2 - Raw CP: 10979 , Rev: 2.000 , RPM: 0.000
Sensor 1 - Raw CP: -827 , Rev: -0.202 , RPM: 4.458
Sensor 2 - Raw CP: 10979 , Rev: 2.000 , RPM: 0.000
Sensor 1 - Raw CP: -887 , Rev: -0.217 , RPM: -8.346
Sensor 2 - Raw CP: 10979 , Rev: 2.000 , RPM: 0.000
Sensor 1 - Raw CP: -739 , Rev: -0.180 , RPM: 20.612
Sensor 2 - Raw CP: 10979 , Rev: 2.000 , RPM: 0.000
Sensor 1 - Raw CP: -770 , Rev: -0.188 , RPM: -4.323
Sensor 2 - Raw CP: 10978 , Rev: 2.000 , RPM: -0.139
Sensor 1 - Raw CP: -858 , Rev: -0.209 , RPM: -12.265
Sensor 2 - Raw CP: 10979 , Rev: 2.000 , RPM: 0.139

in this case of testing motor two is only running for less confusion and I would appreciate any thoughts and idea that can help thank you so much

probably simpler to move to a microcontroller which supports two I2C interfaces, e.g. ESP32
the AS5600 has a 3.3V operating mode so interfacing should be no problem

Please note you are using getCumulativePosition()

turning 2 revs forward ==> 2 minus 4 backwards ==> 2-4 = -2

You might solve this by calling resetCumulativePosition(int32_t position) at the moment you reverse the direction. (set parameter position to 0).

1 Like