Repository navigation
The ESCape32 Firmware
The Remora1 board has to be programmed with software in order for it to be able to operate. If you choose to make one for yourself, you'll need to understand how to obtain the correct software and program or "flash" the board. If you either obtain a Remora1 either from us or from a vendor, it'll already be flashed and ready to use.
The other term for this software is "firmware". The firmware comprises 2 components, namely:
- A bootloader - responsible for loading and starting the program that runs the eCom.
- The motor controller - responsible for starting and running the motor.
The firmware is open source software from a project called ESCape32.
If you want to flash the Remora1 or simply update the motor controller (or rather unlikely - the bootloader), you have a couple of different options. You'll need binary versions of the code that are created by compiling the original source code using a specific process to do that.
You can either obtain the binary files from this git repo, which are maintained in the bin directory.
Or, you can "git clone" the ESCape32 sources, and compile them yourself. To do that you'll need a computer running Linux, macOS or Windows with some additional software installed. There is a bit of complexity to set up the process and it's helpful to already have some software and programming skills to do this. But don't fear, we've explained all that below.
Alternatively - if you wanted something that's not supplied, you could hop on Discord and ask if someone would oblige and provide what you need.
There is a [binary directory called "bin"] in github in which you'll find ESCape32 binaries built specifically for the Remora1. There is a custom bootloader BOOT3_PA2_AUX_FAST_EXIT-rev2.bin and a couple of different firmware builds, named REMORA_*.bin.
You can download the sources of ESCape32 and build them yourself assuming you have a suitable machine on which to do so. We build ours on an Arch Linux laptop - it only takes a few seconds to do. There are other Linux distros. that'll work fine. We have also built them on Windows using Linux Subsystem for Windows (wsl) - the process for which is described below.
Note: the CMake is configured to use the gnu arm cross compiler and it assumes it's running on an Intel machine despite the binary targets being for an arm binary. I made a half hearted effort to try to get it to run on a Apple Silicon Mac without the cross compiler - but failed. I am told it can be run in a UTM virtual machine on macOS - but I haven't tried yet. If you have success doing this we'd like instructions - please file a defect and tell us how, or submit a pull request in git.
The Remora1 is programmed using the ESCape32 firmware. There are a number of good reasons for doing so, namely:
- Writing a brushless motor driver and getting it right, is difficult.
- The skills to do it are hard to find and acquire.
- It's open source.
- It's supported and maintained.
- There is a community and Arseny specifically created a Discord channel for slot-cars (yeah).
- It's lovely, readable code.
- We can't say enough good things about Arseny, its developer, who is helpful and supportive of our efforts.
- It's fully configurable from a command line and WiFi dongle so you do not need to compile custom binaries to make configuration changes - once it's flashed.
There are no code changes or patches to the ESCape32 firmware to run the Remora1. Although the ESCape32 build for it has a specific configuration as it does for other drone ESC's.
In comparison to a commercial drone ESC, the board has some additional features that are not normally found on other ESC's - like the reverse polarity protection, and low voltage operation - that are overkill for a drone ESC. Interestingly, it also supports a digital interface that could theoretically allow it to be used in combination with a controller.
In order to flash the board from scratch you need 2 binary files. Namely:
- The bootloader.
- The driver.
We have provided the bootloader binary and a couple of different builds of the driver. You only need to flash the Remora1 with an ESCape32 binary - once. Because the installed firmware can be updated with new firmware using the command line or the WiFi Link dongle. This is also the means by which you can change its operating parameters. Therefore it's a simple process if you want to try another binary with different compiled-in settings, or in future we advise updating to a newer release of the binary - just use the WiFi Link dongle and a browser.
In the bin directory you'll find the following binaries:
BOOT3_PA2_XF-rev2.bin
REMORA-rev11.bin
They are all built on Linux from the latest ESCape32 sources.
The following build options are used:
For the bootloader:
add_target(BOOT3_PA2_XF STM32F0 AT32F4 IO_PA2 IO_AUX FAST_EXIT)
For the firmware:
add_target(REMORA AT32F421 DEAD_TIME=0 COMP_MAP=123 ANALOG_PIN=6 ARM=0 VOLUME=0 INPUT_MODE=1 IO_AUX ANALOG_MIN=270 ANALOG_MAX=1440 FULL_DUTY DUTY_MIN=100 DUTY_MAX=100 DUTY_SPUP=25 DUTY_RAMP=0 DUTY_RATE=25) # 1.5 - 8V
The firmware build is more complex, there's an explanation below which describes the parameters, there is a complete description of all the build options on the ESCape32 WiKi.
All the binaries are built from sources for ESCape32 and have no software added DEAD_TIME, which introduces a slight delay in switching. Dead time is delegated to the hardware. If you wish to test with dead time (which we know is unnecessary) please build your own or ask us for a build with a specific setting.
Note: The firmware has NOT been compiled with the "ANALOG" option so that the board and ESCape32 can be configured either by connecting a computer serial interface, or a WiFi "dongle" to the signal pins.
You may connect a computer to the eCom and use the command line interface (CLI) on the ESCape32 WiKi., however it's much simpler to connect a WiFi Link dongle using the .6mm connector installed on the Remora1 board. Then use a Web browser to make configuration changes. The WiFi link is described on the github WiKi.
You can also obtain a "WiFi Link" board from Arseny and solder a connection to it, or you can buy a very inexpensive (~$5) ESP32 S2 board from Amazon or Ebay and flash a supplied image onto it. The only significant difference between the two is some additional protection circuitry on the WiFi Link board. To make the ESP32 S2 safe to use at higher voltages we have implemented an adapter board, the KiCad files for which are distributed too, if you want to make your own.
If you want to build and flash your own version of the firmware the best place to study the settings is here: https://github.com/neoxic/ESCape32/wiki/Configuration#settings
Include the ANALOG option if you DON'T want CLI access for configuration, however better just to enable it by leaving the option out.
You need to build 2 custom binaries, namely:
- A boot loader.
- A driver.
Setting these targets in the CMakeLists.txt will enable both CLI and Analog throttle:
In ESCape32/boot/CMakeLists.txt
add_target(BOOT3_PA2_XF STM32F0 AT32F4 IO_PA2 IO_AUX FAST_EXIT)
In ESCape32/CMakeLists.txt
add_target(REMORA AT32F421 DEAD_TIME=0 COMP_MAP=123 ANALOG_PIN=6 ARM=0 VOLUME=0 INPUT_MODE=1 IO_AUX ANALOG_MIN=200 ANALOG_MAX=2218 FULL_DUTY)
Do not alter the build string for the bootloader.
Do not alter the DEAD_TIME, COMP_MAP, ANALOG_PIN, ARM, VOLUME, INPUT_MODE, IO_AUX parameters for the firmware.
The ANALOG_MIN value sets the voltage below which the drag brake takes effect and where pulse width modulation duty cycle ramping take effect.
There will be a quadratic throttle curve when both voltage level and pwm duty cycle are applied. For example: motor voltage is 1/4 at 1/2 "throttle" voltage.
The drag brake determines the duty cycle of the energized phases when the analog voltage drops below ANALOG_MIN. In effect the phases act like a brake, how much of this is applied is determined by the duty drag setting.
The duty drag is set by default in the firmware to 0 and is an alterable parameter that can be set by means of the WiFi dongle or command line. It determines the percentage duty cycle of the drag brake that is applied when the voltage drops below ANALOG_MIN.
The calculated and measured voltage to which the circuit will operate down to is 1.16V. The calculated and measured starting voltage is 1.2VDC. These voltages are a result of adding the buck booster circuit to the board.
The ANALOG_MIN value that's compiled in to the distributed firmware is 200, corresponding to about 1.1VDC, hence there is no room for the drag brake to turn on and have an effect.
Therefore if it's important to be able to set the drag brake to something other than 0, it's necessary to compile the firmware with an ANALOG_MIN value of something higher than 200.
Calculating the ANALOG_MIN/MAX values:
- Let's assume the minimum input voltage is ~2.2VDC, and the maximum input voltage is 10VDC. This corresponds roughly at the low end to the smallest "useful" track voltage to get the motor running and where we want to start ramping up the duty cycle (dc), and below which we want to apply motor drag brakes. At the top end this is a track voltage at which we want to hit 100% duty cycle (we choose 10VDC not 12.4VDC say because often we run low voltage club race nights and still want 100% dc at this maximum voltage)
- A 10K/2.2K ohm voltage divider circuit on the back EMF of each pole is used to detect the voltages in the mcu. Using the formula r2/(r1+r2), we get a factor of 2.2/(10 + 2.2) = .180
- So 2.2VDC translates to 2.2 * .18 = 397mV, 10VDC translates to 10 * .18 = 1803mV on the voltage divider pin, so we'd set the following options:
ANALOG_MIN=397
ANALOG_MAX=1803
REMORA = name of the binary.
AT32F421 = specify the Artery F421 mcu.
DEAD_TIME = microseconds to wait in the firmware for the high/low side switching.
COMP_MAP = Comparator map. Maps the A/B/C (U/V/W) phase back emf signals to mcu pins PA0, PA4, PA5, namely 1, 2, 3,
ANALOG_MIN = the voltage at which the pwm duty cycle starts ramping up.
ANALOG_MAX = the voltage at which the duty cycle reaches 99%.
ANALOG_PIN - assign analog throttle to pin 6 on the AT32F421 MCU.
ARM=1.
VOLUME=0 turn off sounds - the board does not have sound :-)
INPUT_MODE=1 - Analog.
FREQ_MIN = lowest pwm frequency.
FREQ_MAX = highest pwm frequency.
DUTY_DRAG = duty cycle for braking, to enable say 70% dc, set this to 70.
IO_AUX = detect whether on not full duplex signal IO.
FULL_DUTY = enables access to 100% duty cycle.
The REMORA-REV1_0_198|368 binaries are built using the following target in the CMakeLists.txt file
add_target(REMORA AT32F421 DEAD_TIME=66 COMP_MAP=123 ANALOG_PIN=6 ARM=0 VOLUME=0 INPUT_MODE=1 IO_AUX ANALOG_MIN=200 ANALOG_MAX=2218 FULL_DUTY)
The ANALOG_MIN is set to a minimum voltage of about 1.1v, which is below the voltage the board theoretically powers up. You'll note that ANALOG_MIN and ANALOG_MAX need to be compiled in to the firmware and are not settable parameters.
If for example you want the eCom to always run at 100% duty cycle from its starting voltage with no ramp up in the duty cycle, then you need to attach a WiFi link dongle to set and save duty_min to 100, this is the first non-zero duty cycle. When throttle becomes non-zero (voltage above 1.1VDC in our case), it's applied after synchronization. If you wanted 100% throttle at every voltage, change throt_set=100. See https://github.com/neoxic/ESCape32/wiki/Settings#throt_set-0 Note: throt_set is the minimum throttle value in analog mode and it's what ANALOG_MIN translates to. When you set it to some non-zero value, you'll get that throttle value at ANALOG_MIN voltages and lower.
We usually run in analog mode set by INPUT_MODE=1. In digital mode, throt_set is just an initial value that the throttle is set to upon startup. If it's not changed (say, you have no input), it remains at that value. Hence you can get fixed throttle mode out of it.
In analog mode, it also serves as the minimum throttle value. Thus you can get two distinct modes - when you have zero-throttle and when you don't.
When you connect via a WiFi link and change the throttle using a slider control in the browser, it disables analog throttle. That is to make it possible to save settings.
Once a throttle value is established, duty_min and duty_max start playing a role mapping throttle [1...2000] to the duty cycle.
In analog mode, it also serves as the minimum throttle value. Thus you can get two distinct modes - when you have zero-throttle and when you don't.
Also note that DUTY_DRAG is defaulted to 0. Therefore if you want a specific brake setting you'll need to access the firmware through the WiFi link dongle and set it.
Normally you can't disable arming (arm=0) in analog mode (unless you build with ANALOG which disables that). This is because it becomes impossible to distinguish between digital high level and analog high level. But in with ANALOG_PIN overriding the default analog throttle pin (the same as the digital input pin), it becomes possible.
ANALOG_PIN forces the firmware to sample analog throttle values on a different pin. By default, it's the same pin, e.g. PA2 or PA6. However in our case, PA2 is digital input and PA6 is analog. Since they are separated, there's no aforementioned problem, hence no there is no restriction on arming.
The FULL_DUTY build option allows you to set DUTY_MIN to 100% so that you can run at full 100% duty at any input voltage (once the start-up is completed). If you then set DAMP=ON, TIMING=4, FREQ_MIN=24, FREQ_MAX=24 the increase in speed at a 5V supply, compared to firmware that is built without the FULL_DUTY opton, is about 0.3% higher.
If there is one downside to our design, it might be the choice of MCU. When prototyping the design we realized that it has a small start up delay which we think might be caused by memory copying. This article in HackaDay explains something about this issue for other chips. Search for "boot-up delay" to get to the piece. Artery chips are not the same, although it might be something similar.
The AT32F421 startup delay is measured at ~4.2ms.
After startup, there's a little bit of extra time needed to switch clock source, lock PLL, calibrate ADC, etc. For the STM32G071, it all stays within about 1ms altogether. On the other hand, it takes another extra ~1ms for the AT32F421. Not too bad, but since there's an inevitable extra 4.2ms boot delay, it all comes down to ~5.5ms that Richard witnessed in his analysis.
We chose the Artery F421 MCU because of its (low) cost and (high) speed so that we had a fast enough clock speed to commutate a 12 pole motor at very high rpm, say 180,000 rpm+. As motor technology matures we might need to revisit this decision and it's an obvious change to the design that should be fairly simple to make. If you do that, please contribute it back.
There are several parameters to the ESCape32 firmware that can be adjusted to alter motor function.
When a motor spins up, maximum duty cycle is limited at 10% by default before a full synchronized revolution is reached, i.e. 6 sync'ed commutations have commenced. This value can be overridden by the DUTY_SPUP build option. The maximum value is 25%. Please note that allowing even higher DUTY_SPUP values is possible, but generally it is dangerous as a stuck rotor will lead to instant motor overheating. Higher values also degrade smooth spinup most of the time because the motor tends to desync right away and stutters longer. Another option is FREQ_MIN which is 24kHz by default. Setting FREQ_MIN to 48 can help reduce current ripple.
The default acceleration ramp, DUTY_RATE value is 25 (conservative 2.5%/ms) which leads to 100/2.5=40ms from 0% to 100% throttle. This can be easily increased. The maximum value is 100, i.e. 10%/ms.
It's important that increased DUTY_SPUP has much less effect under load. In a real life situation, a motor with a relatively significant load simply can't reach maximum RPM in just 40ms. Increased acceleration ramping might speed it up a bit, but with a progressively diminishing effect, so care must be taken. On the other hand, too rapid a power increase often leads to desyncs in some bigger motors (not our case). That is why the default value of 2.5%/ms is somewhat conservative as a one size fits all value.
Why would you want to override DUTY_SPUP? Is it not alright for a motor to sync on moderate power? Why and how would you want to override DUTY_RATE? Is it not alright for a motor to reach its maximum RPM in 40ms (with no load)? If it's not, then what time is okay? 30ms, 20ms? Do the calculation and go from there.
This blog post is a good primer and might provide some more insight.
All motors and loads are different. You can't know beforehand, so you can't really have some bleeding edge values in the hope they will work with all motors and in all conditions. Hence, the default settings.
An ideal commutation should happen when the rotor is at 90 degrees to the field, so torque is maximized.
But in reality, this is barely feasible because a slight deviation, and you get a desync. Therefore timing is advanced so commutation delay is reduced. With more timing advance you get further and further away from the ideal 90 degrees between the rotor and the field.
The timing setting of n equates to: 3.75 x n degrees
The default is 4, or 15 degrees. The value can be set to between 1 and 7.
In testing, a 1105 10000Kv motor desyncs on 3S (S means the number of LiPo RC batteries in series. 2S is about 7.4VDC, 3S is about 11.1VDC, obviously this varies as a battery discharges) with the default settings. Increased timing helps get rid of desyncs, nothing else. The same 10000Kv motor with 22.5 degree timing (timing=6) instead of the default 15 degrees (timing=4).
set timing 6
set freq_min 48
set freq_max 96
set duty_rate 15
An alternative setting that can be used to limit power based on RPM is duty_ramp (not to be confused with duty_rate). Read the code :-)
You might witness timing effects in a car that won't leave the line smoothly on full power - it'll stutter and "cog". This might be because the motor is not under load because the wheels are spinning (!) due to too much torque from the motor - drone motors have a lot of torque - maybe too much. There are some technical articles ...
When a motor is driven using complementary PWM (so called damped mode) it's literally braking while running. In other words, its two energized phases are either connected to rail and ground (driving) or both connected to ground (braking).
When the duty cycle is close to 100%, the energized phases spend most of the time in the driving state (connected to opposite polarities) giving 0% braking. When duty cycle is close to 0%, the energized phases spend most of the time in the braking state (connected to ground) yielding a rough equivalent of 66% drag brake force. Deadtime obviously slightly reduces running brake by introducing an unconnected gap between transitions from driving to braking.
So with a drag brake setting of 75%, the transition from running brake to drag brake is quite smooth.
But if you need a more abrupt brake, higher than 75%, try setting it, it won't be smooth.
It you want to flash the the part yourself you'll need:
- a computer running Windows or Linux.
- a USB serial interface or "dongle" (different from the WiFi dongle to change the operating parameters) - we use the PWLINK2.. Do a search to find them. You can pck one up from EBay for about $12.
- connectors to connect the dongle to the board - we use spring loaded pin connectors (pictures and links to come). These probably come from Farnell in the UK.
- computer software to flash the board using the dongle - for Windows use Power Writer or the OpenOCD fork for Artery MCU's
To use the PWLINK2 you'll either need a Windows computer on which to run the Powerwriter software, or a Linux/macOS machine to run the OpenOCD software.
Power Writer PWLINK2 that has the capability to flash the Artery F421 MCU as well as several other types of MCU. The ESCape32 WiKi mentions the STLINK device however it's only useful for flashing STM MCU's and we are using the Artery. There is more information on the ESCape32 WiKi about flashing
To connect the PWLINK2 to the board we have some connectors that have very fine spring loaded pins on the ends to touch down on the single wire debug pads on the board (look at the picture in the test document in the docs directory to find these on the board). They are fiddly to use and I don't yet have a link to where to obtain them. If you find a link to buy them - please file a defect and tell us :-). Obviously a better flashing solution is needed.
Power Writer has options to flash a board that has existing software on it. If you are flashing for the first time and do not need to reset the option bytes OpenOCD is a good solution. The official OpenOCD fork for Artery MCU's is in github. I haven't tried using it yet therefore if you do please file a defect and provide some explicit instructions.
Since we built our prototype from an existing drone ESC we used Power Writer. You can obtain Power Writer from this link If you run it from Chrome it'll offer to translate from Chinese to English - useful I'd say.
Here's the process we used:
- Run the software, accept the "Yes" to run in admin mode to access the devices.
- Plug in the PWLINK2 dongle, and run driver installs and updates.
- If PowerWriter offers an update - accept the offer, and wait a bit until it provides the update.
- Click on the Writer Setting tab.
- In Chip Select:
- Click on MCU model:
- For the Artery - use the menus to select AT32F421x8
- Set the following:
Erase type: Don't erase
Interface level 3.3v
Speed: 10M hz
OptionByte: Factory=>Custom
Note: Don't change the Write function configuration - Hit the Save button at the top and save the configuration as a pkg file - it'll save you time later to reload this configuration instead of setting everything again next time you run the program. It asks for a password - (why?) ...
- In Communication configuration:
- Click on Refresh
- It'll update the Device dropdown - on my machine I see COM6 and COM7 - with the dongle on COM7
- Hit Connect - the log window on the right should show you that it has successfully connected to the PWLINK2 dongle
- Select the Option bytes tab
- Only if you are flashing an ESC/MCU for the first time, you need to disable the RDP read protection, otherwise it's not possible to update the firmware.
- Click on the RDP line and ensure it says read protection off
- Wire up the dongle to the "stab pins" (or connectors you are using to connect the dongle to the board - you could solder some wires on but ...) to connect the dongle to the swdio/clk pins.
- Connect a ground wire from the 2 dongle gnd pins to -ve on your power supply (psu).
- Connect the psu to the red/black of the eCom
- If the eCom has already been flashed with firmware, you might want to disconnect the motor from the eCom otherwise the motor might run when you turn power on. (not the case if you use the default firmware)
- Power on - give it about 8VDC (It will beep if it's a drone esc with a buzzer running Beliheli32)
- If it's running the ESCape32 default binaries - no beep.
- Note: If you are flashing the prototype (HAKRC) drone eCom and the shunt is in place on the HAKRC and it's running the default ESCape32 binary, you can connect a serial terminal to the white and black control cable of the esc - see the ESCap32 wiki. https://github.com/neoxic/ESCape32/wiki
- Load up the binaries into Powerwriter.
- Select the Program Memory tab
- Click on + Add firmware
- Locate the bootstrap binary - _BOOT3_FAST-rev2.bin - this is a custom build target and not a default binary - it's in the bin directory of this repo
- Accept the default memory location 08000000
- Click OK
- Again - click on + Add firmware
- Locate the motor commutator binary - _SLOTCAR_rev8.bin
- Give it the location 08001000 - there is a bug in Powerwriter that truncates a zero from the end of the address, just add it.
- Hit the checkmark Apply button
- You are now ready to flash
- Touch the SWD pins from the dongle on to the pads on the eCom.
- Just for good measure, go into the writer settings and hit disconnect/connect - check the log
- If this is a new mcu - select: Option byte
- Hit the "Write" button - this should disable the write protection on the mcu
- Select the Program Memory tab
- If this has already been flashed - you must first erase the current flash before writing the new flash
- With the swd pins connected, hit erase - it take about 2 secs
- Hit "Write" - again takes about 2 sec
- Power off the eCom
- Attach a motor
- Power on at say 4v - restraining the motor
- This is where it's useful to have a command line or a WiFi dongle attached to enable you to change any compiled-in settings ...
We debated whether or not to attach or supply connectors. The pragmatic solution was to just have connector holes drilled in the phase pads. Here's a link to help you if you want to use them.
Copyright © 2025. All rights reserved Adrian Blakey