Seeed-Studio / Seeed_Arduino_AS5600

The library comes with AS5600. Through this library, we can realize read the angles 、get magnetic from a magnet underneath the sensor.
MIT License
105 stars 38 forks source link

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

Open sheffieldnikki opened 2 years ago

sheffieldnikki commented 2 years ago

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

sheffieldnikki commented 2 years ago

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 otherset_() 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 commented 2 years ago

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();
}
dwarning commented 2 years ago

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.