⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 speed_sense.c

📁 Luminary Micro BLDC motor control software
💻 C
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************
//
// speed_sense.c - Routines for determining the speed of the motor (if an
//                 encoder is present).
//
// Copyright (c) 2007-2008 Luminary Micro, Inc.  All rights reserved.
// 
// Software License Agreement
// 
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
// 
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws.  All rights are reserved.  You may not combine
// this software with "viral" open-source software in order to form a larger
// program.  Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
// 
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 716 of the BLDC motor application.
//
//*****************************************************************************

#include "../../DriverLib/hw_ints.h"
#include "../../DriverLib/hw_memmap.h"
#include "../../DriverLib/hw_qei.h"
#include "../../DriverLib/hw_types.h"
#include "../../DriverLib/src/gpio.h"
#include "../../DriverLib/src/interrupt.h"
#include "../../DriverLib/src/qei.h"
#include "main.h"
#include "pins.h"
#include "speed_sense.h"
#include "ui.h"
#include "pwm_ctrl.h"

//*****************************************************************************
//
//! \page speed_sense_intro Introduction
//!
//! When running at slow speeds the time between input edges is measured to
//! determine the speed of the rotor (referred to as edge timing mode).  The
//! edge triggering capability of the GPIO module is used for this measurement.
//!
//! When running at higher speeds while using the encoder, the number of edges
//! in a fixed time period are counted to determine the speed of the rotor
//! (referred to as edge count mode).  The velocity capture feature of the
//! quadrature encoder module is used for this measurement.
//!
//! The transition between the two speed capture modes is performed based on
//! the measured speed.  If in edge timing mode, when the edge time gets too
//! small (that is, there are too many edges per second), it will change into
//! edge count mode.  If in edge count mode, when the number of edges in the
//! time period gets too small (that is, there are not enough edges per time
//! period), it will change into edge timing mode.  There is a bit of
//! hysteresis on the changeover point to avoid constantly switching between
//! modes if the rotor is running near the changeover point.
//!
//! The code for sensing the rotor speed is contained in
//! <tt>speed_sense.c</tt>, with <tt>speed_sense.h</tt> containing the
//! definitions for the variable and functions exported to the remainder of the
//! application.
//
//*****************************************************************************

//*****************************************************************************
//
//! \defgroup speed_sense_api Definitions
//! @{
//
//*****************************************************************************

//*****************************************************************************
//
//! The rate at which the QEI velocity interrupt occurs.
//
//*****************************************************************************
#define QEI_INT_RATE            50

//*****************************************************************************
//
//! The maximum number of edges per second allowed when using the edge timing
//! mode of speed determination (which is also the minimum number of edges
//! per second allowed when using the edge count mode).
//
//*****************************************************************************
#define MAX_EDGE_COUNT          2000

//*****************************************************************************
//
//! The hysteresis applied to #MAX_EDGE_COUNT when changing between the two
//! speed determination modes.
//
//*****************************************************************************
#define EDGE_DELTA              50

//*****************************************************************************
//
//! The bit number of the flag in #g_ulSpeedFlags that indicates that the next
//! edge should be ignored by the edge timing mode.  This is used when the edge
//! timing mode is first enabled since there is no previous edge time to be
//! used to calculate the time between edges.
//
//*****************************************************************************
#define FLAG_SKIP_BIT           0

//*****************************************************************************
//
//! The bit number of the flag in #g_ulSpeedFlags that indicates that edge
//! counting mode is being used to determine the speed.
//
//*****************************************************************************
#define FLAG_COUNT_BIT          1

//*****************************************************************************
//
//! The bit number of the flag in #g_ulSpeedFlags that indicates that an edge
//! has been seen by the edge timing mode.  If an edge hasn't been seen during
//! a QEI velocity interrupt period, the speed is forced to zero.
//
//*****************************************************************************
#define FLAG_EDGE_BIT           2

//*****************************************************************************
//
//! A set of flags that indicate the current state of the motor speed
//! determination routines.
//
//*****************************************************************************
static unsigned long g_ulSpeedFlags = (1 << FLAG_SKIP_BIT);

//*****************************************************************************
//
//! The time accumulated during the QEI velocity interrupts.  This is used to
//! extend the precision of the QEI timer.
//
//*****************************************************************************
static unsigned long g_ulSpeedTime;

//*****************************************************************************
//
//! In edge timing mode, this is the time at which the previous edge was seen
//! and is used to determine the time between edges.  In edge count mode, this
//! is the count of edges during the previous timing period and is used to
//! average the edge count from two periods.
//
//*****************************************************************************
static unsigned long g_ulSpeedPrevious;

//*****************************************************************************
//
//! The current speed of the motor's rotor.
//
//*****************************************************************************
unsigned long g_ulRotorSpeed = 0;

//*****************************************************************************
//
//! Updates the current rotor speed.
//!
//! \param ulNewSpeed is the newly measured speed.
//!
//! This function takes a newly measured rotor speed and uses it to update
//! the current rotor speed.  If the new speed is different from the
//! current speed by too large a margin, the new speed measurement is
//! discarded (a noise filter).  If the new speed is accepted, it is passed
//! through a single-pole IIR low pass filter with a coefficient of 0.75.
//!
//! \return None.
//
//*****************************************************************************
static void
SpeedNewValue(unsigned short ulNewSpeed)
{
    unsigned short usDelta;

    //
    // Compute the difference in the speed.
    //
    if(ulNewSpeed > g_ulRotorSpeed)
    {
        usDelta = ulNewSpeed - g_ulRotorSpeed;
    }
    else
    {
        usDelta = g_ulRotorSpeed - ulNewSpeed;
    }

    //
    // If the speed difference is too large then return without updating the
    // motor speed.
    //
    if(usDelta > (g_sParameters.ulMaxSpeed / 2))
    {
        return;
    }

    //
    // Pass the new rotor speed reading through the low pass filter.
    //
    g_ulRotorSpeed = ((g_ulRotorSpeed * 3) + ulNewSpeed) / 4;
}

//*****************************************************************************
//
//! Handles the GPIO port C interrupt.
//!
//! This function is called when GPIO port C asserts its interrupt.  GPIO port
//! C is configured to generate an interrupt on the rising edge of the encoder
//! input signal.  The time between the current edge and the previous edge is
//! computed and used as a measure of the rotor speed.
//!
//! \return None.
//
//*****************************************************************************
void
GPIOCIntHandler(void)
{
    unsigned long ulTime, ulNewTime;

    //
    // Clear the GPIO interrupt.
    //
    GPIOPinIntClear(PIN_ENCA_PORT, PIN_ENCA_PIN);

    //
    // Get the time of this edge.
    //
    ulNewTime = g_ulSpeedTime + HWREG(QEI0_BASE + QEI_O_TIME);

    //
    // Compute the time between this edge and the previous edge.
    //
    ulTime = ulNewTime - g_ulSpeedPrevious;

    //
    // Save the time of the current edge.
    //
    g_ulSpeedPrevious = ulNewTime;

    //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -