try to fix submodule

This commit is contained in:
2023-11-09 19:02:15 -05:00
parent c1d45aa443
commit deea94b076
366 changed files with 40228 additions and 2 deletions

View File

@@ -0,0 +1,118 @@
/*
* AS5048A.cpp
*
* Created on: 8 Mar 2021
* Author: runger
*/
#include "AS5048A.h"
AS5048A::AS5048A(SPISettings settings, int nCS) : settings(settings), nCS(nCS) {
// nix
}
AS5048A::~AS5048A() {
}
void AS5048A::init(SPIClass* _spi) {
spi = _spi;
if (nCS>=0)
pinMode(nCS, OUTPUT);
digitalWrite(nCS, HIGH);
//SPI has an internal SPI-device counter, it is possible to call "begin()" from different devices
spi->begin();
readRawAngle(); // read an angle
}
float AS5048A::getCurrentAngle(){
readRawAngle();
return ((float)readRawAngle())/(float)AS5048A_CPR * 2.0f * (float)PI;
}
float AS5048A::getFastAngle(){
return ((float)readRawAngle())/(float)AS5048A_CPR * 2.0f * (float)PI;
}
uint16_t AS5048A::readRawAngle(){
uint16_t command = AS5048A_ANGLE_REG | AS5048A_PARITY | AS5048A_RW; // set r=1 and parity=1, result ix 0xFFFF
uint16_t lastresult = spi_transfer16(command)&AS5048A_RESULT_MASK;
return lastresult;
}
uint16_t AS5048A::readMagnitude(){
uint16_t command = AS5048A_MAGNITUDE_REG | AS5048A_RW; // set r=1, result ix 0x7FFE
/*uint16_t cmdresult =*/ spi_transfer16(command);
uint16_t result = nop();
return result;
}
bool AS5048A::isErrorFlag(){
return errorflag;
}
AS5048Error AS5048A::clearErrorFlag(){
uint16_t command = AS5048A_ERROR_REG | AS5048A_RW; // set r=1, result ix 0x4001
/*uint16_t cmdresult =*/ spi_transfer16(command);
uint16_t result = nop();
AS5048Error err = {
.parityError = ((result&0x0004)!=0x0000),
.commandInvalid = ((result&0x0002)!=0x0000),
.framingError = ((result&0x0001)!=0x0000)
};
return err;
}
AS5048Diagnostics AS5048A::readDiagnostics(){
uint16_t command = AS5048A_DIAGNOSTICS_REG | AS5048A_RW; // set r=1, result ix 0x7FFD
/*uint16_t cmdresult =*/ spi_transfer16(command);
AS5048Diagnostics result = {
.reg = nop()
};
return result;
}
uint16_t AS5048A::setZero(uint16_t){
// TODO implement me!
return 0;
}
uint16_t AS5048A::enableOneTimeProgramming(){
// no plans to implement this at the moment. one-time-programming a $10 chip isn't really a "maker" thing to do. The zero
// position can be easily retained in software, stored on the MCU, and thereby the sensor can be reused in another project.
return 0;
}
uint16_t AS5048A::programZero(){
// no plans to implement this at the moment. one-time-programming a $10 chip isn't really a "maker" thing to do. The zero
// position can be easily retained in software, stored on the MCU, and thereby the sensor can be reused in another project.
return 0;
}
uint16_t AS5048A::nop(){
uint16_t result = spi_transfer16(0xFFFF); // using 0xFFFF as nop instead of 0x0000, then next call to fastAngle will return an angle
return result&AS5048A_RESULT_MASK;
}
uint16_t AS5048A::spi_transfer16(uint16_t outdata) {
if (nCS>=0)
digitalWrite(nCS, 0);
spi->beginTransaction(settings);
uint16_t result = spi->transfer16(outdata);
spi->endTransaction();
if (nCS>=0)
digitalWrite(nCS, 1);
// TODO check parity
errorflag = ((result&AS5048A_ERRFLG)>0);
return result;
}

View File

@@ -0,0 +1,89 @@
/*
* AS5048A.h
*
* Created on: 8 Mar 2021
* Author: runger
*/
#ifndef AS5048A_H_
#define AS5048A_H_
#include "Arduino.h"
#include "SPI.h"
union AS5048Diagnostics {
struct {
uint16_t agc:8;
uint16_t ocf:1;
uint16_t cof:1;
uint16_t compLow:1;
uint16_t compHigh:1;
};
uint16_t reg;
};
struct AS5048Error {
bool parityError;
bool commandInvalid;
bool framingError;
};
#define AS5048A_CPR 16384
#define AS5048A_ANGLE_REG 0x3FFF
#define AS5048A_ERROR_REG 0x0001
#define AS5048A_PROGCTL_REG 0x0003
#define AS5048A_OTPHIGH_REG 0x0016
#define AS5048A_OTPLOW_REG 0x0017
#define AS5048A_DIAGNOSTICS_REG 0x3FFD
#define AS5048A_MAGNITUDE_REG 0x3FFE
#define AS5048A_PARITY 0x8000
#define AS5048A_RW 0x4000
#define AS5048A_ERRFLG 0x4000
#define AS5048A_RESULT_MASK 0x3FFF
#define AS5048_BITORDER MSBFIRST
static SPISettings AS5048SPISettings(8000000, AS5048_BITORDER, SPI_MODE1); // @suppress("Invalid arguments")
class AS5048A {
public:
AS5048A(SPISettings settings = AS5048SPISettings, int nCS = -1);
virtual ~AS5048A();
virtual void init(SPIClass* _spi = &SPI);
float getCurrentAngle(); // angle in radians, return current value
float getFastAngle(); // angle in radians, return last value and read new
uint16_t readRawAngle(); // 14bit angle value
uint16_t readMagnitude(); // 14bit magnitude value
bool isErrorFlag();
AS5048Error clearErrorFlag();
AS5048Diagnostics readDiagnostics();
uint16_t setZero(uint16_t);
uint16_t enableOneTimeProgramming();
uint16_t programZero();
private:
uint16_t nop();
uint16_t spi_transfer16(uint16_t outdata);
SPIClass* spi;
SPISettings settings;
bool errorflag = false;
int nCS = -1;
};
#endif /* AS5048A_H_ */

View File

@@ -0,0 +1,26 @@
#include "./MagneticSensorAS5048A.h"
#include "common/foc_utils.h"
#include "common/time_utils.h"
MagneticSensorAS5048A::MagneticSensorAS5048A(int nCS, bool fastMode, SPISettings settings) : AS5048A(settings, nCS), fastMode(fastMode) {
}
MagneticSensorAS5048A::~MagneticSensorAS5048A(){
}
void MagneticSensorAS5048A::init(SPIClass* _spi) {
this->AS5048A::init(_spi);
this->Sensor::init();
}
float MagneticSensorAS5048A::getSensorAngle() {
float angle_data = readRawAngle();
if (!fastMode) // read again to ensure current value
angle_data = readRawAngle();
angle_data = ( angle_data / (float)AS5048A_CPR ) * _2PI;
// return the shaft angle
return angle_data;
}

View File

@@ -0,0 +1,20 @@
#ifndef __MAGNETICSENSORAS5048A_H__
#define __MAGNETICSENSORAS5048A_H__
#include "common/base_classes/Sensor.h"
#include "./AS5048A.h"
class MagneticSensorAS5048A : public Sensor, public AS5048A {
public:
MagneticSensorAS5048A(int nCS = -1, bool fastMode = false, SPISettings settings = AS5048SPISettings);
virtual ~MagneticSensorAS5048A();
virtual float getSensorAngle() override;
virtual void init(SPIClass* _spi = &SPI);
protected:
bool fastMode = false;
};
#endif

View File

@@ -0,0 +1,50 @@
/*
* PreciseMagneticSensorAS5048A.cpp
*
* Created on: 1 May 2021
* Author: runger
*/
#include <encoders/as5048a/PreciseMagneticSensorAS5048A.h>
#include "common/foc_utils.h"
#include "common/time_utils.h"
PreciseMagneticSensorAS5048A::PreciseMagneticSensorAS5048A(int nCS, bool fastMode, SPISettings settings) : AS5048A(settings, nCS), fastMode(fastMode) { }
PreciseMagneticSensorAS5048A::~PreciseMagneticSensorAS5048A() { }
void PreciseMagneticSensorAS5048A::init(SPIClass* _spi) {
this->AS5048A::init(_spi);
// velocity calculation init
current_ts = _micros();
/*uint16_t angle_data =*/ readRawAngle();
current_angle = PreciseAngle(readRawAngle(), 0);
getAngle();
}
float PreciseMagneticSensorAS5048A::getSensorAngle() {
previous_ts = current_ts;
previous_angle = current_angle;
uint16_t angle_data = readRawAngle();
if (!fastMode) // read again to ensure current value
angle_data = readRawAngle();
current_ts = _micros();
current_angle.update(angle_data);
return current_angle.asFloat();
}
/*
unlike the normal MagneticSensorSPI implementation, this one uses the angle previously read by the last call to getAngle to do its
calculation, and does not directly poll any data from the sensor.
This is an optimisation for speed, based on the assumption that loopFOC() (which calls getAngle()) is invoked at least as often as
move() (which calls getVelocity()). If this is the case, getVelocity() should always have a sufficiently "fresh" value to work with.
If using this function in a different context, simply call getAngle() first to be sure of a fresh angle value.
*/
float PreciseMagneticSensorAS5048A::getVelocity() {
return current_angle.velocity(previous_angle, (current_ts-previous_ts));
}

View File

@@ -0,0 +1,33 @@
/*
* PreciseMagneticSensorAS5048A.h
*
* Created on: 1 May 2021
* Author: runger
*/
#ifndef LIBRARIES_ARDUNIO_FOC_DRIVERS_SRC_ENCODERS_AS5048A_PRECISEMAGNETICSENSORAS5048A_H_
#define LIBRARIES_ARDUNIO_FOC_DRIVERS_SRC_ENCODERS_AS5048A_PRECISEMAGNETICSENSORAS5048A_H_
#include "common/base_classes/Sensor.h"
#include "./AS5048A.h"
#include "utilities/PreciseAngle.h"
class PreciseMagneticSensorAS5048A : public Sensor, public AS5048A {
public:
PreciseMagneticSensorAS5048A(int nCS = -1, bool fastMode = false, SPISettings settings = AS5048SPISettings);
virtual ~PreciseMagneticSensorAS5048A();
virtual float getSensorAngle() override;
virtual float getVelocity() override;
virtual void init(SPIClass* _spi = &SPI) override;
protected:
bool fastMode = false;
PreciseAngle previous_angle = PreciseAngle();
PreciseAngle current_angle = PreciseAngle();
unsigned long previous_ts = 0;
unsigned long current_ts = 1;
};
#endif /* LIBRARIES_ARDUNIO_FOC_DRIVERS_SRC_ENCODERS_AS5048A_PRECISEMAGNETICSENSORAS5048A_H_ */

View File

@@ -0,0 +1,86 @@
# AS5048A SimpleFOC driver
While AS5048A absolute position magnetic rotary encoder is supported by the standard MagneticSensorSPI driver included in the base distribution, this AS5048A-specific driver includes some optimisations:
- access to the other registers of the AS5048A, including the magnitude value which can be used to check the magnet strength, and the diagnostics register
- access to the error state of the sensor, and ability to clear errors
- it has a fastMode setting, in which the sensor is sent only 1 command per getAngle() call - the value returned will be from previous getAngle() invocation
## Hardware setup
Connect as per normal for your SPI bus. No special hardware setup is needed to use this driver.
## Software setup
Its actually easier to use than the standard SPI sensor class, because it is less generic:
```c++
#include "Arduino.h"
#include "Wire.h"
#include "SPI.h"
#include "SimpleFOC.h"
#include "SimpleFOCDrivers.h"
#include "encoders/as5048a/MagneticSensorAS5048A.h"
#define SENSOR1_CS 5 // some digital pin that you're using as the nCS pin
MagneticSensorAS5048A sensor1(SENSOR1_CS);
void setup() {
sensor1.init();
}
```
Set some options:
```c++
MagneticSensorAS5048A sensor1(SENSOR1_CS, true, mySPISettings);
```
Use another SPI bus:
```c++
void setup() {
sensor1.init(SPI2);
}
```
Here's how you can use it:
```c++
// update the sensor (only needed if using the sensor without a motor)
sensor1.update();
// get the angle, in radians, including full rotations
float a1 = sensor1.getAngle();
// get the velocity, in rad/s - note: you have to call getAngle() on a regular basis for it to work
float v1 = sensor1.getVelocity();
// get the angle, in radians, no full rotations
float a2 = sensor1.getCurrentAngle();
// get the raw 14 bit value
uint16_t raw = sensor1.readRawAngle();
// read the CORDIC magnitude value, a measure of the magnet field strength
float m1 = sensor1.readMagnitude();
// check for errors
if (sensor1.isErrorFlag()) {
AS5048Error error = sensor1.clearErrorFlag();
if (error.parityError) { // also error.framingError, error.commandInvalid
// etc...
}
}
// get diagnostics
AS5048Diagnostics diagnostics = sensor1.readDiagnostics();
```
## PreciseMagneticSensorAS5048A
This is a variant of the sensor that uses [PreciseAngle](../utilities) to represent the angle, allowing a (much) greater range of rotation.