Seeed_Arduino_AS5600 icon indicating copy to clipboard operation
Seeed_Arduino_AS5600 copied to clipboard

Improvements to setMaxAngle() / setStartPosition() / setEndPosition()

Open sheffieldnikki opened this issue 2 years ago • 3 comments

Sorry for all the editing - changed my mind! See next comment for new versions.

sheffieldnikki avatar Jun 08 '22 20:06 sheffieldnikki

Here are new versions of the set_() and get_() functions. Suggested improvements:

  1. Simplified code if no argument (-1)
  2. Reads back the newly set register value using get_() functions instead of duplicating that code in each set_() function
  3. Uses new shared writeTwoBytes() function to write double byte i2c registers, for smaller code size and better readability
  4. Added return value to setConf(), for consistency with other set_() functions
  5. Fixed typo "setEndtPosition" in comment
  6. Simplified getEndPosition()
  7. Better documentation of what happens if no function argument
  8. Better documentation with min/max values, and how to use start+end or start+range for scaled outputs

I don't think setMaxAngle() / getMaxAngle() are ideal function names since the MANG register doesn't set the "max angle" but rather than angular range or 'width' from the start position angle. I haven't renamed them though, just improved the documentation.

/*******************************************************
  In: new angular range to set 205..4095, OR none
  Out: value of angular range register
  Description: sets a value in angular range register.
  Must be greater than 18 degrees (204). Use with start:
  start=10 deg + range=90 deg gives 10..100 degrees for 
  output from getScaledAngle.
  If no value is provided, method will set from start
  position to current position of magnet.
*******************************************************/
word AMS_5600::setMaxAngle(word newMaxAngle)
{
  if (newMaxAngle == -1) newMaxAngle = getRawAngle();
  writeTwoBytes(_addr_mang, newMaxAngle);
  return getMaxAngle();
}

/*******************************************************
  Method: getMaxAngle
  In: none
  Out: value of angular range register 205..4095
  Description: gets value of angular range register.
*******************************************************/
word AMS_5600::getMaxAngle()
{
  return readTwoBytesSeparately(_addr_mang);
}

/*******************************************************
  Method: setStartPosition
  In: new start angle position 0..4095, OR none
  Out: value of start position register
  Description: sets a value in start position register.
  If no value is provided, method will set to current 
  position of magnet.
*******************************************************/
word AMS_5600::setStartPosition(word startAngle)
{
  if (startAngle == -1) startAngle = getRawAngle();
  writeTwoBytes(_addr_zpos, startAngle);
  return getStartPosition();
}

/*******************************************************
  Method: getStartPosition
  In: none
  Out: value of start position register 0..4095
  Description: gets value of start position register.
*******************************************************/
word AMS_5600::getStartPosition()
{
  return readTwoBytesSeparately(_addr_zpos);
}

/*******************************************************
  Method: setEndPosition
  In: new end angle position 0..4095, OR none
  Out: value of end position register
  Description: sets a value in end position register.
  Use with start: start=10 deg + end=180 deg gives 
  10..180 degrees for output from getScaledAngle.
  If no value is provided, method will set to current 
  position of magnet.
*******************************************************/
word AMS_5600::setEndPosition(word endAngle)
{
  if (endAngle == -1) endAngle = getRawAngle();
  writeTwoBytes(_addr_mpos, endAngle);
  return getEndPosition();
}

/*******************************************************
  Method: getEndPosition
  In: none
  Out: value of end position register 0..4095
  Description: gets value of end position register.
*******************************************************/
word AMS_5600::getEndPosition()
{
  return readTwoBytesSeparately(_addr_mpos);
}

/*******************************************************
  Method: getRawAngle
  In: none
  Out: value of raw angle register 0..4095
  Description: gets raw value of magnet position.
  start, end/max angle settings do not apply.
*******************************************************/
word AMS_5600::getRawAngle()
{
  return readTwoBytesTogether(_addr_raw_angle);
}

/*******************************************************
  Method: getScaledAngle
  In: none
  Out: value of scaled angle register 0..4095
  Description: gets scaled value of magnet position.
  start and end/max angle settings are used to convert
  a reduced range (eg, 10..100 degrees) to full 0..4095 
  values for greater resolution.
*******************************************************/
word AMS_5600::getScaledAngle()
{
  return readTwoBytesTogether(_addr_angle);
}

/*******************************************************
  Method: setConf
  In: value of CONF register, see datasheet
  Out: value of CONF register
  Description: sets value of CONF register.
*******************************************************/
word AMS_5600::setConf(word _conf)
{
  writeTwoBytes(_addr_conf, _conf);
  return getConf();
}

and a new function writeTwoBytes():

/*******************************************************
  Method: writeTwoBytes
  In: address and data to write
  Out: none
  Description: writes two bytes to an i2c register.
*******************************************************/
void AMS_5600::writeTwoBytes(int adr_in, word dat_in)
{
  writeOneByte(adr_in,   highByte(dat_in));
  delay(2);
  writeOneByte(adr_in+1, lowByte(dat_in));
  delay(2);
}

sheffieldnikki avatar Jun 09 '22 08:06 sheffieldnikki

I haven't tested it, but this is a much faster way to write 2 bytes, without setting the register address separately for the high and low bytes, and without delay() calls:

void AMS_5600::writeTwoBytes(int adr_in, word dat_in)
{
  Wire.beginTransmission(_ams5600_Address);
  Wire.write(adr_in);
  Wire.write(highByte(dat_in));
  Wire.write(lowByte(dat_in));  // automatic adr_in+1
  Wire.endTransmission();
}

sheffieldnikki avatar Jun 09 '22 13:06 sheffieldnikki

Sorry, if it is off topic: Arduino 1.8.19 using esp8266 complains that e.g. startAngle == -1 can never happen because word seems unsigned 16bit. In case you want change the functions.

dwarning avatar Aug 04 '22 14:08 dwarning