Example application for X-NUCLEO-IHM07M1 board connected to a 3-phase brushless motor with Hall sensors.

Dependencies:   BLDCmotorDriver RateLimiter mbed

Fork of HelloWorld_IHM07M1 by Antonio Vilei

Getting Started with X-NUCLEO-IHM07M1

This example demonstrates how to use the X-NUCLEO-IHM07M1 component with one of the STM32 Nucleo-64 platforms and a three-phase brushless DC (BLDC) motor with Hall sensors.

HW Prerequisites

  • X-NUCLEO-IHM07M1
  • STM32 Nucleo-64 board
  • external DC power supply
  • low voltage three-phase BLDC motor with Hall sensors

X-NUCLEO-IHM07M1 Jumpers Configuration

/media/uploads/avilei/x-nucleo-ihm07m1_jumpers.jpg
Configure the jumpers of your X-NUCLEO-IHM07M1 board as shown below:

  • JP1 open
  • JP2 open
  • JP3 closed
  • J9 closed
  • J5 closed on 2-3 (single shunt)
  • J6 closed on 2-3 (single shunt)
  • J7 open

For more details please refer to the X-NUCLEO-IHM07M1 user manual.

BLDCmotorDriver Library

This example is based on the BLDCmotorDriver motor control library by the TVZ Mechatronics Team, University of Applied Sciences Zagreb, Professional Study in Mechatronics. The BLDCmotorDriver library is a simple implementation of the six-step algorithm and needs Hall sensors to estimate the correct timing for commutation. If you want to use sensor-less BLDC motors with X-NUCLEO-IHM07M1 or if you want an optimized implementation, you must use a different software package like X-CUBE-SPN7, based on STM32Cube.

The HelloWorld_IHM07M1 application has been tested with the Nanotec DF45M024053-A2 motor, a 24V three-phase brushless motor with Hall sensors. This example implements a temperature check to prevent overheating.
If you use a different motor, please be advised that you may need to tweak the configuration parameters for the BLDCmotorDriver library.

Connecting the Motor

/media/uploads/avilei/wirings.jpg
In the picture above you can see an example setup with the Nanotec DF45M024053-A2 motor and a 24V power supply. If you use the same motor, please connect the brown, grey and yellow phases to the OUT1, OUT2 and OUT3 connectors of the X-NUCLEO-IHM07M1 board respectively. Then connect the blue, green, white, red and black wires for the Hall sensors to the A+/H1, B+/H2, Z+/H3, 5V, GND connectors as shown in the picture. If your motor is different, you must pay attention to connect the motor phases and Hall sensors pins in the correct order otherwise the motor won't spin.

Spinning the Motor

Open a terminal window (baudrate 9600, 8N1) to display the user interface of the HelloWorld_IHM07M1 application.
Press the 'w' character to start spinning the motor and speed it up; press the 's' character to slow it down and turn it off.
/media/uploads/avilei/terminal.png

Note

You need a terminal emulator installed on your PC to perform serial communications with your STM32 Nucleo platform. If you do not have it, please download and install one of the following terminal emulation programs:

Committer:
avilei
Date:
Thu Oct 20 14:44:40 2016 +0000
Revision:
12:33614e1dc638
Parent:
11:0120619cdfb7
Improve comments

Who changed what in which revision?

UserRevisionLine numberNew contents of line
avilei 2:4ae769d0b112 1 /* mbed Microcontroller Library
avilei 2:4ae769d0b112 2 * Copyright (c) 2006-2016 ARM Limited
avilei 2:4ae769d0b112 3 *
avilei 2:4ae769d0b112 4 * Licensed under the Apache License, Version 2.0 (the "License");
avilei 2:4ae769d0b112 5 * you may not use this file except in compliance with the License.
avilei 2:4ae769d0b112 6 * You may obtain a copy of the License at
avilei 2:4ae769d0b112 7 *
avilei 2:4ae769d0b112 8 * http://www.apache.org/licenses/LICENSE-2.0
avilei 2:4ae769d0b112 9 *
avilei 2:4ae769d0b112 10 * Unless required by applicable law or agreed to in writing, software
avilei 2:4ae769d0b112 11 * distributed under the License is distributed on an "AS IS" BASIS,
avilei 2:4ae769d0b112 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
avilei 2:4ae769d0b112 13 * See the License for the specific language governing permissions and
avilei 2:4ae769d0b112 14 * limitations under the License.
avilei 2:4ae769d0b112 15 */
avilei 2:4ae769d0b112 16
avilei 2:4ae769d0b112 17 /**
avilei 2:4ae769d0b112 18 ******************************************************************************
avilei 2:4ae769d0b112 19 * @file SPN7Driver.cpp
avilei 2:4ae769d0b112 20 * @author STMicroelectronics
avilei 2:4ae769d0b112 21 * @brief Implementation of SPN7Driver class
avilei 2:4ae769d0b112 22 ******************************************************************************
avilei 2:4ae769d0b112 23 * @copy
avilei 2:4ae769d0b112 24 *
avilei 2:4ae769d0b112 25 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
avilei 2:4ae769d0b112 26 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
avilei 2:4ae769d0b112 27 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
avilei 2:4ae769d0b112 28 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
avilei 2:4ae769d0b112 29 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
avilei 2:4ae769d0b112 30 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
avilei 2:4ae769d0b112 31 *
avilei 2:4ae769d0b112 32 * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
avilei 2:4ae769d0b112 33 */
avilei 2:4ae769d0b112 34
avilei 7:022c306baeb9 35 // This example is based on the BLDCmotorDriver motor control library
avilei 7:022c306baeb9 36 // by the TVZ Mechatronics Team, University of Applied Sciences Zagreb,
avilei 7:022c306baeb9 37 // Professional Study in Mechatronics:
avilei 7:022c306baeb9 38 // https://developer.mbed.org/teams/TVZ-Mechatronics-Team/code/BLDCmotorDriver/
avilei 7:022c306baeb9 39
avilei 2:4ae769d0b112 40 #include "mbed.h"
avilei 2:4ae769d0b112 41 #include "SPN7Driver.h"
avilei 2:4ae769d0b112 42
avilei 3:4c71d3475814 43 typedef enum {
avilei 3:4c71d3475814 44 ST_BLDC_LOW = 0,
avilei 3:4c71d3475814 45 ST_BLDC_HIGH,
avilei 3:4c71d3475814 46 ST_BLDC_OFF
avilei 3:4c71d3475814 47 } st_bldc_status_t;
avilei 3:4c71d3475814 48
avilei 6:0eec4b6e94ba 49 /**************************************************************************/
avilei 6:0eec4b6e94ba 50 /**
avilei 6:0eec4b6e94ba 51 @brief Constructor
avilei 6:0eec4b6e94ba 52 * @param pIN1 Logic input pin IN1 of L6230 chip
avilei 6:0eec4b6e94ba 53 * @param pIN2 Logic input pin IN2 of L6230 chip
avilei 6:0eec4b6e94ba 54 * @param pIN3 Logic input pin IN3 of L6230 chip
avilei 6:0eec4b6e94ba 55 * @param pEN1 Enable channel pin EN1 of L6230 chip
avilei 6:0eec4b6e94ba 56 * @param pEN2 Enable channel pin EN2 of L6230 chip
avilei 6:0eec4b6e94ba 57 * @param pEN3 Enable channel pin EN3 of L6230 chip
avilei 6:0eec4b6e94ba 58 * @param pH1 Hall sensor pin for phase #1 (A) of X-NUCLEO-IHM07M1
avilei 6:0eec4b6e94ba 59 * @param pH2 Hall sensor pin for phase #2 (B) of X-NUCLEO-IHM07M1
avilei 6:0eec4b6e94ba 60 * @param pH3 Hall sensor pin for phase #3 (Z) of X-NUCLEO-IHM07M1
avilei 6:0eec4b6e94ba 61 * @param pFault Fault LED pin of X-NUCLEO-IHM07M1
avilei 6:0eec4b6e94ba 62 */
avilei 6:0eec4b6e94ba 63 /**************************************************************************/
avilei 2:4ae769d0b112 64 SPN7Driver::SPN7Driver(PinName pIN1, PinName pIN2, PinName pIN3,
avilei 2:4ae769d0b112 65 PinName pEN1, PinName pEN2, PinName pEN3,
avilei 2:4ae769d0b112 66 PinName pH1, PinName pH2, PinName pH3,
avilei 2:4ae769d0b112 67 PinName pFault) :
avilei 2:4ae769d0b112 68 BLDCmotorDriver(pIN1, pIN2, pIN3,
avilei 2:4ae769d0b112 69 pEN1, pEN2, pEN3,
avilei 2:4ae769d0b112 70 pH1, pH2, pH3,
avilei 2:4ae769d0b112 71 pFault)
avilei 2:4ae769d0b112 72 {
avilei 2:4ae769d0b112 73 // The BLDCmotorDriver class was implemented for half-bridge drivers
avilei 2:4ae769d0b112 74 // so the pin names may be misleading when referring to the L6230 chip.
avilei 3:4c71d3475814 75 // Get pointers to each input pin and call them IN[x] (logic input)
avilei 2:4ae769d0b112 76 // to be consistent with the terminology used in the L6230 documentation.
avilei 3:4c71d3475814 77 PwmOut* IN[3] = {&GH_A, &GH_B, &GH_C};
avilei 3:4c71d3475814 78
avilei 2:4ae769d0b112 79 // Set the switching period of the INx logic input pins (PWM driven)
avilei 3:4c71d3475814 80 for (int i = 0; i < 3; i++) {
avilei 3:4c71d3475814 81 IN[i]->period(switchingPeriod);
avilei 3:4c71d3475814 82 }
avilei 2:4ae769d0b112 83
avilei 2:4ae769d0b112 84 // Set the step commutation function (triggered by the Hall sensors)
avilei 2:4ae769d0b112 85 H1.rise(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 86 H2.rise(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 87 H3.rise(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 88 H1.fall(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 89 H2.fall(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 90 H3.fall(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 91 }
avilei 2:4ae769d0b112 92
avilei 6:0eec4b6e94ba 93 /**************************************************************************/
avilei 6:0eec4b6e94ba 94 /**
avilei 6:0eec4b6e94ba 95 @brief Set duty cycle for motor control
avilei 11:0120619cdfb7 96 * @param dc duty cycle value (>0 clockwise; <0 anti-clockwise)
avilei 6:0eec4b6e94ba 97 */
avilei 6:0eec4b6e94ba 98 /**************************************************************************/
avilei 4:3f63eed73ad1 99 void SPN7Driver::setDutyCycle(float dc) {
avilei 11:0120619cdfb7 100 if (dc >= -1 && dc <= 1) {
avilei 4:3f63eed73ad1 101 ticker.attach(this, &SPN7Driver::commutation, sampleTime);
avilei 4:3f63eed73ad1 102 tempDutyCycle = dc;
avilei 4:3f63eed73ad1 103 } else {
avilei 4:3f63eed73ad1 104 coast();
avilei 4:3f63eed73ad1 105 }
avilei 4:3f63eed73ad1 106 }
avilei 4:3f63eed73ad1 107
avilei 11:0120619cdfb7 108 // six-step phase commutation
avilei 3:4c71d3475814 109 void SPN7Driver::commutation()
avilei 3:4c71d3475814 110 {
avilei 3:4c71d3475814 111 // The BLDCmotorDriver class was implemented for half-bridge drivers
avilei 3:4c71d3475814 112 // so the pin names may be misleading when referring to the L6230 chip.
avilei 3:4c71d3475814 113 // Get pointers to each input pin and call them IN[x] (logic input)
avilei 3:4c71d3475814 114 // to be consistent with the terminology used in the L6230 documentation.
avilei 3:4c71d3475814 115 PwmOut* IN[3] = {&GH_A, &GH_B, &GH_C};
avilei 3:4c71d3475814 116 // Get pointers to each enable pin and call them ENx (enable channel)
avilei 3:4c71d3475814 117 // to be consistent with the terminology used in the L6230 documentation.
avilei 3:4c71d3475814 118 DigitalOut* EN[3] = {&GL_A, &GL_B, &GL_C};
avilei 3:4c71d3475814 119
avilei 3:4c71d3475814 120 st_bldc_status_t tab[6][3] = {
avilei 11:0120619cdfb7 121 {ST_BLDC_OFF, ST_BLDC_LOW, ST_BLDC_HIGH},
avilei 11:0120619cdfb7 122 {ST_BLDC_HIGH, ST_BLDC_LOW, ST_BLDC_OFF},
avilei 3:4c71d3475814 123 {ST_BLDC_HIGH, ST_BLDC_OFF, ST_BLDC_LOW},
avilei 3:4c71d3475814 124 {ST_BLDC_OFF, ST_BLDC_HIGH, ST_BLDC_LOW},
avilei 3:4c71d3475814 125 {ST_BLDC_LOW, ST_BLDC_HIGH, ST_BLDC_OFF},
avilei 3:4c71d3475814 126 {ST_BLDC_LOW, ST_BLDC_OFF, ST_BLDC_HIGH},
avilei 3:4c71d3475814 127 };
avilei 2:4ae769d0b112 128
avilei 2:4ae769d0b112 129 dutyCycle = rl.out(tempDutyCycle);
avilei 11:0120619cdfb7 130 int sector = getSector();
avilei 2:4ae769d0b112 131
avilei 3:4c71d3475814 132 if (dutyCycle == 0) {
avilei 3:4c71d3475814 133 // Stop the motor
avilei 2:4ae769d0b112 134 coast();
avilei 3:4c71d3475814 135 return;
avilei 2:4ae769d0b112 136 }
avilei 2:4ae769d0b112 137
avilei 3:4c71d3475814 138 // Move to next sector (i.e. commute phase)
avilei 3:4c71d3475814 139 if (dutyCycle > 0 ) {
avilei 11:0120619cdfb7 140 // Clockwise spinning
avilei 11:0120619cdfb7 141
avilei 11:0120619cdfb7 142 // The rows of the phase status table are offset by one when spinning
avilei 11:0120619cdfb7 143 // clockwise so we need to increment the current sector by two steps
avilei 11:0120619cdfb7 144 sector = (sector + 2) % 6;
avilei 3:4c71d3475814 145 } else {
avilei 11:0120619cdfb7 146 // Anti-clockwise spinning
avilei 11:0120619cdfb7 147 sector--;
avilei 11:0120619cdfb7 148 if(sector < 0) sector = 5;
avilei 3:4c71d3475814 149 }
avilei 3:4c71d3475814 150
avilei 3:4c71d3475814 151 // Get the absolute value of the duty cycle for the PWM
avilei 3:4c71d3475814 152 float d = (dutyCycle > 0) ? dutyCycle : -dutyCycle;
avilei 3:4c71d3475814 153
avilei 3:4c71d3475814 154 // Update the logic inputs and the enable pins
avilei 3:4c71d3475814 155 for (int i = 0; i < 3; i++) {
avilei 11:0120619cdfb7 156 *EN[i] = (tab[sector][i] == ST_BLDC_OFF) ? 0 : 1;
avilei 11:0120619cdfb7 157 *IN[i] = (tab[sector][i] == ST_BLDC_HIGH) ? d : 0;
avilei 3:4c71d3475814 158 }
avilei 2:4ae769d0b112 159 }