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:
Wed Oct 12 13:15:03 2016 +0000
Revision:
2:4ae769d0b112
Child:
3:4c71d3475814
Initial release of the HelloWorld_IHM07M1 example application

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 2:4ae769d0b112 35 #include "mbed.h"
avilei 2:4ae769d0b112 36 #include "SPN7Driver.h"
avilei 2:4ae769d0b112 37
avilei 2:4ae769d0b112 38 // FIXME: add doxygen
avilei 2:4ae769d0b112 39
avilei 2:4ae769d0b112 40 SPN7Driver::SPN7Driver(PinName pIN1, PinName pIN2, PinName pIN3,
avilei 2:4ae769d0b112 41 PinName pEN1, PinName pEN2, PinName pEN3,
avilei 2:4ae769d0b112 42 PinName pH1, PinName pH2, PinName pH3,
avilei 2:4ae769d0b112 43 PinName pFault) :
avilei 2:4ae769d0b112 44 BLDCmotorDriver(pIN1, pIN2, pIN3,
avilei 2:4ae769d0b112 45 pEN1, pEN2, pEN3,
avilei 2:4ae769d0b112 46 pH1, pH2, pH3,
avilei 2:4ae769d0b112 47 pFault)
avilei 2:4ae769d0b112 48 {
avilei 2:4ae769d0b112 49 // The BLDCmotorDriver class was implemented for half-bridge drivers
avilei 2:4ae769d0b112 50 // so the pin names may be misleading when referring to the L6230 chip.
avilei 2:4ae769d0b112 51 // Get a reference of each input pin and call them INx (logic input)
avilei 2:4ae769d0b112 52 // to be consistent with the terminology used in the L6230 documentation.
avilei 2:4ae769d0b112 53 PwmOut& IN1 = GH_A;
avilei 2:4ae769d0b112 54 PwmOut& IN2 = GH_B;
avilei 2:4ae769d0b112 55 PwmOut& IN3 = GH_C;
avilei 2:4ae769d0b112 56
avilei 2:4ae769d0b112 57 // Set the switching period of the INx logic input pins (PWM driven)
avilei 2:4ae769d0b112 58 IN1.period(switchingPeriod);
avilei 2:4ae769d0b112 59 IN2.period(switchingPeriod);
avilei 2:4ae769d0b112 60 IN3.period(switchingPeriod);
avilei 2:4ae769d0b112 61
avilei 2:4ae769d0b112 62 // Set the step commutation function (triggered by the Hall sensors)
avilei 2:4ae769d0b112 63 H1.rise(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 64 H2.rise(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 65 H3.rise(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 66 H1.fall(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 67 H2.fall(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 68 H3.fall(this, &SPN7Driver::commutation);
avilei 2:4ae769d0b112 69 }
avilei 2:4ae769d0b112 70
avilei 2:4ae769d0b112 71 // 6-step phase commutation
avilei 2:4ae769d0b112 72 //
avilei 2:4ae769d0b112 73 // Positive dutycycle:
avilei 2:4ae769d0b112 74 // 1--X--0--0--X--1
avilei 2:4ae769d0b112 75 // X--1--1--X--0--0
avilei 2:4ae769d0b112 76 // 0--0--X--1--1--X
avilei 2:4ae769d0b112 77 //
avilei 2:4ae769d0b112 78 // Negative dutycycle:
avilei 2:4ae769d0b112 79 // 1--1--X--0--0--X
avilei 2:4ae769d0b112 80 // 0--X--1--1--X--0
avilei 2:4ae769d0b112 81 // X--0--0--X--1--1
avilei 2:4ae769d0b112 82 void SPN7Driver::commutation()
avilei 2:4ae769d0b112 83 {
avilei 2:4ae769d0b112 84 // The BLDCmotorDriver class was implemented for half-bridge drivers
avilei 2:4ae769d0b112 85 // so the pin names may be misleading when referring to the L6230 chip.
avilei 2:4ae769d0b112 86
avilei 2:4ae769d0b112 87 // Get a reference of each input pin and call them INx (logic input)
avilei 2:4ae769d0b112 88 // to be consistent with the terminology used in the L6230 documentation.
avilei 2:4ae769d0b112 89 PwmOut& IN1 = GH_A;
avilei 2:4ae769d0b112 90 PwmOut& IN2 = GH_B;
avilei 2:4ae769d0b112 91 PwmOut& IN3 = GH_C;
avilei 2:4ae769d0b112 92 // Get a reference of each enable pin and call them ENx (enable channel)
avilei 2:4ae769d0b112 93 // to be consistent with the terminology used in the L6230 documentation.
avilei 2:4ae769d0b112 94 DigitalOut& EN1 = GL_A;
avilei 2:4ae769d0b112 95 DigitalOut& EN2 = GL_B;
avilei 2:4ae769d0b112 96 DigitalOut& EN3 = GL_C;
avilei 2:4ae769d0b112 97
avilei 2:4ae769d0b112 98 dutyCycle = rl.out(tempDutyCycle);
avilei 2:4ae769d0b112 99 currentSector = getSector();
avilei 2:4ae769d0b112 100
avilei 2:4ae769d0b112 101 if (dutyCycle > 0 ) {
avilei 2:4ae769d0b112 102 // Positive dutycycle
avilei 2:4ae769d0b112 103 currentSector++;
avilei 2:4ae769d0b112 104
avilei 2:4ae769d0b112 105 if(currentSector > 5) currentSector = 0;
avilei 2:4ae769d0b112 106
avilei 2:4ae769d0b112 107 switch(currentSector) {
avilei 2:4ae769d0b112 108 case 0:
avilei 2:4ae769d0b112 109 EN1 = 1; IN1 = dutyCycle;
avilei 2:4ae769d0b112 110 EN2 = 0; IN2 = 0;
avilei 2:4ae769d0b112 111 EN3 = 1; IN3 = 0;
avilei 2:4ae769d0b112 112 break;
avilei 2:4ae769d0b112 113 case 1:
avilei 2:4ae769d0b112 114 EN1 = 0; IN1= 0;
avilei 2:4ae769d0b112 115 EN2 = 1; IN2 = dutyCycle;
avilei 2:4ae769d0b112 116 EN3 = 1; IN3 = 0;
avilei 2:4ae769d0b112 117 break;
avilei 2:4ae769d0b112 118 case 2:
avilei 2:4ae769d0b112 119 EN1 = 1; IN1 = 0;
avilei 2:4ae769d0b112 120 EN2 = 1; IN2 = dutyCycle;
avilei 2:4ae769d0b112 121 EN3 = 0; IN3 = 0;
avilei 2:4ae769d0b112 122 break;
avilei 2:4ae769d0b112 123 case 3:
avilei 2:4ae769d0b112 124 EN1 = 1; IN1 = 0;
avilei 2:4ae769d0b112 125 EN2 = 0; IN2 = 0;
avilei 2:4ae769d0b112 126 EN3 = 1; IN3 = dutyCycle;
avilei 2:4ae769d0b112 127 break;
avilei 2:4ae769d0b112 128 case 4:
avilei 2:4ae769d0b112 129 EN1 = 0; IN1 = 0;
avilei 2:4ae769d0b112 130 EN2 = 1; IN2 = 0;
avilei 2:4ae769d0b112 131 EN3 = 1; IN3 = dutyCycle;
avilei 2:4ae769d0b112 132 break;
avilei 2:4ae769d0b112 133 case 5:
avilei 2:4ae769d0b112 134 EN1 = 1; IN1 = dutyCycle;
avilei 2:4ae769d0b112 135 EN2 = 1; IN2 = 0;
avilei 2:4ae769d0b112 136 EN3 = 0; IN3 = 0;
avilei 2:4ae769d0b112 137 break;
avilei 2:4ae769d0b112 138 }
avilei 2:4ae769d0b112 139 } else if (dutyCycle < 0) {
avilei 2:4ae769d0b112 140 // Negative dutycycle
avilei 2:4ae769d0b112 141 currentSector--;
avilei 2:4ae769d0b112 142
avilei 2:4ae769d0b112 143 if(currentSector < 0) currentSector = 5;
avilei 2:4ae769d0b112 144
avilei 2:4ae769d0b112 145 switch(currentSector) {
avilei 2:4ae769d0b112 146 case 0:
avilei 2:4ae769d0b112 147 EN1 = 1; IN1 = 0;
avilei 2:4ae769d0b112 148 EN2 = 0; IN2=0;
avilei 2:4ae769d0b112 149 EN3 = 1; IN3 = -dutyCycle;
avilei 2:4ae769d0b112 150 break;
avilei 2:4ae769d0b112 151 case 1:
avilei 2:4ae769d0b112 152 EN1 = 0; IN1=0;
avilei 2:4ae769d0b112 153 EN2 = 1; IN2 = 0;
avilei 2:4ae769d0b112 154 EN3 = 1; IN3 = -dutyCycle;
avilei 2:4ae769d0b112 155 break;
avilei 2:4ae769d0b112 156 case 2:
avilei 2:4ae769d0b112 157 EN1 = 1; IN1 = -dutyCycle;
avilei 2:4ae769d0b112 158 EN2 = 1; IN2 = 0;
avilei 2:4ae769d0b112 159 EN3 = 0; IN3= 0;
avilei 2:4ae769d0b112 160 break;
avilei 2:4ae769d0b112 161 case 3:
avilei 2:4ae769d0b112 162 EN1 = 1; IN1 = -dutyCycle;
avilei 2:4ae769d0b112 163 EN2 = 0; IN2 = 0;
avilei 2:4ae769d0b112 164 EN3 = 1; IN3 = 0;
avilei 2:4ae769d0b112 165 break;
avilei 2:4ae769d0b112 166 case 4:
avilei 2:4ae769d0b112 167 EN1 = 0; IN1= 0;
avilei 2:4ae769d0b112 168 EN2 = 1; IN2 = -dutyCycle;
avilei 2:4ae769d0b112 169 EN3 = 1; IN3 = 0;
avilei 2:4ae769d0b112 170 break;
avilei 2:4ae769d0b112 171 case 5:
avilei 2:4ae769d0b112 172 EN1 = 1; IN1 = 0;
avilei 2:4ae769d0b112 173 EN2 = 1; IN2 = -dutyCycle;
avilei 2:4ae769d0b112 174 EN3 = 0; IN3=0;
avilei 2:4ae769d0b112 175 break;
avilei 2:4ae769d0b112 176 }
avilei 2:4ae769d0b112 177
avilei 2:4ae769d0b112 178 } else {
avilei 2:4ae769d0b112 179 coast();
avilei 2:4ae769d0b112 180 }
avilei 2:4ae769d0b112 181
avilei 2:4ae769d0b112 182 }