gg

Dependencies:   mbed MPU6050 RateLimiter test Math

X_NUCLEO_IHM07M1/SPN7Driver.cpp

Committer:
18fmr36
Date:
2020-03-06
Revision:
8:7efca5258efb

File content as of revision 8:7efca5258efb:

/* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
  ******************************************************************************
  * @file    SPN7Driver.cpp 
  * @author  STMicroelectronics
  * @brief   Implementation of SPN7Driver class
  ******************************************************************************
  * @copy
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
  */ 

// This example is based on the BLDCmotorDriver motor control library
// by the TVZ Mechatronics Team, University of Applied Sciences Zagreb,
// Professional Study in Mechatronics:
// https://developer.mbed.org/teams/TVZ-Mechatronics-Team/code/BLDCmotorDriver/

#include "mbed.h"
#include "SPN7Driver.h"

typedef enum {
    ST_BLDC_LOW = 0,
    ST_BLDC_HIGH,
    ST_BLDC_OFF
} st_bldc_status_t;

/**************************************************************************/
/**
    @brief  Constructor
     * @param pIN1     Logic input pin IN1 of L6230 chip
     * @param pIN2     Logic input pin IN2 of L6230 chip
     * @param pIN3     Logic input pin IN3 of L6230 chip
     * @param pEN1     Enable channel pin EN1 of L6230 chip
     * @param pEN2     Enable channel pin EN2 of L6230 chip
     * @param pEN3     Enable channel pin EN3 of L6230 chip
     * @param pH1      Hall sensor pin for phase #1 (A) of X-NUCLEO-IHM07M1
     * @param pH2      Hall sensor pin for phase #2 (B) of X-NUCLEO-IHM07M1
     * @param pH3      Hall sensor pin for phase #3 (Z) of X-NUCLEO-IHM07M1
     * @param pFault   Fault LED pin of X-NUCLEO-IHM07M1
*/
/**************************************************************************/
SPN7Driver::SPN7Driver(PinName pIN1, PinName pIN2, PinName pIN3,
                       PinName pEN1, PinName pEN2, PinName pEN3,
                       PinName pH1,  PinName pH2,  PinName pH3,
                       PinName pC1, PinName pC2, PinName pC3,
                       PinName pFault) :
                        BLDCmotorDriver(pIN1, pIN2, pIN3,
                                        pEN1, pEN2, pEN3,
                                        pH1,  pH2,  pH3,
                                        pC1,  pC2,  pC3,
                                        pFault)
{
    // 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};

    // Set the switching period of the INx logic input pins (PWM driven)
    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);
    H2.rise(this, &SPN7Driver::commutation);
    H3.rise(this, &SPN7Driver::commutation);
    H1.fall(this, &SPN7Driver::commutation);
    H2.fall(this, &SPN7Driver::commutation);
    H3.fall(this, &SPN7Driver::commutation);    
}

/**************************************************************************/
/**
    @brief  Set duty cycle for motor control
     * @param dc       duty cycle value (>0 clockwise; <0 anti-clockwise)
*/
/**************************************************************************/
void SPN7Driver::setDutyCycle(float dc) {
    if (dc >= -1 && dc <= 1) {
        ticker.attach(this, &SPN7Driver::commutation, sampleTime);
        tempDutyCycle = dc;
    } else {
        coast();
    }
}

// six-step phase commutation
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};

    st_bldc_status_t tab[6][3] = {
                            {ST_BLDC_OFF, ST_BLDC_LOW, ST_BLDC_HIGH},
                            {ST_BLDC_HIGH, ST_BLDC_LOW, ST_BLDC_OFF},
                            {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},
                            };

    dutyCycle = rl.out(tempDutyCycle);
    int sector = getSector();

    if (dutyCycle == 0) {
        // Stop the motor
        coast();
        return;
    }
    
    // Move to next sector (i.e. commute phase)
    if (dutyCycle > 0 ) {
         // Clockwise spinning
         
         // The rows of the phase status table are offset by one when spinning
         // clockwise so we need to increment the current sector by two steps
         sector = (sector + 2) % 6;
         
    } else {
        // Anti-clockwise spinning
        sector--;
        if(sector < 0) sector = 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
    for (int i = 0; i < 3; i++) {
         *EN[i] = (tab[sector][i] == ST_BLDC_OFF) ? 0 : 1;
         *IN[i] = (tab[sector][i] == ST_BLDC_HIGH) ? d : 0;
    }    
}