FOC Brushless Actuator (Arduino-Compatible)

Ardunio-Compatible M0/Zero/SAMD21 running Actuator FOC OS with FET Driver, MOSFETs, Absolute Magnetic Encoder, USB and RS485 comms. ~$US50

Public Chat
Similar projects worth following
Ardunio-Compatible M0/Zero/SAMD21 (32bit) running Actuator Operating System paired with Brushless FET Driver, MOSFETs, Absolute Magnetic Encoder, EEPROM, dual voltage regulators, temperature, USB and RS485. 30V @ 30A ~$US50

Ardunio M0/Zero/SAMD21 running Actuator Operating System paired with Brushless FET Driver, MOSFETs, Absolute Magnetic Encoder, EEPROM, dual voltage regulators, temperature, USB and RS485. 30V @ 30A ~$US50


  • Brushless Motor Robotic Joints (with SEA)
  • Brushless Motor CNC axis controllers (closed loop)
  • Electric Skateboards motors

42mm square and 50mm round

Ardunio Actuator Operating System

  • Standard Ardunio Boot code (Reset x2 to enable)
  • Foreground 10kHz motor control task update rate
    • Field Oriented Controller (FOC)
    • SPI with DMA operation for on board Absolute Magnetic Encoder (motor position)
    • Optional Hall effect (motor position)
    • SPI with DMA operation for external Absolute Magnetic Encoder (1 or 2 daisy chain)
    • 6 phase centre aligned PWM motor control (registers/no libraries)
    • 6x ADC free running Sequential operation (no delay)
      • 3 Phase Motor Current Measurement
      • Mosfet Temperature
      • Battery Voltage
      • External Pot/Motor Temp
    • PID joint controller
  • low level interrupt foreground tasks
    • RS485/USB/UART communications
      • RS485 UART with IRQ packet receive and transmit
    • optional Step/Direction
  • Background Tasks
    • OLED I2C (standard Arduino Libraries)
    • Mosfet Driver configuration
    • EEPROM (standard Arduino Libraries)
    • User Functions

2- 8 Cell LiPo

  • 5V SM regulator
  • 3V3 Linear regulator from either LiPo or USB

6x 0.9mOhms 40V N-channel MOSFETS (

3x 1mOhms Sense Resistors with Kelvin Connections

3 Current Shunt Amplifiers

External connections for 

  • USB programming, configuration and control
  • Connectors for RS485 for daisy chain operation
  • Header for UART
  • I2C (OLED display)
  • Connectors for additional Absolute Magnetic Encoders (SPI) in Single or daisy chain configuration
  • Connector for Hall effect sensors
  • Analog/Digital input for potentiometer, motor temperature or Limit Switch
  • Connector for an Isolated USB board for communications in high noise environments.

    Population Options

    • External 24MHz Oscillator
    • Extra Power supply Caps
    • Extra Current Shunt smoothing caps
    • Remove RS485 and use TTL UART
    • MOSFET Heatsink and fan
    • 50V MOSFETS 2mOhms


    ino - 33.67 kB - 08/21/2019 at 16:35


    x-zip-compressed - 3.32 MB - 04/28/2019 at 15:39


    Adobe Portable Document Format - 1.01 MB - 04/28/2019 at 15:39


    • The motor is turning

      Paul Gould08/21/2019 at 16:42 0 comments
    • Actuator Operating System - Base Code

      Paul Gould08/03/2019 at 16:21 0 comments

      Arduino Code for SAMD21 Dev Breakout by Sparkfun

      Updated 2019-Aug-05

      Fixed DRV SPI CS; Added Test Points T0 & T1; Disabled Serial1

      Now on GIT

      Don't use the code below, it will always be out of date

      /* External Encoder SPI
       * Motor Driver Control/Onboard Encoder SPI
       * 3 Phase timer with deadband TCC0
       * Timer IRQ 10KHz Timer 5
       * I2C Diaplay
       * RS485 with time-out Timer 4(start of packet)
       * ADC sequential, free-running (6) and DMA and IRQ
       * SerialUSB is available
       * Serial1 is available but is currently used as test points T0 and T1
       * Joint Control -> PID -> Motor Control (FOC) -> Three Phase Output
      #include <SPI.h>
      #include "wiring_private.h" // pinPeripheral() function
      //  I2c OLED  ///////////////////////////////////////////////////////////
      #include "ssd1306.h" // library by Alexey Dynda
      char display_str[] = "1234567890";
      //  On-Board Encoder + Motor Driver and External Encoder /////////////////
      #define ENC_SPI_MISO 6 //29 D6 PA20 ser 5:2 SER
      #define ENC_SPI_SCK 7 // 30 D7 PA21 ser5:3 SER
      #define ENC_SPI_MOSI A5 //47 A5 PB02 ser5:0 ALT
      #define ENC_CS A0 //PA02
      #define ENC_CS_PORT_PIN PORT_PA02 // Fast Pin Switching REG_PORT_OUTSET0
      #define DRV_SPI_MISO MISO // 21 PA12 SER4:0 ALT
      #define DRV_SPI_SCK SCK // 20 PB11 SER4:3 ALT
      #define DRV_SPI_MOSI MOSI //19 PB10 SER4:2 ALT
      #define DRV_CS 30 // PB22
      #define DRV_CS_PORT_PIN PORT_PB22 // Fast Pin Switching USE REG_PORT_OUTSET1
      uint16_t enc_data, drv_data; 
      //  Three Phase Center Aligned PWM with Dead-band //////////////////
      #define UH 3   //W1 14 PA09
      #define UL 5   //W5 24 PA15
      #define VH 10  //W2 27 PA18
      #define VL 11  //W6 25 PA16
      #define WH 12  //W3 28 PA19 
      #define WL 13  //W7 26 PA17
      //  RS485 Serial with Direction CTRL /////////////////////////////
      #define RS485_TX_SIZE 16
      #define RS485_RX_SIZE 32
      char RS485_txbuf[RS485_TX_SIZE];
      char RS485_rxbuf[RS485_RX_SIZE];
      #define RS485_RX_MAX 4
      #define RS485_TX_PACKET_SIZE 4
      #define UART_ERROR 0x80
      #define TX_COMPLETE 0x02
      #define RX_CHAR 0x04
      char RS485_tx_to_send=0;
      char RS485_tx_left=0;
      char RS485_rx_cnt=0;
      uint8_t i=0;
      #define RS485_RX 38 //PA13 ser2:1 ALT
      #define RS485_TX 4 //PA08 ser2:0 ALT
      #define RS485_DIR 2
      Uart Serial2 (&sercom2, RS485_RX, RS485_TX, SERCOM_RX_PAD_1, UART_TX_PAD_0);
      //  TC4 serial time-out //////////////////////////////////////////
      #define TC4_INTERRUPT 0 //Disable Interrupt 
      //  ADC DMA sequential free running (6) with Interrupts /////////////////
      #define ADCPIN1 A1
      #define ADC_Number 6
      #define HWORDS 7
      uint16_t adcbuf[HWORDS];     
      typedef struct {
          uint16_t btctrl;
          uint16_t btcnt;
          uint32_t srcaddr;
          uint32_t dstaddr;
          uint32_t descaddr;
      } dmacdescriptor ;
      volatile dmacdescriptor wrb[12] __attribute__ ((aligned (16)));
      dmacdescriptor descriptor_section[12] __attribute__ ((aligned (16)));
      dmacdescriptor descriptor __attribute__ ((aligned (16)));
      DmacDescriptor *desc; // DMA descriptor address (so we can change contents)
      static uint32_t ADC_DMA_chnl = 3;  // DMA channel
      /////          BLDC       //////////////////////////////////////////////////////////////////////////////////////
      int count;
      #define SIN_ARRAY_SIZE_BITS 12
      #define MOTOR_POLE_PAIRS    7
      #define FULL_ANGLE 360.0
      #define DEG_RAD (3.1415/180.0)
      #define FULL_PWM_BITS 10
      #define FULL_PWM (1<<FULL_PWM_BITS)
      #define POS_ONE 0
      #define MAGNET_OFFSET -100 //0
      #define PHASE_OFFSET 120
      #define MAX_PWM 250
      /* Store in EEPROM
      #define CONFIG_ARRAY_SIZE 32
      int32 config_array[CONFIG_ARRAY_SIZE];
      #define ID_OS           0
      #define MAG_OFFSET_OS   1
      #define PHASE_OFFSET_OS 2
      #define TEMP_MAX_OS     3
      #define NOMINAL_OS      4
      #define NINETY_OS       5
      int current_config = 0;
      Read more »

    • Software tasks

      Paul Gould04/30/2019 at 16:44 0 comments

      Low Level SAMD21 / Arduino functions with no libraries*

      1. Main OS timer - 100us (10KHz) IRQ                                                 (done)
      2. 3-Phase Motor Controller PWM with deadband                            (done)
        • (6-centre aligned pwms)                                                           (done)
      3. ADC- 6 channels sequential, semi-free-running DMA with IRQ     (done)
        • 3x Current Sensor
        • MOSFET Temperature Sensor
        • Battery Voltage
        • 1 Auxillary Analog Inputs
      4. Dual (same time) SPI (blocking and IRQ)                                             (done
      5. RS485 UART with IRQ (TX & RX)                                                        (done)
        1. with direction CTRL                                                                       (done)
        2. with time-out and packet start detect                                           (done)
      6. UART with DMA                                                                                  (attempted fail)
      7. CPU's Internal EEPROM Emulation (Flash storage)                            (attempted & fail)
      8. External I2C EEPROM support (maybe Libraries)                             (not started, have eeprom)
      9. I2C OLED support (with Libraries)                                                     (done)
      10. SerialUSB with above                                                                         (done)
      11. Serial1 with above                                                                              (done)
      12. Making all the Low level features work together                         (done, done and done)

      High Level Functions

      1. Field Orientated Control (FOC) & Motor Commutation                    (done)
      2. PID Joint Control                                                                                 (done, but just P)
      3. RS485 Packet Structure                                 ...
      Read more »

    View all 3 project logs

    Enjoy this project?



    Javier Laserna wrote 10/02/2019 at 22:44 point

    I’m building it but I have a doubt about what type of package is the SAMD21. In the pdf I see ATSAMD21G18A-AU but for solder on the PCB it doesn’t fit. Maybe it would be ATSAMD21G18A-MUT?

      Are you sure? yes | no

    Paul Gould wrote 10/03/2019 at 14:57 point

    I'm still changing the design of the PCB, the SAMD21 has a lot of pin mapping limitations. Getting all the SERCOM and timer pins correct is a nightmare. I haven't ordered any parts or PCBs yet, so I'm yet to check the BOM.

      Are you sure? yes | no

    Andrey V wrote 09/03/2019 at 06:55 point

    It's interesting for DIY slow speed applications. But you will have some problems with high RPM motors. Modern FOC devices have slightly different design and able to work with up to 100 000RPM motors. Pay attention on TMC6130 IC it costs only around 3$, but module with it costs 150+$. Just the idea) 

      Are you sure? yes | no

    Paul Gould wrote 09/03/2019 at 13:30 point

    This is definitely not a "high end" controller but I'm hoping it will be an ok substitute. The motors I plan to use will max out at 5000RPM and I really only need good control at ~0RPM / holding torque. I've search for a lot of FET drivers and I think that the DRV8323RS is the best "cost per features" there is. 

      Are you sure? yes | no

    bb-bit wrote 09/02/2019 at 05:03 point


      Are you sure? yes | no

    Paul Gould wrote 08/30/2019 at 13:18 point

    You maybe able to use those modules to make closed loop brushless controller, I'm just not sure how. 

    You may not have complete control over the FETs (only HALL and Speed/dir inputs) and I guess they would get hot at 500W. The Ron might be high.

    STM uC doesn't run the Arduino system but they should be able to run the ODRIVE code.

    I use an absolute magnetic encoder to find the motor position and get FOC control.

      Are you sure? yes | no

    florianrutsch wrote 06/16/2019 at 13:00 point

    Really cool, promising project! Hope it all works out, cheers!!

      Are you sure? yes | no

    Similar Projects

    Does this project spark your interest?

    Become a member to follow this project and never miss any updates