📄 speed_sense.c
字号:
//*****************************************************************************
//
// 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 + -