Introduction
-
IoT Brushless Motor Driver
SKU: ROB-22132
-
The SparkFun IoT Brushless Motor Driver is an all-in-one development platform. It includes all the components to create a simple IoT device or learn about control systems. On the boaard, users will find an ESP32 microcontroller, a TMC6300 motor driver, a gimbal motor, a TMAG5273 hall-effect sensor, three INA240A1 inline current sensors, an MCP6021T low-side current sensor, two user buttons, a Qwiic connector, a 3-pin JST connector (for the gimbal motor), and a WS2812 RGB LED.
The TMC6300 from ADI + Trinamic is a powerful and easy-to-use three-phase motor driver with up to 2A (1.4ARMS) of total drive current. Separate high-side and low-side control of the three half-bridges allows for incredible control of each phase of the motor commutation. We've found the Arduino Simple Field Oriented Control library to work well with the TMC6300 motor driver.
However, a field-oriented control (FOC) algorithm requires some feedback to close and optimize the control loop. Therefore, we integrated a TMAG5273 hall-effect sensor and INA240A1 current sensor amplifiers (both manufactured by Texas Instruments) into the design of the IoT motor driver board. This allows users to incorporate a position sensor and current sensing into the FOC algorithm or any feedback control loop they choose to implement.
Purchase from SparkFun
Required Materials
To get started, users will need a few items. Now some users may already have a few of these items, feel free to modify your cart accordingly.
- Computer with an operating system (OS) that is compatible with all the software installation requirements.
-
USB 3.1 Cable A to C - 3 Foot - Used to interface with the IoT Brushless Motor Driver (1)
- If your computer doesn't have a USB-A slot, then choose an appropriate cable or adapter.
-
SparkFun IoT Brushless Motor Driver (ESP32 WROOM, TMC6300) (1)
- The included gimbal motor requires a 6 to 8V power supply. However, for zero-load, low-speed testing, we have found the power from the USB connection to be sufficient.
Jumper Modification
To modify the jumper, users will need soldering equipment and/or a hobby knife.
New to jumper pads?
Check out our Jumper Pads and PCB Traces Tutorial for a quick introduction!
Suggested Reading
As a more sophisticated product, we will skip over the more fundamental tutorials (i.e. Ohm's Law and What is Electricity?). However, below are a few tutorials that may help users familiarize themselves with various aspects of the board.
-
How to Install CH340 Drivers
-
ESP32 Thing Plus (USB-C)
-
TMC6300 BLDC Motor Driver
-
Installing the Arduino IDE
-
Installing Board Definitions in the Arduino IDE
-
Installing an Arduino Library
-
Logic Levels
-
Pulse Width Modulation
-
Analog vs. Digital
-
I2C
-
SPI
-
Serial Communication
-
How to Solder: Through-Hole Soldering
-
How to Work with Jumper Pads and PCB Traces
-
Motors and Selecting the Right One
-
Alternating Current (AC) vs. Direct Current (DC)
Need to control a different type of motor?
This tutorial is primarily focused on utilizing the TMC6300 motor driver to control a 3-phase brushless DC (BLDC) motor. We would recommend users explore other products for these specific motors and actuators. Below, are additional product tutorials and resources for our other actuator and motor types:
Hardware Overview
Board Dimensions
The board dimensions are illustrated in the drawing below; the listed measurements are in inches.
Need more measurements?
For more information about the board's dimensions, users can download the eagle files for the board. These files can be opened in Eagle and additional measurements can be made with the dimensions tool.
Eagle - Free Download!
Eagle is a CAD program for electronics that is free to use for hobbyists and students. However, it does require an account registration to utilize the software.
Dimensions Tool
This video from Autodesk demonstrates how to utilize the dimensions tool in Eagle, to include additional measurements:
USB-C Connector
The USB connector is provided to power and program the board. For most users, it will be the primary programming interface for the ESP32 module on the IoT Motor Driver board.
Power
The IoT Motor Driver only requires 5V to power all of the board's components. The simplest method to power the board is through the USB-C connector. Alternatively, the 3V3
pin can be used to supply power to any of the components, except the motor driver.
Below, is a general summary of the power circuitry on the board:
3V3
- Provides a regulated 3.3V from the USB (5V) power to the board, excluding the TMC6300 motor driver.3V3_A
- Provides a regulated 3.3V from the USB (5V) power to only the TMC6300 motor driver.- The motor driver will not function without power from the USB connector.
- The 3.3V AP63357 LDO regulator can source up to 3.5A.
VUSB
- The voltage from the USB-C connector, usually 5V.- Power source for the entire board.
- Powers the two 3.3V voltage regulators (AP2112 and AP63357).
- Features reverse current protection and a thermal fuse.
MEAS
- These pins can be used to measure the current being drawn through the USB connector (see the Jumpers section).
- Power source for the entire board.
GND
- The common ground or the 0V reference for the voltage supplies.- Qwiic Connector - Provides a regulated 3.3V voltage to the Qwiic devices.
Info
For more details, users can reference the schematic and the datasheets of the individual components on the board.
Motor Voltage
The Gimbal Stabilizer Motor has an operating voltage range of 6 - 8V. However, we have found that it still functions properly with only 3.3V provided by the IoT Motor Driver board.
CH340 Serial-to-UART
The CH340 allows the ESP32-WROOM to communicate with a computer/host device through the board's USB-C connection. This allows the board to show up as a device on the serial (or COM) port of the computer. Users will need to install the latest drivers for the computer to recognize the board (see Software Overview section).
Microcontroller - ESP32-WROOM
The brains of the IoT Motor Driver, is an ESP32-WROOM module with 16MB of flash memory. Espressif's ESP32-WROOM module is a versatile, WiFi+BT+BLE MCU module that targets a wide variety of applications. At the core of this module is the ESP32-D0WDQ6 system on a chip (SoC) which is designed to be both scalable and adaptive microcontroller. Its laundry list of features include:
-
Features:
- Xtensa® Dual-Core 32-bit LX6 Microprocessor (up to 240MHz)
- 448KB ROM and 520KB SRAM
- 16MB of Embedded SPI Flash Storage
- Cryptographic Hardware Accelerators
- AES, SHA2, ECC, RSA-4096
- Integrated 802.11 b/g/n WiFi 2.4GHz Transceiver (up to 150Mbps)
- Integrated dual-mode Bluetooth (Bluetooth v4.2 and BLE)
- 26 GPIO (including strapping pins)
- 8x Capacitive Touch Electrodes
- Operating Voltage: 3.0 to 3.6V
- WiFi: 380mA (peak)
- Light-Sleep: 800µA
- Deep-Sleep: 10 - 150µA
- Xtensa® Dual-Core 32-bit LX6 Microprocessor (up to 240MHz)
Warning
Users should be aware of the following nuances and details of this board
- The ESP32-WROOM is only compatible with 2.4GHz WiFi networks; it will not work on the 5GHz bands.
- For details on the boot mode configuration, please refer to section 3.3 Strapping Pins of the ESP32-WROOM module datasheet.
Info
The ESP32-WROOM module has various power modes:
- Active - The chip radio is powered on. The chip can receive, transmit, or listen.
- Modem Sleep - The CPU is operational and the clock is configurable. The Wi-Fi/Bluetooth baseband and radio are disabled.
- Light Sleep - The CPU is paused. The RTC memory and RTC peripherals, as well as the ULP coprocessor are running.
- Deep Sleep - Only the RTC memory and RTC peripherals are powered on. The ULP coprocessor is functional.
- Hibernation - Only one RTC timer on the slow clock and certain RTC GPIOs are active.
- Off - Chip is powered off
For more information on the power management of the ESP32-WROOM module, pleaser refer to Section 3.7 and Tables: 8 and 17 of the ESP32 SoC Datasheet.
Debugging
For users interested in debugging their code, the JTAG pins are broken out on the board. However, the debugging feature is only available through the ESP-IDF.
TMS
:GPIO 14
TDI
:GPIO 12
TCK
:GPIO 13
TDO
:GPIO 15
Firmware Download Mode
Users can manually force the board into the serial bootloader with the BOOT button. Please, refer to the Boot Button section below for more information.
Peripherals and I/O
Warning
Users should be aware of the following nuances of this board
- ⚡ All the GPIO on the IoT Motor Driver are 3.3V pins.
- The I/O pins are not 5V-tolerant! To interface with higher voltage components, a logic level adapter is recommended.
- ⚡ There are electrical limitations to the amount of current that the ESP32-WROOM module can sink or source. For more details, check out the ESP32-WROOM module datasheet.
- There are some limitations to the ADC performance, see the Note from the ADC Characteristics section of the ESP32 SoC datasheet.
The ESP32-WROOM module has 26 multifunctional GPIO, of which, 16 I/O pins are used to interface with motor driver, sensors, and status LED on the board. Additionally, 13 I/O pins are broken out to PTH pins and the users buttons. All of the IoT Motor Driver pins have a .1" pitch spacing for headers.
While all of the GPIO pins are capable of functioning as digital I/O pins, various pins can have additional capabilities with the pin multiplexing feature of the ESP32 SoC. For more technical specifications on the I/O pins, please refer to the ESP32 SoC datasheet.
- 13x 12-bit analog to digital converter (ADC) channels
- 3x UARTs (only two are configured by default in the Arduino IDE, one UART is used for bootloading/debug)
- 3x SPI (only one is configured by default in the Arduino IDE)
- 2x I2C (only one is configured by default in the Arduino IDE)
- 2x I2S Audio
- 2x digital-to-analog converter (DAC) channels
- 16x 20-bit PWM outputs
- 8x Capacitive Touch Inputs
Info
Users should be aware of the following limitations for the board in the Arduino IDE.
- Not all of the features, listed above, are available in the Arduino IDE. For the full capabilities of the ESP32, the Espressif IDF should be utilized.
- Only one I2C bus is defined.
- Only two UART interfaces are available.
- UART (USB):
Serial
RX
/TX
Pins:Serial1
- UART (USB):
- Only one SPI bus is defined.
Peripheral Devices
This development board features several components operating together to create an IoT device. Their connections are shown in the diagram below and their operations are listed in the boxes below. For more details on each component, please refer to the sections below.
-
Inputs
- TMC6300 Motor Driver
- Diagnostic Pin
- TMAG5273 Hall-Effect Sensor
- INA240 Current-Sense Amplifier
- MCP6021 Operational Amplifier
- User Buttons
- TMC6300 Motor Driver
-
Outputs
- TMC6300 Motor Driver
- Half-Bridge Pins
- Standby Pin
- RGB Status LED
- TMC6300 Motor Driver
Pin Functionality
There are several pins that have special functionality in addition to general digital I/O. These pins and their additional functions are listed in the tabs below. For more technical specifications on the I/O pins, you can refer to the schematic, ESP32-WROOM module datasheet, ESP32 SoC datasheet, and documentation for the ESP32 Arduino core.
Any GPIO pin on the ESP32-WROOM module can function as a digital I/O (input or output). However, users will need to declare the pinMode()
(link) in the setup of their sketch (programs written in the Arduino IDE) to configure a pin as an input or an output.
-
Inputs
When configured properly, an input pin will be looking for a HIGH or LOW state. Input pins are High Impedance and takes very little current to move the input pin from one state to another.
DIAG
(TMC6300)GPIO 34
INT
(TMAG5273)GPIO 04
Button 13 GPIO 13
Button 14 GPIO 14
-
Outputs
When configured as an output the pin will be at a HIGH or LOW voltage. Output pins are Low Impedance: This means that they can provide a relatively substantial amount of current to other circuits.
VIO
(TMC6300)GPIO 05
WS2812 GPIO 02
Warning
⚡ There are electrical limitations to the amount of current that the ESP32-WROOM module can sink or source. For more details, check out the ESP32-WROOM module datasheet.
Tip
Pins cannot be configured to operate simultaneously as an input and output, without implementing the pin as an interrupt.
The ESP32-WROOM module provides a 12-bit ADC input on thirteen of its I/O pins. This functionality is accessed in the Arduino IDE using the analogRead(pin)
function. (The available ADC pins are highlighted in the image below.)
Current Sensor | INA240 (U ) |
INA240 (V ) |
INA240 (W ) |
MCP6021 |
---|---|---|---|---|
Analog Input | GPIO 35 |
GPIO 36 |
GPIO 39 |
GPIO 32 |
Info
By default, in the Arduino IDE, analogRead()
returns a 10-bit value. To change the resolution of the value returned by the analogRead()
function, use the analogReadResolution(bits)
function.
Tip
To learn more about analog vs. digital signals, check out this great tutorial.
The ESP32-WROOM module supports up to sixteen channels of 20-bit PWM (Pulse Width Modulation) outputs on any of its I/O pins. This is accessed in the Arduino IDE using the analogWrite(pin, value)
function. (Any I/O pin can be used for the PWM outputs; the available DAC pins, with true analog outputs, are highlighted in the image below.)
Motor Driver | UH |
UL |
VH |
VL |
WH |
WL |
---|---|---|---|---|---|---|
PWM Output | GPIO 16 |
GPIO 17 |
GPIO 18 |
GPIO 23 |
GPIO 19 |
GPIO 33 |
Info
By default, in the Arduino IDE, analogWrite()
accepts an 8-bit value. To change the resolution of the PWM signal for the analogWrite()
function, use the analogWriteResolution(bits)
function. (The PWM output is not a true analog signal.)
Tip
To learn more about pulse width modulation (PWM), check out this great tutorial.
The ESP32-WROOM module provides three UART ports. By default, the UART port for the USB connection (Serial
) and the labeled UART I/O pins on the board (Serial1
) can be accessed through the Arduino IDE using the serial communication class.
Info
By default, in the Arduino IDE, the
Serial
- UART (USB)Serial1
- Pins:RX
/TX
(GPIO 16
/GPIO 17
)
Note
- The
GPIO 16
andGPIO 17
pins ofSerial1
are already dedicated to theUH
/UL
half-bridge on the TMC63000 motor driver and are not broken out for users to access. - In order to utilize the serial communication on the strapping pins, users will need to create a custom serial port object and declare which pins to access.
Tip
We have noticed that with the ESP32 Arduino core, Serial.available()
does not operate instantaneously. This is due to an interrupt triggered by the UART, to empty the FIFO when the RX
pin is inactive for two byte periods:
- At 9600 baud,
hwAvailable
takes [number of bytes received
+ 2] x 1 ms = 11 ms before the UART indicates that data was received from:\r\nERROR\r\n
. - At 115200 baud,
hwAvailable
takes [number of bytes received
+ 2] x .087 ms = ~1 ms before the UART indicates that data was received from:\r\nERROR\r\n
.
For more information, please refer to this chatroom discussion.
The ESP32-WROOM module provides three SPI buses. By default, in the Arduino IDE, the SPI class is configured to utilize pins GPIO 18
(SCK), GPIO 19
(POCI), GPIO 23
(PICO). In order to utilize the other SPI ports or objects, users will need to create a custom SPI object and declare which pins to access.
Info
To comply with the latest OSHW design practices, we have adopted the new SPI signal nomenclature (SDO/SDI and PICO/POCI). The terms Master and Slave are now referred to as Controller and Peripheral. The MOSI
signal on a controller has been replaced with SDO
or PICO
. Please refer to this announcement on the decision to deprecate the MOSI/MISO terminology and transition to the SDO/SDI naming convention.
SCK | GPIO 18 (SCK ) |
---|---|
SDI or POCI | GPIO 19 (MISO ) |
SDO or PICO | GPIO 23 (MOSI ) |
CS | GPIO 5 (SS ) |
Note
- The
GPIO 18
,GPIO 19
, andGPIO 23
pins of theSPI
bus are already dedicated to theVH
/WH
/VL
MOSFETs on the TMC63000 motor driver and are not broken out for users to access. - The
CS
pin associated withGPIO 05
is also already dedicated to theSTBY
pin of the TMC63000 motor driver and is not broken out for users to access.
Tip
To learn more about the serial peripheral interface (SPI) protocol, check out this great tutorial.
The ESP32-WROOM module module can support up to two I2C buses. By default, in the Arduino IDE, the Wire class is configured to utilize pins GPIO 21
(SDA) and GPIO 22
(SCL). These pins share the same I2C bus with the Qwiic connector and TMAG5273 hall-effect sensor. In order to utilize the other I2C ports, users will need to create a custom Wire object and declare which pins to access.
-
I2C Pins
SCL GPIO 22
SDA GPIO 21
TMAG5273 I2C Address:
- 0x35 (Default) (7-bit)
- 0x6A (write)/0x6B (read)
Tip
To learn more about the inter-integrated circuit (I2C) protocol, check out this great tutorial.
Motor Driver - TMC6300
The TMC6300 from Trinamic Motion Control, part of Analog Devices, is a low voltage, 3-Phase BLDC/PMSM motor driver utilizing separate high-side and low-side control signals for its three half-bridges.
-
Features:
- VIN: 2.0V to 11.0V
- Operating current: 7mA
- Standby current: 30nA
- VOUT: 1.8V
- 3 Half-Bridges
- 3 High-side MOSFETs
- 3 Low-side MOSFETs
- I/O Supply Voltage Input
- Diagnostic Output
- Overtemperature Protection
- Shutdown Temperature: 150°C
- Typical Power Dissipation: 1W
- Short Protection
Info
For more details, please refer to the TMC6300 datasheet.
- VIN: 2.0V to 11.0V
-
For users unfamiliar with the TMC6300 motor driver, please check out our hookup guide below.
Half-Bridges
The TMC6300 features high-side and low-side MOSFET pairs of the three available half-bridges which control the commutation of the three motor phases.
The electronic commutation sequence for these MOSFETs will depend on the motor that is connected. For most cases, users will provide a PWM signal to each of these pins. These are active-high pins.
ESP32-WROOM | 16 |
17 |
18 |
23 |
19 |
33 |
---|---|---|---|---|---|---|
Motor Driver | UH |
UL |
VH |
VL |
WH |
WL |
Active High
By pulling the pin high, the MOSFET will enable power to flow through that section of the half-bridge.
With the electronic commutation sequence provided to the half-bridges, the output motor phases will drive a connected motor.
Motor Commutation
The TMC6300 relies on an electrical commutation sequence/signal to drive the motor phases to a BLDC or PMSM motor. The commutation signals for these motors are trapezoidal for BLDC motors and sinusoidal for PMSM motors.
Gimbal Motor
Based on measuring the output from one of the coils, our gimbal motor is a PMSM and would require a sinusoidal waveform to drive the motor. It should be noted that a trapezodial waveform can probably be used; however, users may notice effects such as cogging.
For a trapezoidal signal, the high-side (HS) and low-side (LS) MOSFETs, can just be driven high or low. However, in order to approximate a sinusoidal signal, a progressively varying PWM signal must be provided with all six signals in sync with each other.
VIO
/Standby Pin
In it's default configuration, the VIO
pin is used to enable the motor driver and set the logic level voltage of the TMC6300 inputs. However, the VIO
pin also operates as a standby pin when it is pulled LOW
. In standby, the TMC6300 resets and sits in standby mode.
Users can control the VIO
pin with GPIO 05
on the ESP32-WROOM module, to reset the TMC6300 or put it in standby mode.
Diagnostic Pin
The diagnostic pin is triggered based on different faults (i.e. shorts and overtemperature) detected by the IC. By default, the status will be indicated by the, green diagnostic, DIAG
LED and will remail LOW
until triggered. Once triggered, users will need to disable and reset the TMC6300 or power cycle the board.
Users can monitor the diagnostic pin with GPIO 34
on the ESP32-WROOM module, to determine if the TMC6300 need to be reset to clear a fault.
Current Sense Pin
The current sense pin is the foot point of the U
and V
half-bridges, with a 0.12Ω resistor attached. Users can measure the voltage across the resistor to determine the current flowing to the motor (see the Low-side Op Amp - MCP6021 section below).
Hall-Effect Sensor - TMAG5273
The TMAG5273 from Texas Instruments, is a 3-axis hall-effect sensor utilizing a 12-bit ADC. For more information, please refer to the TMAG5273 datasheet.
-
Features:
- I2C Address:
- 0x35 (Default) (7-bit)
- 0x6A (write)/0x6B (read)
- Magnetic Range (Sensitivity):
- ± 40mT (820 LSB/mT)
- ± 80mT (410 LSB/mT)
- Magnetic Drift: 5%
- Rotational Accuracy: ± 0.5°/360° rotation
- Voltage Range: 1.7 - 3.6V
- Sleep: 5nA
- Wake-Up/Sleep: 1µA
- Active: 2.3mA
- Operating Temperature: –40 - 125°C
- Integrated temperature compensation
- Configurable sample rate
- I2C Address:
-
Magnetic Axes
On the IoT Motor Driver, users will primarily be interested in magnetic field of the X-Y axes to measure the position of the gimbal motor.
Info
For more details, please refer to the TMAG5273 datasheet.
Interrupt Pin
The interrupt pin of the TMAG5723 can be configured in different modes to utilize either the INT
or SCL
pins.
- No interrupt
- Interrupt through
INT
- Interrupt through
INT
except when I2C busy - Interrupt through
SCL
- Interrupt through
SCL
except when I2C busy
Tip
We recommend utilizing the default INT
pin to trigger interrupts; as it is already connected to GPIO 04
of the ESP32-WROOM module.
Bus Contention
Texas Instruments does not recommend sharing the I2C bus with multiple devices when using the SCL
pin for the interrupt function. The SCL
interrupt can potentially corrupt the transactions with other devices, when present on the same I2C bus.
Note
The TMAG5273 is programmed to detect a magnetic threshold in wake-up or sleep mode. Once the magnetic threshold cross is detected, the device asserts a latched interrupt signal through the INT pin, and goes back to stand-by mode. The interrupt latch is cleared through the SCL
pin.
Current Sensors
There are two different types of Op Amps on the board to amplify the input voltage for the current measurements.
- The INA240 is used for the in-line current measurements between the TMC6300 and the gimabal motor.
- The MCP6021 is used on the low-side current measurement of the TMC63000's half-bridges.
Current Sensor | INA240 (U ) |
INA240 (V ) |
INA240 (W ) |
MCP6021 |
---|---|---|---|---|
Analog Input | GPIO 35 |
GPIO 36 |
GPIO 39 |
GPIO 32 |
Inline - INA240
The INA240 from Texas Instruments, is a voltage-output, current-sense amplifier. For more information, please refer to the INA240 datasheet.
-
Configured Gain 20 &PlusMn;0.2% Bandwidth 100kHz Voltage Range Range: 2.7 - 5.5V Quiescent Current 1.8 - 2.6mA Operating Temperature –40 - 125°C
Low-side Op Amp - MCP6021
The MCP6021 from Microchip Technology, Inc., is a rail-to-rail input and output operational amplifier. The chip . For more information, please refer to the MCP6021 datasheet.
-
Configured Gain 21 Bandwidth 10MHz Voltage Range Range: 2.5 - 5.5V Quiescent Current 0.5 - 1.35mA Operating Temperature –40 - 125°C
Status LEDs
There are five status LEDs on the TMC6300 motor driver:
PWR
- Power (Red)- Turns on once power is supplied through the USB-C connector
MPWR
- Power (Red)- Turns on once power is supplied through the USB-C connector
DIAG
- Diagnostics (Green)- Turns on to indicate a fault (see diagnostic pin section)
STBY
- Standby (Blue)- Turns on when the motor driver is enabled
- Turns off, when the IC has been reset and the motor driver is in standby mode
STAT
- User (RGB)- Controlled through
GPIO 02
- Controlled through
WS2812 RGB LED
The WS2812 RGB LED is controlled with a 24-bit (GRB) data signal. This indicator is connected to GPIO 02
and the digital output pin from the LED is available through a test point. For more information, please refer to the WS2812C datasheet.
Info
The latest ESP32 Arduino core, now provides a basic RGB LED driver for a WS2812 (or NeoPixel) LED populated the board. For an example of how to utilize the RGB LED driver check out the BlinkRGB example code, which can be accessed from the File drop down menu (i.e File > Examples > ESP32 > GPIO > BlinkRGB).
Buttons
There are four buttons on IoT Motor Driver: RST, BOOT, 13, and 14 buttons.
Factory Programming
The IoT Motor Driver board will come pre-programmed out of the bag. By default, the 13/14 buttons can be used to operate the motor:
- 13 - Start/Stop the motor's rotation
- 14 - Switch the direction that the motor is spinning
Reset Button
The RST (reset) button allows users to reset the program running on the ESP32-WROOM module without unplugging the board.
Boot Control
The BOOT button can be used to force the board into the serial bootloader. Holding down the BOOT button, while connecting the board to a computer through its USB-C connector or resetting the board will cause it to enter the Firmware Download mode. The board will remain in this mode until it power cycles (happens automatically after uploading new firmware) or the RST button is pressed.
- Hold the BOOT button down.
- Reset the MCU.
- While unpowered, connect the board to a computer with through the USB-C connection.
- While powered, press the RST button.
- Release the BOOT button.
- After programming is completed, reboot the MCU.
- Press the RST button.
- Power cycle the board.
Info
⚡ The BOOT button is also connected to GPIO 0
.
User Buttons
The 13 and 14 buttons are available for users to configure for their own purposes.
Factory Programming
The IoT Motor Driver board will come pre-programmed out of the bag. By default, these buttons can be used to operate the motor:
- 13 - Start/Stop the motor's rotation
- 14 - Switch the direction that the motor is spinning
Tip
When utilizing the buttons, users should enable the internal pull-up resistors for the GPIO pins.
Jumpers
Never modified a jumper before?
Check out our Jumper Pads and PCB Traces tutorial for a quick introduction!
There are nine jumpers on the back of the board that can be used to easily modify a hardware connections on the board.
- SHLD - This jumper can be used to disconnect the shield of the USB-C connector from
GND
. - MEAS - This jumper can be used to measure the current consumption of the board.
- BYP - This jumper can be used to bypass the thermal fuse.
- LED Jumpers
- PWR - This jumper can be used to remove power from the red, power LED on the AP2112 LDO regulator.
- MPWR - This jumper can be used to remove power from the red, power LED on the AP63357 LDO regulator.
- STBY - This jumper can be used to remove power from the blue, standby LED.
- DIAG - This jumper can be used to remove power from the green, diagnostic LED.
- INT - This jumper can be used to remove the pull-up resistor from the
INT
pin of the hall-effect sensor. - I2C - This jumper can be used to remove the pull-up resistors on the I2C bus.
Primary I2C Bus
The Qwiic connector and hall-effect sensor are attached to the primary I2C bus. The primary I2C bus for this board utilizes the pin connections, detailed in the table below:
Connection | VDD |
GND |
SCL |
SDA |
---|---|---|---|---|
Hall-Effect Sensor (TMAG5273) |
3V3 |
GND | GPIO 22 |
GPIO 21 |
Qwiic Connector | 3V3 |
GND | GPIO 22 |
GPIO 21 |
Qwiic Connector
A Qwiic connector is provided for users to seamlessly integrate with SparkFun's Qwiic Ecosystem. Otherwise, users can connect their I2C devices through the PTH pins broken out on the board.
What is Qwiic?
The Qwiic connect system is a solderless, polarized connection system that allows users to seamlessly daisy chain I2C boards together. Play the video below to learn more about the Qwiic connect system or click on the banner above to learn more about Qwiic products.
Features of the Qwiic System
Qwiic cables (4-pin JST) plug easily from development boards to sensors, shields, accessory boards and more, making easy work of setting up a new prototype.
There's no need to worry about accidentally swapping the SDA and SCL wires on your breadboard. The Qwiic connector is polarized so you know you’ll have it wired correctly every time, right from the start.
The PCB connector is part number SM04B-SRSS (Datasheet) or equivalent. The mating connector used on cables is part number SHR04V-S-B or an equivalent (1mm pitch, 4-pin JST connector).
It’s time to leverage the power of the I2C bus! Most Qwiic boards will have two or more connectors on them, allowing multiple devices to be connected.
Hardware Assembly
USB Programming
The USB connection is utilized for programming and serial communication. Users only need to plug their IoT Motor Driver into a computer using a USB-C cable.
Headers
New to soldering?
If you have never soldered before or need a quick refresher, check out our How to Solder: Through-Hole Soldering guide.
The pins for the IoT Motor Driver are broken out into 0.1"-spaced pins on the outer edges of the board. When selecting headers, be sure you are aware of the functionality you require.
Qwiic Devices
The Qwiic system allows users to effortlessly prototype with a Qwiic compatible I2C device without soldering. Users can attach any Qwiic compatible sensor or board, with just a Qwiic cable. (*The example below, is for demonstration purposes and is not pertinent to the board functionality or this tutorial.)
Software Overview
CH340 Driver
Users will need to install the appropriate driver for their computer to recognize the serial-to-UART chip on their board/adapter. Most of the latest operating systems will recognize the CH340C chip on the board and automatically install the required driver.
To manually install the CH340 driver on their computer, users can download it from the WCH website. For more information, check out our How to Install CH340 Drivers Tutorial.
Arduino IDE
Tip
For first-time users, who have never programmed before and are looking to use the Arduino IDE, we recommend beginning with the SparkFun Inventor's Kit (SIK), which is designed to help users get started programming with the Arduino IDE.
Most users may already be familiar with the Arduino IDE and its use. However, for those of you who have never heard the name Arduino before, feel free to check out the Arduino website. To get started with using the Arduino IDE, check out our tutorials below:
Install Board Definition
Install the latest ESP32 board definitions in the Arduino IDE.
Installing Board Definitions in the Arduino IDE
Info
For more instructions, users can follow this tutorial on Installing Additional Cores provided by Arduino. Users will also need the .json
file for the Espressif Arduino core:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
When selecting a board to program in the Arduino IDE, users should select the SparkFun ESP32 Thing Plus C from the Tools
drop-down menu (_i.e. Tools > Board > ESP32 Arduino > SparkFun ESP32 Thing Plus C). Alternatively, users can also select the ESP32 Dev Module; however, they may lose some pin assignments.
Arduino IDE 2.x.x - Alternative Method
In the newest version of the Arduino IDE 2.x
.x
, users can also select their board (green) and port (blue) from the Select Board & Port
dropdown menu (yellow).
SparkFun TMAG5273 Arduino Library
The SparkFun TMAG5273 Arduino Library can be installed from the library manager in the Arduino IDE.
Arduino IDE (v1.x.x)
In the Arduino IDE v1.x.x, the library manager will have the following appearance for the SimpleFOC library:
This library will be primarily used to interact with the TMAG5273 hall-effect sensor and return the rotation angle of the motor.
SimpleFOC Arduino Library
The Simple Field Oriented Control Library can be installed from the library manager in the Arduino IDE.
Arduino IDE (v1.x.x)
In the Arduino IDE v1.x.x, the library manager will have the following appearance for the SimpleFOC library:
This library utilizes a motor control scheme called field oriented control (FOC), which can utilize a feedback control loop to drive a motor with a higher power efficiency and precision characteristics, like evenly distributed torque control.
Info
For more details about the library, check out the online documentation.
Supported Hardware
For a detailed and up-to-date list of the hardware supported by this library, check out the library's documentation. The following are excerpts taken from the library's documentation page:
Arduino SimpleFOClibrary supports:
MCU | 2 PWM mode | 4 PWM mode | 3 PWM mode | 6 PWM mode | pwm frequency config |
---|---|---|---|---|---|
Arduino (8-bit) | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ (either 4kHz or 32kHz) |
Arduino DUE | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |
stm32 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
esp32 MCPWM | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
esp32 LEDC | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |
esp8266 | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |
samd21/51 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
teensy | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
Raspberry Pi Pico | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
Portenta H7 | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |
nRF52 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
From this table you can see that if you need the 6 PWM mode for your application you should avoid using Teensy and Arduino DUE boards for now.
Info
For more details, please refer to the SimpleFOC Arduino library documentation.
Arduino SimpleFOClibrary has a goal to support as many BLDC and stepper motor drivers as possible. Till this moment there are two kinds of motor drivers supported by this library:
- BLDC motor driver
- 3 PWM signals ( 3 phase )
- 6 PWM signals ( 3 phase )
Current Limitations
Before running any BLDC motor with the SimpleFOClibrary please make sure your hardware can handle the currents your motor requires.
The simplest way to do it is by checking the motor phase resistance R
. Either check the datasheet of your motor and search for the resistance value or measure it yourself using a multimeter. Then check the value of your power supply voltage V_dc
and once when you have the values you can find the maximum current I_max
value by calculating:
I_max
with the datasheet of your driver board. If the I_max
is too high you can lower the power supply voltage V_dc
in order prevent too high peaks of the current. If you are not able to change your power supply voltage you can limit the voltage set to motor in software.
NOTE
The equation above calculates the worst case maximum currentI_max
and in most cases calculatedI_max
is higher than the actual value. Maximum current depends both of the motor hardware such as winding configuration and the control algorithm.
Tip
While the TMC6300 isn't directly listed as part of the supported hardware for the SimpleFOC Arduino library, we have verified that is compatible with the library.
Info
For more details, please refer to the SimpleFOC Arduino library documentation.
Arduino SimpleFOClibrary supports two types of BLDC motors:
-
BLDC motors
-
3 phase (3 wire):
Gimbal Motors
Gimbal motors will work basically with any BLDC motor driver, but since the high-performance drivers have current measurement circuits optimized for high currents you will not have any benefit of using them. Therefore low-power BLDC motor drivers will have comparable performance as the expensive high-power, high-performance drivers for gimbal motors. What is in my opinion very cool! 😃 This was one of the main motivations to start developing SimpleFOCShield.
Some of the characteristics of Gimbal motors are:
- High torque on low velocities
- Very smooth operation
- Internal resistance >10Ω
- Currents up to 5A
Gimbal motors are very versatile and their main benefit is very smooth operation on low speeds and high torque. They can be used in may different applications everywhere from being a high-quality replacement for your stepper motor or DC servo motor to very smooth camera gimbals and many different robotics applications. One of very interesting use cases are student experiments, where BLDC motors provide a very high degree of control and dynamics, such examples are ball and plate, inverted pendulums, balancing robots and similar.
High-performance Motors
Gimbal motors are just a subset of all the BLDC motors there is. As suggested in previous chapters, when using high-torque ( currents > 5A), low-resistance (~1Ω) BLDC motors such as drone motors make sure your BLDC driver can support the currents necessary. SimpleFOClibrary has been tested with several high performance BLDC drivers (supported BLDC drivers list).
-
-
Stepper motors
- 2 phase (4 wire)
Current Limitations
Before running any BLDC motor with the SimpleFOClibrary please make sure your hardware can handle the currents your motor requires.
The simplest way to do it is by checking the motor phase resistance R
. Either check the datasheet of your motor and search for the resistance value or measure it yourself using a multimeter. Then check the value of your power supply voltage V_dc
and once when you have the values you can find the maximum current I_max
value by calculating:
I_max
with the datasheet of your driver board. If the I_max
is too high you can lower the power supply voltage V_dc
in order prevent too high peaks of the current. If you are not able to change your power supply voltage you can limit the voltage set to motor in software.
NOTE
The equation above calculates the worst case maximum currentI_max
and in most cases calculatedI_max
is higher than the actual value. Maximum current depends both of the motor hardware such as winding configuration and the control algorithm.
Info
For more details, please refer to the SimpleFOC Arduino library documentation.
6PWM Motor Driver
Users will need to utilize the BLDCDriver6PWM
class to provide the six PWM signals required for the TMC6300 motor driver.
BLDCDriver6PWM
-
This class provides an abstraction layer for most of the common BLDC drivers, which require six PWM signals. This method offers more control than a three PWM motor drivers, since each of the 6 half-bridges MOSFETs can be controlled independently.
To create the interface to the BLDC driver you need to specify the 6
PWM
pin numbers for each motor phase and optionallyenable
pin.// BLDCDriver6PWM( int phA_h, int phA_l, int phB_h, int phB_l, int phC_h, int phC_l, int en) // - phA_h, phA_l - A phase pwm pin high/low pair // - phB_h, phB_l - B phase pwm pin high/low pair // - phB_h, phC_l - C phase pwm pin high/low pair // - enable pin - (optional input) BLDCDriver6PWM driver = BLDCDriver6PWM(5,6, 9,10, 3,11, 8);
Microcontroller Considerations
Arduino UNO and all the atmega328 based boards have only 6 PWM pins and in order to use the
BLDCDrievr6PWM
we need to use all of them. Those are3
,5
,6
,9
,10
and11
. Furthermore in order for the algorithm to work well we need to use the PWM pins that belong to the same timer for each high/low side pair of each phase. So Atmega328 pins belonging to the timers are:TIM0
TIM1
TIM2
5
,6
9
,10
3
,11
Therefore it is important that
phA_h
andphA_l
belong to one timer,phB_h
andphB_l
to second timer andphC_h
andphC_l
to the last timer. If we decide that phaseA
belongs to the timerTIM0
we can setphA_h
either to pin5
or pin6
.Stm32 boards have two possible 6 PWM modes:
- Hardware 6 PWM mode
- Software 6 PWM mode
-
Hardware PWM
In hardware 6 PWM mode the user uses only one timer, usually Timer 1 for all the 6 PWM channels. Stm32 boards usually have at least one timer which has automatic complementary channels which avoids the need for a complicated channel inverting configuration. SimpleFOClibrary automatically enables this control mode if you provide the pins that support this interface to the constructor of the
BLDCDriver6PWM
class. For example, both STM32 Bluepill and STM32 Nucleo boards have this interface supported by pins:T1C1
T1C2
T1C3
T1C1N
T1C2N
T1C3N
PA8
PA9
PA10
PB13
PB14
PB15
Where
T1Cx
are the Timer 1 channels andT1CxN
are their complementary channels (inverted channels). Each pair ofT1Cx
andT1CxN
is used for one pair of the high/low PWM pins. The library will configure the necessary timers and registers if you provide these pins to the constrictor of theBLDCDriver6PWM
class. For example: -
Software PWM
If it is not possible to use the hardware 6 PWM mode with your board SimpleFOClibrary enables you to use any two channels of any of the timers as your high/low side PWM pair. Basically, the library will automatically configure the complementary channels on the provided low side pins. The only requirement for this code to work properly is exatcly the same as for the Arudino UNO, each phase high/low PWM pair needs to belong to the same timer. For example, if we take STM32 Nucleo F401RE board we can take for example:
Where// BLDCDriver6PWM( int phA_h, int phA_l, int phB_h, int phB_l, int phC_h, int phC_l, int en) BLDCDriver6PWM driver = BLDCDriver6PWM(7, 2, 6, 3, 5, 4);
T1C1
T1C3
T2C3
T2C2
T3C1
T3C2
7
2
6
3
5
4
On Bluepill we could use:
Where// BLDCDriver6PWM( int phA_h, int phA_l, int phB_h, int phB_l, int phC_h, int phC_l, int en) BLDCDriver6PWM driver = BLDCDriver6PWM(PA8, PA9, PB6, PB7, PB8, PB9);
T1C1
T1C2
T4C1
T4C2
T4C3
T4C4
PA8
PA9
PB6
PB7
PB8
PB9
ESP32 boards support
MCPWM
interface that is intended for this kind of applications. Each ESP32 board has two of theMCPWM
channels and can support two 6 PWM drivers. There is no pin specific requirements for the ESP32, each pin can be used in PWM mode. But please make sure not to use the pins that have predefined states on boot because this could result malfunction. You can find this information online easily, here is a YouTube video with more details.Info
For more details about the
BLDCDriver6PWM
class, check out the online documentation.
BLDC Motor
All BLDC motors are handled with the BLDCMotor
class.
BLDCMotor
-
This class implements the BLDC FOC algorithm, motion control loops, and monitoring.
To instantiate the BLDC motor we need to create an instance of the
BLDCMotor
class and provide it the number ofpole pairs
of the motor.// BLDCMotor(int pp, (optional R, KV)) // - pp - pole pair number // - R - phase resistance value - optional // - KV - motor KV rating [rpm/V] - optional BLDCMotor motor = BLDCMotor(11, 10.5, 120);
Motor Considerations
While, the datasheet for our gimbal motor, indicates that there are 8 pole pairs, we have found that the motor operates more smoothly if the
BLDCMotor
class is instantiated with 7 pole pairs instead.Info
For more details about the
BLDCMotor
class, check out the online documentation.
Position Sensor
In order to incorporate the TMAG5273 hall-effect sensor into the FOC algorithm, users will need to utilize the GenericSensor
class.
GenericSensor
-
This class allows users to link a custom position sensor (not already implemented in the SimpleFOC library) by incorporating a few functions into their sketch.
-
Implement two functions; one to initialize the TMAG5273 and another to read and return the sensor's current position.
-
Instantiate the
GenericSensor
class and initialize the class by providing it pointers to the two functions. -
There are two ways to use sensors implemented within the SimpleFOC library:
- As standalone position sensor
- In this configuration users would simply read the sensor's position, independently from incorporating the readings into the FOC algorithm.
-
Incorporate it as the motor position sensor for FOC algorithm
-
Initialize the sensor in the
setup()
loop: -
Link the sensor in the
setup()
loop:
-
- As standalone position sensor
-
Info
For more instructions on incorporating the GenericSensor
class, please refer to the SimpleFOC documentation.
In-line Current Sensing
In order to incorporate the current sensing into the FOC algorithm, users will need to utilize the InlineCurrentSense
class.
InlineCurrentSense
-
This class allows users to link a custom position sensor (not already implemented in the SimpleFOC library) by incorporating a few functions into their sketch.
-
Instantiate the
InlineCurrentSense
class and initialize the class by providing the hardware configuration.To instantiate the inline current sensor using the SimpleFOClibrary just create an instance of the class
InlineCurrentSense
. ```cpp // InlineCurrentSensor constructor // - shunt_resistor - shunt resistor value // - gain - current-sense op-amp gain // - phA - A phase adc pin // - phB - B phase adc pin // - phC - C phase adc pin (optional) InlineCurrentSense current_sense = InlineCurrentSense(0.01, 20, A0, A1, A2); -
Incorporate the current sensor into the FOC algorithm:
-
Initialize the sensor in the
setup()
loop:Once the current sense has been created it can be initialised. This
init()
function configures the ADC hardware for reading and finds the zero offsets of the ADC for each channel. ```cpp // init current sense current_sense.init(); -
Link the sensor to the motor driver in the
setup()
loop:To use the
InlineCurrentSense
with the FOC algorithm, first thing you'll need to do is to associate (link) your current sense with theBLDCDriver
: ```cpp // link current sense and driver current_sense.linkDriver(&driver); -
Link the sensor to the motor in the
setup()
loop:Once the driver is linked to the current sense, last step is to link the current sense with the
BLDCMotor
you wish to use it with: ```cpp // link motor and current sense motor.linkCurrentSense(¤t_sense);
It is very important that the the current sensing
init
function is called after theBLDCMotor
andBLDCDriver
init functions are called. Which will make sure that the driver is enabled when current sense calibration is taking place. Also, it is important that the current senseinit
function is called before starting the foc algorithm with theinitFOC
function.So the suggested code structure would be:
```cpp void loop(){ .... // driver init driver.init(); // link the driver to the current sense current_sense.linkDriver(&driver); .... // motor init motor.init(); .... // init current sense current_sense.init(); // link the current sense to the motor motor.linkCurrentSense(¤t_sense); ... // start the FOC motor.initFOC(); }
-
-
Info
For instructions on incorporating the InlineCurrentSense
class, please refer to the SimpleFOC documentation.
Example - BLDC
In this example, users will be utilizing the TMC6300 motor driver to spin the motor.
Example Code
After installing and setting up the Arduino IDE and the Simple FOC Arduino library, users will need to upload the following example code using the SparkFun ESP32 Thing Plus C board definition. This code can be copied or downloaded below:
BLDC.ino
Example Code
Example Code
// Open loop motor control example
#include <SimpleFOC.h>
// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(7);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver6PWM driver = BLDCDriver6PWM(5, 6, 9,10, 3, 11);
// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6, 8);
//target variable
float target_velocity = 6;
// // instantiate the commander
Commander command = Commander(Serial);
// void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }
// void doLimit(char* cmd) { command.scalar(&motor.voltage_limit, cmd); }
void setup() {
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 5;
// limit the maximal dc voltage the driver can set
// as a protection measure for the low-resistance motors
// this value is fixed on startup
driver.voltage_limit = 5;
// pwm frequency to be used [Hz]
// for atmega328 fixed to 32kHz
// esp32/stm32/teensy configurable
driver.pwm_frequency = 32000;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);
// limiting motor movements
// limit the voltage to be set to the motor
// start very low for high resistance motors
// current = voltage / resistance, so try to be well under 1Amp
motor.voltage_limit = 3; // [V]
// open loop control config
motor.controller = MotionControlType::velocity_openloop;
// init motor hardware
motor.init();
// add target command T
// command.add('T', doTarget, "target velocity");
// command.add('L', doLimit, "voltage limit");
Serial.begin(115200);
Serial.println("Motor ready!");
Serial.println("Set target velocity [rad/s]");
_delay(1000);
}
void loop() {
// open loop velocity movement
// using motor.voltage_limit and motor.velocity_limit
motor.move(target_velocity);
// user communication
command.run();
}
Running the Motor
By default, the motor should spin automatically. However, if users wish to control the speed of the motor, they can uncomment lines 21-22 and 56-57 of code and reprogram the board.
Code Changes Highlighted
Uncomment the following lines of code (21-22 and 56-57):
// Open loop motor control example
#include <SimpleFOC.h>
// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(7);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver6PWM driver = BLDCDriver6PWM(5, 6, 9,10, 3, 11);
// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6, 8);
//target variable
float target_velocity = 6;
// // instantiate the commander
Commander command = Commander(Serial);
// void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }
// void doLimit(char* cmd) { command.scalar(&motor.voltage_limit, cmd); }
void setup() {
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 5;
// limit the maximal dc voltage the driver can set
// as a protection measure for the low-resistance motors
// this value is fixed on startup
driver.voltage_limit = 5;
// pwm frequency to be used [Hz]
// for atmega328 fixed to 32kHz
// esp32/stm32/teensy configurable
driver.pwm_frequency = 32000;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);
// limiting motor movements
// limit the voltage to be set to the motor
// start very low for high resistance motors
// current = voltage / resistance, so try to be well under 1Amp
motor.voltage_limit = 3; // [V]
// open loop control config
motor.controller = MotionControlType::velocity_openloop;
// init motor hardware
motor.init();
// add target command T
// command.add('T', doTarget, "target velocity");
// command.add('L', doLimit, "voltage limit");
Serial.begin(115200);
Serial.println("Motor ready!");
Serial.println("Set target velocity [rad/s]");
_delay(1000);
}
void loop() {
// open loop velocity movement
// using motor.voltage_limit and motor.velocity_limit
motor.move(target_velocity);
// user communication
command.run();
}
In order to drive the motor, users will need to access the serial monitor and provide the commands necessary to drive the motor. A full list of the available commands can be found in the Simple FOC Arduino library documentation. However, only the T
and L
commands are enabled in the example code.
- Sending a
T
command will set the target motor velocity in rads/s- Example - Entering
T6
into the serial monitor, will set the target motor velocity to 6 radians/s.
- Example - Entering
- Sending a
L
command will set the voltage limit of the motor driver and in turn, the current limit (voltage_limit / motor_resistance)- Example - Entering
L5
into the serial monitor, will set the voltage limit to 5V and the current limit to .5A (5V/10Ω).
- Example - Entering
Baud Rate
The serial monitor baud rate should be configured to 115200bps
.
Example - FOC Algorithm
Example - Factory Reset
This example, allows users to reprogram their board with the same sketch that it comes pre-programmed with from SparkFun.
Example Code
After installing and setting up the Arduino IDE and the Simple FOC Arduino library, users will need to upload the following example code using the SparkFun ESP32 Thing Plus C board definition. This code can be copied or downloaded below:
IoT_MotorDriver.ino
Example Code
Example Code
/******************************************************************************
IoT Motor Driver Example
Written By:
Madison Chodikov
Eric Orosel
Company: SparkFun Electronics
Date: September 1 2023
This sketch is a stripped down version of the firmware that is preprogrammed
on the IoT Motor Driver. It is based on the open loop, velocity motor control
example from the SimpleFOC Arduino library.
This sketch will spin the motor based on the button inputs:
- Button 13: Starts/Stops the motor rotation
- Button 14: When spinning, switches the direction of rotation
===============================================================================
Products:
IoT Brushless Motor Driver: https://www.sparkfun.com/products/22132
Repository:
https://github.com/sparkfun/SparkFun_IoT_Brushless_Motor_Driver
===============================================================================
SparkFun code, firmware, and software is released under the MIT
License (http://opensource.org/licenses/MIT).
Distributed as-is; no warranty is given.
******************************************************************************/
#include <Wire.h>
#include <SimpleFOC.h> //http://librarymanager/All#Simple%20FOC
//GPIO
#define auxBtn2 13
#define auxBtn1 14
//driver
#define uh16 16
#define ul17 17
#define vh18 18
#define wh19 19
#define vl23 23
#define wl33 33
#define curSense 32
bool state = true;
//motor driver
BLDCMotor motor = BLDCMotor(7);
BLDCDriver6PWM driver = BLDCDriver6PWM(uh16, ul17, vh18, vl23, wh19, wl33, curSense);
float target_velocity = 0.0;
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }
void doLimit(char* cmd) { command.scalar(&motor.voltage_limit, cmd); }
//////////////////////motor demo stuff///////////////////////////
struct Button{
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
};
Button aux1 = {auxBtn1, 0, false};
Button aux2 = {auxBtn2, 0, false};
void IRAM_ATTR isr1(){
aux1.pressed = true;
target_velocity = target_velocity*(-1);
Serial.println("Changing directions.. ");
}
void IRAM_ATTR isr2(){
aux2.numberKeyPresses++;
aux2.pressed = true;
if((aux2.numberKeyPresses % 2) == 0)
{
target_velocity = 0;
Serial.println("Stopping motor.. ");
}
else
{
target_velocity = 5;
motor.enable();
Serial.println("Starting motor.. ");
}
}
void setup() {
//motor demo stuff
driver.voltage_power_supply = 3.3;
driver.pwm_frequency = 20000;
driver.voltage_limit = 4;
driver.init();
motor.linkDriver(&driver);
motor.voltage_limit = 4;
motor.controller = MotionControlType::velocity_openloop;
motor.init();
motor.disable();
pinMode(aux1.PIN, INPUT_PULLUP); // Sets pin 14 on the ESP32 as an interrupt
attachInterrupt(aux1.PIN, isr1, FALLING); // Triggers when aux1 is pulled to GND (button pressed)
pinMode(aux2.PIN, INPUT_PULLUP); // Sets pin 13 on the ESP32 as an interrupt
attachInterrupt(aux2.PIN, isr2, FALLING); // Triggers when aux2 is pulled to GND (button pressed)
delay(100);
Serial.begin(115200);
}
/////////////////////////////////////////////////////////////////////////
void loop() {
// Button Press ISR
if(aux1.pressed){
aux1.pressed = false;
}
// Turning motor on and off
if(aux2.pressed){
aux2.pressed = false;
}
// open loop velocity movement
// using motor.voltage_limit and motor.velocity_limit
// Basic motor movement
motor.move(target_velocity);
// user communication
command.run();
delay(5);
}
Running the Motor
By default, the motor should be disabled and spin freely. Users can utilize the user buttons 13 and 14 to control the motor.
- 13 - Starts and stops the motor spin
- 14 - Reverses the direction of the motor's rotation, when it is spinning
Motor Overheating
When the motor is stopped, the motor driver is still enabled. Therefore, current is still running through the stator coils and holding the motor in place. After a few minutes, users may notice that the motor begins to heat up a bit.
If this becomes an issue, users can modify their code to disable the motor driver when the motor stops. This will prevent the motor from heating up, but the motor will spin freely as the motor driver is no longer engaged.
Modification
Modify the sketch and insert motor.disable();
between lines 80
- 81
.
/******************************************************************************
IoT Motor Driver Example
Written By:
Madison Chodikov
Eric Orosel
Company: SparkFun Electronics
Date: September 1 2023
This sketch is a stripped down version of the firmware that is preprogrammed
on the IoT Motor Driver. It is based on the open loop, velocity motor control
example from the SimpleFOC Arduino library.
This sketch will spin the motor based on the button inputs:
- Button 13: Starts/Stops the motor rotation
- Button 14: When spinning, switches the direction of rotation
===============================================================================
Products:
IoT Brushless Motor Driver: https://www.sparkfun.com/products/22132
Repository:
https://github.com/sparkfun/SparkFun_IoT_Brushless_Motor_Driver
===============================================================================
SparkFun code, firmware, and software is released under the MIT
License (http://opensource.org/licenses/MIT).
Distributed as-is; no warranty is given.
******************************************************************************/
#include <Wire.h>
#include <SimpleFOC.h> //http://librarymanager/All#Simple%20FOC
//GPIO
#define auxBtn2 13
#define auxBtn1 14
//driver
#define uh16 16
#define ul17 17
#define vh18 18
#define wh19 19
#define vl23 23
#define wl33 33
#define curSense 32
bool state = true;
//motor driver
BLDCMotor motor = BLDCMotor(7);
BLDCDriver6PWM driver = BLDCDriver6PWM(uh16, ul17, vh18, vl23, wh19, wl33, curSense);
float target_velocity = 0.0;
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }
void doLimit(char* cmd) { command.scalar(&motor.voltage_limit, cmd); }
//////////////////////motor demo stuff///////////////////////////
struct Button{
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
};
Button aux1 = {auxBtn1, 0, false};
Button aux2 = {auxBtn2, 0, false};
void IRAM_ATTR isr1(){
aux1.pressed = true;
target_velocity = target_velocity*(-1);
Serial.println("Changing directions.. ");
}
void IRAM_ATTR isr2(){
aux2.numberKeyPresses++;
aux2.pressed = true;
if((aux2.numberKeyPresses % 2) == 0)
{
target_velocity = 0;
Serial.println("Stopping motor.. ");
}
else
{
target_velocity = 5;
motor.enable();
Serial.println("Starting motor.. ");
}
}
void setup() {
//motor demo stuff
driver.voltage_power_supply = 3.3;
driver.pwm_frequency = 20000;
driver.voltage_limit = 4;
driver.init();
motor.linkDriver(&driver);
motor.voltage_limit = 4;
motor.controller = MotionControlType::velocity_openloop;
motor.init();
motor.disable();
pinMode(aux1.PIN, INPUT_PULLUP); // Sets pin 14 on the ESP32 as an interrupt
attachInterrupt(aux1.PIN, isr1, FALLING); // Triggers when aux1 is pulled to GND (button pressed)
pinMode(aux2.PIN, INPUT_PULLUP); // Sets pin 13 on the ESP32 as an interrupt
attachInterrupt(aux2.PIN, isr2, FALLING); // Triggers when aux2 is pulled to GND (button pressed)
delay(100);
Serial.begin(115200);
}
/////////////////////////////////////////////////////////////////////////
void loop() {
// Button Press ISR
if(aux1.pressed){
aux1.pressed = false;
}
// Turning motor on and off
if(aux2.pressed){
aux2.pressed = false;
}
// open loop velocity movement
// using motor.voltage_limit and motor.velocity_limit
// Basic motor movement
motor.move(target_velocity);
// user communication
command.run();
delay(5);
}
Troubleshooting Tips
Need Help?
If you need technical assistance or more information on a product that is not working as you expected, we recommend heading on over to the SparkFun Technical Assistance page for some initial troubleshooting.
If you can't find what you need there, the SparkFun Forums is a great place to search product forums and ask questions.
Account Registration Required
If this is your first visit to our forum, you'll need to create a Forum Account to post questions.
ESP32 Compile Error
If users run into an error similar to, fatal error: soc/soc_caps.h: No such file or directory
, it may be due to an issue with the version of the ESP32 Arduino core that is installed in the Boards Manager. Users should make sure the have the latest version of the ESP32 Arduino core installed; or at least a version later than v2.0.1
.
Info
For more information, please reference this forum post for the Simple FOC Arduino library.
Resources:
Product Resources
- Product Page
- Component Documentation
- Design Files:
- Arduino Library:
- SFE Product Showcase
- Hardware Repo
Additional Resources
🏭 Manufacturer's Resources
Analog Devices + Trinamic also provides great resources for the TMC6300 motor driver:
Background Resources
Below, are several articles, application notes, and other technical resources on 3-phase motors and utilizing a field-oriented control (FOC) scheme:
- Microchip Technology
- Diodes Incorporated
- Monolithic Power Systems
- Texas Instruments
- Demystifying BLDC motor commutation: Trap, Sine, & FOC
- Sensored Field-Oriented Control of 3-Phase Permanent Magnet Synchronous Motors
- Sensorless Field-Oriented Control of 3-Phase Permanent Magnet Synchronous Motors
- Brushless-DC Motor Driver Considerations and Selection Guide
- High-Performance Brushless DC Motor Control
- Field-oriented control of permanent magnet synchronous motors
- Field-Oriented Control of Permanent Magnet Motors
- MATLAB
- Analog Devices + Trinamic
- Infineon Technologies
- ST Microelectronics