Hi,
I’m developing a small robotic SCARA-type arm. Right now I can send commands to two iPower GM2804 motors with AS5048A magnetic encoders from a browser.
Here’s the code, which is basically the angle_control example:
/**
*
* Position/angle motion control example
* Steps:
* 1) Configure the motor and magnetic sensor
* 2) Run the code
* 3) Set the target angle (in radians) from serial terminal
*
*/
#include <SimpleFOC.h>
// magnetic sensor instance - SPI
// MagneticSensorSPI sensor = MagneticSensorSPI(AS5048_SPI, 10);
MagneticSensorSPI sensor = MagneticSensorSPI(7, 14, 0x3FFF);
// magnetic sensor instance - MagneticSensorI2C
// MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);
// magnetic sensor instance - analog output
// MagneticSensorAnalog sensor = MagneticSensorAnalog(A1, 14, 1020);
// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(7);
BLDCDriver3PWM driver = BLDCDriver3PWM(6, 5, 4, 3);
// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6, 8);
// angle set point variable
float target_angle = 0;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_angle, cmd); }
void setup() {
// initialise magnetic sensor hardware
sensor.init();
// link the motor to the sensor
motor.linkSensor(&sensor);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);
// choose FOC modulation (optional)
motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
// set motion control loop to be used
motor.controller = MotionControlType::angle;
// contoller configuration
// default parameters in defaults.h
// velocity PI controller parameters
motor.PID_velocity.P = 0.2f; //ORIGINALLY 0.2f -Svavar
motor.PID_velocity.I = 5; //ORIGINALLY 20 -Svavar
motor.PID_velocity.D = 0; //ORIGINALLY 0 -Svavar
// maximal voltage to be set to the motor
motor.voltage_limit = 6;
// velocity low pass filtering time constant
// the lower the less filtered
motor.LPF_velocity.Tf = 0.01f; //ORIGINALLY 0.01f -Svavar
// angle P controller
motor.P_angle.P = 5; // this was originally 20 -Svavar
// maximal velocity of the position control
motor.velocity_limit = 10; // this was originally 20 -Svavar
// use monitoring with serial
Serial.begin(115200);
// comment out if not needed
motor.useMonitoring(Serial);
// VERBOSE MONITORING OUTPUT
command.verbose = VerboseMode::machine_readable; // can be set using the webcontroller - optional
// initialize motor
motor.init();
// align sensor and start FOC
motor.initFOC();
// add target command T
command.add('T', doTarget, "target angle");
Serial.println(F("Motor ready."));
Serial.println(F("Set the target angle using serial terminal:"));
_delay(1000);
}
void loop() {
// OUTPUT MONITORING DATA TO SIMPLEFOC STUDIO
motor.monitor();
// main FOC algorithm function
// the faster you run this function the better
// Arduino UNO loop ~1kHz
// Bluepill loop ~10kHz
motor.loopFOC();
// Motion control function
// velocity, position or voltage (defined in motor.controller)
// this function can be run at much lower frequency than loopFOC() function
// You can also use motor.move() and set the motor.target in the code
motor.move(target_angle);
// function intended to be used with serial plotter to monitor motor variables
// significantly slowing the execution down!!!!
// motor.monitor();
// user communication
command.run();
}
I got this to work with after applying the fix for the Xiao SAMD21 suggested by @runger. I’m using Xiao SAMD21 modules with SimpleFOC Mini drivers. Now I’m designing my own board for the robot arm, and I’d like to use the bare SAMD21E18A chip instead of the Xiao module.
I have a SAMD21E18A on a basic board, not connected to a motor driver, just to see if I can get code onto it. I’ve managed to put a bootloader on it using EDBG and in the Arduino IDE I can get it to echo serial messages back to me. Nice!
I’m using a SAMD Arduino core that was made for the Fab Lab community. The core supports the SAMD21E18A chip, but I’m wondering if another core would work better with SimpleFOC, because I get an Error compiling for board Generic x21E
when trying to compile the angle_control example. I’ve tried it with and without the @runger fix for the Xiao SAMD21 module. It works better with the fix, but I still get the following errors:
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd21_mcu.cpp: In function 'EPioType getPeripheralOfPermutation(int, int)':
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd21_mcu.cpp:128:49: error: 'PIO_TIMER_ALT' was not declared in this scope
return ((permutation>>pin_position)&0x01)==0x1?PIO_TIMER_ALT:PIO_TIMER;
^~~~~~~~~~~~~
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd21_mcu.cpp:128:49: note: suggested alternative: 'PER_TIMER_ALT'
return ((permutation>>pin_position)&0x01)==0x1?PIO_TIMER_ALT:PIO_TIMER;
^~~~~~~~~~~~~
PER_TIMER_ALT
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd21_mcu.cpp:128:63: error: 'PIO_TIMER' was not declared in this scope
return ((permutation>>pin_position)&0x01)==0x1?PIO_TIMER_ALT:PIO_TIMER;
^~~~~~~~~
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd21_mcu.cpp:128:63: note: suggested alternative: 'PER_TIMER'
return ((permutation>>pin_position)&0x01)==0x1?PIO_TIMER_ALT:PIO_TIMER;
^~~~~~~~~
PER_TIMER
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd_mcu.cpp: In function 'tccConfiguration getTCCChannelNr(int, EPioType)':
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd_mcu.cpp:82:64: error: invalid conversion from 'uint8_t {aka unsigned char}' to 'EPortType {aka _EPortType}' [-fpermissive]
struct wo_association& association = getWOAssociation(pinDesc.ulPort, pinDesc.ulPin);
~~~~~~~~^~~~~~
In file included from C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd_mcu.cpp:4:0:
c:\users\...\documents\arduino\libraries\simple_foc\src\drivers\hardware_specific\samd\samd_mcu.h:110:24: note: initializing argument 1 of 'wo_association& getWOAssociation(EPortType, uint32_t)'
struct wo_association& getWOAssociation(EPortType port, uint32_t pin);
^~~~~~~~~~~~~~~~
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd_mcu.cpp:85:18: error: 'PIO_TIMER' was not declared in this scope
if (peripheral==PIO_TIMER) {
^~~~~~~~~
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd_mcu.cpp:85:18: note: suggested alternative: 'PER_TIMER'
if (peripheral==PIO_TIMER) {
^~~~~~~~~
PER_TIMER
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd_mcu.cpp:89:23: error: 'PIO_TIMER_ALT' was not declared in this scope
else if (peripheral==PIO_TIMER_ALT) {
^~~~~~~~~~~~~
C:\Users\...\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\samd\samd_mcu.cpp:89:23: note: suggested alternative: 'PER_TIMER_ALT'
else if (peripheral==PIO_TIMER_ALT) {
^~~~~~~~~~~~~
PER_TIMER_ALT
Using library Simple_FOC at version 2.3.0 in folder: C:\Users\...\Documents\Arduino\libraries\Simple_FOC
Using library SPI at version 1.0 in folder: C:\Users\...\AppData\Local\Arduino15\packages\Fab_SAM_Arduino\hardware\samd\1.11.0\libraries\SPI
Using library Wire at version 1.0 in folder: C:\Users\...\AppData\Local\Arduino15\packages\Fab_SAM_Arduino\hardware\samd\1.11.0\libraries\Wire
exit status 1
Error compiling for board Generic x21E.