Actuator Electronic Design (v1)
Status: Current Project (Jun 2020)
Electronic Systems
Processor
The best choice at the time seemed to be the STM32F405. The F103 series I was semi-familiar with wasnt powerful enough so the next logical family was the F4 series. The F405RGT was the cheapest available IC on JLCPCB so I went with it. The F405RGT also has been quite popular in the STMduino community e.g. the Feather STM32F405 express [1]. Perhaps the F446 would have been a better choice since it is the IC STM uses on their dev boards for teaching purposes but I could not get it as cheaply as the F405 from JLCPCB.
The decision between F103 and F4 series was also because in the memory space for the USB and CAN bus peripherals are in the same location, meaning you could only use one peripheral.
STM32F405RGT IC pinout for the actuator driver.
FOC Firmware (work in progress)
In order to control the brushless motor at low speeds while maintaining max torque per amp, I would have to use field oriented control (FOC). My first idea was to look at the firmware Ben Katz developed however I did not understand much at all [2]. I would however use the same general structure as code mixed in with other sources such as the Arduino-FOC library [3].
I then switched to watching a series of lectures that Texas Instruments made called "Teaching Old Motors New Tricks". In addition to those lectures I have compiled several other great videos into a playlist embedded on the right. [4].
The current firmware block diagram can be seen below. I have yet to add features such as velocity control and an emulated EEPROM and other small features however the general gist should be visible.
My code can be found at: https://github.com/NL-AE/STM32-Actuator
My motor control playlist.
Block diagram of firmware.
20KHz PWM channels. Blue channel is used as a trigger to check when the TIM1 interrupt begins. Other three channels are centre aligned PWM.
The TIM1 interrupt is triggered in the middle of the three centre aligned PWM pulses. This simultaneously tells the ADCs to register a current reading.
This method prevents the ADCs from picking up ringing from the rising and falling edge of the PWM pulses.
Another benefit is it ensures then next PWM pulse can be correctly oriented immediately after performing the FOC algorithms.
MOSFETs and Drivers
Since the STM32F405 cannot directly drive the three phase inverter, a driver IC must be used. I firstly looked at Ben Katz's design which used an DRV8302 however I could not find any available. Looking around for an IC in the same family, I found the DRV8305 IC and decided to use it. My confidence was bolstered after seeing Paul Gould using it in his projects [5].
One issue with the DRV8503 is its max operating voltage of 45V. 45V is very close to the 42V max battery voltage I was using. Regenerative braking might bump the 42V over the 45V limit...
Encoder
To find a magnetic encoder, I firstly looked at what the Arduino community was using. Most posts/articles pointed to the AS5600 absolute encoder. Unfortunately for me to purchase one, it would cost around £8 off RS components and was not available on JLCPCB. I thus looked around what encoders they offered and eventually found the TLE5012B. It costed around £1.2, was a 16bit absolute encoder, used SPI, had an incremental interface and it was available for JLCPCB assembly!
I would later find out that it used Synchronous Serial Communication (SSC) instead of SPI. This was easily fixed by changing the STM32 SPI configuration to half-duplex master. The SSC communication even at 10MHz took around 3.2us to transmit the 16bit angle to the STM32 which was too long for the FOC algorithm, meaning I would have to use the incremental interface (IIF).
One other downside was that the IIF was only 12bit unless I wanted to do something fancy with both raising and falling edge detection on both phase A and B. This wasn't too much of an issue since 12 bits gives an angular resolution of 0.0879 degrees. Any additional accuracy wouldn't matter since the sin/cosine lookup tables would introduce much more error.
CAN Communications
Nothing special. I just chose the cheapest ICs from a reputable manufacturer (Texas Instruments) that was available for assembly on JLCPCB, was in large quantities of >1000, ran on 3.3V logic and could support 1Mbps mode.
V1 PCB Layout + Schematic
Used a 2 layer 1.0mm board. Honestly looking back I really should have used a 4 layer board due to the trouble I had routing the mosfet gate traces over ground planes. This board is certainly not winning any EMC awards.
The number of vias isn't really necessary either as well as the two fingers I made to fit inside an XT60 connector. Next version will fix that.
Top side of actuator driver board.
Bottom side of actuator driver board.
Actuator Driver v1.0. Many connections were moved and pin assignments changed from this schematic.
V2 PCB Layout + Schematic (work in progress)
Actuator Driver v2.0. Most up to date version.
Soldering and Testing
V1 Bodges and Fixes
As soon as the boards arrived, I noticed many errors in my pin mappings. This entailed many traces having to be jumped and cut out. This was caused mainly by my inexperience with STM32 and the hardware systems required for FOC to work.
My original layout used six PWM outputs from the STM32 to the DRV8305 IC however the STM32 timer PWM compare can only use four pins as a PWM output. A workaround would be to slave one timer to another and use the complementary switching option however I thought it would be much easier to physically switch the pins.
I had assigned ADC pins for convenient routing without fully understanding the triple simultaneous ADC function so some ADC pins had to be switched around.
It was only after the PCBs arrived that I discovered the SWO pin that essentially allows CubeIDE to open up an debug console and plot variables. Luckily for some reason I felt it necessary to assign the reset pin to the connector and switched the pin to the SWO line. Unfortunately in order to route the bodge, I had to use a wire that wrapped around from the top of the board to the bottom which was horrible for signal integrity. This board will sometimes output wrong characters and sometimes the read variables will jump to their maximum or minimums because one of their bits got flipped.
Bad signal integrity made my board start spitting chinese.
I also had not implemented a way to assign individual CAN bus addresses to the driver boards. This can easily be fixed in software however it is annoying to recompile for each board.
Removed a 10K resistor because I did not read the CAN transceiver IC datasheet properly.
Also forgot to connect the ground for the crystal to the main ground. It is internally connected however it isnt ideal since the ADC uses that particular ground pin as its VSS reference.
Soldering connectors and bottom side components.
5 assembled boards.
Fun short directly across the main power rails. Probably would have sorted itself if my PSU didnt have overcurrent protection.
I really should get a SMD resistor kit.
One strand of 30AWG wire for pin swapping.
Vertical USB plug makes for a good grounding post while debugging.
Actuator Driver v1.0 board with annotations as to pinswaps.
Simple FOC motor test.
V2 Bodges and Fixes (work in progress)
Sources, Links and Resources
[1] https://www.adafruit.com/product/4382
[2] https://github.com/bgkatz/motorcontrol
[3] https://github.com/simplefoc/Arduino-FOC
[4] https://www.youtube.com/playlist?list=PLpuqPap6opFNElsUjybB8aVintqmqmS0B
[5] https://hackaday.io/project/165217-brushless-actuator-arduino-compatible