Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Components/STSPIN820/STSPIN820.cpp
- Committer:
- Davidroid
- Date:
- 2018-04-27
- Revision:
- 1:bc265521eb00
File content as of revision 1:bc265521eb00:
/**
******************************************************************************
* @file STSPIN820.cpp
* @author STM
* @version V1.0.0
* @date August 7th, 2017
* @brief STSPIN820 driver (fully integrated microstepping motor driver)
* @note (C) COPYRIGHT 2017 STMicroelectronics
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Generated with STM32CubeTOO -----------------------------------------------*/
/* Revision ------------------------------------------------------------------*/
/*
Repository: http://svn.x-nucleodev.codex.cro.st.com/svnroot/X-NucleoDev
Branch/Trunk/Tag: trunk
Based on: X-CUBE-SPN14/trunk/Drivers/BSP/Components/STSPIN820/STSPIN820.c
Revision: 0
*/
/* Includes ------------------------------------------------------------------*/
#include "STSPIN820.h"
/* Private function prototypes -----------------------------------------------*/
/** @defgroup STSPIN820_Private_Functions STSPIN820 Private Functions
* @{
*/
/* Methods -------------------------------------------------------------------*/
/** @defgroup STSPIN820_Exported_Variables STSPIN820 Exported Variables
* @{
*/
/** @defgroup STSPIN820_Library_Functions STSPIN820 Library Functions
* @{
*/
/******************************************************//**
* @brief Return motor handle (pointer to the STSPIN820 motor driver structure)
* @retval Pointer to the MOTOR_vt_t structure
**********************************************************/
MOTOR_vt_t* STSPIN820::STSPIN820_GetMotorHandle(void)
{
return (&STSPIN820_drv);
}
/******************************************************//**
* @brief Start the STSPIN820 library
* @param[in] pInit pointer to the initialization data
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_Init(void* pInit)
{
device_instance++;
/* Initialise the GPIOs */
STSPIN820_Board_GpioInit();
/* Initialise the timer used for the step clock and ------------------------*/
/* the PWM for the reference voltage generation ----------------------------*/
STSPIN820_Board_TimStckInit();
STSPIN820_Board_PwmRefInit();
if (pInit == 0)
{
/* Set all context variables to the predefined values */
/* from STSPIN820_config.h */
STSPIN820_SetDeviceParamsToPredefinedValues();
}
else
{
STSPIN820_SetDeviceParamsToGivenValues((STSPIN820_init_t*) pInit);
}
}
/******************************************************//**
* @brief Read id
* @retval Id of the STSPIN820 Driver Instance
**********************************************************/
uint16_t STSPIN820::STSPIN820_ReadId(void)
{
return (device_instance);
}
/******************************************************//**
* @brief Attach a user callback to the error Handler.
* The call back will be then called each time the library
* detects an error
* @param[in] callback Name of the callback to attach
* to the error Hanlder
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_AttachErrorHandler(void (*callback)(uint16_t error))
{
error_handler_callback = (void (*)(uint16_t error))callback;
}
/******************************************************//**
* @brief Attach a user callback to the flag Interrupt
* The call back will be then called each time the status
* flag pin will be pulled down due to the occurrence of
* a programmed alarms ( OCD, thermal pre-warning or
* shutdown, UVLO, wrong command, non-performable command)
* @param[in] callback Name of the callback to attach
* to the Flag Interrupt
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_AttachFlagInterrupt(void (*callback)(void))
{
flag_interrupt_callback = (void (*)(void))callback;
}
/******************************************************//**
* @brief Check if STSPIN820 has a fault by reading EN pin position.
* @retval One if STSPIN820 has EN pin down, otherwise zero
**********************************************************/
uint8_t STSPIN820::STSPIN820_CheckStatusHw(void)
{
if(!STSPIN820_Board_EN_AND_FAULT_PIN_GetState())
{
return 0x01;
}
else
{
return 0x00;
}
}
/******************************************************//**
* @brief Disable the power bridges (leave the output bridges HiZ)
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_Disable(uint8_t deviceId)
{
STSPIN820_Board_Disable();
}
/******************************************************//**
* @brief Enable the power bridges
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_Enable(uint8_t deviceId)
{
STSPIN820_Board_Enable();
}
/******************************************************//**
* @brief Error handler which calls the user callback (if defined)
* @param[in] error Number of the error
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_ErrorHandler(uint16_t error)
{
if (error_handler_callback != 0)
{
(void) error_handler_callback(error);
}
else
{
while(1)
{
/* Infinite loop */
}
}
}
/******************************************************//**
* @brief Exit STSPIN820 device from standby (low power consumption)
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_ExitDeviceFromStandby(uint8_t deviceId)
{
uint32_t sequencerPosition = device_prm.sequencerPosition;
/* Exit standby and set step mode */
/* Disable step clock */
if (STSPIN820_Board_TimStckStop(&toggle_odd) == 0)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_STEP_CLOCK);
}
/* Let the PWM REF and bridges enabled at least for DISABLE_DELAY time */
/* after the last step clock rising edge triggering the last step */
STSPIN820_Board_Delay(DISABLE_DELAY);
/* Set reference voltage to 0 */
STSPIN820_SetTorque(0, CURRENT_TORQUE, 0);
/* Disable power bridges */
STSPIN820_Board_Disable();
device_prm.commandExecuted = NO_CMD;
device_prm.stepsToTake = 0;
device_prm.speed = 0;
/* Reset the microstepping sequencer position */
device_prm.sequencerPosition = 0;
/* Reset current and mark positions */
device_prm.currentPosition = 0;
device_prm.markPosition = 0;
STSPIN820_SetStepMode(deviceId, device_prm.stepMode);
STSPIN820_Board_ReleaseReset();
STSPIN820_Board_Delay(AFTER_STANDBY_EXIT_DEAD_TIME);
STSPIN820_SetHome(deviceId);
STSPIN820_SetMark(deviceId);
if (device_prm.sequencerPosition != 0)
{
/* Set direction to FORWARD to ensure the HW sequencer is increased at */
/* each step clock rising edge */
STSPIN820_SetDirection(0, FORWARD);
/* Going out of standby */
device_prm.motionState = STANDBYTOINACTIVE;
/* Initialize the step clock timer */
STSPIN820_Board_TimStckInit();
/* Program the step clock */
STSPIN820_Board_TimStckCompareInit();
STSPIN820_Board_TimStckSetFreq(STSPIN820_MAX_STCK_FREQ);
toggle_odd = 0;
STSPIN820_Board_TimStckStart();
while (device_prm.sequencerPosition != 0);
while (toggle_odd!=0);
device_prm.sequencerPosition = sequencerPosition;
}
device_prm.motionState = INACTIVE;
}
/******************************************************//**
* @brief Return the acceleration of the specified device
* @param[in] deviceId Unused parameter
* @retval Acceleration in pps^2
**********************************************************/
uint16_t STSPIN820::STSPIN820_GetAcceleration(int8_t deviceId)
{
return (device_prm.acceleration);
}
/******************************************************//**
* @brief Return the current speed of the specified device
* @param[in] deviceId Unused parameter
* @retval Speed in pps
**********************************************************/
uint16_t STSPIN820::STSPIN820_GetCurrentSpeed(int8_t deviceId)
{
return device_prm.speed;
}
/******************************************************//**
* @brief Return the decay mode of the specified device
* @param[in] deviceId Unused parameter
* @retval Decay Mode State (SLOW or MIXED)
**********************************************************/
motor_decay_mode_t STSPIN820::STSPIN820_GetDecayMode(uint8_t deviceId)
{
motor_decay_mode_t status;
if (STSPIN820_Board_GetDecayGpio() != 0)
{
status = SLOW_DECAY;
}
else
{
status = MIXED_DECAY;
}
return status;
}
/******************************************************//**
* @brief Return the deceleration of the specified device
* @param[in] deviceId Unused parameter
* @retval Deceleration in pps^2
**********************************************************/
uint16_t STSPIN820::STSPIN820_GetDeceleration(uint8_t deviceId)
{
return (device_prm.deceleration);
}
/******************************************************//**
* @brief Return the device state
* @param[in] deviceId Unused parameter
* @retval State (ACCELERATING, DECELERATING, STEADY or INACTIVE)
**********************************************************/
motor_state_t STSPIN820::STSPIN820_GetDeviceState(uint8_t deviceId)
{
return device_prm.motionState;
}
/******************************************************//**
* @brief Get the motor current direction
* @param[in] deviceId Unused parameter
* @retval direction
**********************************************************/
motor_direction_t STSPIN820::STSPIN820_GetDirection(uint8_t deviceId)
{
return device_prm.direction;
}
/******************************************************//**
* @brief Return the FW version of the library
* @retval Stspin220_FW_VERSION
**********************************************************/
uint32_t STSPIN820::STSPIN820_GetFwVersion(void)
{
return (STSPIN820_FW_VERSION);
}
/******************************************************//**
* @brief Return the mark position of the specified device
* @param[in] deviceId Unused parameter
* @retval mark position value
**********************************************************/
int32_t STSPIN820::STSPIN820_GetMark(uint8_t deviceId)
{
return device_prm.markPosition;
}
/******************************************************//**
* @brief Return the max speed of the specified device
* @param[in] deviceId Unused parameter
* @retval maxSpeed in pps
**********************************************************/
uint16_t STSPIN820::STSPIN820_GetMaxSpeed(uint8_t deviceId)
{
return (device_prm.maxSpeed);
}
/******************************************************//**
* @brief Return the min speed of the specified device
* @param[in] deviceId Unused parameter
* @retval minSpeed in pps
**********************************************************/
uint16_t STSPIN820::STSPIN820_GetMinSpeed(uint8_t deviceId)
{
return (device_prm.minSpeed);
}
/******************************************************//**
* @brief Returns the number of devices
* @retval number of devices
**********************************************************/
uint8_t STSPIN820::STSPIN820_GetNbDevices(void)
{
return (number_of_devices);
}
/******************************************************//**
* @brief Return the current position value of the specified device
* @param[in] deviceId Unused parameter
* @retval current position value
**********************************************************/
int32_t STSPIN820::STSPIN820_GetPosition(uint8_t deviceId)
{
return device_prm.currentPosition;
}
/******************************************************//**
* @brief Get the motor step mode
* @param[in] deviceId Unused parameter
* @retval step mode
**********************************************************/
motor_step_mode_t STSPIN820::STSPIN820_GetStepMode(uint8_t deviceId)
{
return device_prm.stepMode;
}
/******************************************************//**
* @brief Get the selected stop mode
* @param[in] deviceId Unused parameter
* @retval the selected stop mode
**********************************************************/
motor_stop_mode_t STSPIN820::STSPIN820_GetStopMode(uint8_t deviceId)
{
return device_prm.stopMode;
}
/******************************************************//**
* @brief Get the torque of the specified device
* @param[in] deviceId Unused parameter
* @param[in] torqueMode torque mode
* @retval the torqueValue in % (from 0 to 100)
* @note
**********************************************************/
uint8_t STSPIN820::STSPIN820_GetTorque(uint8_t deviceId, motor_torque_mode_t torqueMode)
{
uint8_t torqueValue = 0;
switch(torqueMode)
{
case ACC_TORQUE:
torqueValue = device_prm.accelTorque;
break;
case DEC_TORQUE:
torqueValue = device_prm.decelTorque;
break;
case RUN_TORQUE:
torqueValue = device_prm.runTorque;
break;
case HOLD_TORQUE:
torqueValue = device_prm.holdTorque;
break;
case CURRENT_TORQUE:
torqueValue = device_prm.currentTorque;
break;
default:
break;
}
return torqueValue;
}
/******************************************************//**
* @brief Get the torque boost feature status
* @param[in] deviceId Unused parameter
* @retval TRUE if enabled, FALSE if disabled
**********************************************************/
bool STSPIN820::STSPIN820_GetTorqueBoostEnable(uint8_t deviceId)
{
return device_prm.torqueBoostEnable;
}
/******************************************************//**
* @brief Get the torque boost threshold
* @param[in] deviceId (from 0 to MAX_NUMBER_OF_DEVICES - 1)
* @retval the torque boost threshold above which the step mode is
* changed to full step
**********************************************************/
uint16_t STSPIN820::STSPIN820_GetTorqueBoostThreshold(uint8_t deviceId)
{
return device_prm.torqueBoostSpeedThreshold;
}
/******************************************************//**
* @brief Request the motor to move to the home position (ABS_POSITION = 0)
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_GoHome(uint8_t deviceId)
{
deviceId = 0;
STSPIN820_GoTo(deviceId, 0);
}
/******************************************************//**
* @brief Request the motor to move to the mark position
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_GoMark(uint8_t deviceId)
{
deviceId = 0;
STSPIN820_GoTo(deviceId, device_prm.markPosition);
}
/******************************************************//**
* @brief Request the motor to move to the specified position
* @param[in] deviceId Unused parameter
* @param[in] targetPosition absolute position in steps
* @retval None
* @note The position is at the resolution corresponding to the
* selected step mode.
* STEP_MODE_FULL : Full step
* STEP_MODE_HALF : 1/2 step
* STEP_MODE_1_4 : 1/4 step
* STEP_MODE_1_8 : 1/8 step
* STEP_MODE_1_16 : 1/16 step
* STEP_MODE_1_32 : 1/32 step
* STEP_MODE_1_128 : 1/128 step
* STEP_MODE_1_256 : 1/256 step
* @note The 1/64 step mode is not allowed
**********************************************************/
void STSPIN820::STSPIN820_GoTo(uint8_t deviceId, int32_t targetPosition)
{
motor_direction_t direction;
deviceId = 0;
/* Exit from standby if needed */
if (device_prm.motionState == STANDBY)
{
STSPIN820_ExitDeviceFromStandby(deviceId);
}
/* Deactivate motor if needed */
else if (device_prm.motionState != INACTIVE)
{
STSPIN820_HardHiZ(deviceId);
}
if (targetPosition > device_prm.currentPosition)
{
device_prm.stepsToTake = targetPosition -\
device_prm.currentPosition;
if (device_prm.stepsToTake < (STSPIN820_POSITION_RANGE>>1))
{
direction = FORWARD;
}
else
{
direction = BACKWARD;
device_prm.stepsToTake = STSPIN820_POSITION_RANGE -\
device_prm.stepsToTake;
}
}
else
{
device_prm.stepsToTake = device_prm.currentPosition -\
targetPosition;
if (device_prm.stepsToTake < (STSPIN820_POSITION_RANGE>>1))
{
direction = BACKWARD;
}
else
{
direction = FORWARD;
device_prm.stepsToTake = STSPIN820_POSITION_RANGE -\
device_prm.stepsToTake;
}
}
if (device_prm.stepsToTake != 0)
{
device_prm.commandExecuted = MOVE_CMD;
/* Direction setup */
STSPIN820_SetDirection(deviceId, direction);
STSPIN820_ComputeSpeedProfile(deviceId, device_prm.stepsToTake);
/* Motor activation */
STSPIN820_StartMovement(deviceId);
}
}
/******************************************************//**
* @brief Move the motor to the absolute position
* @param[in] deviceId Unused parameter
* @param[in] direction FORWARD or BACKWARD
* @param[in] targetPosition 32 bit signed value position
* @retval None
* @note The position is at the resolution corresponding to the
* selected step mode.
* STEP_MODE_FULL : step
* STEP_MODE_HALF : 1/2 step
* STEP_MODE_1_4 : 1/4 step
* STEP_MODE_1_8 : 1/8 step
* STEP_MODE_1_16 : 1/16 step
* STEP_MODE_1_32 : 1/32 step
* STEP_MODE_1_128 : 1/128 step
* STEP_MODE_1_256 : 1/256 step
* @note The 1/64 step mode is not allowed
**********************************************************/
void STSPIN820::STSPIN820_GoToDir(uint8_t deviceId, motor_direction_t direction, int32_t targetPosition)
{
deviceId = 0;
/* Exit from standby if needed */
if (device_prm.motionState == STANDBY)
{
STSPIN820_ExitDeviceFromStandby(deviceId);
}
/* Deactivate motor if needed */
else if (device_prm.motionState != INACTIVE)
{
STSPIN820_HardHiZ(deviceId);
}
if (direction != BACKWARD)
{
if (targetPosition > device_prm.currentPosition)
{
device_prm.stepsToTake = targetPosition -\
device_prm.currentPosition;
}
else
{
device_prm.stepsToTake = STSPIN820_POSITION_RANGE +\
(targetPosition -\
device_prm.currentPosition);
}
}
else
{
if (targetPosition > device_prm.currentPosition)
{
device_prm.stepsToTake = STSPIN820_POSITION_RANGE +\
(device_prm.currentPosition -\
targetPosition);
}
else
{
device_prm.stepsToTake = device_prm.currentPosition -\
targetPosition;
}
}
if (device_prm.stepsToTake != 0)
{
device_prm.commandExecuted = MOVE_CMD;
/* Direction setup */
STSPIN820_SetDirection(deviceId, direction);
STSPIN820_ComputeSpeedProfile(deviceId, device_prm.stepsToTake);
/* Motor activation */
STSPIN820_StartMovement(deviceId);
}
}
/******************************************************//**
* @brief Immediatly stop the motor and disable the power bridge
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_HardHiZ(uint8_t deviceId)
{
/* Set inactive state */
device_prm.motionState = INACTIVE;
/* Disable step clock */
if (STSPIN820_Board_TimStckStop(handle &toggle_odd) == 0)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_STEP_CLOCK);
}
/* Let the PWM REF and bridges enabled at least for DISABLE_DELAY time */
/* after the last step clock rising edge triggering the last step */
STSPIN820_Board_Delay(DISABLE_DELAY);
/* Set reference voltage to 0 */
STSPIN820_SetTorque(0, CURRENT_TORQUE, 0);
/* Disable power bridges */
STSPIN820_Board_Disable();
/* Comeback to nominal step mode */
if (device_prm.stepModeLatched != device_prm.stepMode)
{
motor_step_mode_t StepMode = device_prm.stepModeLatched;
STSPIN820_SetStepMode(0, StepMode);
device_prm.stepMode = device_prm.stepModeLatched;
}
device_prm.commandExecuted = NO_CMD;
device_prm.stepsToTake = 0;
device_prm.speed = 0;
}
/******************************************************//**
* @brief Immediatly stop the motor
* and either set holding torque when stop mode is HOLD_MODE,
* or call STSPIN820_HardHiz function when stop mode is HIZ_MODE,
* or call STSPIN820_PutDeviceInStandby function when stop mode is STANDBY_MODE
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_HardStop(uint8_t deviceId)
{
deviceId = 0;
if (device_prm.stopMode == HOLD_MODE)
{
/* Set inactive state */
device_prm.motionState = INACTIVE;
/* Disable step clock */
if (STSPIN820_Board_TimStckStop(&toggle_odd) == 0)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_STEP_CLOCK);
}
/* Set holding torque */
STSPIN820_ApplyTorque(deviceId, HOLD_TORQUE);
/* Comeback to nominal step mode */
if (device_prm.stepModeLatched != device_prm.stepMode)
{
motor_step_mode_t StepMode = device_prm.stepModeLatched;
STSPIN820_SetStepMode(0, StepMode);
device_prm.stepMode = device_prm.stepModeLatched;
}
device_prm.commandExecuted = NO_CMD;
device_prm.stepsToTake = 0;
device_prm.speed = 0;
}
else if (device_prm.stopMode == HIZ_MODE)
{
STSPIN820_HardHiZ(deviceId);
}
else if (device_prm.stopMode == STANDBY_MODE)
{
STSPIN820_PutDeviceInStandby(deviceId);
}
}
/******************************************************//**
* @brief Moves the motor of the specified number of steps
* @param[in] deviceId Unused parameter
* @param[in] direction FORWARD or BACKWARD
* @param[in] stepCount Number of steps to perform
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_Move(uint8_t deviceId, motor_direction_t direction, uint32_t stepCount)
{
deviceId = 0;
/* Exit from standby if needed */
if (device_prm.motionState == STANDBY)
{
STSPIN820_ExitDeviceFromStandby(deviceId);
}
/* Deactivate motor if needed */
else if (device_prm.motionState != INACTIVE)
{
STSPIN820_HardHiZ(deviceId);
}
if (stepCount != 0)
{
device_prm.stepsToTake = stepCount;
device_prm.commandExecuted = MOVE_CMD;
/* Direction setup */
STSPIN820_SetDirection(deviceId, direction);
STSPIN820_ComputeSpeedProfile(deviceId, stepCount);
/* Motor activation */
STSPIN820_StartMovement(deviceId);
}
}
/******************************************************//**
* @brief Put STSPIN820 device in standby (low power consumption)
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_PutDeviceInStandby(uint8_t deviceId)
{
/* Stop movement */
STSPIN820_HardHiZ(deviceId);
/* Enter standby */
STSPIN820_Board_Reset();
device_prm.motionState = STANDBY;
}
/******************************************************//**
* @brief Runs the motor. It will accelerate from the min
* speed up to the max speed by using the device acceleration.
* @param[in] deviceId Unused parameter
* @param[in] direction FORWARD or BACKWARD
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_Run(uint8_t deviceId, motor_direction_t direction)
{
/* Exit from standby if needed */
if (device_prm.motionState == STANDBY)
{
STSPIN820_ExitDeviceFromStandby(deviceId);
}
/* Deactivate motor if needed */
else if (device_prm.motionState != INACTIVE)
{
STSPIN820_HardHiZ(deviceId);
}
/* Direction setup */
STSPIN820_SetDirection(deviceId,direction);
device_prm.commandExecuted = RUN_CMD;
/* Motor activation */
STSPIN820_StartMovement(deviceId);
}
/******************************************************//**
* @brief Changes the acceleration of the specified device
* @param[in] deviceId Unused parameter
* @param[in] newAcc New acceleration to apply in pps^2
* @retval true if the command is successfully executed, else false
* @note The command is not performed if the device is executing
* a MOVE or GOTO command (but it can be used during a RUN command)
**********************************************************/
bool STSPIN820::STSPIN820_SetAcceleration(uint8_t deviceId, uint16_t newAcc)
{
bool cmdExecuted = FALSE;
if ((newAcc != 0)&&
(((device_prm.motionState & INACTIVE) == INACTIVE)||
(device_prm.commandExecuted == RUN_CMD)))
{
device_prm.acceleration = newAcc;
cmdExecuted = TRUE;
}
return cmdExecuted;
}
/******************************************************//**
* @brief Specifies the decay mode
* @param[in] deviceId Unused parameter
* @param[in] decay SLOW_DECAY or MIXED_DECAY
* @retval true if the command is successfully executed, else false
**********************************************************/
void STSPIN820::STSPIN820_SetDecayMode(uint8_t deviceId, motor_decay_mode_t decay)
{
if (decay == SLOW_DECAY)
{
STSPIN820_Board_SetDecayGpio(1);
}
else if (decay == MIXED_DECAY)
{
STSPIN820_Board_SetDecayGpio(0);
}
}
/******************************************************//**
* @brief Changes the deceleration of the specified device
* @param[in] deviceId Unused parameter
* @param[in] newDec New deceleration to apply in pps^2
* @retval true if the command is successfully executed, else false
* @note The command is not performed if the device is executing
* a MOVE or GOTO command (but it can be used during a RUN command)
**********************************************************/
bool STSPIN820::STSPIN820_SetDeceleration(uint8_t deviceId, uint16_t newDec)
{
bool cmdExecuted = FALSE;
if ((newDec != 0)&&
(((device_prm.motionState & INACTIVE) == INACTIVE)||
(device_prm.commandExecuted == RUN_CMD)))
{
device_prm.deceleration = newDec;
cmdExecuted = TRUE;
}
return cmdExecuted;
}
/******************************************************//**
* @brief Specifies the direction
* @param[in] deviceId Unused parameter
* @param[in] dir FORWARD or BACKWARD
* @note The direction change is applied if the device
* is in INACTIVE or STANDBY state or if the device is
* executing a run command
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_SetDirection(uint8_t deviceId, motor_direction_t dir)
{
if ((device_prm.motionState == INACTIVE)||\
(device_prm.motionState == STANDBY))
{
device_prm.direction = dir;
STSPIN820_Board_SetDirectionGpio(dir);
}
else if ((device_prm.commandExecuted&RUN_CMD)!=0)
{
device_prm.commandExecuted|=STSPIN820_DIR_CHANGE_BIT_MASK;
}
}
/******************************************************//**
* @brief Set current position to be the Home position
* (current position set to 0)
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_SetHome(uint8_t deviceId)
{
device_prm.currentPosition = 0;
}
/******************************************************//**
* @brief Set current position to be the Mark position
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_SetMark(uint8_t deviceId)
{
device_prm.markPosition = device_prm.currentPosition;
}
/******************************************************//**
* @brief Changes the max speed of the specified device
* @param[in] deviceId Unused parameter
* @param[in] newMaxSpeed New max speed to apply in pps
* @retval true if the command is successfully executed, else false
* @note The command is not performed is the device is executing
* a MOVE or GOTO command (but it can be used during a RUN command).
**********************************************************/
bool STSPIN820::STSPIN820_SetMaxSpeed(uint8_t deviceId, uint16_t newMaxSpeed)
{
bool cmdExecuted = FALSE;
if ((newMaxSpeed >= STSPIN820_MIN_STCK_FREQ)&&\
((newMaxSpeed <= STSPIN820_MAX_STCK_FREQ)||\
((device_prm.torqueBoostEnable != FALSE)&&\
((newMaxSpeed>>STSPIN820_GetStepMode(deviceId))<= STSPIN820_MAX_STCK_FREQ)))&&\
(device_prm.minSpeed <= newMaxSpeed) &&\
(((device_prm.motionState & INACTIVE) == INACTIVE)||\
(device_prm.commandExecuted == RUN_CMD)))
{
device_prm.maxSpeed = newMaxSpeed;
cmdExecuted = TRUE;
}
return cmdExecuted;
}
/******************************************************//**
* @brief Changes the min speed of the specified device
* @param[in] deviceId Unused parameter
* @param[in] newMinSpeed New min speed to apply in pps
* @retval true if the command is successfully executed, else false
* @note The command is not performed is the device is executing
* a MOVE or GOTO command (but it can be used during a RUN command).
**********************************************************/
bool STSPIN820::STSPIN820_SetMinSpeed(uint8_t deviceId, uint16_t newMinSpeed)
{
bool cmdExecuted = FALSE;
if ((newMinSpeed >= STSPIN820_MIN_STCK_FREQ)&&
(newMinSpeed <= STSPIN820_MAX_STCK_FREQ) &&
(newMinSpeed <= device_prm.maxSpeed) &&
(((device_prm.motionState & INACTIVE) == INACTIVE)||
(device_prm.commandExecuted == RUN_CMD)))
{
device_prm.minSpeed = newMinSpeed;
cmdExecuted = TRUE;
}
return cmdExecuted;
}
/******************************************************//**
* @brief Sets the number of devices to be used
* @param[in] nbDevices (from 1 to MAX_NUMBER_OF_DEVICES)
* @retval TRUE if successfull, FALSE if failure, attempt to set a number of
* devices greater than MAX_NUMBER_OF_DEVICES
**********************************************************/
bool STSPIN820::STSPIN820_SetNbDevices(uint8_t nbDevices)
{
if (nbDevices <= MAX_NUMBER_OF_DEVICES)
{
number_of_devices = nbDevices;
return TRUE;
}
else
{
return FALSE;
}
}
/******************************************************//**
* @brief Set the stepping mode
* @param[in] deviceId Unused parameter
* @param[in] stepMode from full step to 1/256 microstep
* as specified in enum motor_step_mode_t
* 1/64 microstep mode not supported by STSPIN820
* @retval true if the command is successfully executed, else false
**********************************************************/
bool STSPIN820::STSPIN820_SetStepMode(uint8_t deviceId, motor_step_mode_t stepMode)
{
/* Store step mode */
device_prm.stepMode = stepMode;
device_prm.stepModeLatched = stepMode;
/* Set the mode pins to the levels corresponding to the selected step mode */
switch (stepMode)
{
case STEP_MODE_FULL:
STSPIN820_Board_SetFullStep();
break;
case STEP_MODE_HALF:
STSPIN820_Board_SetModePins(1, 0, 0);
break;
case STEP_MODE_1_4:
STSPIN820_Board_SetModePins(0, 1, 0);
break;
case STEP_MODE_1_8:
STSPIN820_Board_SetModePins(1, 1, 0);
break;
case STEP_MODE_1_16:
STSPIN820_Board_SetModePins(0, 0, 1);
break;
case STEP_MODE_1_32:
STSPIN820_Board_SetModePins(1, 0, 1);
break;
case STEP_MODE_1_128:
STSPIN820_Board_SetModePins(0, 1, 1);
break;
case STEP_MODE_1_256:
STSPIN820_Board_SetModePins(1, 1, 1);
break;
default:
return FALSE;
}
return TRUE;
}
/******************************************************//**
* @brief Select the mode to stop the motor.
* @param[in] deviceId Unused parameter
* @param[in] stopMode HOLD_MODE to let power bridge enabled
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_SetStopMode(uint8_t deviceId, motor_stop_mode_t stopMode)
{
device_prm.stopMode = stopMode;
}
/******************************************************//**
* @brief Set the torque of the specified device
* @param[in] deviceId Unused parameter
* @param[in] torqueMode Torque mode as specified in enum motor_torque_mode_t
* @param[in] torqueValue in % (from 0 to 100)
* @retval None
* @note
**********************************************************/
void STSPIN820::STSPIN820_SetTorque(uint8_t deviceId, motor_torque_mode_t torqueMode, uint8_t torqueValue)
{
device_prm.updateTorque = TRUE;
if (torqueValue>100)
{
torqueValue = 100;
}
switch(torqueMode)
{
case ACC_TORQUE:
device_prm.accelTorque = torqueValue;
break;
case DEC_TORQUE:
device_prm.decelTorque = torqueValue;
break;
case RUN_TORQUE:
device_prm.runTorque = torqueValue;
break;
case HOLD_TORQUE:
device_prm.holdTorque = torqueValue;
if (device_prm.motionState != INACTIVE)
{
break;
}
case CURRENT_TORQUE:
device_prm.currentTorque = torqueValue;
STSPIN820_Board_PwmRefSetFreqAndDutyCycle(device_prm.refPwmFreq,torqueValue);
default:
device_prm.updateTorque = FALSE;
break; //ignore error
}
}
/******************************************************//**
* @brief Enable or disable the torque boost feature
* @param[in] deviceId Unused parameter
* @param[in] enable true to enable torque boost, false to disable
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_SetTorqueBoostEnable(uint8_t deviceId, bool enable)
{
device_prm.torqueBoostEnable = enable;
}
/******************************************************//**
* @brief Set the torque boost threshold
* @param[in] deviceId (from 0 to MAX_NUMBER_OF_DEVICES - 1)
* @param[in] speedThreshold speed threshold above which the step mode is
* changed to full step
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_SetTorqueBoostThreshold(uint8_t deviceId, uint16_t speedThreshold)
{
device_prm.torqueBoostSpeedThreshold = speedThreshold;
}
/******************************************************//**
* @brief Stops the motor by using the device deceleration
* @param[in] deviceId Unused parameter
* @retval true if the command is successfully executed, else false
* @note The command is not performed if the device is in INACTIVE,
* STANDBYTOINACTIVE or STANDBY state.
**********************************************************/
bool STSPIN820::STSPIN820_SoftStop(uint8_t deviceId)
{
bool cmdExecuted = FALSE;
if ((device_prm.motionState & INACTIVE) != INACTIVE)
{
device_prm.commandExecuted |= STSPIN820_SOFT_STOP_BIT_MASK;
cmdExecuted = TRUE;
}
return (cmdExecuted);
}
/******************************************************//**
* @brief Get the frequency of REF PWM of the specified device
* @param[in] deviceId Unused parameter
* @retval the frequency of REF PWM in Hz
* @note
**********************************************************/
uint32_t STSPIN820::STSPIN820_VrefPwmGetFreq(uint8_t deviceId)
{
return device_prm.refPwmFreq;
}
/******************************************************//**
* @brief Set the frequency of REF PWM of the specified device
* @param[in] deviceId Unused parameter
* @param[in] newFreq in Hz
* @retval None
* @note
**********************************************************/
void STSPIN820::STSPIN820_VrefPwmSetFreq(uint8_t deviceId, uint32_t newFreq)
{
device_prm.refPwmFreq = newFreq;
STSPIN820_Board_PwmRefSetFreqAndDutyCycle(newFreq,device_prm.currentTorque);
}
/******************************************************//**
* @brief Locks until the device state becomes Inactive
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_WaitWhileActive(uint8_t deviceId)
{
/* Wait while motor is running */
while (((STSPIN820_GetDeviceState(deviceId)&INACTIVE)!=INACTIVE)||\
(((STSPIN820_GetDeviceState(deviceId)&INACTIVE)==INACTIVE)&&(toggle_odd!=0)));
}
/******************************************************//**
* @brief Updates the current speed of the device
* @param[in] deviceId Unused parameter
* @param[in] newSpeed in pps
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_ApplySpeed(uint8_t deviceId, uint16_t newSpeed)
{
if (device_prm.torqueBoostEnable != FALSE)
{
if (device_prm.stepMode > STEP_MODE_1_256)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_APPLY_SPEED);
}
if (device_prm.stepMode != STEP_MODE_FULL)
{
if (((newSpeed>>device_prm.stepModeLatched)>\
device_prm.torqueBoostSpeedThreshold)&&\
(((device_prm.commandExecuted & STSPIN820_MOVE_BIT_MASK) != MOVE_CMD) ||\
((device_prm.stepsToTake-device_prm.relativePos)>=\
(1<<device_prm.stepModeLatched))))
{
if ((device_prm.sequencerPosition & 0xFF) == 0x80)
{
STSPIN820_Board_SetFullStep();
device_prm.stepMode = STEP_MODE_FULL;
device_prm.accu >>= device_prm.stepModeLatched;
newSpeed >>= device_prm.stepModeLatched;
}
}
}
else if (((newSpeed <= device_prm.torqueBoostSpeedThreshold) &&\
(device_prm.stepModeLatched != STEP_MODE_FULL))||\
(((device_prm.commandExecuted & STSPIN820_MOVE_BIT_MASK) == MOVE_CMD)&&\
((device_prm.stepsToTake-device_prm.relativePos)<=\
(1<<device_prm.stepModeLatched))))
{
STSPIN820_SetStepMode(0, device_prm.stepModeLatched);
device_prm.stepMode = device_prm.stepModeLatched;
device_prm.accu <<= device_prm.stepModeLatched;
newSpeed <<= device_prm.stepModeLatched;
}
}
else if (device_prm.stepMode != device_prm.stepModeLatched)
{
//torqueBoostEnable has just been disabled
STSPIN820_SetStepMode(0, device_prm.stepModeLatched);
device_prm.stepMode = device_prm.stepModeLatched;
device_prm.accu <<= device_prm.stepModeLatched;
newSpeed <<= device_prm.stepModeLatched;
}
if (newSpeed < STSPIN820_MIN_STCK_FREQ)
{
newSpeed = STSPIN820_MIN_STCK_FREQ;
}
if (newSpeed > STSPIN820_MAX_STCK_FREQ)
{
newSpeed = STSPIN820_MAX_STCK_FREQ;
}
device_prm.speed = newSpeed;
STSPIN820_Board_TimStckSetFreq(newSpeed);
}
/******************************************************//**
* @brief Apply the set torque to the specified device
* @param[in] deviceId Unused parameter
* @param[in] torqueMode torque mode
* @retval None
* @note
**********************************************************/
void STSPIN820::STSPIN820_ApplyTorque(uint8_t deviceId, motor_torque_mode_t torqueMode)
{
uint8_t torqueValue = 0;
device_prm.updateTorque = FALSE;
switch(torqueMode)
{
case ACC_TORQUE:
device_prm.currentTorque = device_prm.accelTorque;
break;
case DEC_TORQUE:
device_prm.currentTorque = device_prm.decelTorque;
break;
case RUN_TORQUE:
device_prm.currentTorque = device_prm.runTorque;
break;
case HOLD_TORQUE:
device_prm.currentTorque = device_prm.holdTorque;
break;
case CURRENT_TORQUE:
break;
default:
return; //ignore error
}
torqueValue = device_prm.currentTorque;
STSPIN820_Board_PwmRefSetFreqAndDutyCycle(device_prm.refPwmFreq,torqueValue);
}
/******************************************************//**
* @brief Computes the speed profile according to the number of steps to move
* @param[in] deviceId Unused parameter
* @param[in] nbSteps number of steps to perform
* @retval None
* @note Using the acceleration and deceleration of the device,
* this function determines the duration in steps of the acceleration,
* steady and deceleration phases.
* If the total number of steps to perform is big enough, a trapezoidal move
* is performed (i.e. there is a steady phase where the motor runs at the maximum
* speed.
* Else, a triangular move is performed (no steady phase: the maximum speed is never
* reached.
**********************************************************/
void STSPIN820::STSPIN820_ComputeSpeedProfile(uint8_t deviceId, uint32_t nbSteps)
{
uint32_t reqAccSteps;
uint32_t reqDecSteps;
/* compute the number of steps to get the targeted speed */
uint16_t minSpeed = device_prm.minSpeed;
reqAccSteps = (device_prm.maxSpeed - minSpeed);
reqAccSteps *= (device_prm.maxSpeed + minSpeed);
reqDecSteps = reqAccSteps;
reqAccSteps /= (uint32_t)device_prm.acceleration;
reqAccSteps /= 2;
/* compute the number of steps to stop */
reqDecSteps /= (uint32_t)device_prm.deceleration;
reqDecSteps /= 2;
if(( reqAccSteps + reqDecSteps ) > nbSteps)
{
/* Triangular move */
/* reqDecSteps = (Pos * Dec) /(Dec+Acc) */
uint32_t dec = device_prm.deceleration;
uint32_t acc = device_prm.acceleration;
reqDecSteps = ((uint32_t) dec * nbSteps) / (acc + dec);
if (reqDecSteps > 1)
{
reqAccSteps = reqDecSteps - 1;
if(reqAccSteps == 0)
{
reqAccSteps = 1;
}
}
else
{
reqAccSteps = 0;
}
device_prm.endAccPos = reqAccSteps;
device_prm.startDecPos = reqDecSteps;
}
else
{
/* Trapezoidal move */
/* accelerating phase to endAccPos */
/* steady phase from endAccPos to startDecPos */
/* decelerating from startDecPos to stepsToTake*/
device_prm.endAccPos = reqAccSteps;
device_prm.startDecPos = nbSteps - reqDecSteps - 1;
}
}
/******************************************************//**
* @brief Handlers of the flag interrupt which calls the user callback (if defined)
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_FlagInterruptHandler(void)
{
if (flag_interrupt_callback != 0)
{
flag_interrupt_callback();
}
}
/******************************************************//**
* @brief Set the parameters of the device whose values are not defined in
* STSPIN820_config.h
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_SetDeviceParamsOtherValues(void)
{
uint16_t tmp;
device_prm.accu = 0;
device_prm.currentPosition = 0;
device_prm.sequencerPosition = 0;
device_prm.endAccPos = 0;
device_prm.relativePos = 0;
device_prm.startDecPos = 0;
device_prm.stepsToTake = 0;
device_prm.updateTorque = FALSE;
device_prm.speed = 0;
device_prm.commandExecuted = NO_CMD;
device_prm.direction = FORWARD;
tmp = device_prm.minSpeed;
if (((device_prm.torqueBoostEnable != FALSE)&&\
(device_prm.torqueBoostSpeedThreshold>STSPIN820_MAX_STCK_FREQ))||\
(tmp>device_prm.maxSpeed))
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_INIT);
}
}
/******************************************************//**
* @brief Set the parameters of the device to values of initDevicePrm structure
* @param pInitDevicePrm structure containing values to initialize the device
* parameters
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_SetDeviceParamsToGivenValues(STSPIN820_init_t* pInitDevicePrm)
{
device_prm.motionState = STANDBY;;
if (STSPIN820_SetAcceleration(0,pInitDevicePrm->acceleration)==FALSE)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_SET_ACCELERATION);
}
if (STSPIN820_SetDeceleration(0,pInitDevicePrm->deceleration)==FALSE)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_SET_DECELERATION);
}
if (STSPIN820_SetMaxSpeed(0,pInitDevicePrm->maxSpeed)==FALSE)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_SET_MAX_SPEED);
}
if (STSPIN820_SetMinSpeed(0,pInitDevicePrm->minSpeed)==FALSE)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_SET_MIN_SPEED);
}
STSPIN820_VrefPwmSetFreq(0,pInitDevicePrm->vrefPwmFreq);
STSPIN820_SetTorque(0,ACC_TORQUE,pInitDevicePrm->accelTorque);
STSPIN820_SetTorque(0,DEC_TORQUE,pInitDevicePrm->decelTorque);
STSPIN820_SetTorque(0,RUN_TORQUE,pInitDevicePrm->runTorque);
STSPIN820_SetTorque(0,HOLD_TORQUE,pInitDevicePrm->holdTorque);
device_prm.torqueBoostEnable = pInitDevicePrm->torqueBoostEnable;
device_prm.torqueBoostSpeedThreshold = pInitDevicePrm->torqueBoostSpeedThreshold;
STSPIN820_SetStopMode(0,pInitDevicePrm->stopMode);
STSPIN820_SetDeviceParamsOtherValues();
/* Eventually deactivate motor */
if ((device_prm.motionState != INACTIVE)&&\
(device_prm.motionState != STANDBY))
{
STSPIN820_HardHiZ(0);
}
/* Enter standby */
STSPIN820_Board_Reset();
/* Reset the microstepping sequencer position */
device_prm.sequencerPosition = 0;
/* Reset current and mark positions */
device_prm.currentPosition = 0;
device_prm.markPosition = 0;
/* Set predefined step mode */
STSPIN820_SetStepMode(0, pInitDevicePrm->stepMode);
/* Wait */
STSPIN820_Board_Delay(SELECT_STEP_MODE_DELAY);
/* Exit standby */
STSPIN820_Board_ReleaseReset();
/* Let a delay after reset release*/
STSPIN820_Board_Delay(AFTER_STANDBY_EXIT_DEAD_TIME);
}
/******************************************************//**
* @brief Sets the parameters of the device to predefined values
* from STSPIN820_config.h
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_SetDeviceParamsToPredefinedValues(void)
{
device_prm.motionState = STANDBY;
if (STSPIN820_SetAcceleration(0,STSPIN820_CONF_PARAM_ACC)==FALSE)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_SET_ACCELERATION);
}
if (STSPIN820_SetDeceleration(0,STSPIN820_CONF_PARAM_DEC)==FALSE)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_SET_DECELERATION);
}
if (STSPIN820_SetMaxSpeed(0,STSPIN820_CONF_PARAM_RUNNING_SPEED)==FALSE)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_SET_MAX_SPEED);
}
if (STSPIN820_SetMinSpeed(0,STSPIN820_CONF_PARAM_MIN_SPEED)==FALSE)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_SET_MIN_SPEED);
}
STSPIN820_VrefPwmSetFreq(0,STSPIN820_CONF_PARAM_REF_PWM_FREQUENCY);
STSPIN820_SetTorque(0,ACC_TORQUE,STSPIN820_CONF_PARAM_ACC_TORQUE);
STSPIN820_SetTorque(0,DEC_TORQUE,STSPIN820_CONF_PARAM_DEC_TORQUE);
STSPIN820_SetTorque(0,RUN_TORQUE,STSPIN820_CONF_PARAM_RUNNING_TORQUE);
STSPIN820_SetTorque(0,HOLD_TORQUE,STSPIN820_CONF_PARAM_HOLDING_TORQUE);
device_prm.torqueBoostEnable = STSPIN820_CONF_PARAM_TORQUE_BOOST_EN;
device_prm.torqueBoostSpeedThreshold = STSPIN820_CONF_PARAM_TORQUE_BOOST_TH;
STSPIN820_SetStopMode(0,STSPIN820_CONF_PARAM_AUTO_HIZ_STOP);
STSPIN820_SetDeviceParamsOtherValues();
/* Eventually deactivate motor */
if ((device_prm.motionState != INACTIVE)&&\
(device_prm.motionState != STANDBY))
{
STSPIN820_HardHiZ(0);
}
/* Enter standby */
STSPIN820_Board_Reset();
/* Reset the microstepping sequencer position */
device_prm.sequencerPosition = 0;
/* Reset current and mark positions */
device_prm.currentPosition = 0;
device_prm.markPosition = 0;
/* Set predefined step mode */
STSPIN820_SetStepMode(0, STSPIN820_CONF_PARAM_STEP_MODE);
/* Wait */
STSPIN820_Board_Delay(SELECT_STEP_MODE_DELAY);
/* Exit standby */
STSPIN820_Board_ReleaseReset();
/* Let a delay after reset release*/
STSPIN820_Board_Delay(AFTER_STANDBY_EXIT_DEAD_TIME);
}
/******************************************************//**
* @brief Initialises the bridge parameters to start the movement
* and enable the power bridge
* @param[in] deviceId Unused parameter
* @retval None
**********************************************************/
void STSPIN820::STSPIN820_StartMovement(uint8_t deviceId)
{
deviceId = 0;
/* Enable STSPIN820 powerstage */
STSPIN820_Enable(deviceId);
toggle_odd = 0;
device_prm.accu = 0;
device_prm.relativePos = 0;
if ((device_prm.endAccPos == 0)&&\
(device_prm.commandExecuted != RUN_CMD))
{
device_prm.motionState = DECELERATING;
STSPIN820_ApplyTorque(deviceId, DEC_TORQUE);
}
else
{
device_prm.motionState = ACCELERATING;
STSPIN820_ApplyTorque(deviceId, ACC_TORQUE);
}
STSPIN820_Board_PwmRefStart();
/* Initialize the step clock timer */
STSPIN820_Board_TimStckInit();
/* Program the step clock */
STSPIN820_Board_TimStckCompareInit();
STSPIN820_ApplySpeed(deviceId, device_prm.minSpeed);
STSPIN820_Board_TimStckStart();
}
/******************************************************//**
* @brief Handles the device state machine at each pulse
* @param[in] deviceId Unused parameter
* @retval None
* @note Must only be called by the timer ISR
**********************************************************/
void STSPIN820::STSPIN820_StepClockHandler(uint8_t deviceId)
{
uint32_t stepModeShift = device_prm.stepModeLatched - device_prm.stepMode;
uint16_t tmp;
deviceId = 0;
if (device_prm.motionState == STANDBYTOINACTIVE)
{
if (toggle_odd != 0)
{
toggle_odd = 0;
if (device_prm.sequencerPosition == 0)
{
if (STSPIN820_Board_TimStckStop(&toggle_odd) == 0)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_STEP_CLOCK);
}
return;
}
}
else
{
toggle_odd = 1;
tmp = (1 << (STEP_MODE_1_256-device_prm.stepMode));
device_prm.sequencerPosition -= tmp;
}
STSPIN820_Board_TimStckSetFreq(STSPIN820_MAX_STCK_FREQ);
return;
}
if (toggle_odd == 0)
{
toggle_odd = 1;
}
else
{
toggle_odd = 0;
/* Incrementation of the relative position */
device_prm.relativePos += (1 << stepModeShift);
/* Incrementation of the current position */
if (device_prm.direction != BACKWARD)
{
device_prm.currentPosition += (1 << stepModeShift);
tmp = (1 << (STEP_MODE_1_256-device_prm.stepMode));
device_prm.sequencerPosition += tmp;
if (device_prm.sequencerPosition >= (SEQUENCER_MAX_VALUE+1))
{
device_prm.sequencerPosition -= (SEQUENCER_MAX_VALUE+1);
}
}
else
{
device_prm.currentPosition -= (1 << stepModeShift);
tmp = (1 << (STEP_MODE_1_256-device_prm.stepMode));
device_prm.sequencerPosition -= tmp;
if (device_prm.sequencerPosition < 0)
{
device_prm.sequencerPosition += (SEQUENCER_MAX_VALUE+1);
}
}
switch (device_prm.motionState)
{
case ACCELERATING:
{
uint32_t relPos = device_prm.relativePos;
uint32_t endAccPos = device_prm.endAccPos;
uint16_t speed = device_prm.speed;
uint32_t acc = ((uint32_t)device_prm.acceleration << 16)>>stepModeShift;
if (((device_prm.commandExecuted&(STSPIN820_SOFT_STOP_BIT_MASK|STSPIN820_DIR_CHANGE_BIT_MASK))!=0)||\
((device_prm.commandExecuted==MOVE_CMD)&&(relPos>=device_prm.startDecPos)))
{
device_prm.motionState = DECELERATING;
device_prm.accu = 0;
/* Apply decelerating torque */
STSPIN820_ApplyTorque(deviceId, DEC_TORQUE);
}
else if ((speed>=(device_prm.maxSpeed>>stepModeShift))||\
((device_prm.commandExecuted==MOVE_CMD)&&(relPos >= endAccPos)))
{
device_prm.motionState = STEADY;
/* Apply running torque */
STSPIN820_ApplyTorque(deviceId, RUN_TORQUE);
}
else
{
bool speedUpdated = FALSE;
/* Go on accelerating */
if (speed==0)
{
speed =1;
}
device_prm.accu += acc / speed;
while (device_prm.accu>=(0X10000L))
{
device_prm.accu -= (0X10000L);
speed +=1;
speedUpdated = TRUE;
}
if (speedUpdated)
{
if (speed>(device_prm.maxSpeed>>stepModeShift))
{
speed = device_prm.maxSpeed>>stepModeShift;
}
device_prm.speed = speed;
}
if (device_prm.updateTorque!=FALSE)
{
/* Apply accelerating torque */
STSPIN820_ApplyTorque(deviceId, ACC_TORQUE);
}
}
break;
}
case STEADY:
{
uint16_t maxSpeed = device_prm.maxSpeed>>stepModeShift;
uint32_t relativePos = device_prm.relativePos;
if (device_prm.updateTorque!=FALSE)
{
/* Apply accelerating torque */
STSPIN820_ApplyTorque(deviceId, RUN_TORQUE);
}
if (((device_prm.commandExecuted&(STSPIN820_SOFT_STOP_BIT_MASK|STSPIN820_DIR_CHANGE_BIT_MASK))!=0)||\
((device_prm.commandExecuted==MOVE_CMD)&&\
(relativePos>=(device_prm.startDecPos)))||\
((device_prm.commandExecuted==RUN_CMD)&&\
(device_prm.speed>maxSpeed)))
{
device_prm.motionState = DECELERATING;
device_prm.accu = 0;
/* Apply decelerating torque */
STSPIN820_ApplyTorque(deviceId, DEC_TORQUE);
}
else if ((device_prm.commandExecuted==RUN_CMD)&&(device_prm.speed<maxSpeed))
{
device_prm.motionState = ACCELERATING;
device_prm.accu = 0;
/* Apply accelerating torque */
STSPIN820_ApplyTorque(deviceId, ACC_TORQUE);
}
break;
}
case DECELERATING:
{
uint32_t relativePos = device_prm.relativePos;
uint16_t speed = device_prm.speed;
uint32_t dec = ((uint32_t)device_prm.deceleration << 16)>>stepModeShift;
if ((((device_prm.commandExecuted&(STSPIN820_SOFT_STOP_BIT_MASK|STSPIN820_DIR_CHANGE_BIT_MASK))!=0)&&\
(speed<=(device_prm.minSpeed>>stepModeShift)))||\
((device_prm.commandExecuted==MOVE_CMD)&&(relativePos>=device_prm.stepsToTake)))
{
/* Motion process complete */
if ((device_prm.commandExecuted&STSPIN820_DIR_CHANGE_BIT_MASK)!=0)
{
device_prm.commandExecuted&=~STSPIN820_DIR_CHANGE_BIT_MASK;
if (device_prm.direction==BACKWARD)
{
device_prm.direction=FORWARD;
}
else device_prm.direction=BACKWARD;
STSPIN820_Board_SetDirectionGpio(device_prm.direction);
if ((device_prm.commandExecuted&STSPIN820_SOFT_STOP_BIT_MASK)==0)
{
device_prm.motionState = ACCELERATING;
device_prm.accu = 0;
/* Apply accelerating torque */
STSPIN820_ApplyTorque(deviceId, ACC_TORQUE);
break;
}
}
if (device_prm.stopMode==HOLD_MODE)
{
STSPIN820_HardStop(deviceId);
}
else if (device_prm.stopMode==STANDBY_MODE)
{
STSPIN820_PutDeviceInStandby(deviceId);
}
else
{
STSPIN820_HardHiZ(deviceId);
}
}
else if ((device_prm.commandExecuted==RUN_CMD)&&
(speed<=(device_prm.maxSpeed>>stepModeShift)))
{
device_prm.motionState = STEADY;
/* Apply running torque */
STSPIN820_ApplyTorque(deviceId, RUN_TORQUE);
}
else
{
/* Go on decelerating */
if (speed>(device_prm.minSpeed>>stepModeShift))
{
bool speedUpdated = FALSE;
if (speed==0)
{
speed = 1;
}
device_prm.accu += dec / speed;
while (device_prm.accu>=(0X10000L))
{
device_prm.accu -= (0X10000L);
if (speed>1)
{
speed -=1;
}
speedUpdated = TRUE;
}
if (speedUpdated)
{
if (speed<(device_prm.minSpeed>>stepModeShift))
{
speed = device_prm.minSpeed>>stepModeShift;
}
device_prm.speed = speed;
}
if (device_prm.updateTorque!=FALSE)
{
/* Apply decelerating torque */
STSPIN820_ApplyTorque(deviceId, DEC_TORQUE);
}
}
}
break;
}
default:
{
break;
}
}
}
if ((device_prm.motionState & INACTIVE) != INACTIVE)
{
STSPIN820_ApplySpeed(deviceId, device_prm.speed);
}
else
{
if (STSPIN820_Board_TimStckStop(&toggle_odd) == 0)
{
STSPIN820_ErrorHandler(STSPIN820_ERROR_STEP_CLOCK);
}
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/