AS5600.h rotary position sensor trouble

I got it to work mechanically, it gives accurate fast readings, great device.
Two problems remain.

  1. On startup before the motor turns I get weird reading that does not make sense. As soon as I turn the motor , the degrees become accurate.
    AS5600_LIB_VERSION: 0.4.1
    Address For AS5600 54
    Connect: 1
    -1
    5729°
    0

    -1
    5760°
    0

    0

    0

    0

    This is a big problem because the degrees will be fed in the input of a PID. They have to be 0-359.

Second problem, I am trying to reset the revolution counts to zero when the motor goes fwd or back past the 360 degrees.
The count resets for going Fwd, but not back. Please see my code.

//    FILE: AS5600_position.ino
//  AUTHOR: Rob Tillaart
// PURPOSE: demo
//    DATE: 2022-12-20


#include "AS5600.h"
#include "Wire.h"

AS5600 as5600_R;   //  use default Wire
int Raw_R;
int Raw_Prev;

float Deg_R=0;
float Deg_Prev_R=1;

void setup()
{
  Serial.begin(230400);
  Serial.println(__FILE__);
  Serial.print("AS5600_LIB_VERSION: ");
  Serial.println(AS5600_LIB_VERSION);

  //  ESP32
  //  as5600.begin(14, 15);
  //  AVR
  as5600_R.begin(14);  //  set direction pin.
  as5600_R.setDirection(AS5600_CLOCK_WISE);  // default, just be explicit.
Serial.print ("Address For AS5600 ");
  Serial.println(as5600_R.getAddress());

  //  as5600.setAddress(0x40);  // AS5600L only

  int b = as5600_R.isConnected();
  Serial.print("Connect: ");
  Serial.println(b);

  delay(1000);
}


void loop()
{
  static uint32_t lastTime = 0;

 Deg_R=convertRawAngleToDegrees(as5600_R.getCumulativePosition());
  //  update every 100 ms
  //  should be enough up to ~200 RPM
  if (millis() - lastTime >= 100 and Deg_R != Deg_Prev_R)
  {
    lastTime = millis();

    Serial.println(as5600_R.getRevolutions());
    Serial.println(String(Deg_R,0) +"°" );
 
    Deg_Prev_R =Deg_R;
  }

  //  just to show how reset can be used
  if (as5600_R.getRevolutions() >= 1 or as5600_R.getRevolutions() <= -1 )
  {
    as5600_R.resetPosition();
  }
}

float convertRawAngleToDegrees(word newAngle)
{
  /* Raw data reports 0 - 4095 segments, which is 0.087890625 of a degree */
  float retVal = newAngle * 0.087890625;
  retVal=round(retVal);
 // retVal=retVal/10;
  return retVal;
}

If you look inside the library for getCumulativePosition() and assume the device powers up initially with a reading of 0x0FFF (4095), you will see that getCumulativePosition() returns -1.

Since your convertRawAngleToDegrees() takes a word aka unsigned 16 bit values, that -1 gets converted to 65535. Multiply that by 0.08790625 and round it and you will get 5729.

You should make

float convertRawAngleToDegrees(word newAngle)

be

float convertRawAngleToDegrees(uint32_t newAngle)

so the parameter you pass matches the parameter type returned by .getCumulativePosition()

1 Like

Thanks a lot friend

Good observation, I tried but the same problem:
Now the initial number is even bigger
AS5600_LIB_VERSION: 0.4.1
Address For AS5600 54
Connect: 1
-1
377487260°
0

0

0

0

0

maybe call the .resetPosition() function in setup() to it resets everything before you start using it.

I have put that in the setup and it works, I get a degree reading when I Boot.

Thank you.
I am trying to implement 2 sensors on the same IC2 bus. I bought the one called AS5600L that has an address of 0x40. Tried to implement it using setAddress, but the library won't execute it.
Says there is no member. Please help.

#include "AS5600.h"
#include "Wire.h"

AS5600 as5600_R;   //  use default Wire

AS5600 as5600L;   //  use default Wire
int Raw_R;
int Raw_Prev;

float Deg_R=0;
float Deg_Prev_R=1;

void setup()
{
  Serial.begin(230400);
  Serial.println(__FILE__);
  Serial.print("AS5600_LIB_VERSION: ");
  Serial.println(AS5600_LIB_VERSION);
  
  as5600L.setAddress(0x40);  // AS5600L only
    as5600L.begin(15);  //  set direction pin.
  as5600L.setDirection(AS5600_CLOCK_WISE);  // default, just be explicit.
  as5600_R.begin(14);  //  set direction pin.
  as5600_R.setDirection(AS5600_CLOCK_WISE);  // default, just be explicit.
Serial.print ("Address For AS5600 ");
  Serial.println(as5600_R.getAddress());


  int b = as5600_R.isConnected();
  Serial.print("Connect: ");
  Serial.println(b);

  delay(1000);
   as5600_R.resetPosition();
}

If you are using an AS5600L device, then you have to use that class, not the AS5600 class

AS5600 as5600_R;   //  use default Wire
AS5600L as5600L;   //  use default Wire

And you won't have to call .setAddress() since you are using the default 0x40

Thanks a lot, that worked.
Here is the code for the other viewers:



#include "AS5600.h"
#include "Wire.h"

AS5600 as5600_R;   //  use default Wire

AS5600L as5600_L;   //  use default Wire
int Raw_R;
int Raw_Prev;

float Deg_R,  Deg_L;
float Deg_Prev_R, Deg_Prev_L;
static uint32_t lastTime = 0;
void setup()
{
  Serial.begin(230400);
  Serial.println(__FILE__);
  Serial.print("AS5600_LIB_VERSION: ");
  Serial.println(AS5600_LIB_VERSION);
 Wire.begin();
  // as5600_L.setAddress(0x40);  // AS5600L only
  as5600_L.begin(15);  //  set direction pin.
  as5600_L.setDirection(AS5600_CLOCK_WISE);  //
  delay(1000);
  as5600_R.begin(14);  //  set direction pin.
  as5600_R.setDirection(AS5600_CLOCK_WISE);  // default, just be explicit.

  delay(1000);
  Serial.print ("Address For AS5600 R ");
  Serial.println(as5600_R.getAddress());
  Serial.print ("Address For AS5600 L ");
  Serial.println(as5600_L.getAddress());

  int b = as5600_R.isConnected();
 
  Serial.print("Connect_R: ");
  Serial.println(as5600_R.isConnected() ? "true" : "false");

    Serial.print("Connect device LEFT: ");
  Serial.println(as5600_L.isConnected() ? "true" : "false");

  delay(1000);
  as5600_R.resetPosition();
  as5600_L.resetPosition();
}


void loop()
{
  

 Deg_R = convertRawAngleToDegrees(as5600_R.getCumulativePosition());
 Deg_L = convertRawAngleToDegrees(as5600_L.getCumulativePosition());
  //  update every 100 ms
  //  should be enough up to ~200 RPM
  if (millis() - lastTime >= 100 and Deg_R != Deg_Prev_R)
  {
    lastTime = millis();
   
    Serial.println("REV R: "+ String(as5600_R.getRevolutions()));
       Serial.println("REV L: "+ String(as5600_L.getRevolutions()));
    Serial.println("DEG R= "+String(Deg_R, 0) + "°" );
    Serial.println("DEG L= " +String(Deg_L, 0) + "°" );
    Deg_Prev_R = Deg_R;
  }

  //  just to show how reset can be used
  if (as5600_R.getRevolutions() >= 1 )
  {
    as5600_R.resetPosition();

    if ( as5600_R.getRevolutions() <= -1 )
    {
      as5600_R.resetPosition();
    }
  }
}

float convertRawAngleToDegrees(uint32_t newAngle)
{
  /* Raw data reports 0 - 4095 segments, which is 0.087890625 of a degree */
  float retVal = newAngle * 0.087890625;
  retVal = round(retVal);
  // retVal=retVal/10;
  return retVal;
}

If this works for you tick the 'mark as solution' box.  That way this thread will show up to others as a possible help.

Having 2 sensors on one bus works. But there is still the issue of not getting good initial readings.

Despite the
as5600_R.resetPosition();
as5600_L.resetPosition();

when there are 2 sensors I get erroneous readings such as
REV R: -1
REV L: 0
DEG R= 377487200°
DEG L= 132°

Rolling the motors forward increases the angles as expected, but rolling them back past 0 deg. is
resulting in those huge numbers . Ideally it would go to 359 , 358 etc degrees ,

Would you know what to do about that?
Thanks
mitch

Your function that converts to degrees takes an unsigned 32 bit value (uint32_t) which means that -1 == 4294967295

If you are dealing with positive and negative numbers, don't make your parameter unsigned.

1 Like

Yes that worked


float convertRawAngleToDegrees(int newAngle)
{
  /* Raw data reports 0 - 4095 segments, which is 0.087890625 of a degree */
  float retVal = newAngle * 0.087890625;
  retVal = round(retVal);
  // retVal=retVal/10;
  return retVal;
}

Still , it drives me crazy.

Sometime when I boot, I get negative degrees and I move it and they turn to positive degrees.
Then I re boot and I get negative again....
Any ideas?
Revolutions show at -1 despite of the reset position...

I decided to replace the cumulative function that is experimental with readAngle().
It is more stable, and there are no negative numbers....

.getCummulativePosition() returns a 32 bit integer and then you truncate it down to a 16 bit integer. It is important to learn about types and keep them straight or they end up biting you.

float convertRawAngleToDegrees(int32_t newAngle)

did you try .resetCummulativePosition()? It is a good idea to look inside your library and see what is going on.

I am gonna stick with the rawAngle for right now. Thanks for the suggestion.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.