On this page
I2C Magnetic sensor setup
Step 1. Instantiate MagneticSensorI2C
class
Now in order to use your I2C magnetic position sensor with SimpleFOClibrary first create an instance of the MagneticSensorI2C
class:
// MagneticSensorI2C(uint8_t _chip_address, float _cpr, uint8_t _angle_register_msb)
// chip_address - I2C chip address
// bit_resolution - resolution of the sensor
// angle_register_msb - angle read register msb
// bits_used_msb - number of used bits in msb register
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);
The parameters of the class are:
chip_address
- I2C address of the magnetic sensorbit_resolution
- resolution of your sensor (number of bits of the sensor internal counter register) and yourangle_register_msb
- register number containing the MSB part of the angle value. ( ex. AS5600 -0x0E
, AS5048 -0xFE
)bits_used_msb
- number of used bits in MSB register
How to find the MSB register values and used bits value?
Since I2C registers are Byte(8-bit) registers they contain the 12-14 bit angle representation separated in two Byte addresses, MSB(most significant byte) and LSB(least significant byte). To instantiate the I2C magnetic sensor you need to provide the MSB register address and tell the library how is the angle value separated in the two registers. By specifying the number of bits used in the MSB register and specifying thebit_resolution
value the library can calculate how many bits are used in the LSB register and can reconstruct the complete angle value.
Example MSB/LSB division:
- AS5600 (12 bit) - MSB (4bit), LSB (8bit)
- AS5048B (14bit): - MSB (8bit), LSB(6bit)
AS5600 example
- First we open AS5600 sensor's datasheet .
- In the datasheet we find the table of I2C registers (page 18)
- The
angle_register_msb
value is the first (upper in datasheet) register value -0x0E
- The
bits_used_msb
value is number of bits in the MSB register -4
Finally, after the configuration, you just call the init()
function. This function prepares the I2C interface and configures the sensor hardware. So your magnetic sensor initialization code will look like:
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);
void setup(){
...
sensor.init();
...
}
If you wish to use more than one magnetic sensor using SPI interface, make sure your sensors have different addresses, here is a simple example:
MagneticSensorI2C sensor1 = MagneticSensorI2C(0x36, 12, 0x0E, 4);
MagneticSensorI2C sensor2 = MagneticSensorI2C(0x37, 12, 0x0E, 4);
void setup(){
...
sensor1.init();
sensor2.init();
...
}
Multiple I2C busses
Additionally, the library enables you to already configured I2C bus to the sensor using the init()
function.
Wire.setClock(400000);
Wire.begin();
// providing
sensor.init(&Wire)
For microcontrollers where that is possible (not for Arduino UNO) you can use different I2C busses for multiple I2C sensors. See the examples in utils > sensor_test > magnetic_sensors > magnetic_sensor_i2c_dual_bus_examples
.
Quick configuration for common sensors
For the most common I2C magnetic sensors, the library provides the simplified configuration constructor. Namely for AS5600 12-bit sensor and AS5048 14-bit sensor.
// instance of AS5600 sensor
MagneticSensorI2C sensor2 = MagneticSensorI2C(AS5600_I2C);
// instance of AS5048B sensor
MagneticSensorI2C sensor2 = MagneticSensorI2C(AS5048_I2C);
If wish to implement your own quick configuration structure, you will need to create an instance of the structure:
struct MagneticSensorI2CConfig_s {
int chip_address;
int bit_resolution;
int angle_register;
int data_start_bit;
};
and provide it to the constructor, here is an example:
// configuration for AS5600 sensor
MagneticSensorI2CConfig_s MySensorConfig = {
.chip_address = 0x36,
.bit_resolution = 12,
.angle_register=0x0E,
.data_start_bit=11
};
// the sensor class with desired sensor configuration
MagneticSensorI2C sensor = MagneticSensorI2C(MySensorConfig);
void setup(){
sensor.init();
...
}
Please check the magnetic_sensor_i2_example.ino
example for a quick test of your sensor. All the features of I2C magnetic sensors are implemented in the MagneticSensorI2C.cpp/h
files.
Step 2. Using magnetic sensor in real-time
There are two ways to use magnetic sensor implemented within this library:
- As a motor position sensor for FOC algorithm
- As a standalone position sensor
Position sensor for FOC algorithm
To use the ensor with the FOC algorithm implemented in this library, once when you have initialized sensor.init()
you just need to link it to the BLDC motor by executing:
motor.linkSensor(&sensor);
And you will be able to access the angle and velocity of the motor using the motor instance:
motor.shaft_angle; // motor angle
motor.shaft_velocity; // motor velocity
or through the sensor instance:
sensor.getAngle(); // motor angle
sensor.getVelocity(); // motor velocity
Example code
Here is a quick example for AS5600 magnetic sensor with a BLDC motor and driver:
#include <SimpleFOC.h>
// motor and driver
BLDCMotor motor = BLDCMotor(7);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
// as5600 sensor quick config
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);
void setup() {
// driver
driver.init()
motor.linkDriver(&driver);
// init magnetic sensor hardware
sensor.init();
motor.linkSensor(&sensor);
// init motor hardware
motor.init();
motor.initFOC();
Serial.println("Motor ready");
_delay(1000);
}
void loop(){
motor.loopFOC();
motor.move();
}
Standalone sensor
To get the magnetic sensor angle and velocity at any given time you can use the public methods:
class MagneticSensorI2C{
public:
// shaft velocity getter
float getVelocity();
// shaft angle getter
float getAngle();
}
Calling
getVelocity
multiple timesWhen calling
getVelocity
it will only calculate the velocity if the elapsed time from the previous call is longer than the time specified in teh variablemin_elapsed_time
(default 100us). If the elapsed time from the last call is shorter thanmin_elapsed_time
the function will return previously calculated value. Variablemin_elapsed_time
can be changed easily if necessary:sensor.min_elapsed_time = 0.0001; // 100us by default
Example code
Here is a quick example for AS5600 magnetic sensor with I2C communication:
#include <SimpleFOC.h>
// MagneticSensorI2C(uint8_t _chip_address, float _cpr, uint8_t _angle_register_msb)
// chip_address - I2C chip address
// bit_resolution - resolution of the sensor
// angle_register_msb - angle read register msb
// bits_used_msb - number of used bits in msb register
MagneticSensorI2C as5600 = MagneticSensorI2C(0x36, 12, 0x0E, 4);
// or quick config
MagneticSensorI2C as5600 = MagneticSensorI2C(AS5600_I2C);
void setup() {
// monitoring port
Serial.begin(115200);
// init magnetic sensor hardware
as5600.init();
Serial.println("AS5600 ready");
_delay(1000);
}
void loop() {
// IMPORTANT - call as frequently as possible
// update the sensor values
as5600.update();
// display the angle and the angular velocity to the terminal
Serial.print(as5600.getAngle());
Serial.print("\t");
Serial.println(as5600.getVelocity());
}