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.
Dependencies: ST_INTERFACES
Dependents: HelloWorld_IHM14A1
Fork of X_NUCLEO_IHM14A1 by
Diff: Components/STSPIN820/STSPIN820.cpp
- Revision:
- 1:bc265521eb00
- Child:
- 2:4fd08b67958c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Components/STSPIN820/STSPIN820.cpp Fri Apr 27 17:02:08 2018 +0000 @@ -0,0 +1,1799 @@ +/** + ****************************************************************************** + * @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****/