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:

Files at this revision

API Documentation at this revision

Comitter:
avilei
Date:
Thu Oct 13 15:48:50 2016 +0000
Parent:
2:4ae769d0b112
Child:
4:3f63eed73ad1
Commit message:
Improve commutation method

Changed in this revision

X_NUCLEO_IHM07M1/SPN7Driver.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/X_NUCLEO_IHM07M1/SPN7Driver.cpp	Wed Oct 12 13:15:03 2016 +0000
+++ b/X_NUCLEO_IHM07M1/SPN7Driver.cpp	Thu Oct 13 15:48:50 2016 +0000
@@ -35,6 +35,12 @@
 #include "mbed.h"
 #include "SPN7Driver.h"
 
+typedef enum {
+    ST_BLDC_LOW = 0,
+    ST_BLDC_HIGH,
+    ST_BLDC_OFF
+} st_bldc_status_t;
+
 // FIXME: add doxygen
 
 SPN7Driver::SPN7Driver(PinName pIN1, PinName pIN2, PinName pIN3,
@@ -48,16 +54,14 @@
 {
     // The BLDCmotorDriver class was implemented for half-bridge drivers
     // so the pin names may be misleading when referring to the L6230 chip.
-    // Get a reference of each input pin and call them INx (logic input)
+    // Get pointers to each input pin and call them IN[x] (logic input)
     // to be consistent with the terminology used in the L6230 documentation.
-    PwmOut& IN1 = GH_A;
-    PwmOut& IN2 = GH_B;
-    PwmOut& IN3 = GH_C;
-    
+    PwmOut* IN[3] = {&GH_A, &GH_B, &GH_C};
+
     // Set the switching period of the INx logic input pins (PWM driven)
-    IN1.period(switchingPeriod);
-    IN2.period(switchingPeriod);
-    IN3.period(switchingPeriod);
+    for (int i = 0; i < 3; i++) {
+        IN[i]->period(switchingPeriod);
+    }    
     
     // Set the step commutation function (triggered by the Hall sensors)
     H1.rise(this, &SPN7Driver::commutation);
@@ -69,114 +73,61 @@
 }
 
 // 6-step phase commutation
-//
-// Positive dutycycle:
+void SPN7Driver::commutation()
+{    
+    // The BLDCmotorDriver class was implemented for half-bridge drivers
+    // so the pin names may be misleading when referring to the L6230 chip.
+    // Get pointers to each input pin and call them IN[x] (logic input)
+    // to be consistent with the terminology used in the L6230 documentation.
+    PwmOut* IN[3] = {&GH_A, &GH_B, &GH_C};
+    // Get pointers to each enable pin and call them ENx (enable channel)
+    // to be consistent with the terminology used in the L6230 documentation.
+    DigitalOut* EN[3] = {&GL_A, &GL_B, &GL_C};
+
 //      1--X--0--0--X--1
 //      X--1--1--X--0--0
-//      0--0--X--1--1--X
-//        
-// Negative dutycycle:
-//      1--1--X--0--0--X
-//      0--X--1--1--X--0
-//      X--0--0--X--1--1
-void SPN7Driver::commutation()
-{
-    // The BLDCmotorDriver class was implemented for half-bridge drivers
-    // so the pin names may be misleading when referring to the L6230 chip.
-    
-    // Get a reference of each input pin and call them INx (logic input)
-    // to be consistent with the terminology used in the L6230 documentation.
-    PwmOut& IN1 = GH_A;
-    PwmOut& IN2 = GH_B;
-    PwmOut& IN3 = GH_C;
-    // Get a reference of each enable pin and call them ENx (enable channel)
-    // to be consistent with the terminology used in the L6230 documentation.
-    DigitalOut& EN1 = GL_A;
-    DigitalOut& EN2 = GL_B;
-    DigitalOut& EN3 = GL_C;
+//      0--0--X--1--1--X    
+    st_bldc_status_t tab[6][3] = {
+                            {ST_BLDC_HIGH, ST_BLDC_OFF, ST_BLDC_LOW},
+                            {ST_BLDC_OFF, ST_BLDC_HIGH, ST_BLDC_LOW},
+                            {ST_BLDC_LOW, ST_BLDC_HIGH, ST_BLDC_OFF},
+                            {ST_BLDC_LOW, ST_BLDC_OFF, ST_BLDC_HIGH},
+                            {ST_BLDC_OFF, ST_BLDC_LOW, ST_BLDC_HIGH},
+                            {ST_BLDC_HIGH, ST_BLDC_LOW, ST_BLDC_OFF},
+                            };
 
     dutyCycle = rl.out(tempDutyCycle);
     currentSector = getSector();
 
-    if (dutyCycle > 0 ) {
-         // Positive dutycycle
-         currentSector++;
-         
-         if(currentSector > 5) currentSector = 0;
-         
-         switch(currentSector) {  
-             case 0:                   
-                 EN1 = 1; IN1 = dutyCycle;
-                 EN2 = 0; IN2 = 0;
-                 EN3 = 1; IN3 = 0;                               
-                 break;
-             case 1:            
-                 EN1 = 0; IN1= 0;
-                 EN2 = 1; IN2 = dutyCycle;
-                 EN3 = 1; IN3 = 0;                
-                 break;
-             case 2:             
-                 EN1 = 1; IN1 = 0;
-                 EN2 = 1; IN2 = dutyCycle;
-                 EN3 = 0; IN3 = 0;                
-                 break;
-            case 3:             
-                 EN1 = 1; IN1 = 0;
-                 EN2 = 0; IN2 = 0;
-                 EN3 = 1; IN3 = dutyCycle;              
-                 break;
-            case 4:              
-                 EN1 = 0; IN1 = 0;
-                 EN2 = 1; IN2 = 0;
-                 EN3 = 1; IN3 = dutyCycle;               
-                 break;
-            case 5:           
-                 EN1 = 1; IN1 = dutyCycle;
-                 EN2 = 1; IN2 = 0;
-                 EN3 = 0; IN3 = 0;
-                 break;
-        }
-    } else if (dutyCycle < 0) { 
-        // Negative dutycycle
-        currentSector--;
-        
-        if(currentSector < 0) currentSector = 5;
-        
-        switch(currentSector) {  
-           case 0:
-                EN1 = 1; IN1 = 0;
-                EN2 = 0; IN2=0;
-                EN3 = 1; IN3 = -dutyCycle;
-                break;
-            case 1:
-                EN1 = 0; IN1=0;
-                EN2 = 1; IN2 = 0;
-                EN3 = 1; IN3 = -dutyCycle;
-                break;
-           case 2:
-                EN1 = 1; IN1 = -dutyCycle;
-                EN2 = 1; IN2 = 0;
-                EN3 = 0; IN3= 0;                
-                break;
-           case 3:
-                EN1 = 1; IN1 = -dutyCycle;
-                EN2 = 0; IN2 = 0;
-                EN3 = 1; IN3 = 0;
-                break;
-           case 4:
-                EN1 = 0; IN1= 0;
-                EN2 = 1; IN2 = -dutyCycle;
-                EN3 = 1; IN3 = 0;
-                break;
-           case 5:
-                EN1 = 1; IN1 = 0;
-                EN2 = 1; IN2 = -dutyCycle;
-                EN3 = 0; IN3=0;
-                break;
-       }
-         
-    } else {
+    if (dutyCycle == 0) {
+        // Stop the motor
         coast();
+        return;
     }
     
+    // Move to next sector (i.e. commute phase)
+    if (dutyCycle > 0 ) {
+         // Move forward
+         currentSector++;
+         if(currentSector > 5) currentSector = 0;
+    } else {
+        // Move backward
+        currentSector--;
+        if(currentSector < 0) currentSector = 5;
+    }
+    
+    // Get the absolute value of the duty cycle for the PWM
+    float d = (dutyCycle > 0) ? dutyCycle : -dutyCycle;
+    
+    // Update the logic inputs and the enable pins
+    //printf("Commutation sector %d\n\r", currentSector);
+    for (int i = 0; i < 3; i++) {
+         *EN[i] = (tab[currentSector][i] == ST_BLDC_OFF) ? 0 : 1;
+         *IN[i] = (tab[currentSector][i] == ST_BLDC_HIGH) ? d : 0;
+/*
+         int ena = (tab[currentSector][i] == ST_BLDC_OFF) ? 0 : 1;
+         float inp = (tab[currentSector][i] == ST_BLDC_HIGH) ? d : 0;         
+         printf("EN[%d] = %d, IN[%d] = %f\n\r", i, ena, i, inp);
+*/
+    }    
 }
--- a/main.cpp	Wed Oct 12 13:15:03 2016 +0000
+++ b/main.cpp	Thu Oct 13 15:48:50 2016 +0000
@@ -38,6 +38,10 @@
 
 int main() {
     printf("Press 'w' to speed up, 's' to speed down\n\r");
+    
+    // sampleTime = 1e-3, switchingFrequency = 20e3, rampUpSlope = 1, rampDownSlope = -1
+    //M.configure(1e-3, 50e3, 0.1f, -0.1f);
+    
     while(true) { 
 
         char c = getchar();