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

📄 pmsm.h

📁 Atmel算法(pid)-步进电机驱动源码 HOWTO,不好用你找我,绝对ok!
💻 H
字号:
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
 *
 * \brief
 *      Motor control header file.
 *
 *      This file contains all #defines, typedefs and prototypes related to
 *      the motor control.
 *
 * \par Application note:
 *      AVR447: Sinusoidal driving of three-phase permanent motor using
 *      ATmega48/88/168
 *
 * \par Documentation
 *      For comprehensive code documentation, supported compilers, compiler
 *      settings and supported devices see readme.html
 *
 * \author
 *      Atmel Corporation: http://www.atmel.com \n
 *      Support email: avr@atmel.com
 *
 * $Name: RELEASE_1_0 $
 * $Revision: 1.9 $
 * $RCSfile: PMSM.h,v $
 * $Date: 2006/03/27 07:20:51 $  \n
 ******************************************************************************/

#ifndef _PMSM_H_
#define _PMSM_H_


//! FALSE constant value.
#define FALSE   0

//! TRUE constant value, defined to be compatible with comparisons.
#define TRUE    (!FALSE)

/*! This value specifies half the dead time in number of clock cycles. Divide by frequency to get duration.
 *
 *  \todo Specify the dead time.
 */
#define DEAD_TIME_HALF    4

//! The number of elements in the sine modulation table per phase.
#define SINE_TABLE_LENGTH 192U

#if SINE_TABLE_LENGTH != 192U
#warning "Changing sine modulation table length can have unwanted side effects. Consult the documentation for more information."
#endif

//! The number of elements in the sine modulation table for each phase per commutation sector.
#define TABLE_ELEMENTS_PER_COMMUTATION_SECTOR   (SINE_TABLE_LENGTH / 6)

//! Bit pattern of PWM pins placed on PORTB.
#define PWM_PATTERN_PORTB   ((1 << PB1) | (1 << PB2) | (1 << PB3))

//! Bit pattern of PWM pins placed on PORTD.
#define PWM_PATTERN_PORTD   ((1 << PD3) | (1 << PD5) | (1 << PD6))

//! Forward direction flag value.
#define DIRECTION_FORWARD       0

//! Reverse direction flag value.
#define DIRECTION_REVERSE       1

//! Unknown direction flag value.
#define DIRECTION_UNKNOWN       3

/*! Uncomment this to disable internal pullup resistors on hall sensor inputs.
 *
 *  \todo Select whether internal pull-ups on hall sensor inputs should be
 *  enabled.
 */
#define HALL_PULLUP_ENABLE      FALSE

//! PIN register for Hall sensor input.
#define HALL_PIN      PINC

//! Pin where H1 is connected.
#define H1_PIN        PC0

//! Pin where H2 is connected.
#define H2_PIN        PC1

//! Pin where H3 is connected.
#define H3_PIN        PC2

//! The ADC channel where the analog speed reference is connected.
#define ADC_CHANNEL_SPEED_REF   3

//! The ADC channel where the motor current shunt resistor is connected.
#define ADC_CHANNEL_CURRENT     4

//! ADC clock prescaler 8 setting.
#define ADC_PRESCALER_8        ((0 << ADPS2) | (1 << ADPS1) | (0 << ADPS0))

//! ADC clock prescaler 64 setting.
#define ADC_PRESCALER_64        ((1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0))

//! ADC clock prescaler used in this application.
#define ADC_PRESCALER           ADC_PRESCALER_8

//! ADC internal voltage reference channel value.
#define ADC_REFERENCE_VOLTAGE_INTERNAL      ((1 << REFS1) | (1 << REFS0))

//! ADC VCC voltage reference channel value.
#define ADC_REFERENCE_VOLTAGE_VCC           ((0 << REFS1) | (1 << REFS0))

//! ADC AREF voltage reference channel value.
#define ADC_REFERENCE_VOLTAGE_AREF          ((0 << REFS1) | (0 << REFS0))

/*! ADC voltage reference used in this application.
 *
 *  \todo Select ADC voltage reference channel.
 */
#define ADC_REFERENCE_VOLTAGE               ADC_REFERENCE_VOLTAGE_INTERNAL

//! ADMUX settings for analog speed reference measurement.
#define ADMUX_SPEED_REF   (ADC_REFERENCE_VOLTAGE | (1 << ADLAR) | (ADC_CHANNEL_SPEED_REF << MUX0))

//! ADMUX settings for motor current measurement.
#define ADMUX_CURRENT     (ADC_REFERENCE_VOLTAGE | (1 << ADLAR) | (ADC_CHANNEL_CURRENT << MUX0))

/*! Pin where direction command input is located.
 *
 *  Do not change to pin on a different PORT!
 */
#define DIRECTION_COMMAND_PIN   PD2

/*! Pin where reverse rotation signal output is located.
 *
 *  Do not change to pin on a different PORT!
 */
#define REV_ROTATION_PIN        PD4

/*! Pin where tacho signal output is located.
 *
 *  Do not change to pin on a different PORT!
 */
#define TACHO_OUTPUT_PIN        PD7

/*! Emergency shutdown input pin
 *
 *  Do not change to pin on a different PORT!
 */
#define EMERGENCY_SHUTDOWN_PIN  PB5

//! Waveform constant for block commutation. Used as status flag.
#define WAVEFORM_BLOCK_COMMUTATION    0

//! Waveform status flag for sinusoidal driving.
#define WAVEFORM_SINUSOIDAL           1

//! Waveform status flag for braking.
#define WAVEFORM_BRAKING              2

//! Waveform status flag used in transitions between different types of driving.
#define WAVEFORM_UNDEFINED            3

/*! The number of commutation 'ticks' that must pass without any hall changes
 *  before the motor is considered to be stopped.
 *
 *  \todo Adjust the motor stopped limit.
 */
#define COMMUTATION_TICKS_STOPPED     6000

/*! Enables/disables the tacho signal output. TRUE = enabled, FALSE = disabled.
 *
 *  \todo Select whether the Tacho output signal should be enabled.
 */
#define TACHO_OUTPUT_ENABLED              TRUE

/*! Enables/disables the reverse rotation signal output. TRUE = enabled, FALSE = disabled.
 *
 *  \todo Select whether the 'Reverse rotation' signal should be enabled.
 */
#define REVERSE_ROTATION_SIGNAL_ENABLE    TRUE

//! TURN_MODE value for coasting (disabled drivers).
#define TURN_MODE_COAST               0

//! TURN_MODE value for braking (drivers connected to ground).
#define TURN_MODE_BRAKE               1

/*! Turn mode. Set to either TURN_MODE_COAST or TURN_MODE_BRAKE.
 *
 *  \todo Select turn mode.
 */
#define TURN_MODE                     TURN_MODE_BRAKE

//! The number to multiply speed input with to produce duty cycle compare value (0-255).
#define BLOCK_COMMUTATION_DUTY_MULTIPLIER   3

/*! This constant specifies the number of subsequent detections of correct
 *  direction of rotation needed before the firmware is considered synchronized
 *  with the motor. (SYNCHRONIZATION_COUNT + 1) hall sensor changes in the
 *  same direction are needed.
 */
#define SYNCHRONIZATION_COUNT       2

//! Speed control selection for open loop control.
#define SPEED_CONTROL_OPEN_LOOP     0

//! Speed control selection for closed loop control.
#define SPEED_CONTROL_CLOSED_LOOP   1

/*! Type of speed control. select either SPEED_CONTROL_OPEN_LOOP or
 *  SPEED_CONTROL_CLOSED_LOOP.
 *  \todo Select speed control method.
 */
#define SPEED_CONTROL_METHOD        SPEED_CONTROL_OPEN_LOOP

/*! The number of ticks between each iteration of the speed loop.
 *  \todo Adjust speed control loop time base.
 */
#define SPEED_CONTROLLER_TIME_BASE   150

/*! PID controller proportional gain constant.
 *  \todo Adjust PID controller proportional gain. (Only for closed loop)
 */
#define PID_K_P    50

/*! PID controller integral gain constant.
 *  \todo Adjust PID controller integral gain. (Only for closed loop)
 */
#define PID_K_I    5

/*! PID controller derivative gain constant.
 *  \todo Adjust PID controller derivative gain. (Only for closed loop)
 */
#define PID_K_D    10

/*! The maximum increment (maximum speed) to use as setpoint when the maximum
 *  speed reference value is input.
 *
 *  \todo Adjust maximum increment. (Maximum speed, used by speed controller)
 */
#define SPEED_CONTROLLER_MAX_INCREMENT      550

/*! Max speed reference input. (Rounded up to closest power of 2 in this case,
 *  which is recommended to speed up division.
 *
 *  \todo Adjust Maximum speed reference input value.
 */
#define SPEED_CONTROLLER_MAX_INPUT          256


//Typedefs
/*! \brief Collection of all motor control flags.
 *
 *  This struct contains all motor control flags used in this implementation.
 */
typedef struct PMSMflags
{
  uint8_t motorStopped : 1;     //! Is motor stopped?
  uint8_t motorSynchronized: 1; //! Is motor synchronized? Does not have any meaning when motorStopped is TRUE.
  uint8_t actualDirection : 2;  //! The actual direction of rotation.
  uint8_t desiredDirection : 1; //! The desired direction of rotation.
  uint8_t driveWaveform : 2;    //! The current waveform that should be produced.
} PMSMflags_t;


//Function prototypes
static void TimersInit(void);
static void TimersSetModeSinusoidal(void);
static void TimersSetModeBlockCommutation(void);
static void TimersSetModeBrake(void);
static void TimersWaitForNextPWMCycle(void);
static void BlockCommutationSetDuty(const uint8_t duty);
static void PortsInit(void);
static void PinChangeIntInit(void);
static void ADCInit(void);
static void CheckEmergencyShutdown(void);
static void SpeedController(void);
static uint8_t GetDesiredDirection(void);
static uint8_t GetActualDirection(void);
static void BlockCommutate(const uint8_t direction, uint8_t hall);
static uint8_t GetHall(void);
static void DesiredDirectionUpdate(void);
static uint8_t CalculateActualDirection(const uint8_t lastHall, const uint8_t newHall);
static void ActualDirectionUpdate(uint8_t lastHall, const uint8_t newHall);
static void ReverseRotationSignalUpdate(void);
static void InsertDeadband(const uint8_t compareValue, uint8_t * compareHighPtr, uint8_t * compareLowPtr);
static void AdjustSineTableIndex(const uint16_t increment);
static uint16_t SineTableIncrementCalculate(const uint16_t ticks);
static void SetAdvanceCommutation(const uint8_t leadAngle);
static void TachoOutputUpdate(const uint8_t hall);
static void EnablePWMOutputs(void);
static void DisablePWMOutputs(void);
static void CommutationTicksUpdate(void);
static void MotorSynchronizedUpdate(void);
static uint8_t IsMotorSynchronized(void);

//Prototypes for ISRs, required by MISRA
#pragma vector=PCINT0_vect
__interrupt void EmergencyInterruptISR(void);

#pragma vector=PCINT1_vect
__interrupt void HallChangeISR(void);

#pragma vector=PCINT2_vect
__interrupt void DirectionInputChangeISR(void);

#pragma vector=TIMER1_CAPT_vect
__interrupt void Timer1CaptureISR(void);

#pragma vector=TIMER2_OVF_vect
__interrupt void Timer2OverflowISR(void);

#pragma vector=WDT_vect
__interrupt void WatchdogISR(void);

#pragma vector=ADC_vect
__interrupt void ADCCompleteISR(void);


/*! \mainpage
* \section intro Introduction
* This documents data structures, functions, variables, defines, enums, and
* typedefs in the software for application note AVR447.
*
* \section compinfo Compilation Info
* This software was written for the IAR Embedded Workbench, 4.11B.\n
* To make project:\n
* Add the main.c and pid.c files to project. Use device --cpu=m48, enable bit
* definitions in I/O include files, optimization should be high on speed for
* best performance but might need to be lowered for easier debugging, output
* format: ubrof8 for Debug and intel_extended for Release.
* Under "C/C++ compiler->Code" chose 9 registers locked for global variables.
*
* \section deviceinfo Device Info
* ATmega48/ATmega88/ATmega168 can be used. The example is
* written for ATmega48.
*
* \section note Note
*
* Most of the source code in this application note is placed in one file (main.c)
* to be able to take full advantage of the compiler's optimization.
*
* Please see the \ref todo for a list of changes that should be considered
* before running this firmware.
*
* \section contactinfo Contact Info
* For more info about Atmel AVR visit
* <A href="http://www.atmel.com/products/AVR/" >Atmel AVR</A> \n
* <A href="http://www.atmel.com/dyn/products/app_notes.asp?family_id=607"
  >AVR Application Notes</A>\n
* Support mail: avr@atmel.com
*/



#endif

⌨️ 快捷键说明

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