mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
[P142] Add AS5600 Magnetic angle sensor
This commit is contained in:
@@ -0,0 +1,640 @@
|
||||
//
|
||||
// FILE: AS56000.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.6.1
|
||||
// PURPOSE: Arduino library for AS5600 magnetic rotation meter
|
||||
// DATE: 2022-05-28
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
// CONFIGURATION REGISTERS
|
||||
const uint8_t AS5600_ZMCO = 0x00;
|
||||
const uint8_t AS5600_ZPOS = 0x01; // + 0x02
|
||||
const uint8_t AS5600_MPOS = 0x03; // + 0x04
|
||||
const uint8_t AS5600_MANG = 0x05; // + 0x06
|
||||
const uint8_t AS5600_CONF = 0x07; // + 0x08
|
||||
|
||||
// CONFIGURATION BIT MASKS - byte level
|
||||
const uint8_t AS5600_CONF_POWER_MODE = 0x03;
|
||||
const uint8_t AS5600_CONF_HYSTERESIS = 0x0C;
|
||||
const uint8_t AS5600_CONF_OUTPUT_MODE = 0x30;
|
||||
const uint8_t AS5600_CONF_PWM_FREQUENCY = 0xC0;
|
||||
const uint8_t AS5600_CONF_SLOW_FILTER = 0x03;
|
||||
const uint8_t AS5600_CONF_FAST_FILTER = 0x1C;
|
||||
const uint8_t AS5600_CONF_WATCH_DOG = 0x20;
|
||||
|
||||
|
||||
// UNKNOWN REGISTERS 0x09-0x0A
|
||||
|
||||
// OUTPUT REGISTERS
|
||||
const uint8_t AS5600_RAW_ANGLE = 0x0C; // + 0x0D
|
||||
const uint8_t AS5600_ANGLE = 0x0E; // + 0x0F
|
||||
|
||||
// I2C_ADDRESS REGISTERS (AS5600L)
|
||||
const uint8_t AS5600_I2CADDR = 0x20;
|
||||
const uint8_t AS5600_I2CUPDT = 0x21;
|
||||
|
||||
// STATUS REGISTERS
|
||||
const uint8_t AS5600_STATUS = 0x0B;
|
||||
const uint8_t AS5600_AGC = 0x1A;
|
||||
const uint8_t AS5600_MAGNITUDE = 0x1B; // + 0x1C
|
||||
const uint8_t AS5600_BURN = 0xFF;
|
||||
|
||||
// STATUS BITS
|
||||
const uint8_t AS5600_MAGNET_HIGH = 0x08;
|
||||
const uint8_t AS5600_MAGNET_LOW = 0x10;
|
||||
const uint8_t AS5600_MAGNET_DETECT = 0x20;
|
||||
|
||||
|
||||
AS5600::AS5600(TwoWire *wire)
|
||||
{
|
||||
_wire = wire;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::begin(uint8_t directionPin)
|
||||
{
|
||||
_directionPin = directionPin;
|
||||
if (_directionPin != AS5600_SW_DIRECTION_PIN)
|
||||
{
|
||||
pinMode(_directionPin, OUTPUT);
|
||||
}
|
||||
setDirection(AS5600_CLOCK_WISE);
|
||||
|
||||
if (! isConnected()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::isConnected()
|
||||
{
|
||||
_wire->beginTransmission(_address);
|
||||
return ( _wire->endTransmission() == 0);
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getAddress()
|
||||
{
|
||||
return _address;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// CONFIGURATION REGISTERS + direction pin
|
||||
//
|
||||
void AS5600::setDirection(uint8_t direction)
|
||||
{
|
||||
_direction = direction;
|
||||
if (_directionPin != AS5600_SW_DIRECTION_PIN)
|
||||
{
|
||||
digitalWrite(_directionPin, _direction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getDirection()
|
||||
{
|
||||
if (_directionPin != AS5600_SW_DIRECTION_PIN)
|
||||
{
|
||||
_direction = digitalRead(_directionPin);
|
||||
}
|
||||
return _direction;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getZMCO()
|
||||
{
|
||||
uint8_t value = readReg(AS5600_ZMCO);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setZPosition(uint16_t value)
|
||||
{
|
||||
if (value > 0x0FFF) return false;
|
||||
writeReg2(AS5600_ZPOS, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint16_t AS5600::getZPosition()
|
||||
{
|
||||
uint16_t value = readReg2(AS5600_ZPOS) & 0x0FFF;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setMPosition(uint16_t value)
|
||||
{
|
||||
if (value > 0x0FFF) return false;
|
||||
writeReg2(AS5600_MPOS, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint16_t AS5600::getMPosition()
|
||||
{
|
||||
uint16_t value = readReg2(AS5600_MPOS) & 0x0FFF;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setMaxAngle(uint16_t value)
|
||||
{
|
||||
if (value > 0x0FFF) return false;
|
||||
writeReg2(AS5600_MANG, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint16_t AS5600::getMaxAngle()
|
||||
{
|
||||
uint16_t value = readReg2(AS5600_MANG) & 0x0FFF;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// CONFIGURATION
|
||||
//
|
||||
bool AS5600::setConfigure(uint16_t value)
|
||||
{
|
||||
if (value > 0x3FFF) return false;
|
||||
writeReg2(AS5600_CONF, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint16_t AS5600::getConfigure()
|
||||
{
|
||||
uint16_t value = readReg2(AS5600_CONF) & 0x3FFF;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// details configure
|
||||
bool AS5600::setPowerMode(uint8_t powerMode)
|
||||
{
|
||||
if (powerMode > 3) return false;
|
||||
uint8_t value = readReg(AS5600_CONF + 1);
|
||||
value &= ~AS5600_CONF_POWER_MODE;
|
||||
value |= powerMode;
|
||||
writeReg(AS5600_CONF + 1, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getPowerMode()
|
||||
{
|
||||
return readReg(AS5600_CONF + 1) & 0x03;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setHysteresis(uint8_t hysteresis)
|
||||
{
|
||||
if (hysteresis > 3) return false;
|
||||
uint8_t value = readReg(AS5600_CONF + 1);
|
||||
value &= ~AS5600_CONF_HYSTERESIS;
|
||||
value |= (hysteresis << 2);
|
||||
writeReg(AS5600_CONF + 1, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getHysteresis()
|
||||
{
|
||||
return (readReg(AS5600_CONF + 1) >> 2) & 0x03;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setOutputMode(uint8_t outputMode)
|
||||
{
|
||||
if (outputMode > 2) return false;
|
||||
uint8_t value = readReg(AS5600_CONF + 1);
|
||||
value &= ~AS5600_CONF_OUTPUT_MODE;
|
||||
value |= (outputMode << 4);
|
||||
writeReg(AS5600_CONF + 1, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getOutputMode()
|
||||
{
|
||||
return (readReg(AS5600_CONF + 1) >> 4) & 0x03;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setPWMFrequency(uint8_t pwmFreq)
|
||||
{
|
||||
if (pwmFreq > 3) return false;
|
||||
uint8_t value = readReg(AS5600_CONF + 1);
|
||||
value &= ~AS5600_CONF_PWM_FREQUENCY;
|
||||
value |= (pwmFreq << 6);
|
||||
writeReg(AS5600_CONF + 1, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getPWMFrequency()
|
||||
{
|
||||
return (readReg(AS5600_CONF + 1) >> 6) & 0x03;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setSlowFilter(uint8_t mask)
|
||||
{
|
||||
if (mask > 3) return false;
|
||||
uint8_t value = readReg(AS5600_CONF);
|
||||
value &= ~AS5600_CONF_SLOW_FILTER;
|
||||
value |= mask;
|
||||
writeReg(AS5600_CONF, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getSlowFilter()
|
||||
{
|
||||
return readReg(AS5600_CONF) & 0x03;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setFastFilter(uint8_t mask)
|
||||
{
|
||||
if (mask > 7) return false;
|
||||
uint8_t value = readReg(AS5600_CONF);
|
||||
value &= ~AS5600_CONF_FAST_FILTER;
|
||||
value |= (mask << 2);
|
||||
writeReg(AS5600_CONF, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getFastFilter()
|
||||
{
|
||||
return (readReg(AS5600_CONF) >> 2) & 0x07;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setWatchDog(uint8_t mask)
|
||||
{
|
||||
if (mask > 1) return false;
|
||||
uint8_t value = readReg(AS5600_CONF);
|
||||
value &= ~AS5600_CONF_WATCH_DOG;
|
||||
value |= (mask << 5);
|
||||
writeReg(AS5600_CONF, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::getWatchDog()
|
||||
{
|
||||
return (readReg(AS5600_CONF) >> 5) & 0x01;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// OUTPUT REGISTERS
|
||||
//
|
||||
uint16_t AS5600::rawAngle()
|
||||
{
|
||||
int16_t value = readReg2(AS5600_RAW_ANGLE) & 0x0FFF;
|
||||
if (_offset > 0) value = (value + _offset) & 0x0FFF;
|
||||
|
||||
if ((_directionPin == AS5600_SW_DIRECTION_PIN) &&
|
||||
(_direction == AS5600_COUNTERCLOCK_WISE))
|
||||
{
|
||||
value = (4096 - value) & 0x0FFF;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
uint16_t AS5600::readAngle()
|
||||
{
|
||||
uint16_t value = readReg2(AS5600_ANGLE) & 0x0FFF;
|
||||
if (_offset > 0) value = (value + _offset) & 0x0FFF;
|
||||
|
||||
if ((_directionPin == AS5600_SW_DIRECTION_PIN) &&
|
||||
(_direction == AS5600_COUNTERCLOCK_WISE))
|
||||
{
|
||||
value = (4096 - value) & 0x0FFF;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::setOffset(float degrees)
|
||||
{
|
||||
// expect loss of precision.
|
||||
if (abs(degrees) > 36000) return false;
|
||||
bool neg = (degrees < 0);
|
||||
if (neg) degrees = -degrees;
|
||||
|
||||
uint16_t offset = round(degrees * AS5600_DEGREES_TO_RAW);
|
||||
offset &= 4095;
|
||||
if (neg) offset = 4096 - offset;
|
||||
_offset = offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
float AS5600::getOffset()
|
||||
{
|
||||
return _offset * AS5600_RAW_TO_DEGREES;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::increaseOffset(float degrees)
|
||||
{
|
||||
// add offset to existing offset in degrees.
|
||||
return setOffset((_offset * AS5600_RAW_TO_DEGREES) + degrees);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// STATUS REGISTERS
|
||||
//
|
||||
uint8_t AS5600::readStatus()
|
||||
{
|
||||
uint8_t value = readReg(AS5600_STATUS);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::readAGC()
|
||||
{
|
||||
uint8_t value = readReg(AS5600_AGC);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
uint16_t AS5600::readMagnitude()
|
||||
{
|
||||
uint16_t value = readReg2(AS5600_MAGNITUDE) & 0x0FFF;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::detectMagnet()
|
||||
{
|
||||
return (readStatus() & AS5600_MAGNET_DETECT) > 0;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::magnetTooStrong()
|
||||
{
|
||||
return (readStatus() & AS5600_MAGNET_HIGH) > 0;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600::magnetTooWeak()
|
||||
{
|
||||
return (readStatus() & AS5600_MAGNET_LOW) > 0;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// BURN COMMANDS
|
||||
//
|
||||
// DO NOT UNCOMMENT - USE AT OWN RISK - READ DATASHEET
|
||||
//
|
||||
// void AS5600::burnAngle()
|
||||
// {
|
||||
// writeReg(AS5600_BURN, x0x80);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// See https://github.com/RobTillaart/AS5600/issues/38
|
||||
// void AS5600::burnSetting()
|
||||
// {
|
||||
// writeReg(AS5600_BURN, 0x40);
|
||||
// delay(5);
|
||||
// writeReg(AS5600_BURN, 0x01);
|
||||
// writeReg(AS5600_BURN, 0x11);
|
||||
// writeReg(AS5600_BURN, 0x10);
|
||||
// delay(5);
|
||||
// }
|
||||
|
||||
|
||||
float AS5600::getAngularSpeed(uint8_t mode)
|
||||
{
|
||||
uint32_t now = micros();
|
||||
int angle = readAngle();
|
||||
uint32_t deltaT = now - _lastMeasurement;
|
||||
int deltaA = angle - _lastAngle;
|
||||
|
||||
// assumption is that there is no more than 180° rotation
|
||||
// between two consecutive measurements.
|
||||
// => at least two measurements per rotation (preferred 4).
|
||||
if (deltaA > 2048) deltaA -= 4096;
|
||||
if (deltaA < -2048) deltaA += 4096;
|
||||
float speed = (deltaA * 1e6) / deltaT;
|
||||
|
||||
// remember last time & angle
|
||||
_lastMeasurement = now;
|
||||
_lastAngle = angle;
|
||||
|
||||
// return radians, RPM or degrees.
|
||||
if (mode == AS5600_MODE_RADIANS)
|
||||
{
|
||||
return speed * AS5600_RAW_TO_RADIANS;
|
||||
}
|
||||
if (mode == AS5600_MODE_RPM)
|
||||
{
|
||||
return speed * AS5600_RAW_TO_RPM;
|
||||
}
|
||||
// default return degrees
|
||||
return speed * AS5600_RAW_TO_DEGREES;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// POSITION cumulative
|
||||
//
|
||||
int32_t AS5600::getCumulativePosition()
|
||||
{
|
||||
int16_t value = readReg2(AS5600_ANGLE) & 0x0FFF;
|
||||
if (_error != AS5600_OK) return _position;
|
||||
|
||||
// whole rotation CW?
|
||||
// less than half a circle
|
||||
if ((_lastPosition > 2048) && ( value < (_lastPosition - 2048)))
|
||||
{
|
||||
_position = _position + 4096 - _lastPosition + value;
|
||||
}
|
||||
// whole rotation CCW?
|
||||
// less than half a circle
|
||||
else if ((value > 2048) && ( _lastPosition < (value - 2048)))
|
||||
{
|
||||
_position = _position - 4096 - _lastPosition + value;
|
||||
}
|
||||
else _position = _position - _lastPosition + value;
|
||||
_lastPosition = value;
|
||||
|
||||
return _position;
|
||||
}
|
||||
|
||||
|
||||
int32_t AS5600::getRevolutions()
|
||||
{
|
||||
int32_t p = _position >> 12; // divide by 4096
|
||||
return p;
|
||||
// if (p < 0) p++;
|
||||
// return p;
|
||||
}
|
||||
|
||||
|
||||
int32_t AS5600::resetPosition(int32_t position)
|
||||
{
|
||||
int32_t old = _position;
|
||||
_position = position;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
int32_t AS5600::resetCumulativePosition(int32_t position)
|
||||
{
|
||||
_lastPosition = readReg2(AS5600_RAW_ANGLE) & 0x0FFF;
|
||||
int32_t old = _position;
|
||||
_position = position;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
int AS5600::lastError()
|
||||
{
|
||||
int value = _error;
|
||||
_error = AS5600_OK;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// PROTECTED AS5600
|
||||
//
|
||||
uint8_t AS5600::readReg(uint8_t reg)
|
||||
{
|
||||
_error = AS5600_OK;
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(reg);
|
||||
if (_wire->endTransmission() != 0)
|
||||
{
|
||||
_error = AS5600_ERROR_I2C_READ_0;
|
||||
return 0;
|
||||
}
|
||||
uint8_t n = _wire->requestFrom(_address, (uint8_t)1);
|
||||
if (n != 1)
|
||||
{
|
||||
_error = AS5600_ERROR_I2C_READ_1;
|
||||
return 0;
|
||||
}
|
||||
uint8_t _data = _wire->read();
|
||||
return _data;
|
||||
}
|
||||
|
||||
|
||||
uint16_t AS5600::readReg2(uint8_t reg)
|
||||
{
|
||||
_error = AS5600_OK;
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(reg);
|
||||
if (_wire->endTransmission() != 0)
|
||||
{
|
||||
_error = AS5600_ERROR_I2C_READ_2;
|
||||
return 0;
|
||||
}
|
||||
uint8_t n = _wire->requestFrom(_address, (uint8_t)2);
|
||||
if (n != 2)
|
||||
{
|
||||
_error = AS5600_ERROR_I2C_READ_3;
|
||||
return 0;
|
||||
}
|
||||
uint16_t _data = _wire->read();
|
||||
_data <<= 8;
|
||||
_data += _wire->read();
|
||||
return _data;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::writeReg(uint8_t reg, uint8_t value)
|
||||
{
|
||||
_error = AS5600_OK;
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(reg);
|
||||
_wire->write(value);
|
||||
if (_wire->endTransmission() != 0)
|
||||
{
|
||||
_error = AS5600_ERROR_I2C_WRITE_0;
|
||||
}
|
||||
return _error;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600::writeReg2(uint8_t reg, uint16_t value)
|
||||
{
|
||||
_error = AS5600_OK;
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(reg);
|
||||
_wire->write(value >> 8);
|
||||
_wire->write(value & 0xFF);
|
||||
if (_wire->endTransmission() != 0)
|
||||
{
|
||||
_error = AS5600_ERROR_I2C_WRITE_0;
|
||||
}
|
||||
return _error;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AS5600L
|
||||
//
|
||||
AS5600L::AS5600L(uint8_t address, TwoWire *wire) : AS5600(wire)
|
||||
{
|
||||
_address = address;; // 0x40 = default address AS5600L.
|
||||
}
|
||||
|
||||
|
||||
bool AS5600L::setAddress(uint8_t address)
|
||||
{
|
||||
// skip reserved I2C addresses
|
||||
if ((address < 8) || (address > 119)) return false;
|
||||
|
||||
// note address need to be shifted 1 bit.
|
||||
writeReg(AS5600_I2CADDR, address << 1);
|
||||
writeReg(AS5600_I2CUPDT, address << 1);
|
||||
|
||||
// remember new address.
|
||||
_address = address;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool AS5600L::setI2CUPDT(uint8_t address)
|
||||
{
|
||||
// skip reserved I2C addresses
|
||||
if ((address < 8) || (address > 119)) return false;
|
||||
writeReg(AS5600_I2CUPDT, address << 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t AS5600L::getI2CUPDT()
|
||||
{
|
||||
return (readReg(AS5600_I2CUPDT) >> 1);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: AS5600.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.6.1
|
||||
// PURPOSE: Arduino library for AS5600 magnetic rotation meter
|
||||
// DATE: 2022-05-28
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
|
||||
|
||||
#define AS5600_LIB_VERSION (F("0.6.1"))
|
||||
|
||||
|
||||
// default addresses
|
||||
const uint8_t AS5600_DEFAULT_ADDRESS = 0x36;
|
||||
const uint8_t AS5600L_DEFAULT_ADDRESS = 0x40;
|
||||
const uint8_t AS5600_SW_DIRECTION_PIN = 255;
|
||||
|
||||
// setDirection
|
||||
const uint8_t AS5600_CLOCK_WISE = 0; // LOW
|
||||
const uint8_t AS5600_COUNTERCLOCK_WISE = 1; // HIGH
|
||||
|
||||
// 0.087890625;
|
||||
const float AS5600_RAW_TO_DEGREES = 360.0 / 4096;
|
||||
const float AS5600_DEGREES_TO_RAW = 4096 / 360.0;
|
||||
// 0.00153398078788564122971808758949;
|
||||
const float AS5600_RAW_TO_RADIANS = PI * 2.0 / 4096;
|
||||
// 4.06901041666666e-6
|
||||
const float AS5600_RAW_TO_RPM = 60.0 / 4096;
|
||||
|
||||
// getAngularSpeed
|
||||
const uint8_t AS5600_MODE_DEGREES = 0;
|
||||
const uint8_t AS5600_MODE_RADIANS = 1;
|
||||
const uint8_t AS5600_MODE_RPM = 2;
|
||||
|
||||
|
||||
// ERROR CODES
|
||||
const int AS5600_OK = 0;
|
||||
const int AS5600_ERROR_I2C_READ_0 = -100;
|
||||
const int AS5600_ERROR_I2C_READ_1 = -101;
|
||||
const int AS5600_ERROR_I2C_READ_2 = -102;
|
||||
const int AS5600_ERROR_I2C_READ_3 = -103;
|
||||
const int AS5600_ERROR_I2C_WRITE_0 = -200;
|
||||
const int AS5600_ERROR_I2C_WRITE_1 = -201;
|
||||
|
||||
|
||||
// CONFIGURE CONSTANTS
|
||||
// check datasheet for details
|
||||
|
||||
// setOutputMode
|
||||
const uint8_t AS5600_OUTMODE_ANALOG_100 = 0;
|
||||
const uint8_t AS5600_OUTMODE_ANALOG_90 = 1;
|
||||
const uint8_t AS5600_OUTMODE_PWM = 2;
|
||||
|
||||
// setPowerMode
|
||||
const uint8_t AS5600_POWERMODE_NOMINAL = 0;
|
||||
const uint8_t AS5600_POWERMODE_LOW1 = 1;
|
||||
const uint8_t AS5600_POWERMODE_LOW2 = 2;
|
||||
const uint8_t AS5600_POWERMODE_LOW3 = 3;
|
||||
|
||||
// setPWMFrequency
|
||||
const uint8_t AS5600_PWM_115 = 0;
|
||||
const uint8_t AS5600_PWM_230 = 1;
|
||||
const uint8_t AS5600_PWM_460 = 2;
|
||||
const uint8_t AS5600_PWM_920 = 3;
|
||||
|
||||
// setHysteresis
|
||||
const uint8_t AS5600_HYST_OFF = 0;
|
||||
const uint8_t AS5600_HYST_LSB1 = 1;
|
||||
const uint8_t AS5600_HYST_LSB2 = 2;
|
||||
const uint8_t AS5600_HYST_LSB3 = 3;
|
||||
|
||||
// setSlowFilter
|
||||
const uint8_t AS5600_SLOW_FILT_16X = 0;
|
||||
const uint8_t AS5600_SLOW_FILT_8X = 1;
|
||||
const uint8_t AS5600_SLOW_FILT_4X = 2;
|
||||
const uint8_t AS5600_SLOW_FILT_2X = 3;
|
||||
|
||||
// setFastFilter
|
||||
const uint8_t AS5600_FAST_FILT_NONE = 0;
|
||||
const uint8_t AS5600_FAST_FILT_LSB6 = 1;
|
||||
const uint8_t AS5600_FAST_FILT_LSB7 = 2;
|
||||
const uint8_t AS5600_FAST_FILT_LSB9 = 3;
|
||||
const uint8_t AS5600_FAST_FILT_LSB18 = 4;
|
||||
const uint8_t AS5600_FAST_FILT_LSB21 = 5;
|
||||
const uint8_t AS5600_FAST_FILT_LSB24 = 6;
|
||||
const uint8_t AS5600_FAST_FILT_LSB10 = 7;
|
||||
|
||||
// setWatchDog
|
||||
const uint8_t AS5600_WATCHDOG_OFF = 0;
|
||||
const uint8_t AS5600_WATCHDOG_ON = 1;
|
||||
|
||||
|
||||
|
||||
class AS5600
|
||||
{
|
||||
public:
|
||||
AS5600(TwoWire *wire = &Wire);
|
||||
|
||||
bool begin(uint8_t directionPin = AS5600_SW_DIRECTION_PIN);
|
||||
bool isConnected();
|
||||
|
||||
// address = fixed 0x36 for AS5600,
|
||||
// = default 0x40 for AS5600L
|
||||
uint8_t getAddress();
|
||||
|
||||
|
||||
// SET CONFIGURE REGISTERS
|
||||
// read datasheet first
|
||||
|
||||
// 0 = AS5600_CLOCK_WISE
|
||||
// 1 = AS5600_COUNTERCLOCK_WISE
|
||||
// all other = AS5600_COUNTERCLOCK_WISE
|
||||
void setDirection(uint8_t direction = AS5600_CLOCK_WISE);
|
||||
uint8_t getDirection();
|
||||
|
||||
uint8_t getZMCO();
|
||||
|
||||
// 0 .. 4095
|
||||
// returns false if parameter out of range
|
||||
bool setZPosition(uint16_t value);
|
||||
uint16_t getZPosition();
|
||||
|
||||
// 0 .. 4095
|
||||
// returns false if parameter out of range
|
||||
bool setMPosition(uint16_t value);
|
||||
uint16_t getMPosition();
|
||||
|
||||
// 0 .. 4095
|
||||
// returns false if parameter out of range
|
||||
bool setMaxAngle(uint16_t value);
|
||||
uint16_t getMaxAngle();
|
||||
|
||||
// access the whole configuration register
|
||||
// check datasheet for bit fields
|
||||
// returns false if parameter out of range
|
||||
bool setConfigure(uint16_t value);
|
||||
uint16_t getConfigure();
|
||||
|
||||
// access details of the configuration register
|
||||
// 0 = Normal
|
||||
// 1,2,3 are low power mode - check datasheet
|
||||
// returns false if parameter out of range
|
||||
bool setPowerMode(uint8_t powerMode);
|
||||
uint8_t getPowerMode();
|
||||
|
||||
// 0 = off 1 = lsb1 2 = lsb2 3 = lsb3
|
||||
// returns false if parameter out of range
|
||||
// suppresses noise when the magnet is not moving.
|
||||
bool setHysteresis(uint8_t hysteresis);
|
||||
uint8_t getHysteresis();
|
||||
|
||||
// 0 = analog 0-100%
|
||||
// 1 = analog 10-90%
|
||||
// 2 = PWM
|
||||
// returns false if parameter out of range
|
||||
bool setOutputMode(uint8_t outputMode);
|
||||
uint8_t getOutputMode();
|
||||
|
||||
// 0 = 115 1 = 230 2 = 460 3 = 920 (Hz)
|
||||
// returns false if parameter out of range
|
||||
bool setPWMFrequency(uint8_t pwmFreq);
|
||||
uint8_t getPWMFrequency();
|
||||
|
||||
// 0 = 16x 1 = 8x 2 = 4x 3 = 2x
|
||||
// returns false if parameter out of range
|
||||
bool setSlowFilter(uint8_t mask);
|
||||
uint8_t getSlowFilter();
|
||||
|
||||
// 0 = none 1 = LSB6 2 = LSB7 3 = LSB9
|
||||
// 4 = LSB18 5 = LSB21 6 = LSB24 7 = LSB10
|
||||
// returns false if parameter out of range
|
||||
bool setFastFilter(uint8_t mask);
|
||||
uint8_t getFastFilter();
|
||||
|
||||
// 0 = OFF
|
||||
// 1 = ON (auto low power mode)
|
||||
// returns false if parameter out of range
|
||||
bool setWatchDog(uint8_t mask);
|
||||
uint8_t getWatchDog();
|
||||
|
||||
|
||||
// READ OUTPUT REGISTERS
|
||||
uint16_t rawAngle();
|
||||
uint16_t readAngle();
|
||||
|
||||
// software based offset.
|
||||
// degrees = -359.99 .. 359.99 (preferred)
|
||||
// returns false if abs(parameter) > 36000
|
||||
// => expect loss of precision
|
||||
bool setOffset(float degrees); // sets an absolute offset
|
||||
float getOffset();
|
||||
bool increaseOffset(float degrees); // adds to existing offset.
|
||||
|
||||
|
||||
// READ STATUS REGISTERS
|
||||
uint8_t readStatus();
|
||||
uint8_t readAGC();
|
||||
uint16_t readMagnitude();
|
||||
|
||||
// access detail status register
|
||||
bool detectMagnet();
|
||||
bool magnetTooStrong();
|
||||
bool magnetTooWeak();
|
||||
|
||||
|
||||
// BURN COMMANDS
|
||||
// DO NOT UNCOMMENT - USE AT OWN RISK - READ DATASHEET
|
||||
// void burnAngle();
|
||||
// void burnSetting();
|
||||
|
||||
|
||||
// EXPERIMENTAL 0.1.2 - to be tested.
|
||||
// approximation of the angular speed in rotations per second.
|
||||
// mode == 1: radians /second
|
||||
// mode == 0: degrees /second (default)
|
||||
float getAngularSpeed(uint8_t mode = AS5600_MODE_DEGREES);
|
||||
|
||||
// EXPERIMENTAL CUMULATIVE POSITION
|
||||
// reads sensor and updates cumulative position
|
||||
int32_t getCumulativePosition();
|
||||
// converts last position to whole revolutions.
|
||||
int32_t getRevolutions();
|
||||
// resets position only (not the i)
|
||||
// returns last position but not internal lastPosition.
|
||||
int32_t resetPosition(int32_t position = 0);
|
||||
// resets position and internal lastPosition
|
||||
// returns last position.
|
||||
int32_t resetCumulativePosition(int32_t position = 0);
|
||||
|
||||
// EXPERIMENTAL 0.5.2
|
||||
int lastError();
|
||||
|
||||
|
||||
protected:
|
||||
uint8_t readReg(uint8_t reg);
|
||||
uint16_t readReg2(uint8_t reg);
|
||||
uint8_t writeReg(uint8_t reg, uint8_t value);
|
||||
uint8_t writeReg2(uint8_t reg, uint16_t value);
|
||||
|
||||
uint8_t _address = AS5600_DEFAULT_ADDRESS;
|
||||
uint8_t _directionPin = 255;
|
||||
uint8_t _direction = AS5600_CLOCK_WISE;
|
||||
int _error = AS5600_OK;
|
||||
|
||||
TwoWire* _wire;
|
||||
|
||||
// for getAngularSpeed()
|
||||
uint32_t _lastMeasurement = 0;
|
||||
int16_t _lastAngle = 0;
|
||||
|
||||
// for readAngle() and rawAngle()
|
||||
uint16_t _offset = 0;
|
||||
|
||||
|
||||
// EXPERIMENTAL
|
||||
// cumulative position counter
|
||||
// works only if the sensor is read often enough.
|
||||
int32_t _position = 0;
|
||||
int16_t _lastPosition = 0;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AS5600L
|
||||
//
|
||||
class AS5600L : public AS5600
|
||||
{
|
||||
public:
|
||||
AS5600L(uint8_t address = AS5600L_DEFAULT_ADDRESS, TwoWire *wire = &Wire);
|
||||
|
||||
bool setAddress(uint8_t address);
|
||||
|
||||
// UPDT = UPDATE
|
||||
// are these two needed?
|
||||
bool setI2CUPDT(uint8_t value);
|
||||
uint8_t getI2CUPDT();
|
||||
};
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
# Change Log AS5600
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.6.1] - 2024-03-31
|
||||
- improve **getCumulativePosition()**, catch I2C error, see #62
|
||||
- update readme.md (incl reorder future work).
|
||||
- update GitHub actions
|
||||
- minor edits
|
||||
|
||||
|
||||
## [0.6.0] - 2024-01-25
|
||||
- add experimental error handling
|
||||
- add **int lastError()** so user can check the status of last I2C actions.
|
||||
- update readme.md
|
||||
- update examples
|
||||
- minor edits
|
||||
|
||||
----
|
||||
|
||||
## [0.5.1] - 2023-12-31
|
||||
- fix #51, add **increaseOffset(float degrees)**
|
||||
- update keywords.txt
|
||||
- update readme.md (several cleanups)
|
||||
|
||||
## [0.5.0] - 2023-12-07
|
||||
- refactor API, begin()
|
||||
- update readme.md
|
||||
- update examples
|
||||
- add examples
|
||||
- patch library.properties => category=Sensors
|
||||
|
||||
----
|
||||
|
||||
## [0.4.1] - 2023-09-16
|
||||
- fix #45 support STM32 set I2C pins ARDUINO_ARCH_STM32
|
||||
- update readme badges
|
||||
- minor edits
|
||||
|
||||
## [0.4.0] - 2023-06-27
|
||||
- fix #39 support for Wire2 on ESP32
|
||||
- update readme.md
|
||||
|
||||
----
|
||||
|
||||
## [0.3.8] - 2023-06-18
|
||||
- add **void burnSetting()** improvements from #38
|
||||
- use with care
|
||||
- add sketches to burn settings (use with care!)
|
||||
- minor edits.
|
||||
|
||||
## [0.3.7] - 2023-05-09
|
||||
- change **getCumulativePosition()** to use **AS5600_ANGLE**
|
||||
so filters can be applied.
|
||||
- add **AS5600_DEGREES_TO_RAW** to constants.
|
||||
- add **AS5600_SW_DIRECTION_PIN** to constants.
|
||||
- minor edits.
|
||||
|
||||
## [0.3.6] - 2023-02-20
|
||||
- add **resetCumulativePosition(int32_t position)** to completely reset the cumulative counter.
|
||||
This includes the delta since last call to **getCumulativePosition()**.
|
||||
- add parameter position to **resetPosition(int32_t position)** so a new position can be set.
|
||||
This does not reset the delta since last call to **getCumulativePosition()**.
|
||||
- update readme.md
|
||||
|
||||
## [0.3.5] - 2023-02-01
|
||||
- update GitHub actions
|
||||
- update license 2023
|
||||
- update readme.md
|
||||
|
||||
## [0.3.4] - 2022-12-22
|
||||
- fix #26 edges problem of the experimental cumulative position (CP).
|
||||
- decoupled CP from **rawAngle()**
|
||||
- now one needs to call **getCumulativePosition()** to update the CP.
|
||||
- updated the readme.md section about CP.
|
||||
|
||||
## [0.3.3] - 2022-12-19
|
||||
- add experimental continuous position.
|
||||
- add **getCumulativePosition()**
|
||||
- add **resetPosition()**
|
||||
- add **getRevolutions()**
|
||||
- move code from .h to .cpp
|
||||
- add AS5600_MODE_RPM to **getAngularSpeed()**
|
||||
- add AS5600_RAW_TO_RPM
|
||||
- add example for AS5600_MODE_RPM.
|
||||
- add AS5600_DEFAULT_ADDRESS
|
||||
- add AS5600L_DEFAULT_ADDRESS
|
||||
- update readme.md
|
||||
|
||||
## [0.3.2] - 2022-10-16
|
||||
- add CHANGELOG.md
|
||||
- update readme.md
|
||||
- update build-CI to support RP2040
|
||||
|
||||
## [0.3.1] - 2022-08-11
|
||||
- add support for AS5600L (I2C address)
|
||||
- add magnetTooStrong() + magnetTooWeak();
|
||||
- add / update examples
|
||||
- update documentation
|
||||
|
||||
## [0.3.0] - 2022-07-07
|
||||
- fix #18 invalid mask setConfigure().
|
||||
|
||||
----
|
||||
|
||||
## [0.2.1] - not released
|
||||
- add bool return to set() functions.
|
||||
- update Readme (analog / PWM out)
|
||||
|
||||
## [0.2.0] - 2022-06-28
|
||||
- add software based direction control.
|
||||
- add examples
|
||||
- define constants for configuration functions.
|
||||
- fix conversion constants (4096 based)
|
||||
- add get- setOffset(degrees) functions. (no radians yet)
|
||||
|
||||
----
|
||||
|
||||
## [0.1.4] - 2022-06-27
|
||||
- fix #7 use readReg2() to improve I2C performance.
|
||||
- define constants for configuration functions.
|
||||
- add examples - especially OUT pin related.
|
||||
- fix default parameter of the begin function.
|
||||
|
||||
## [0.1.3] - 2022-06-26
|
||||
- add AS5600_RAW_TO_RADIANS.
|
||||
- add getAngularSpeed() mode parameter.
|
||||
- fix #8 bug in configure.
|
||||
|
||||
## [0.1.2] - 2022-06-02
|
||||
- add getAngularSpeed().
|
||||
|
||||
## [0.1.1] - 2022-05-31
|
||||
- add readReg2() to speed up reading 2 byte values.
|
||||
- fix clock wise and counter clock wise.
|
||||
- fix shift-direction @ getZPosition, getMPosition,
|
||||
getMaxAngle and getConfigure.
|
||||
|
||||
## [0.1.0] - 2022-05-28
|
||||
- initial version
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022-2024 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,786 @@
|
||||
|
||||
[](https://github.com/marketplace/actions/arduino_ci)
|
||||
[](https://github.com/RobTillaart/AS5600/actions/workflows/arduino-lint.yml)
|
||||
[](https://github.com/RobTillaart/AS5600/actions/workflows/jsoncheck.yml)
|
||||
[](https://github.com/RobTillaart/AS5600/issues)
|
||||
|
||||
[](https://github.com/RobTillaart/AS5600/blob/master/LICENSE)
|
||||
[](https://github.com/RobTillaart/AS5600/releases)
|
||||
[](https://registry.platformio.org/libraries/robtillaart/AS5600)
|
||||
|
||||
|
||||
# AS5600
|
||||
|
||||
Arduino library for AS5600 and AS5600L magnetic rotation meter.
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
#### AS5600
|
||||
|
||||
**AS5600** is a library for an AS5600 / AS5600L based magnetic **rotation** meter.
|
||||
More exact, it measures the angle (rotation w.r.t. reference) and not RPM.
|
||||
Multiple angle measurements allows one to calculate or estimate the RPM.
|
||||
|
||||
The AS5600 and AS5600L sensors are pin compatible (always check your model's datasheet).
|
||||
|
||||
**Warning: experimental**
|
||||
|
||||
The sensor can measure a full rotation in 4096 steps.
|
||||
The precision of the position is therefore limited to approx 0.1°.
|
||||
Noise levels are unknown, but one might expect that the sensor is affected by electric
|
||||
and or magnetic signals in the environment.
|
||||
Also unknown is the influence of metals near the sensor or an unstable
|
||||
or fluctuating power supply.
|
||||
|
||||
Please share your experiences.
|
||||
|
||||
|
||||
#### 0.5.0 Breaking change
|
||||
|
||||
Version 0.5.0 introduced a breaking change.
|
||||
You cannot set the SDA and SCL pins in **begin()** any more.
|
||||
This reduces the dependency of processor dependent Wire implementations.
|
||||
The user has to call **Wire.begin()** and can optionally set the I2C pins
|
||||
before calling **AS5600.begin()**.
|
||||
|
||||
|
||||
#### Related libraries
|
||||
|
||||
- https://github.com/RobTillaart/Angle
|
||||
- https://github.com/RobTillaart/AngleConvertor
|
||||
- https://github.com/RobTillaart/AverageAngle
|
||||
- https://github.com/RobTillaart/runningAngle
|
||||
|
||||
|
||||
## Hardware connection
|
||||
|
||||
The I2C address of the **AS5600** is always 0x36.
|
||||
|
||||
The sensor should connect the I2C lines SDA and SCL and the
|
||||
VCC and GND to communicate with the processor.
|
||||
Do not forget to add the pull up resistors to improve the I2C signals.
|
||||
|
||||
The AS5600 datasheet states it supports Fast-Mode == 400 KHz
|
||||
and Fast-Mode-Plus == 1000 KHz.
|
||||
|
||||
|
||||
#### Pull ups
|
||||
|
||||
I2C performance tests with an AS5600L with an UNO failed at 400 KHz.
|
||||
After investigation it became clear that pull ups are mandatory.
|
||||
The UNO expects 5 Volt I2C signals from the AS5600.
|
||||
However the device only provides 3V3 pulses on the bus.
|
||||
So the signal was not stable fast enough (not "square enough").
|
||||
After applying pull ups the AS5600L worked up to 1000 KHz.
|
||||
|
||||
|
||||
#### DIR pin
|
||||
|
||||
From datasheet, page 30 - Direction (clockwise vs. counter-clockwise)
|
||||
|
||||
_**The AS5600 allows controlling the direction of the magnet
|
||||
rotation with the DIR pin. If DIR is connected to GND (DIR = 0)
|
||||
a clockwise rotation viewed from the top will generate an
|
||||
increment of the calculated angle. If the DIR pin is connected
|
||||
to VDD (DIR = 1) an increment of the calculated angle will
|
||||
happen with counter-clockwise rotation.**_
|
||||
|
||||
This AS5600 library offers a 3rd option for the DIR (direction) pin of the sensor:
|
||||
|
||||
1. Connect to **GND** ==> fixed clockwise(\*). This is the default.
|
||||
1. Connect to **VCC** ==> fixed counter-clockwise.
|
||||
1. Connect to an IO pin of the processor == Hardware Direction Control by library.
|
||||
|
||||
In the 3rd configuration the library controls the direction of counting by initializing
|
||||
this pin in **begin(directionPin)**, followed by **setDirection(direction)**.
|
||||
For the parameter direction the library defines two constants named:
|
||||
|
||||
- **AS5600_CLOCK_WISE (0)**
|
||||
- **AS5600_COUNTERCLOCK_WISE (1)**
|
||||
|
||||
(\*) if **begin()** is called without **directionPin** or with this
|
||||
parameter set to **255**, Software Direction Control is enabled.
|
||||
|
||||
See Software Direction Control below for more information.
|
||||
|
||||
|
||||
#### OUT pin
|
||||
|
||||
The sensor has an output pin named **OUT**.
|
||||
This pin can be used for an analogue or PWM output signal (AS5600),
|
||||
and only for PWM by the AS5600L.
|
||||
|
||||
See **Analogue Pin** and **PWM Pin** below.
|
||||
|
||||
Examples are added to show how to use this pin with **setOutputMode()**.
|
||||
|
||||
See more in the sections Analog OUT and PWM OUT below.
|
||||
|
||||
|
||||
##### Note: (From Zipdox2 - See issue #36)
|
||||
|
||||
Some AS5600 modules seem to have a resistor between **PGO** and **GND**.
|
||||
This causes the AS5600 to disable the output (to use it for programming, see datasheet).
|
||||
This resistor needs to be removed to use the **OUT** pin.
|
||||
|
||||
|
||||
#### PGO pin
|
||||
|
||||
Not tested. ==> Read the datasheet!
|
||||
|
||||
PGO stands for ProGramming Option, it is used to calibrate and program the sensor.
|
||||
As the sensor can be programmed only a few times one should
|
||||
use this functionality with extreme care.
|
||||
See datasheet for a detailed list of steps to be done.
|
||||
|
||||
See **Make configuration persistent** below.
|
||||
|
||||
|
||||
## I2C
|
||||
|
||||
The I2C address of the **AS5600** is always 0x36.
|
||||
|
||||
#### Address
|
||||
|
||||
| sensor | address | changeable |
|
||||
|:--------:|:---------:|:-------------|
|
||||
| AS5600 | 0x36 | NO |
|
||||
| AS5600L | 0x40 | YES, check setAddress() |
|
||||
|
||||
To use more than one **AS5600** on one I2C bus, see Multiplexing below.
|
||||
|
||||
The **AS5600L** supports the change of I2C address, optionally permanent.
|
||||
Check the **setAddress()** function for non-permanent change.
|
||||
|
||||
|
||||
#### I2C multiplexing
|
||||
|
||||
Sometimes you need to control more devices than possible with the default
|
||||
address range the device provides.
|
||||
This is possible with an I2C multiplexer e.g. TCA9548 which creates up
|
||||
to eight channels (think of it as I2C subnets) which can use the complete
|
||||
address range of the device.
|
||||
|
||||
Drawback of using a multiplexer is that it takes more administration in
|
||||
your code e.g. which device is on which channel.
|
||||
This will slow down the access, which must be taken into account when
|
||||
deciding which devices are on which channel.
|
||||
Also note that switching between channels will slow down other devices
|
||||
too if they are behind the multiplexer.
|
||||
|
||||
- https://github.com/RobTillaart/TCA9548
|
||||
|
||||
Alternative could be the use of a AND port for the I2C clock line to prevent
|
||||
the sensor from listening to signals on the I2C bus.
|
||||
|
||||
Finally the sensor has an analogue output **OUT**.
|
||||
This output could be used to connect multiple sensors to different analogue ports of the processor.
|
||||
|
||||
**Warning**: If and how well this analog option works is not verified or tested.
|
||||
|
||||
|
||||
#### Performance
|
||||
|
||||
| board | sensor | results | notes |
|
||||
|:-------------:|:---------:|:-----------------|:--------|
|
||||
| Arduino UNO | AS5600 | up to 900 KHz. | https://github.com/RobTillaart/AS5600/issues/22
|
||||
| Arduino UNO | AS5600L | up to 300 KHz. |
|
||||
| ESP32 | AS5600 | no data |
|
||||
| ESP32 | AS5600L | up to 800 KHz |
|
||||
|
||||
No other boards tested yet.
|
||||
|
||||
|
||||
#### ESP32 and I2C
|
||||
|
||||
When polling the AS5600 with an ESP32 to measure RPM an issue has been reported.
|
||||
See https://github.com/RobTillaart/AS5600/issues/28
|
||||
|
||||
The problem is that the ESP32 can be blocking for up to one second if there is a
|
||||
problem in the connection with the sensor.
|
||||
Using **setWireTimeout()** does not seem to solve the problem (2023-01-31).
|
||||
In the issue the goal was to measure the turns of a rotating device at around 3800 RPM.
|
||||
|
||||
3800 RPM == 64 rounds / second.
|
||||
|
||||
To measure speed one need at least 3 angle measurements per rotation.
|
||||
This results in at least 192 measurements per second which is about 1 per 5 milliseconds.
|
||||
|
||||
Given that the ESP32 can block for a second, it can not be guaranteed to be up to date.
|
||||
Not for speed, but also not for total number of rotations.
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
```cpp
|
||||
#include "AS5600.h"
|
||||
```
|
||||
|
||||
#### Constants
|
||||
|
||||
Most important are:
|
||||
|
||||
```cpp
|
||||
// setDirection
|
||||
const uint8_t AS5600_CLOCK_WISE = 0; // LOW
|
||||
const uint8_t AS5600_COUNTERCLOCK_WISE = 1; // HIGH
|
||||
|
||||
// 0.087890625;
|
||||
const float AS5600_RAW_TO_DEGREES = 360.0 / 4096;
|
||||
// 0.00153398078788564122971808758949;
|
||||
const float AS5600_RAW_TO_RADIANS = PI * 2.0 / 4096;
|
||||
// 4.06901041666666e-6
|
||||
const float AS5600_RAW_TO_RPM = 1.0 / 4096 / 60;
|
||||
|
||||
// getAngularSpeed
|
||||
const uint8_t AS5600_MODE_DEGREES = 0;
|
||||
const uint8_t AS5600_MODE_RADIANS = 1;
|
||||
const uint8_t AS5600_MODE_RPM = 2;
|
||||
```
|
||||
|
||||
See AS5600.h file (and datasheet) for all constants.
|
||||
Also Configuration bits below for configuration related ones.
|
||||
|
||||
|
||||
#### Constructor + I2C
|
||||
|
||||
- **AS5600(TwoWire \*wire = &Wire)** Constructor with optional Wire
|
||||
interface as parameter.
|
||||
- **bool begin(uint8_t directionPin = AS5600_SW_DIRECTION_PIN)**
|
||||
set the value for the directionPin.
|
||||
If the pin is set to AS5600_SW_DIRECTION_PIN, the default value,
|
||||
there will be software direction control instead of hardware control.
|
||||
See below.
|
||||
- **bool isConnected()** checks if the address 0x36 (AS5600) is on the I2C bus.
|
||||
- **uint8_t getAddress()** returns the fixed device address 0x36 (AS5600).
|
||||
|
||||
|
||||
#### Direction
|
||||
|
||||
To define in which way the sensor counts up.
|
||||
|
||||
- **void setDirection(uint8_t direction = AS5600_CLOCK_WISE)** idem.
|
||||
- **uint8_t getDirection()** returns AS5600_CLOCK_WISE (0) or
|
||||
AS5600_COUNTERCLOCK_WISE (1).
|
||||
|
||||
See Software Direction Control below for more information.
|
||||
|
||||
|
||||
#### Configuration registers
|
||||
|
||||
Please read the datasheet for details.
|
||||
|
||||
- **bool setZPosition(uint16_t value)** set start position for limited range.
|
||||
Value = 0..4095. Returns false if parameter is out of range.
|
||||
- **uint16_t getZPosition()** get current start position.
|
||||
- **bool setMPosition(uint16_t value)** set stop position for limited range.
|
||||
Value = 0..4095. Returns false if parameter is out of range.
|
||||
- **uint16_t getMPosition()** get current stop position.
|
||||
- **bool setMaxAngle(uint16_t value)** set limited range.
|
||||
Value = 0..4095. Returns false if parameter is out of range.
|
||||
See datasheet **Angle Programming**
|
||||
- **uint16_t getMaxAngle()** get limited range.
|
||||
|
||||
|
||||
#### Configuration bits
|
||||
|
||||
Please read datasheet for details.
|
||||
|
||||
- **bool setConfigure(uint16_t value)** value == 0..0x3FFF
|
||||
Access the register as bit mask.
|
||||
Returns false if parameter is out of range.
|
||||
- **uint16_t getConfigure()** returns the current configuration register a bit mask.
|
||||
|
||||
|
||||
| Bit | short | Description | Values |
|
||||
|:-------:|:--------|:----------------|:-------------------------------------------------------|
|
||||
| 0-1 | PM | Power mode | 00 = NOM, 01 = LPM1, 10 = LPM2, 11 = LPM3 |
|
||||
| 2-3 | HYST | Hysteresis | 00 = OFF, 01 = 1 LSB, 10 = 2 LSB, 11 = 3 LSB |
|
||||
| 4-5 | OUTS | Output Stage | 00 = analog (0-100%), 01 = analog (10-90%), 10 = PWM |
|
||||
| 6-7 | PWMF | PWM frequency | 00 = 115, 01 = 230, 10 = 460, 11 = 920 (Hz) |
|
||||
| 8-9 | SF | Slow Filter | 00 = 16x, 01 = 8x, 10 = 4x, 11 = 2x |
|
||||
| 10-12 | FTH | Fast Filter | Threshold 000 - 111 check datasheet |
|
||||
| 13 | WD | Watch Dog | 0 = OFF, 1 = ON |
|
||||
| 15-14 | | not used |
|
||||
|
||||
|
||||
The library has functions to address these fields directly.
|
||||
|
||||
The setters() returns false if parameter is out of range.
|
||||
|
||||
- **bool setPowerMode(uint8_t powerMode)**
|
||||
- **uint8_t getPowerMode()**
|
||||
- **bool setHysteresis(uint8_t hysteresis)**
|
||||
Suppresses "noise" on the output when the magnet is not moving.
|
||||
In a way one is trading precision for stability.
|
||||
- **uint8_t getHysteresis()**
|
||||
- **bool setOutputMode(uint8_t outputMode)**
|
||||
- **uint8_t getOutputMode()**
|
||||
- **bool setPWMFrequency(uint8_t pwmFreq)**
|
||||
- **uint8_t getPWMFrequency()**
|
||||
- **bool setSlowFilter(uint8_t mask)**
|
||||
- **uint8_t getSlowFilter()**
|
||||
- **bool setFastFilter(uint8_t mask)**
|
||||
- **uint8_t getFastFilter()**
|
||||
- **bool setWatchDog(uint8_t mask)**
|
||||
- **uint8_t getWatchDog()**
|
||||
|
||||
|
||||
#### Read Angle
|
||||
|
||||
- **uint16_t rawAngle()** returns 0 .. 4095. (12 bits)
|
||||
Conversion factor AS5600_RAW_TO_DEGREES = 360 / 4096 = 0.087890625
|
||||
or use AS5600_RAW_TO_RADIANS if needed.
|
||||
- **uint16_t readAngle()** returns 0 .. 4095. (12 bits)
|
||||
Conversion factor AS5600_RAW_TO_DEGREES = 360 / 4096 = 0.087890625
|
||||
or use AS5600_RAW_TO_RADIANS if needed.
|
||||
The value of this register can be affected by the configuration bits above.
|
||||
This is the one most used.
|
||||
- **bool setOffset(float degrees)** overwrites the **existing** offset.
|
||||
It sets an offset in degrees, e.g. to calibrate the sensor after mounting.
|
||||
Typical values are -359.99 - 359.99 probably smaller.
|
||||
Larger values will be mapped back to this interval.
|
||||
Be aware that larger values will affect / decrease the precision of the
|
||||
measurements as floats have only 7 significant digits.
|
||||
Verify this for your application.
|
||||
Returns false if **degrees** > 360000.
|
||||
- **float getOffset()** returns offset in degrees.
|
||||
- **bool increaseOffset(float degrees)** adds degrees to the **existing** offset.
|
||||
If **setOffset(20)** is called first and **increaseOffset(-30)** thereafter the
|
||||
new offset is -10 degrees.
|
||||
Returns false if **degrees** > 360000.
|
||||
|
||||
In issue #14 there is a discussion about **setOffset()**.
|
||||
A possible implementation is to ignore all values outside the
|
||||
-359.99 - 359.99 range.
|
||||
This would help to keep the precision high. User responsibility.
|
||||
|
||||
In #51 increaseOffset is discussed.
|
||||
|
||||
```cpp
|
||||
// offset == 0;
|
||||
as.setOffset(20);
|
||||
// offset == 20;
|
||||
as.setOffset(-30);
|
||||
// offset = -30;
|
||||
|
||||
// versus
|
||||
|
||||
// offset == 0;
|
||||
as.setOffset(20);
|
||||
// offset == 20;
|
||||
as.increaseOffset(-30);
|
||||
// offset = -10;
|
||||
```
|
||||
|
||||
|
||||
#### Angular Speed
|
||||
|
||||
- **float getAngularSpeed(uint8_t mode = AS5600_MODE_DEGREES)** is an experimental function that returns
|
||||
an approximation of the angular speed in rotations per second.
|
||||
The function needs to be called at least **four** times per rotation
|
||||
or once per second to get a reasonably precision.
|
||||
|
||||
| mode | value | description | notes |
|
||||
|:----------------------|:-------:|:---------------|:--------|
|
||||
| AS5600_MODE_RADIANS | 1 | radians /sec | |
|
||||
| AS5600_MODE_DEGREES | 0 | degrees /sec | default |
|
||||
| other | - | degrees /sec | |
|
||||
|
||||
Negative return values indicate reverse rotation.
|
||||
What that exactly means depends on the setup of your project.
|
||||
|
||||
Note: the first call will return an erroneous value as it has no
|
||||
reference angle or time.
|
||||
Also if one stops calling this function
|
||||
for some time the first call after such delays will be incorrect.
|
||||
|
||||
Note: the frequency of calling this function of the sensor depends on the application.
|
||||
The faster the magnet rotates, the faster it may be called.
|
||||
Also if one wants to detect minute movements, calling it more often is the way to go.
|
||||
|
||||
An alternative implementation is possible in which the angle is measured twice
|
||||
with a short interval. The only limitation then is that both measurements
|
||||
should be within 180° = half a rotation.
|
||||
|
||||
|
||||
#### Cumulative position (experimental)
|
||||
|
||||
Since 0.3.3 an experimental cumulative position can be requested from the library.
|
||||
The sensor does not provide interrupts to indicate a movement or revolution
|
||||
Therefore one has to poll the sensor at a frequency at least **three** times
|
||||
per revolution with **getCumulativePosition()**
|
||||
|
||||
The cumulative position (32 bits) consists of 3 parts
|
||||
|
||||
| bit | meaning | notes |
|
||||
|:-------:|:--------------|:--------|
|
||||
| 31 | sign | typical + == CW, - == CCW
|
||||
| 30-12 | revolutions |
|
||||
| 11-00 | raw angle | call getCumulativePosition()
|
||||
|
||||
|
||||
Functions are:
|
||||
|
||||
- **int32_t getCumulativePosition()** reads sensor and updates cumulative position.
|
||||
- **int32_t getRevolutions()** converts last position to whole revolutions.
|
||||
Convenience function.
|
||||
- **int32_t resetPosition(int32_t position = 0)** resets the "revolutions" to position (default 0).
|
||||
It does not reset the delta (rotation) since last call to **getCumulativePosition()**.
|
||||
Returns last position (before reset).
|
||||
- **int32_t resetCumulativePosition(int32_t position = 0)** completely resets the cumulative counter.
|
||||
This includes the delta (rotation) since last call to **getCumulativePosition()**.
|
||||
Returns last position (before reset).
|
||||
|
||||
As this code is experimental, names might change in the future (0.4.0)?
|
||||
As the function are mostly about counting revolutions the current thoughts for new names are:
|
||||
|
||||
```cpp
|
||||
int32_t updateRevolutions() replaces getCumulativePosition()
|
||||
int32_t getRevolutions()
|
||||
int32_t resetRevolutions() replaces resetPosition()
|
||||
```
|
||||
|
||||
|
||||
#### Status registers
|
||||
|
||||
- **uint8_t readStatus()** see Status bits below.
|
||||
- **uint8_t readAGC()** returns the Automatic Gain Control.
|
||||
0..255 in 5V mode, 0..128 in 3V3 mode.
|
||||
- **uint16_t readMagnitude()** reads the current internal magnitude.
|
||||
(page 9 datasheet)
|
||||
Scale is unclear, can be used as relative scale.
|
||||
- **bool detectMagnet()** returns true if device sees a magnet.
|
||||
- **bool magnetTooStrong()** idem.
|
||||
- **bool magnetTooWeak()** idem.
|
||||
|
||||
|
||||
#### Status bits
|
||||
|
||||
Please read datasheet for details.
|
||||
|
||||
| Bit | short | Description | Values |
|
||||
|:-----:|:------|:-------------:|:----------------------|
|
||||
| 0-2 | | not used | |
|
||||
| 3 | MH | overflow | 1 = magnet too strong |
|
||||
| 4 | ML | underflow | 1 = magnet too weak |
|
||||
| 5 | MD | magnet detect | 1 = magnet detected |
|
||||
| 6-7 | | not used | |
|
||||
|
||||
|
||||
#### Error handling
|
||||
|
||||
Since 0.5.2 the library has added **experimental** error handling.
|
||||
For now only lowest level I2C errors are checked for transmission errors.
|
||||
Error handling might be improved upon in the future.
|
||||
|
||||
Note: The public functions do not act on error conditions.
|
||||
This might change in the future.
|
||||
So the user should check for error conditions.
|
||||
|
||||
```cpp
|
||||
int e = lastError();
|
||||
if (e != AS5600_OK)
|
||||
{
|
||||
// handle error
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
- **int lastError()** returns the last error code.
|
||||
After reading the error status is cleared to **AS5600_OK**.
|
||||
|
||||
|
||||
| Error codes | value | notes |
|
||||
|:--------------------------|:-------:|:----------|
|
||||
| AS5600_OK | 0 | default |
|
||||
| AS5600_ERROR_I2C_READ_0 | -100 |
|
||||
| AS5600_ERROR_I2C_READ_1 | -101 |
|
||||
| AS5600_ERROR_I2C_READ_2 | -102 |
|
||||
| AS5600_ERROR_I2C_READ_3 | -103 |
|
||||
| AS5600_ERROR_I2C_WRITE_0 | -200 |
|
||||
| AS5600_ERROR_I2C_WRITE_1 | -201 |
|
||||
|
||||
|
||||
## Make configuration persistent. BURN
|
||||
|
||||
#### Read burn count
|
||||
|
||||
- **uint8_t getZMCO()** reads back how many times the ZPOS and MPOS
|
||||
registers are written to permanent memory.
|
||||
You can only burn a new Angle 3 times to the AS5600, and only 2 times for the AS5600L. This function is safe as it is readonly.
|
||||
|
||||
|
||||
#### BURN function
|
||||
|
||||
The burn functions are used to make settings persistent.
|
||||
These burn functions are permanent, therefore they are commented in the library.
|
||||
Please read datasheet twice, before uncomment them.
|
||||
|
||||
**USE AT OWN RISK**
|
||||
|
||||
Please read datasheet **twice** as these changes are not reversible.
|
||||
|
||||
The risk is that you make your AS5600 / AS5600L **USELESS**.
|
||||
|
||||
**USE AT OWN RISK**
|
||||
|
||||
These are the two "unsafe" functions:
|
||||
- **void burnAngle()** writes the ZPOS and MPOS registers to permanent memory.
|
||||
You can only burn a new Angle maximum **THREE** times to the AS5600
|
||||
and **TWO** times for the AS5600L.
|
||||
- **void burnSetting()** writes the MANG register to permanent memory.
|
||||
You can write this only **ONE** time to the AS5600.
|
||||
|
||||
Some discussion about burning see issue #38
|
||||
(I have no hands on experience with this functions)
|
||||
|
||||
**USE AT OWN RISK**
|
||||
|
||||
|
||||
## Software Direction Control
|
||||
|
||||
Experimental 0.2.0
|
||||
|
||||
Normally one controls the direction of the sensor by connecting the DIR pin
|
||||
to one of the available IO pins of the processor.
|
||||
This IO pin is set in the library as parameter of the **begin(directionPin)** function.
|
||||
|
||||
The directionPin is default set to 255, which defines a **Software Direction Control**.
|
||||
|
||||
To have this working one has to connect the **DIR pin of the sensor to GND**.
|
||||
This puts the sensor in a hardware clockwise mode. Then it is up to the library
|
||||
to do the additional math so the **readAngle()** and **rawAngle()** behave as
|
||||
if the DIR pin was connected to a processor IO pin.
|
||||
|
||||
The user still calls **setDirection()** as before to change the direction
|
||||
of the increments and decrements.
|
||||
|
||||
The advantage is one does not need that extra IO pin from the processor.
|
||||
This makes connecting the sensor a bit easier.
|
||||
|
||||
TODO: measure performance impact.
|
||||
|
||||
TODO: investigate impact on functionality of other registers.
|
||||
|
||||
|
||||
## Analog OUT
|
||||
|
||||
(details datasheet - page 25 = AS5600)
|
||||
|
||||
The OUT pin can be configured with the function:
|
||||
|
||||
- **bool setOutputMode(uint8_t outputMode)**
|
||||
|
||||
|
||||
#### AS5600
|
||||
|
||||
When the analog OUT mode is set the OUT pin provides a voltage
|
||||
which is linear with the angle.
|
||||
|
||||
| VDD | mode | percentage | output | 1° in V |
|
||||
|:---:|:------:|:----------:|:---------:|:----------:|
|
||||
| 5V0 | 0 | 0 - 100% | 0.0 - 5.0 | 0.01388889 |
|
||||
| 5V0 | 1 | 10 - 90% | 0.5 - 4.5 | 0.01111111 |
|
||||
| 3V3 | 0 | 0 - 100% | 0.0 - 3.3 | 0.00916667 |
|
||||
| 3V3 | 1 | 10 - 90% | 0.3 - 3.0 | 0.00750000 |
|
||||
|
||||
To measure these angles a 10 bit ADC or higher is needed.
|
||||
|
||||
When analog OUT is selected **readAngle()** will still return valid values.
|
||||
|
||||
|
||||
#### AS5600L
|
||||
|
||||
The AS5600L does **NOT** support analog OUT.
|
||||
Both mode 0 and 1 will set the OUT pin to VDD (+5V0 or 3V3).
|
||||
|
||||
|
||||
## PWM OUT
|
||||
|
||||
(details datasheet - page 27 = AS5600)
|
||||
|
||||
The OUT pin can be configured with the function:
|
||||
|
||||
- **bool setOutputMode(uint8_t outputMode)** outputMode = 2 = PWM
|
||||
|
||||
When the PWM OUT mode is set the OUT pin provides a duty cycle which is linear
|
||||
with the angle. However they PWM has a lead in (HIGH) and a lead out (LOW).
|
||||
|
||||
The pulse width is 4351 units, 128 high, 4095 angle, 128 low.
|
||||
|
||||
| Angle | HIGH | LOW | HIGH % | LOW % | Notes |
|
||||
|:-------:|:-------:|:------:|:--------:|:--------:|:--------|
|
||||
| 0 | 128 | 4223 | 2,94% | 97,06% |
|
||||
| 10 | 242 | 4109 | 5,56% | 94,44% |
|
||||
| 20 | 356 | 3996 | 8,17% | 91,83% |
|
||||
| 45 | 640 | 3711 | 14,71% | 85,29% |
|
||||
| 90 | 1152 | 3199 | 26,47% | 73,53% |
|
||||
| 135 | 1664 | 2687 | 38,24% | 61,76% |
|
||||
| 180 | 2176 | 2176 | 50,00% | 50,00% |
|
||||
| 225 | 2687 | 1664 | 61,76% | 38,24% |
|
||||
| 270 | 3199 | 1152 | 73,53% | 26,47% |
|
||||
| 315 | 3711 | 640 | 85,29% | 14,71% |
|
||||
| 360 | 4223 | 128 | 97,06% | 2,94% | in fact 359.9 something as 360 == 0
|
||||
|
||||
|
||||
#### Formula:
|
||||
|
||||
based upon the table above ```angle = map(dutyCycle, 2.94, 97.06, 0.0, 359.9);```
|
||||
|
||||
or in code ..
|
||||
```cpp
|
||||
t0 = micros(); // rising;
|
||||
t1 = micros(); // falling;
|
||||
t2 = micros(); // rising; new t0
|
||||
|
||||
// note that t2 - t0 should be a constant depending on frequency set.
|
||||
// however as there might be up to 5% variation it cannot be hard coded.
|
||||
float dutyCycle = (1.0 * (t1 - t0)) / (t2 - t0);
|
||||
float angle = (dutyCycle - 0.0294) * (359.9 / (0.9706 - 0.0294));
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### PWM frequency
|
||||
|
||||
The AS5600 allows one to set the PWM base frequency (~5%)
|
||||
- **bool setPWMFrequency(uint8_t pwmFreq)**
|
||||
|
||||
| mode | pwmFreq | step in us | 1° in time |
|
||||
|:----:|:-------:|:----------:|:----------:|
|
||||
| 0 | 115 Hz | 2.123 | 24.15 |
|
||||
| 1 | 230 Hz | 1.062 | 12.77 |
|
||||
| 2 | 460 Hz | 0.531 | 6.39 |
|
||||
| 3 | 920 Hz | 0.216 | 3.20 |
|
||||
|
||||
Note that at the higher frequencies the step size becomes smaller
|
||||
and smaller and it becomes harder to measure.
|
||||
You need a sub-micro second hardware timer to measure the pulse width
|
||||
with enough precision to get the max resolution.
|
||||
|
||||
When PWM OUT is selected **readAngle()** will still return valid values.
|
||||
|
||||
|
||||
----
|
||||
|
||||
## AS5600L class
|
||||
|
||||
- **AS5600L(uint8_t address = 0x40, TwoWire \*wire = &Wire)** constructor.
|
||||
As the I2C address can be changed in the AS5600L, the address is a parameter of the constructor.
|
||||
This is a difference with the AS5600 constructor.
|
||||
|
||||
|
||||
#### Setting I2C address
|
||||
|
||||
- **bool setAddress(uint8_t address)** Returns false if the I2C address is not in valid range (8-119).
|
||||
|
||||
|
||||
#### Setting I2C UPDT
|
||||
|
||||
UPDT = update page 30 - AS5600L
|
||||
|
||||
- **bool setI2CUPDT(uint8_t value)**
|
||||
- **uint8_t getI2CUPDT()**
|
||||
|
||||
These functions seems to have only a function in relation to **setAddress()** so possibly obsolete in the future.
|
||||
If you got other insights on these functions please let me know.
|
||||
|
||||
----
|
||||
|
||||
## Operational
|
||||
|
||||
The base functions are:
|
||||
|
||||
```cpp
|
||||
AS5600 as5600;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
...
|
||||
as5900.begin(4); // set the direction pin
|
||||
as5600.setDirection(AS5600_CLOCK_WISE);
|
||||
...
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
...
|
||||
Serial.println(as5600.readAngle());
|
||||
delay(1000);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
See examples.
|
||||
|
||||
|
||||
## Future
|
||||
|
||||
Some ideas are kept here so they won't get lost.
|
||||
priority is relative.
|
||||
|
||||
|
||||
#### Must
|
||||
|
||||
- re-organize readme
|
||||
- rename revolution functions
|
||||
- to what?
|
||||
|
||||
|
||||
#### Should
|
||||
|
||||
- implement extended error handling in public functions.
|
||||
- will increase footprint !! how much?
|
||||
- **call writeReg() only if readReg() is OK** ==> prevent incorrect writes
|
||||
- ```if (_error != 0) return false;```
|
||||
- idem readReg2()
|
||||
- set AS5600_ERROR_PARAMETER e.g. setZPosition()
|
||||
- a derived class with extended error handling?
|
||||
- investigate **readMagnitude()**
|
||||
- combination of AGC and MD, ML and MH flags?
|
||||
- investigate **OUT** behaviour in practice
|
||||
- analogue
|
||||
- PWM
|
||||
- need AS5600 on breakout with support
|
||||
- check / verify Power-up time
|
||||
- 1 minute (need HW)
|
||||
- check Timing Characteristics (datasheet)
|
||||
- is there improvement possible.
|
||||
|
||||
|
||||
#### Could
|
||||
|
||||
- investigate **PGO** programming pin.
|
||||
- check for compatible devices
|
||||
- AS5200 ?
|
||||
- investigate performance
|
||||
- basic performance per function
|
||||
- I2C improvements
|
||||
- software direction
|
||||
- write examples:
|
||||
- as5600_calibration.ino (needs HW and lots of time)
|
||||
- different configuration options
|
||||
|
||||
#### Wont (unless)
|
||||
|
||||
- fix for AS5600L as it does not support analog OUT.
|
||||
- type field?
|
||||
- other class hierarchy?
|
||||
- base class with commonalities?
|
||||
- ==> just ignore for now.
|
||||
- add mode parameter to offset functions.
|
||||
- see getAngularSpeed()
|
||||
|
||||
|
||||
## Support
|
||||
|
||||
If you appreciate my libraries, you can support the development and maintenance.
|
||||
Improve the quality of the libraries by providing issues and Pull Requests, or
|
||||
donate through PayPal or GitHub sponsors.
|
||||
|
||||
Thank you,
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// FILE: AS5600L_set_address.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600L ASL; // use default Wire
|
||||
// AS5600 ASL; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
ASL.begin(4); // set direction pin.
|
||||
ASL.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
int b = ASL.isConnected();
|
||||
Serial.print("Connect: ");
|
||||
Serial.println(b);
|
||||
|
||||
Serial.print("ADDR: ");
|
||||
Serial.println(ASL.getAddress());
|
||||
|
||||
ASL.setAddress(0x38);
|
||||
|
||||
Serial.print("ADDR: ");
|
||||
Serial.println(ASL.getAddress());
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Serial.print(millis());
|
||||
// Serial.print("\t");
|
||||
Serial.print(ASL.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(ASL.rawAngle() * AS5600_RAW_TO_DEGREES);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// FILE: AS5600_I2C_frequency.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600L as5600; // use default Wire
|
||||
|
||||
uint32_t clk = 0;
|
||||
|
||||
uint32_t start, stop;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
// as5600.setAddress(0x40); // AS5600L only
|
||||
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
int b = as5600.isConnected();
|
||||
Serial.print("Connect: ");
|
||||
Serial.println(b);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
clk += 100000;
|
||||
if (clk > 800000) clk = 100000;
|
||||
Wire.setClock(clk);
|
||||
|
||||
delay(10);
|
||||
start = micros();
|
||||
int angle = as5600.readAngle();
|
||||
stop = micros();
|
||||
|
||||
Serial.print(clk);
|
||||
Serial.print("\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.print(angle);
|
||||
Serial.print("\t");
|
||||
Serial.println(as5600.rawAngle() * AS5600_RAW_TO_DEGREES);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// FILE: AS5600_angular_speed.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600L as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
|
||||
Serial.println(as5600.getAddress());
|
||||
|
||||
// as5600.setAddress(0x40); // AS5600L only
|
||||
|
||||
int b = as5600.isConnected();
|
||||
Serial.print("Connect: ");
|
||||
Serial.println(b);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Serial.print("\ta = ");
|
||||
// Serial.print(as5600.readAngle());
|
||||
// Serial.print("\tω = ");
|
||||
Serial.println(as5600.getAngularSpeed());
|
||||
delay(25);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// FILE: AS5600_angular_speed_RPM.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
|
||||
Serial.println(as5600.getAddress());
|
||||
|
||||
// as5600.setAddress(0x40); // AS5600L only
|
||||
|
||||
int b = as5600.isConnected();
|
||||
Serial.print("Connect: ");
|
||||
Serial.println(b);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Serial.print("\ta = ");
|
||||
// Serial.print(as5600.readAngle());
|
||||
Serial.print("\tω = ");
|
||||
Serial.println(as5600.getAngularSpeed(AS5600_MODE_RPM));
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,176 @@
|
||||
//
|
||||
// FILE: AS5600_burn_conf_mang.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo (not tested yet - see issue #38)
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// WARNING
|
||||
// As burning the settings can only be done once this sketch has to be used with care.
|
||||
//
|
||||
// You need to
|
||||
// - read the datasheet so you understand what you do
|
||||
// - read issue #38 to understand the discussion that lead to this sketch
|
||||
// - uncomment burnSettings() in AS5600.h and AS5600.cpp.
|
||||
// - adjust settings and MaxAngle in burn_mang() function below ==> line 77++
|
||||
// - uncomment line 167 of this sketch
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
// AS5600L as5600;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
|
||||
if (as5600.isConnected())
|
||||
{
|
||||
Serial.println("Connected");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Failed to connect. Check wires and reboot.");
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
Serial.println("\nWARNING WARNING WARNING WARNING WARNING WARNING\n");
|
||||
Serial.println("This sketch will burn settings to your AS5600.");
|
||||
Serial.println("Adjust the settings in the sketch to your needs.");
|
||||
Serial.println("Press any key to continue.");
|
||||
Serial.println("\nWARNING WARNING WARNING WARNING WARNING WARNING\n\n");
|
||||
while (Serial.available()) Serial.read();
|
||||
while (!Serial.available());
|
||||
Serial.read();
|
||||
|
||||
|
||||
while (Serial.available()) Serial.read();
|
||||
Serial.print("Are you sure to burn settings + maxangle? [Y for Yes]");
|
||||
while (!Serial.available());
|
||||
char c = Serial.read();
|
||||
if (c == 'Y')
|
||||
{
|
||||
burn_mang();
|
||||
}
|
||||
|
||||
Serial.println("\nDone..");
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void burn_mang()
|
||||
{
|
||||
// ADJUST settings
|
||||
const uint16_t POWERMODE = 0;
|
||||
const uint16_t HYSTERESIS = 0;
|
||||
const uint16_t OUTPUTMODE = 0;
|
||||
const uint16_t PWMFREQUENCY = 0;
|
||||
const uint16_t SLOWFILTER = 0;
|
||||
const uint16_t FASTFILTER = 0;
|
||||
const uint16_t WATCHDOG = 0;
|
||||
const uint16_t MAXANGLE = 0;
|
||||
|
||||
bool OK = true;
|
||||
OK = OK && as5600.setPowerMode(POWERMODE);
|
||||
OK = OK && (POWERMODE == as5600.getPowerMode());
|
||||
if (OK == false)
|
||||
{
|
||||
Serial.println("ERROR: POWERMODE.");
|
||||
return;
|
||||
}
|
||||
|
||||
OK = OK && as5600.setHysteresis(HYSTERESIS);
|
||||
OK = OK && (HYSTERESIS == as5600.getHysteresis());
|
||||
if (OK == false)
|
||||
{
|
||||
Serial.println("ERROR: HYSTERESIS");
|
||||
return;
|
||||
}
|
||||
|
||||
OK = OK && as5600.setOutputMode(OUTPUTMODE);
|
||||
OK = OK && (OUTPUTMODE == as5600.getOutputMode());
|
||||
if (OK == false)
|
||||
{
|
||||
Serial.println("ERROR: OUTPUTMODE");
|
||||
return;
|
||||
}
|
||||
|
||||
OK = OK && as5600.setPWMFrequency(PWMFREQUENCY);
|
||||
OK = OK && (PWMFREQUENCY == as5600.getPWMFrequency());
|
||||
if (OK == false)
|
||||
{
|
||||
Serial.println("ERROR: PWMFREQUENCY");
|
||||
return;
|
||||
}
|
||||
|
||||
OK = OK && as5600.setSlowFilter(SLOWFILTER);
|
||||
OK = OK && (SLOWFILTER == as5600.getSlowFilter());
|
||||
if (OK == false)
|
||||
{
|
||||
Serial.println("ERROR: SLOWFILTER");
|
||||
return;
|
||||
}
|
||||
|
||||
OK = OK && as5600.setFastFilter(FASTFILTER);
|
||||
OK = OK && (FASTFILTER == as5600.getFastFilter());
|
||||
if (OK == false)
|
||||
{
|
||||
Serial.println("ERROR: FASTFILTER");
|
||||
return;
|
||||
}
|
||||
|
||||
OK = OK && as5600.setWatchDog(WATCHDOG);
|
||||
OK = OK && (WATCHDOG == as5600.getWatchDog());
|
||||
if (OK == false)
|
||||
{
|
||||
Serial.println("ERROR: WATCHDOG");
|
||||
return;
|
||||
}
|
||||
|
||||
OK = OK && as5600.setMaxAngle(MAXANGLE);
|
||||
OK = OK && (MAXANGLE == as5600.getMaxAngle());
|
||||
if (OK == false)
|
||||
{
|
||||
Serial.println("ERROR: MAXANGLE");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.println("burning in 5 seconds");
|
||||
delay(1000);
|
||||
Serial.println("burning in 4 seconds");
|
||||
delay(1000);
|
||||
Serial.println("burning in 3 seconds");
|
||||
delay(1000);
|
||||
Serial.println("burning in 2 seconds");
|
||||
delay(1000);
|
||||
Serial.println("burning in 1 seconds");
|
||||
delay(1000);
|
||||
Serial.print("burning ...");
|
||||
// uncomment next line
|
||||
// as5600.burnSettings();
|
||||
Serial.println(" done.");
|
||||
Serial.println("Reboot AS5600 to use the new settings.");
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// FILE: AS5600_burn_zpos.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo (not tested yet - see issue #38)
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// WARNING
|
||||
// As burning the angle can only be done three times this sketch has to be used with care.
|
||||
//
|
||||
// You need to
|
||||
// - read the datasheet so you understand what you do
|
||||
// - read issue #38 to understand the discussion that lead to this sketch
|
||||
// - uncomment burnAngle() in AS5600.h and AS5600.cpp.
|
||||
// - adjust settings and MaxAngle in burn_zpos() function below ==> line 77++
|
||||
// - uncomment line 105 of this sketch
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
// AS5600L as5600;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
|
||||
if (as5600.isConnected())
|
||||
{
|
||||
Serial.println("Connected");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Failed to connect. Check wires and reboot.");
|
||||
//while (1);
|
||||
}
|
||||
|
||||
|
||||
Serial.println("\nWARNING WARNING WARNING WARNING WARNING WARNING\n");
|
||||
Serial.println("This sketch will burn settings to your AS5600.");
|
||||
Serial.println("Adjust the settings in the sketch to your needs.");
|
||||
Serial.println("Press any key to continue.");
|
||||
Serial.println("\nWARNING WARNING WARNING WARNING WARNING WARNING\n\n");
|
||||
while (Serial.available()) Serial.read();
|
||||
while (!Serial.available());
|
||||
Serial.read();
|
||||
|
||||
|
||||
while (Serial.available()) Serial.read();
|
||||
Serial.print("Are you sure to burn zpos? [Y for Yes]");
|
||||
while (!Serial.available());
|
||||
char c = Serial.read();
|
||||
if (c == 'Y')
|
||||
{
|
||||
burn_zpos();
|
||||
}
|
||||
|
||||
Serial.println("\nDone..");
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void burn_zpos()
|
||||
{
|
||||
// ADJUST ZPOS
|
||||
const uint16_t ZPOS = 0;
|
||||
|
||||
bool OK = true;
|
||||
OK = OK && as5600.setZPosition(ZPOS);
|
||||
OK = OK && (ZPOS == as5600.getZPosition());
|
||||
if (OK == false)
|
||||
{
|
||||
Serial.println("\nERROR: in settings, burn_zpos() cancelled.");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.println("burning in 5 seconds");
|
||||
delay(1000);
|
||||
Serial.println("burning in 4 seconds");
|
||||
delay(1000);
|
||||
Serial.println("burning in 3 seconds");
|
||||
delay(1000);
|
||||
Serial.println("burning in 2 seconds");
|
||||
delay(1000);
|
||||
Serial.println("burning in 1 seconds");
|
||||
delay(1000);
|
||||
Serial.print("burning ...");
|
||||
delay(1000);
|
||||
// uncomment next line
|
||||
// as5600.burnAngle();
|
||||
Serial.println(" done.");
|
||||
Serial.println("Reboot AS5600 to use the new settings.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// FILE: AS5600_demo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600L as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
int b = as5600.isConnected();
|
||||
Serial.print("Connect: ");
|
||||
Serial.println(b);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Serial.print(millis());
|
||||
// Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(as5600.rawAngle());
|
||||
// Serial.println(as5600.rawAngle() * AS5600_RAW_TO_DEGREES);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,28 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
# - uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
# - m4
|
||||
- esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
# - rpipico
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// FILE: AS5600_demo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600L as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin(14, 15);
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
int b = as5600.isConnected();
|
||||
Serial.print("Connect: ");
|
||||
Serial.println(b);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Serial.print(millis());
|
||||
// Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(as5600.rawAngle());
|
||||
// Serial.println(as5600.rawAngle() * AS5600_RAW_TO_DEGREES);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,28 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
# - uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
# - m4
|
||||
# - esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
- rpipico
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// FILE: AS5600_demo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600L as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.setSDA(14);
|
||||
Wire.setSCL(15);
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
int b = as5600.isConnected();
|
||||
Serial.print("Connect: ");
|
||||
Serial.println(b);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Serial.print(millis());
|
||||
// Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(as5600.rawAngle());
|
||||
// Serial.println(as5600.rawAngle() * AS5600_RAW_TO_DEGREES);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,28 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
# - uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
# - m4
|
||||
# - esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
# - rpipico
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// FILE: AS5600_demo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// tested compilation with Nucleo-64
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600L as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.setSDA(14);
|
||||
Wire.setSCL(15);
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
int b = as5600.isConnected();
|
||||
Serial.print("Connect: ");
|
||||
Serial.println(b);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Serial.print(millis());
|
||||
// Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(as5600.rawAngle());
|
||||
// Serial.println(as5600.rawAngle() * AS5600_RAW_TO_DEGREES);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// FILE: AS5600_demo_offset.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
float offset = 0;
|
||||
while (offset < 360)
|
||||
{
|
||||
as5600.setOffset(offset);
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.getOffset(), 2);
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(as5600.rawAngle() * AS5600_RAW_TO_DEGREES);
|
||||
delay(100);
|
||||
offset += 12.34;
|
||||
}
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// FILE: AS5600_demo_radians.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(as5600.rawAngle() * AS5600_RAW_TO_RADIANS);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// FILE: AS5600_demo_software_direction.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo software direction control
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// connect the DIR pin of the AS5600 to GND
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
|
||||
uint8_t counter = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(); // set software direction control. default parameter == 255
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// toggle direction every 10 reads.
|
||||
counter++;
|
||||
if (counter < 10) as5600.setDirection(AS5600_CLOCK_WISE);
|
||||
else as5600.setDirection(AS5600_COUNTERCLOCK_WISE);
|
||||
if (counter >= 20) counter = 0;
|
||||
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.getDirection());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(as5600.rawAngle() * AS5600_RAW_TO_DEGREES);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// FILE: AS5600_demo_status.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600L as5600(0x40); // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print("STATUS:\t ");
|
||||
Serial.println(as5600.readStatus(), HEX);
|
||||
Serial.print("CONFIG:\t ");
|
||||
Serial.println(as5600.getConfigure(), HEX);
|
||||
Serial.print(" GAIN:\t ");
|
||||
Serial.println(as5600.readAGC(), HEX);
|
||||
Serial.print("MAGNET:\t ");
|
||||
Serial.println(as5600.readMagnitude(), HEX);
|
||||
Serial.print("DETECT:\t ");
|
||||
Serial.println(as5600.detectMagnet(), HEX);
|
||||
Serial.print("M HIGH:\t ");
|
||||
Serial.println(as5600.magnetTooStrong(), HEX);
|
||||
Serial.print("M LOW:\t ");
|
||||
Serial.println(as5600.magnetTooWeak(), HEX);
|
||||
Serial.println();
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,28 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
# - uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
# - m4
|
||||
# - esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
- rpipico
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// FILE: AS5600_demo_two_I2C.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo two I2C busses
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Works only if Wire1 bus is present e.g.
|
||||
// - nano33 ble
|
||||
// - teensy 4.1
|
||||
// - RP2040
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600_0(&Wire);
|
||||
AS5600 as5600_1(&Wire1);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
Wire1.begin();
|
||||
|
||||
as5600_0.begin(4); // set direction pin.
|
||||
as5600_0.setDirection(AS5600_CLOCK_WISE);
|
||||
Serial.print("Connect device 0: ");
|
||||
Serial.println(as5600_0.isConnected() ? "true" : "false");
|
||||
delay(1000);
|
||||
|
||||
as5600_1.begin(5); // set direction pin.
|
||||
as5600_1.setDirection(AS5600_COUNTERCLOCK_WISE);
|
||||
Serial.print("Connect device 1: ");
|
||||
Serial.println(as5600_1.isConnected() ? "true" : "false");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600_0.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600_1.readAngle());
|
||||
Serial.print("\n");
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// FILE: AS5600_outmode_analog_100.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: experimental demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// connect the OUT pin to the analog port of the processor
|
||||
//
|
||||
// The AS5600L does not support analog OUT.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
as5600.setOutputMode(AS5600_OUTMODE_ANALOG_100);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(analogRead(A0));
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// FILE: AS5600_outmode_analog_90.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: experimental demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
// connect the OUT pin to the analog port of the processor
|
||||
//
|
||||
// The AS5600L does not support analog OUT.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
as5600.setOutputMode(AS5600_OUTMODE_ANALOG_90);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(analogRead(A0));
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// FILE: AS5600_outmode_analog_pwm.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: experimental
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// connect the OUT pin to the analog port of the processor
|
||||
// use a resistor and a capacitor to create a low pass filter
|
||||
// so the PWM behave a bit like a analog signal
|
||||
//
|
||||
// alternative one can read the PWM with interrupt pin and
|
||||
// determine the duty cycle
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
as5600.setOutputMode(AS5600_OUTMODE_PWM);
|
||||
as5600.setPWMFrequency(AS5600_PWM_920);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println(analogRead(A0));
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// FILE: AS5600_outmode_pwm_interrupt.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
|
||||
const uint8_t irqPin = 2;
|
||||
|
||||
volatile uint32_t duration = 0;
|
||||
|
||||
void capturePWM()
|
||||
{
|
||||
static uint32_t lastTime = 0;
|
||||
uint32_t now = micros();
|
||||
if (digitalRead(2) == HIGH)
|
||||
{
|
||||
duration = now - lastTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
attachInterrupt(digitalPinToInterrupt(2), capturePWM, CHANGE);
|
||||
|
||||
as5600.begin(4);
|
||||
as5600.setOutputMode(AS5600_OUTMODE_PWM);
|
||||
as5600.setPWMFrequency(AS5600_PWM_115);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.readAngle());
|
||||
Serial.print("\t");
|
||||
Serial.print(as5600.rawAngle() * AS5600_RAW_TO_DEGREES);
|
||||
Serial.print("\t");
|
||||
Serial.println(duration);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,99 @@
|
||||
// FILE: AS5600_plus_AS5600L.ino
|
||||
// AUTHOR: laptophead
|
||||
// PURPOSE: showing working of a AS5600 and AS5600L side by side
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
// URL: https://github.com/RobTillaart/AS5600/issues/48
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600_R; // uses default Wire
|
||||
AS5600L as5600_L; // uses 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());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// FILE: AS5600_position.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600 as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4); // set direction pin.
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
|
||||
Serial.println(as5600.getAddress());
|
||||
|
||||
// as5600.setAddress(0x40); // AS5600L only
|
||||
|
||||
int b = as5600.isConnected();
|
||||
Serial.print("Connect: ");
|
||||
Serial.println(b);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
static uint32_t lastTime = 0;
|
||||
|
||||
// set initial position
|
||||
as5600.getCumulativePosition();
|
||||
|
||||
// update every 100 ms
|
||||
// should be enough up to ~200 RPM
|
||||
if (millis() - lastTime >= 100)
|
||||
{
|
||||
lastTime = millis();
|
||||
Serial.print(as5600.getCumulativePosition());
|
||||
Serial.print("\t");
|
||||
Serial.println(as5600.getRevolutions());
|
||||
}
|
||||
|
||||
// just to show how reset can be used
|
||||
if (as5600.getRevolutions() >= 10)
|
||||
{
|
||||
as5600.resetPosition();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// FILE: AS5600_pwm_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
// https://forum.arduino.cc/t/questions-using-the-as5600-in-pwm-mode/1266957/3
|
||||
//
|
||||
// monitor the PWM output to determine the angle
|
||||
// not tested with hardware yet
|
||||
|
||||
int PWMpin = 7;
|
||||
|
||||
long fullPeriod = 0;
|
||||
|
||||
|
||||
float measureAngle()
|
||||
{
|
||||
// wait for LOW
|
||||
while (digitalRead(PWMpin) == HIGH);
|
||||
// wait for HIGH
|
||||
while (digitalRead(PWMpin) == LOW);
|
||||
uint32_t rise = micros();
|
||||
|
||||
// wait for LOW
|
||||
while (digitalRead(PWMpin) == HIGH);
|
||||
uint32_t highPeriod = micros() - rise;
|
||||
|
||||
// wait for HIGH
|
||||
while (digitalRead(PWMpin) == LOW);
|
||||
fullPeriod = micros() - rise;
|
||||
|
||||
float bitTime = fullPeriod / 4351.0;
|
||||
float dataPeriod = highPeriod - 128 * bitTime;
|
||||
float angle = 360.0 * dataPeriod / (4095 * bitTime);
|
||||
return angle;
|
||||
}
|
||||
|
||||
|
||||
//float testMath(uint32_t fullPeriod, uint32_t highPeriod)
|
||||
//{
|
||||
// float bitTime = fullPeriod / 4351.0;
|
||||
// float dataPeriod = highPeriod - 128 * bitTime;
|
||||
// float angle = 360.0 * dataPeriod / (4095 * bitTime);
|
||||
// return angle;
|
||||
//}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
|
||||
pinMode(PWMpin, INPUT_PULLUP);
|
||||
|
||||
// // test code
|
||||
// for (int pwm = 0; pwm < 4096; pwm++)
|
||||
// {
|
||||
// Serial.println(testMath(4351, 128 + pwm), 2);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
float angle = measureAngle();
|
||||
Serial.println(angle, 1); // print with 1 decimal
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,28 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
# - uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
# - m4
|
||||
- esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
# - rpipico
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// FILE: AS5600_resetCumulativeCounter.ino
|
||||
// AUTHOR: Daniel-Frenkel, (slightly modified by Rob Tillaart)
|
||||
// PURPOSE: demo - see issue #30
|
||||
// URL: https://github.com/RobTillaart/AS5600
|
||||
//
|
||||
// Examples may use AS5600 or AS5600L devices.
|
||||
// Check if your sensor matches the one used in the example.
|
||||
// Optionally adjust the code.
|
||||
|
||||
|
||||
#include "AS5600.h"
|
||||
|
||||
|
||||
AS5600L as5600; // use default Wire
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("AS5600_LIB_VERSION: ");
|
||||
Serial.println(AS5600_LIB_VERSION);
|
||||
|
||||
Wire.begin(14, 15); // ESP32
|
||||
|
||||
as5600.begin();
|
||||
as5600.setAddress(0x40); // AS5600L has address
|
||||
|
||||
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
|
||||
delay(1000);
|
||||
as5600.resetCumulativePosition(777);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
static uint32_t lastTime = 0;
|
||||
|
||||
// set initial position
|
||||
as5600.getCumulativePosition();
|
||||
|
||||
// update every 100 ms
|
||||
if (millis() - lastTime >= 100)
|
||||
{
|
||||
lastTime = millis();
|
||||
Serial.println(as5600.getCumulativePosition());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
# Syntax Colouring Map For AS5600
|
||||
|
||||
|
||||
# Data types (KEYWORD1)
|
||||
AS5600 KEYWORD1
|
||||
AS5600L KEYWORD1
|
||||
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
begin KEYWORD2
|
||||
isConnected KEYWORD2
|
||||
setAddress KEYWORD2
|
||||
getAddress KEYWORD2
|
||||
|
||||
setDirection KEYWORD2
|
||||
getDirection KEYWORD2
|
||||
|
||||
getZMCO KEYWORD2
|
||||
setZPosition KEYWORD2
|
||||
getZPosition KEYWORD2
|
||||
setMPosition KEYWORD2
|
||||
getMPosition KEYWORD2
|
||||
|
||||
setMaxAngle KEYWORD2
|
||||
getMaxAngle KEYWORD2
|
||||
|
||||
setConfigure KEYWORD2
|
||||
getConfigure KEYWORD2
|
||||
|
||||
setPowerMode KEYWORD2
|
||||
getPowerMode KEYWORD2
|
||||
setHysteresis KEYWORD2
|
||||
getHysteresis KEYWORD2
|
||||
|
||||
setOutputMode KEYWORD2
|
||||
getOutputMode KEYWORD2
|
||||
setPWMFrequency KEYWORD2
|
||||
getPWMFrequency KEYWORD2
|
||||
|
||||
setSlowFilter KEYWORD2
|
||||
getSlowFilter KEYWORD2
|
||||
setFastFilter KEYWORD2
|
||||
getFastFilter KEYWORD2
|
||||
|
||||
setWatchDog KEYWORD2
|
||||
getWatchDog KEYWORD2
|
||||
|
||||
rawAngle KEYWORD2
|
||||
readAngle KEYWORD2
|
||||
setOffset KEYWORD2
|
||||
increaseOffset KEYWORD2
|
||||
getOffset KEYWORD2
|
||||
|
||||
readStatus KEYWORD2
|
||||
readAGC KEYWORD2
|
||||
readMagnitude KEYWORD2
|
||||
|
||||
detectMagnet KEYWORD2
|
||||
magnetTooStrong KEYWORD2
|
||||
magnetTooWeak KEYWORD2
|
||||
|
||||
burnAngle KEYWORD2
|
||||
burnSetting KEYWORD2
|
||||
|
||||
getAngularSpeed KEYWORD2
|
||||
|
||||
getCumulativePosition KEYWORD2
|
||||
getRevolutions KEYWORD2
|
||||
resetPosition KEYWORD2
|
||||
resetCumulativePosition KEYWORD2
|
||||
|
||||
lastError KEYWORD2
|
||||
|
||||
|
||||
# CONFIGURATION FIELDS
|
||||
setPowerMode KEYWORD2
|
||||
getPowerMode KEYWORD2
|
||||
setHysteresis KEYWORD2
|
||||
getHysteresis KEYWORD2
|
||||
|
||||
setOutputMode KEYWORD2
|
||||
getOutputMode KEYWORD2
|
||||
setPWMFrequency KEYWORD2
|
||||
getPWMFrequency KEYWORD2
|
||||
|
||||
setSlowFilter KEYWORD2
|
||||
getSlowFilter KEYWORD2
|
||||
setFastFilter KEYWORD2
|
||||
getFastFilter KEYWORD2
|
||||
|
||||
setWatchDog KEYWORD2
|
||||
getWatchDog KEYWORD2
|
||||
|
||||
|
||||
# Constants (LITERAL1)
|
||||
AS5600_LIB_VERSION LITERAL1
|
||||
|
||||
AS5600_DEFAULT_ADDRESS LITERAL1
|
||||
AS5600L_DEFAULT_ADDRESS LITERAL1
|
||||
|
||||
AS5600_CLOCK_WISE LITERAL1
|
||||
AS5600_COUNTERCLOCK_WISE LITERAL1
|
||||
|
||||
AS5600_RAW_TO_DEGREES LITERAL1
|
||||
AS5600_DEGREES_TO_RAW LITERAL1
|
||||
AS5600_RAW_TO_RADIANS LITERAL1
|
||||
AS5600_RAW_TO_RPM LITERAL1
|
||||
|
||||
AS5600_MODE_DEGREES LITERAL1
|
||||
AS5600_MODE_RADIANS LITERAL1
|
||||
AS5600_MODE_RPM LITERAL1
|
||||
|
||||
AS5600_OUTMODE_ANALOG_100 LITERAL1
|
||||
AS5600_OUTMODE_ANALOG_90 LITERAL1
|
||||
AS5600_OUTMODE_PWM LITERAL1
|
||||
|
||||
AS5600_POWERMODE_NOMINAL LITERAL1
|
||||
AS5600_POWERMODE_LOW1 LITERAL1
|
||||
AS5600_POWERMODE_LOW2 LITERAL1
|
||||
AS5600_POWERMODE_LOW3 LITERAL1
|
||||
|
||||
AS5600_PWM_115 LITERAL1
|
||||
AS5600_PWM_230 LITERAL1
|
||||
AS5600_PWM_460 LITERAL1
|
||||
AS5600_PWM_920 LITERAL1
|
||||
|
||||
AS5600_HYST_OFF LITERAL1
|
||||
AS5600_HYST_LSB1 LITERAL1
|
||||
AS5600_HYST_LSB2 LITERAL1
|
||||
AS5600_HYST_LSB3 LITERAL1
|
||||
|
||||
AS5600_SLOW_FILT_16X LITERAL1
|
||||
AS5600_SLOW_FILT_8X LITERAL1
|
||||
AS5600_SLOW_FILT_4X LITERAL1
|
||||
AS5600_SLOW_FILT_2X LITERAL1
|
||||
|
||||
AS5600_FAST_FILT_NONE LITERAL1
|
||||
AS5600_FAST_FILT_LSB6 LITERAL1
|
||||
AS5600_FAST_FILT_LSB7 LITERAL1
|
||||
AS5600_FAST_FILT_LSB9 LITERAL1
|
||||
AS5600_FAST_FILT_LSB18 LITERAL1
|
||||
AS5600_FAST_FILT_LSB21 LITERAL1
|
||||
AS5600_FAST_FILT_LSB24 LITERAL1
|
||||
AS5600_FAST_FILT_LSB10 LITERAL1
|
||||
|
||||
AS5600_WATCHDOG_OFF LITERAL1
|
||||
AS5600_WATCHDOG_ON LITERAL1
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "AS5600",
|
||||
"keywords": "AS5600,AS5600L",
|
||||
"description": "Arduino library for AS5600 and AS5600L magnetic rotation meter.",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Rob Tillaart",
|
||||
"email": "Rob.Tillaart@gmail.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/AS5600.git"
|
||||
},
|
||||
"version": "0.6.1",
|
||||
"license": "MIT",
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
"headers": "AS5600.h"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
name=AS5600
|
||||
version=0.6.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for AS5600 and AS5600L magnetic rotation meter.
|
||||
paragraph=
|
||||
category=Sensors
|
||||
url=https://github.com/RobTillaart/AS5600
|
||||
architectures=*
|
||||
includes=AS5600.h
|
||||
depends=
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
## notes on PWM
|
||||
|
||||
#### Description
|
||||
|
||||
If you do not know the PWM frequency you can determine the angle
|
||||
with PWM in the following way.
|
||||
|
||||
In one period there are 4351 bits (128 + 4095 + 128)
|
||||
These come typically in one pulse like
|
||||
|
||||
```
|
||||
00001111111111111111111111111111111111100000000
|
||||
HEADER DATA POSTLOW
|
||||
```
|
||||
|
||||
#### Step 1
|
||||
|
||||
Determine the duration of one cycle by measuring the time between two RISING edges.
|
||||
Lets call this time FULLSCALE == 4351 bits.
|
||||
|
||||
Then the time for one bit BITTIME = round(FULLSCALE / 4351.0);
|
||||
|
||||
#### Step 2
|
||||
|
||||
Measure the duration of the HIGHPERIOD == HEADER + DATA
|
||||
|
||||
We know the HEADER is 128 bits and FULLSCALE = 4351 bits.
|
||||
|
||||
DATAPERIOD = HIGHPERIOD - 128 \* BITTIME
|
||||
|
||||
ANGLE = 360 \* DATAPERIOD / (4095 \* BITTIME)
|
||||
|
||||
Code: AS5600_pwm_test.ino
|
||||
|
||||
#### Related
|
||||
|
||||
https://github.com/RobTillaart/AS5600
|
||||
https://forum.arduino.cc/t/questions-using-the-as5600-in-pwm-mode/1266957/3
|
||||
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
//
|
||||
// FILE: unit_test_001.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 2022-05-28
|
||||
// PURPOSE: unit tests for the AS5600 library
|
||||
// https://github.com/RobTillaart/AS5600
|
||||
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
|
||||
//
|
||||
|
||||
// supported assertions
|
||||
// ----------------------------
|
||||
// assertEqual(expected, actual); // a == b
|
||||
// assertNotEqual(unwanted, actual); // a != b
|
||||
// assertComparativeEquivalent(expected, actual); // abs(a - b) == 0 or (!(a > b) && !(a < b))
|
||||
// assertComparativeNotEquivalent(unwanted, actual); // abs(a - b) > 0 or ((a > b) || (a < b))
|
||||
// assertLess(upperBound, actual); // a < b
|
||||
// assertMore(lowerBound, actual); // a > b
|
||||
// assertLessOrEqual(upperBound, actual); // a <= b
|
||||
// assertMoreOrEqual(lowerBound, actual); // a >= b
|
||||
// assertTrue(actual);
|
||||
// assertFalse(actual);
|
||||
// assertNull(actual);
|
||||
|
||||
// // special cases for floats
|
||||
// assertEqualFloat(expected, actual, epsilon); // fabs(a - b) <= epsilon
|
||||
// assertNotEqualFloat(unwanted, actual, epsilon); // fabs(a - b) >= epsilon
|
||||
// assertInfinity(actual); // isinf(a)
|
||||
// assertNotInfinity(actual); // !isinf(a)
|
||||
// assertNAN(arg); // isnan(a)
|
||||
// assertNotNAN(arg); // !isnan(a)
|
||||
|
||||
|
||||
#include <ArduinoUnitTests.h>
|
||||
|
||||
#include "AS5600.h"
|
||||
#include "Wire.h"
|
||||
|
||||
|
||||
unittest_setup()
|
||||
{
|
||||
fprintf(stderr, "AS5600_LIB_VERSION: %s\n", (char *) AS5600_LIB_VERSION);
|
||||
}
|
||||
|
||||
|
||||
unittest_teardown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
unittest(test_constants_base)
|
||||
{
|
||||
assertEqual(0, AS5600_CLOCK_WISE);
|
||||
assertEqual(1, AS5600_COUNTERCLOCK_WISE);
|
||||
|
||||
assertEqual(0, AS5600_MODE_DEGREES);
|
||||
assertEqual(1, AS5600_MODE_RADIANS);
|
||||
assertEqual(2, AS5600_MODE_RPM);
|
||||
|
||||
assertEqualFloat(360.0/4096, AS5600_RAW_TO_DEGREES, 0.0001);
|
||||
assertEqualFloat(4096/360.0, AS5600_DEGREES_TO_RAW, 0.0001);
|
||||
assertEqualFloat((PI*2.0)/4096, AS5600_RAW_TO_RADIANS, 0.0001);
|
||||
assertEqualFloat(60.0/4096, AS5600_RAW_TO_RPM, 0.0001);
|
||||
|
||||
assertEqual(0x36, AS5600_DEFAULT_ADDRESS);
|
||||
assertEqual(0x40, AS5600L_DEFAULT_ADDRESS);
|
||||
|
||||
assertEqual(255, AS5600_SW_DIRECTION_PIN);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_constants_configuration)
|
||||
{
|
||||
assertEqual(0, AS5600_OUTMODE_ANALOG_100);
|
||||
assertEqual(1, AS5600_OUTMODE_ANALOG_90);
|
||||
assertEqual(2, AS5600_OUTMODE_PWM);
|
||||
|
||||
assertEqual(0, AS5600_POWERMODE_NOMINAL);
|
||||
assertEqual(1, AS5600_POWERMODE_LOW1);
|
||||
assertEqual(2, AS5600_POWERMODE_LOW2);
|
||||
assertEqual(3, AS5600_POWERMODE_LOW3);
|
||||
|
||||
assertEqual(0, AS5600_PWM_115);
|
||||
assertEqual(1, AS5600_PWM_230);
|
||||
assertEqual(2, AS5600_PWM_460);
|
||||
assertEqual(3, AS5600_PWM_920);
|
||||
|
||||
assertEqual(0, AS5600_HYST_OFF);
|
||||
assertEqual(1, AS5600_HYST_LSB1);
|
||||
assertEqual(2, AS5600_HYST_LSB2);
|
||||
assertEqual(3, AS5600_HYST_LSB3);
|
||||
|
||||
assertEqual(0, AS5600_SLOW_FILT_16X);
|
||||
assertEqual(1, AS5600_SLOW_FILT_8X);
|
||||
assertEqual(2, AS5600_SLOW_FILT_4X);
|
||||
assertEqual(3, AS5600_SLOW_FILT_2X);
|
||||
|
||||
assertEqual(0, AS5600_FAST_FILT_NONE);
|
||||
assertEqual(1, AS5600_FAST_FILT_LSB6);
|
||||
assertEqual(2, AS5600_FAST_FILT_LSB7);
|
||||
assertEqual(3, AS5600_FAST_FILT_LSB9);
|
||||
assertEqual(4, AS5600_FAST_FILT_LSB18);
|
||||
assertEqual(5, AS5600_FAST_FILT_LSB21);
|
||||
assertEqual(6, AS5600_FAST_FILT_LSB24);
|
||||
assertEqual(7, AS5600_FAST_FILT_LSB10);
|
||||
|
||||
assertEqual(0, AS5600_WATCHDOG_OFF);
|
||||
assertEqual(1, AS5600_WATCHDOG_ON);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_constructor)
|
||||
{
|
||||
AS5600 as5600;
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4);
|
||||
assertTrue(as5600.isConnected()); // keep CI happy
|
||||
|
||||
AS5600L asl(0x40);
|
||||
asl.begin(5);
|
||||
assertTrue(asl.isConnected()); // keep CI happy
|
||||
}
|
||||
|
||||
|
||||
unittest(test_address)
|
||||
{
|
||||
AS5600 as5600;
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4);
|
||||
assertEqual(0x36, as5600.getAddress());
|
||||
|
||||
AS5600L asl;
|
||||
as5600.begin(5);
|
||||
assertEqual(0x40, asl.getAddress());
|
||||
|
||||
AS5600L asl2(0x41);
|
||||
asl2.begin(6);
|
||||
assertEqual(0x41, asl2.getAddress());
|
||||
}
|
||||
|
||||
|
||||
unittest(test_hardware_direction)
|
||||
{
|
||||
AS5600 as5600;
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(4);
|
||||
assertEqual(AS5600_CLOCK_WISE, as5600.getDirection());
|
||||
|
||||
as5600.setDirection();
|
||||
assertEqual(AS5600_CLOCK_WISE, as5600.getDirection());
|
||||
|
||||
as5600.setDirection(AS5600_COUNTERCLOCK_WISE);
|
||||
assertEqual(AS5600_COUNTERCLOCK_WISE, as5600.getDirection());
|
||||
|
||||
as5600.setDirection(AS5600_CLOCK_WISE);
|
||||
assertEqual(AS5600_CLOCK_WISE, as5600.getDirection());
|
||||
}
|
||||
|
||||
|
||||
unittest(test_software_direction)
|
||||
{
|
||||
AS5600 as5600;
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin(255);
|
||||
assertEqual(AS5600_CLOCK_WISE, as5600.getDirection());
|
||||
|
||||
as5600.setDirection();
|
||||
assertEqual(AS5600_CLOCK_WISE, as5600.getDirection());
|
||||
|
||||
as5600.setDirection(AS5600_COUNTERCLOCK_WISE);
|
||||
assertEqual(AS5600_COUNTERCLOCK_WISE, as5600.getDirection());
|
||||
|
||||
as5600.setDirection(AS5600_CLOCK_WISE);
|
||||
assertEqual(AS5600_CLOCK_WISE, as5600.getDirection());
|
||||
}
|
||||
|
||||
|
||||
unittest(test_offset_I)
|
||||
{
|
||||
AS5600 as5600;
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin();
|
||||
|
||||
for (int of = 0; of < 360; of += 40)
|
||||
{
|
||||
as5600.setOffset(of);
|
||||
assertEqualFloat(of, as5600.getOffset(), 0.05);
|
||||
}
|
||||
|
||||
assertTrue(as5600.setOffset(-40.25));
|
||||
assertEqualFloat(319.75, as5600.getOffset(), 0.05);
|
||||
|
||||
assertTrue(as5600.setOffset(-400.25));
|
||||
assertEqualFloat(319.75, as5600.getOffset(), 0.05);
|
||||
|
||||
assertTrue(as5600.setOffset(753.15));
|
||||
assertEqualFloat(33.15, as5600.getOffset(), 0.05);
|
||||
|
||||
assertFalse(as5600.setOffset(36000.1));
|
||||
assertFalse(as5600.setOffset(-36000.1));
|
||||
}
|
||||
|
||||
|
||||
unittest(test_offset_II)
|
||||
{
|
||||
AS5600 as5600;
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin();
|
||||
|
||||
as5600.setOffset(200);
|
||||
assertEqualFloat(200, as5600.getOffset(), 0.05);
|
||||
|
||||
as5600.setOffset(30);
|
||||
assertEqualFloat(30, as5600.getOffset(), 0.05);
|
||||
|
||||
as5600.setOffset(200);
|
||||
assertEqualFloat(200, as5600.getOffset(), 0.05);
|
||||
|
||||
as5600.setOffset(-30);
|
||||
assertEqualFloat(330, as5600.getOffset(), 0.05);
|
||||
|
||||
|
||||
// as cummulative error can be larger ==> 0.1
|
||||
as5600.setOffset(200);
|
||||
assertEqualFloat(200, as5600.getOffset(), 0.1);
|
||||
|
||||
as5600.increaseOffset(30);
|
||||
assertEqualFloat(230, as5600.getOffset(), 0.1);
|
||||
|
||||
as5600.setOffset(200);
|
||||
assertEqualFloat(200, as5600.getOffset(), 0.1);
|
||||
|
||||
as5600.increaseOffset(-30);
|
||||
assertEqualFloat(170, as5600.getOffset(), 0.1);
|
||||
|
||||
as5600.setOffset(200);
|
||||
assertEqualFloat(200, as5600.getOffset(), 0.1);
|
||||
|
||||
as5600.increaseOffset(-300);
|
||||
assertEqualFloat(260, as5600.getOffset(), 0.1);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_failing_set_commands)
|
||||
{
|
||||
AS5600 as5600;
|
||||
|
||||
Wire.begin();
|
||||
|
||||
as5600.begin();
|
||||
|
||||
assertFalse(as5600.setZPosition(4096));
|
||||
assertFalse(as5600.setMPosition(4096));
|
||||
assertFalse(as5600.setMaxAngle(4096));
|
||||
|
||||
assertFalse(as5600.setConfigure(0x4000));
|
||||
assertFalse(as5600.setPowerMode(4));
|
||||
assertFalse(as5600.setHysteresis(4));
|
||||
assertFalse(as5600.setOutputMode(3));
|
||||
assertFalse(as5600.setPWMFrequency(4));
|
||||
assertFalse(as5600.setSlowFilter(4));
|
||||
assertFalse(as5600.setFastFilter(8));
|
||||
assertFalse(as5600.setWatchDog(2));
|
||||
}
|
||||
|
||||
|
||||
// FOR REMAINING ONE NEED A STUB
|
||||
|
||||
|
||||
unittest_main()
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
Reference in New Issue
Block a user