How to Drive DC Motors with the X-NUCLEO-IHM12A1 Shield

Created by Jerry Sturre, last modified on Jun 02, 2017

Go to start of metadata

Parts list:

The STMicroelectronics Nucleo board is a great jumping-off point for anyone wanting to get started with ARM hardware, but it does take a bit of know-how to get everything working. In this example we will be using 497-14362-ND, which is based on the STM32F103RB 32-bit microcontroller with an ARM Cortex-M3 core, to drive up to two brushed DC motors. All Nucleo boards have a built-in ST-Link debugger/programmer, so no additional SWD or JTAG hardware is required – just a USB cable and a PC. The board also has Arduino Uno V3 headers in addition to the ST Morpho headers, allowing easy use of the many Arduino shields available.


Since the Nucleo board isn’t capable of driving DC motors directly, a motor driver is required. The X-NUCLEO-IHM12A1 (Figure 2) from STMicro mounts easily to the Nucleo board via the Arduino-type headers, while still giving access to all the ST Morpho extension pins (with the addition of spacing headers) making all the STM32 I/Os available. This expansion board is based on the STSPIN240 motor driver IC. It’s a two channel brushed DC motor driver, capable of voltages from 1.8V up to 10V output, providing a maximum current of 1.3A per channel. It includes overcurrent, overtemperature, and short circuit protection as well as allowing for a zero consumption state to significantly increases runtime while battery powered.


The Hardware

Begin by mounting the motor board to the Nucleo board. The preinstalled Arduino-type headers should mate securely together. Take care to align the pins correctly before firmly seating the boards.


The motor board has a green 6 position header for connecting up to two DC motors, along with VIN and Gnd. The header is labeled as such: GND, VIN, A+, A-, B-, and B+. Connect the positive from the power supply to the VIN contact, and the ground from the supply to GND. Keep in mind this is the power for the motors only, not the motor driver or Nucleo. The Nucleo will be powered by USB, and will in turn power the motor driver board circuitry.

The two wires from the motor will be connected to A+ and A- (or B+ and B-). Which wire you connect to A+ only matters if there is concern about the direction the motor turns (reversing the wires will reverse the rotation). Make sure the motor voltage rating is at or above the voltage provided by the power supply to avoid damaging the motor. The below image shows both boards, power supply, and one motor connected. To add an additional motor, simply wire it to the B+ and B- terminals.


That’s it! The hardware section is complete.

The Software

Programming the Nucleo can be done in a variety of IDEs, but in this case we will use both mbed and Keil µVision5. mbed is a free-to-use ARM developer site which allows the user to create and upload programs to ARM based microcontrollers quickly and easily through a web browser, no download needed. It has the advantages of being completely free, there are many libraries that can be imported right from the IDE, and each user has the ability to access their projects from any internet connected computer and can share these projects with others. This has to be balanced by the lack of debugging functions and working on a program is not possible without an internet connection. Exporting the program to µVision (or your preferred non-browser based IDE) will solve these problems. This article assumes some familiarity with mbed, but if not, there are tutorials available online.

This project will exclusively use the Arduino Uno R3 headers, but the pins on X-NUCLEO-IHM12A1 are hardwired to the control IC so not every pin is available for any function. The list of pins that must be assigned in code are:

  • D4 – B motor control (speed, PWM)
  • D5 – A motor control (speed, PWM)
  • D6 – A motor phase (direction, digital)
  • D7 – B motor phase (direction, digital)
  • A0 – Voltage reference pin (not being used as analog input)
  • D9 – Standby/Reset (digital, active-low)

D2 is labeled as the enable pin on the X-NUCLEO-IHM12A1 board. It is used by the overcurrent and over temperature protection circuitry to protect the device from these fault conditions. For normal operation, D2 should be configured as output LOW. If D2 is configured as output HIGH, the device will not recover from these fault conditions automatically and a reset will be required. If the user wishes to disable the motor driver, they should set D9 LOW to place the device in standby mode (this will also reset the device).

This simple code will make the motor spin clockwise for one second, slow to half speed and run in reverse for 1 second, and then repeat.

#include "mbed.h"                       //Include the mbed library     

PwmOut Motor(D5);                       //Pins A+ and A- are pwm'd by D5 on the board - cannot be changed

/*If adding a second motor, the B pins are hardwired to D4*/

DigitalOut motorPhase(D6);              //Pin to determine motor A direction - either a 1 or 0
/*B pin phase control is on pin D7*/

DigitalOut ref(A0);                     //Voltage reference pin
/*D2 is the enable pin on the X-NUCLEO-IHM12A1 board.  Do not connect anything to it.*/

int main() {         
    Motor.period_ms(1);                 //Setting up the period for pwm on one motor - 1 second    
    ref = 1;                            //Bring the reference pin to 5V              

    while(1) {        
        motorPhase = 0;                 //Motor spins clockwise, depending on wiring        
        Motor = 1.0;                    //Motor set to full speed        
        wait(1);                        //Wait one second        
        Motor = 0.5;                    //Motor set to 1/2 speed        
        motorPhase = 1;                 //Motor spins counterclockwise        
        wait(1);                        //Wait on seconed    

Changing the state of the phase pin will reverse the current flow through the motor, reversing its direction. The motor speed is variable and controlled by varying the motor voltage via PWM, using a decimal between 0.0 and 1.0 in code – if the PWM pin is set to 1.0, VIN is applied to the motor, setting it to 0.5 will apply VIN/2 to the motor, etc. In the example above, the motor is set to run at full and then ½ speed. The wait function is part of mbed.h and is measured in seconds – decimals can also be used for fractions of a second. The reference pin on the X-NUCLEO-IHM12A1 board (A0) is brought high to provide the STSPIN240 with the required reference input voltage (see section 6.3 of the STSPIN240 datasheet for more details), which it uses to determine the overcurrent conditions.

If the Nucleo board is plugged into the PC, the code can be uploaded and run on the board. This code can also be exported completely to Keil µVision for use in that program. This has the advantage of giving access to a full debugger and not being dependent on an internet connection to modify the code, while still having the ability to use mbed’s assortment of easy to use libraries.

To export the mbed code to Keil µVison, right click the program name in the Program Workspace menu on the left side of the mbed window. In the contextual menu that opens, select “Export Program”.


Once the “Export program” popup is on the screen, verify that the Export Target field lists the correct board, Export Toolchain is set to Keil µVision5 (or the appropriate IDE), and check the box marked “Export All Files”. Then click “Export”.

After a few seconds, an option to save will appear at the bottom of the window. Click the dropdown next to Save and choose Save As to export the file to a custom location. After the export is complete, simply extract the files to a new folder and then open the file type “µVision5 Project”, in this example is should be named motor_control (it should match the original program name). This should open a µVision project window with all the exported code and files originally created in mbed, allowing modification and debugging.

The series of Nucleo boards from STMicro are a great way to begin using ARM hardware. With a little setup, it can be almost as easy as using an Arduino but with the advantages of more I/Os, peripherals, and memory, and higher performance.