Error compiling to SAMD21 (bare chip)

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.

Oh no! I wonder what is going on here - some kind of incompatibility with the headers that get included for the Generic x21E variant.

I’ll have to look into this. In the meantime you could try and see if there are other boards using this chip that you could try instead…

1 Like

Thanks for looking into it!

I’ve seen that some people on this forum, like @AdinAck and @Magneon, have made boards with SAMD21 chips, I wonder which Arduino core they’re using. Maybe I just need to use a different one.

The code is already running on the Xiao SAMD21 modules, so I’ll just embed those onto the first version of my boards.

When I made my board, I simply flashed it with Adafruit’s bootloader for the Feather M0 Basic Proto. I designed the board such that it conformed to the Feather (not much to do for that).

So when I programmed it with PlatformIO (or Arduino IDE) I just told it I was programming a Feather.

I have no experience with the Generic x21E core, but @runger and I got the RPI Pico to play ball really easily. So if he’s on the case, you’re in good hands!

P.S. I made my motor controller for a SCARA robot arm too :smiling_face:. I would love to see videos of it working if you don’t mind.

1 Like

Thanks for the answer @AdinAck , it has nudged me in a useful direction. Getting SimpleFOC to compile to the Fab SAM core would be best because OSAP (the plug-and-play networking layer library I’m using) works nicely on it. But I’ll see if I can hack something together in the meantime. Right now I’m looking into any and all Arduino cores for the SAMD21 that might work with both SimpleFOC and OSAP.

Right now I just have a nest of wires. I’ll post a video when the robot is moving!

Hey,

I’m actually testing a custom board at the moment, based on ATSAMD21E16BU.

I’m using PlatformIO, with the following versions:

PLATFORM: Atmel SAM (8.1.0)
Dependency Graph
|-- Simple FOC @ 2.3.0
|-- SimpleFOCDrivers @ 1.0.4

I don’t have any compile problems. I’m using the dev branch versions of the libraries. Have you tried the dev-branch versions? But I don’t think there are actually any changes that would relate to this error…

I’m guessing the key difference is that I have a custom board definition set up.

Do you know what is the difference between your SAMD21E18A chip and other models that would cause this? Does it have a different assignment of the timers to the pins?

1 Like

Hmm, I don’t know the chip that well. Thanks for the info, I’ll check out PlatformIO with your settings and the dev-branch libraries. I just use the Arduino IDE and I’m in over my head!

After AdinAck said that he used the Adafruit Feather board definition I started trying out different Arduino cores and found that the core for the Arduino Nano 33 IoT works for me! I’ve been busy working on my robot and today was my final presentation in the Fab Academy (1 min 22 s video):

The robot is not quite complete, but it’s promising and I like the look of it. I’m gonna keep working on it. Thanks for the help, @runger and @AdinAck!

P.S. I might end up using something other than the Nano 33 IoT board definition though, because it doesn’t define some of the pins that I want to use. Now I’m looking into PORT_PA00, etc. to address the ports directly.

1 Like

Very cool! Glad you could get it working. It looks like you milled the PCBs yourself? If that is the case that is awesome!

I do highly recommend you investigate PlatformIO, it will make developing for Arduinos a much calmer experience to say the least :sweat_smile:

Also, this could be nothing, but in that video it looked to me like the motors were cogging a bit? I don’t think that 3D printed arm was so heavy it would cause that. Would your input voltage happen to be lower than what you set it to be in SimpleFOC? Perhaps I am seeing things, or it is an artifact of your PID terms, but it looked to behave a little wonky to me. Maybe get a second opinion from @runger.

Nevertheless, cool project, glad to see you got it done in time, welcome to the FOC revolution!

This looks like a great result! :heart_eyes:

I’m thinking some class is very lucky to have this “tired teacher”, and will learn a lot while also having fun!

1 Like

I milled the PCBs. But not without breaking a 0.01" flat endmill! It is so fragile that everything really needs to be perfect (feeds, speeds, low runout etc.) in order to get any use out of it. In the subsequent attempt I used a V-bit instead to mill the pads for the DRV8313 and the SAMD21. That went well, and I’m proud of the results! I didn’t know you could solder such small IC pins with a soldering iron, but when it came to crunch time, I managed it!

On the cogging, that’s well spotted! The robot is powered by a 3A USB-C port. I realized a bit late that the DRV8313 driver shuts down below 8V, so I had to add a step-up converter to the circuit to convert the USB 5V into about 10V for the gimbal motors. I bought this one just in case I needed a quick voltage adjustment in my final project. I set the voltage in the step-up converter to 9.7V but forgot to change the default 12V value in the Arduino sketch accordingly. So that will be a quick fix! I wonder if there’s a motor driver that goes down to 5V that I could use instead of the DRV8313, so that I can get rid of the step-up converter.

I played around with the PID values for a bit but I’m really bad at tuning them. I probably need to take a look a the tuning guide. Do you know of any other good resources on PID tuning?

The DRV8316 can go down to 4.5V, but I haven’t seen one of those in stock for a long time. You can, of course, use discrete FETs at basically whatever voltage your heart desires.

You should change the SimpleFOC PSU voltage value so the FOC waveform is not clipped!

The tuning guide should be fine, PID tuning is something you get a feel for the more you… fail at it :sweat_smile: