Speed profile working
Fork of Easyspin_lib by
Embed:
(wiki syntax)
Show/hide line numbers
easyspin.cpp
Go to the documentation of this file.
00001 /******************************************************//** 00002 * @file easyspin.cpp 00003 * @version V1.0 00004 * @date June 29, 2015 00005 * @brief easyspin library for mbed 00006 * 00007 * This file is free software; you can redistribute it and/or modify 00008 * it under the terms of either the GNU General Public License version 2 00009 * or the GNU Lesser General Public License version 2.1, both as 00010 * published by the Free Software Foundation. 00011 **********************************************************/ 00012 00013 #include "easyspin.h" 00014 #include "mbed.h" 00015 00016 const uint16_t Easyspin::prescalerArrayTimer0_1[PRESCALER_ARRAY_TIMER0_1_SIZE] = { 0, 1, 8, 64, 256, 1024}; 00017 const uint16_t Easyspin::prescalerArrayTimer2[PRESCALER_ARRAY_TIMER2_SIZE] = {0, 1, 8, 32, 64, 128, 256, 1024}; 00018 volatile void (*Easyspin::flagInterruptCallback)(void); 00019 volatile uint8_t Easyspin::numberOfShields; 00020 uint8_t Easyspin::spiTxBursts[Easyspin_CMD_ARG_MAX_NB_BYTES][MAX_NUMBER_OF_SHIELDS]; 00021 uint8_t Easyspin::spiRxBursts[Easyspin_CMD_ARG_MAX_NB_BYTES][MAX_NUMBER_OF_SHIELDS]; 00022 volatile bool Easyspin::spiPreemtionByIsr = false; 00023 volatile bool Easyspin::isrFlag = false; 00024 volatile class Easyspin* Easyspin::instancePtr = NULL; 00025 00026 /******************************************************//** 00027 * @brief Constructor 00028 * @param None 00029 * @retval None 00030 **********************************************************/ 00031 Easyspin::Easyspin():reset(Easyspin_Reset_Pin), dir1(Easyspin_DIR_1_Pin), dir2(Easyspin_DIR_2_Pin), 00032 dir3(Easyspin_DIR_3_Pin), CS(Easyspin_CS_Pin), flag(Easyspin_FLAG_Pin), pwm1(Easyspin_PWM_1_Pin), 00033 pwm2(Easyspin_PWM_2_Pin), pwm3(Easyspin_PWM_3_Pin), spi(Easyspin_MOSI_Pin, Easyspin_MISO_Pin, Easyspin_SCK_Pin) 00034 { 00035 uint8_t i; 00036 for (i = 0; i < MAX_NUMBER_OF_SHIELDS; i++) { 00037 shieldPrm[i].motionState = INACTIVE; 00038 shieldPrm[i].commandExecuted = NO_CMD; 00039 shieldPrm[i].stepsToTake = MAX_STEPS; 00040 } 00041 instancePtr = this; 00042 } 00043 00044 /******************************************************//** 00045 * @brief Attaches a user callback to the flag Interrupt 00046 * The call back will be then called each time the status 00047 * flag pin will be pulled down due to the occurrence of 00048 * a programmed alarms ( OCD, thermal pre-warning or 00049 * shutdown, UVLO, wrong command, non-performable command) 00050 * @param[in] callback Name of the callback to attach 00051 * to the Flag Interrupt 00052 * @retval None 00053 **********************************************************/ 00054 void Easyspin::AttachFlagInterrupt(void (*callback)(void)) 00055 { 00056 flagInterruptCallback = (volatile void (*)())callback; 00057 } 00058 00059 /******************************************************//** 00060 * @brief Starts the Easyspin library 00061 * @param[in] nbShields Number of Easyspin shields to use (from 1 to 3) 00062 * @retval None 00063 **********************************************************/ 00064 void Easyspin::Begin(uint8_t nbShields) 00065 { 00066 numberOfShields = nbShields; 00067 00068 // start the SPI library: 00069 //SPI.begin(); 00070 //SPI.setBitOrder(MSBFIRST); 00071 spi.format(8, 3); 00072 //SPI.setClockDivider(SPI_CLOCK_DIV4); 00073 00074 // flag pin 00075 //pinMode(Easyspin_FLAG_Pin, INPUT_PULLUP); 00076 flag.mode(PullUp); 00077 flag.fall(&FlagInterruptHandler); 00078 00079 //reset pin 00080 //pinMode(Easyspin_Reset_Pin, OUTPUT); 00081 00082 switch (nbShields) { 00083 case 3: 00084 //pinMode(Easyspin_DIR_3_Pin, OUTPUT); 00085 //pinMode(Easyspin_PWM_3_Pin, OUTPUT); 00086 PwmInit(2); 00087 case 2: 00088 //pinMode(Easyspin_DIR_2_Pin, OUTPUT); 00089 //pinMode(Easyspin_PWM_2_Pin, OUTPUT); 00090 PwmInit(1); 00091 case 1: 00092 //pinMode(Easyspin_DIR_1_Pin, OUTPUT); 00093 //pinMode(Easyspin_PWM_1_Pin, OUTPUT); 00094 PwmInit(0); 00095 default: 00096 ; 00097 } 00098 00099 /* Standby-reset deactivation */ 00100 ReleaseReset(); 00101 00102 /* Set all registers and context variables to the predefined values from Easyspin_target_config.h */ 00103 SetShieldParamsToPredefinedValues(); 00104 00105 /* Disable Easyspin powerstage */ 00106 for (uint32_t i = 0; i < nbShields; i++) { 00107 CmdDisable(i); 00108 /* Get Status to clear flags after start up */ 00109 CmdGetStatus(i); 00110 } 00111 } 00112 00113 /******************************************************//** 00114 * @brief Returns the acceleration of the specified shield 00115 * @param[in] shieldId (from 0 to 2) 00116 * @retval Acceleration in pps^2 00117 **********************************************************/ 00118 uint16_t Easyspin::GetAcceleration(uint8_t shieldId) 00119 { 00120 return (shieldPrm[shieldId].acceleration); 00121 } 00122 00123 /******************************************************//** 00124 * @brief Returns the current speed of the specified shield 00125 * @param[in] shieldId (from 0 to 2) 00126 * @retval Speed in pps 00127 **********************************************************/ 00128 uint16_t Easyspin::GetCurrentSpeed(uint8_t shieldId) 00129 { 00130 return shieldPrm[shieldId].speed; 00131 } 00132 00133 /******************************************************//** 00134 * @brief Returns the deceleration of the specified shield 00135 * @param[in] shieldId (from 0 to 2) 00136 * @retval Deceleration in pps^2 00137 **********************************************************/ 00138 uint16_t Easyspin::GetDeceleration(uint8_t shieldId) 00139 { 00140 return (shieldPrm[shieldId].deceleration); 00141 } 00142 00143 /******************************************************//** 00144 * @brief Returns the FW version of the library 00145 * @param None 00146 * @retval Easyspin_FW_VERSION 00147 **********************************************************/ 00148 uint8_t Easyspin::GetFwVersion(void) 00149 { 00150 return (Easyspin_FW_VERSION); 00151 } 00152 00153 /******************************************************//** 00154 * @brief Returns the mark position of the specified shield 00155 * @param[in] shieldId (from 0 to 2) 00156 * @retval Mark register value converted in a 32b signed integer 00157 **********************************************************/ 00158 int32_t Easyspin::GetMark(uint8_t shieldId) 00159 { 00160 return ConvertPosition(CmdGetParam(shieldId,Easyspin_MARK)); 00161 } 00162 00163 /******************************************************//** 00164 * @brief Returns the max speed of the specified shield 00165 * @param[in] shieldId (from 0 to 2) 00166 * @retval maxSpeed in pps 00167 **********************************************************/ 00168 uint16_t Easyspin::GetMaxSpeed(uint8_t shieldId) 00169 { 00170 return (shieldPrm[shieldId].maxSpeed); 00171 } 00172 00173 /******************************************************//** 00174 * @brief Returns the min speed of the specified shield 00175 * @param[in] shieldId (from 0 to 2) 00176 * @retval minSpeed in pps 00177 **********************************************************/ 00178 uint16_t Easyspin::GetMinSpeed(uint8_t shieldId) 00179 { 00180 return (shieldPrm[shieldId].minSpeed); 00181 } 00182 00183 /******************************************************//** 00184 * @brief Returns the ABS_POSITION of the specified shield 00185 * @param[in] shieldId (from 0 to 2) 00186 * @retval ABS_POSITION register value converted in a 32b signed integer 00187 **********************************************************/ 00188 int32_t Easyspin::GetPosition(uint8_t shieldId) 00189 { 00190 return ConvertPosition(CmdGetParam(shieldId,Easyspin_ABS_POS)); 00191 } 00192 00193 /******************************************************//** 00194 * @brief Returns the shield state 00195 * @param[in] shieldId (from 0 to 2) 00196 * @retval State (ACCELERATING, DECELERATING, STEADY or INACTIVE) 00197 **********************************************************/ 00198 shieldState_t Easyspin::GetShieldState(uint8_t shieldId) 00199 { 00200 return shieldPrm[shieldId].motionState; 00201 } 00202 00203 /******************************************************//** 00204 * @brief Requests the motor to move to the home position (ABS_POSITION = 0) 00205 * @param[in] shieldId (from 0 to 2) 00206 * @retval None 00207 **********************************************************/ 00208 void Easyspin::GoHome(uint8_t shieldId) 00209 { 00210 GoTo(shieldId, 0); 00211 } 00212 00213 /******************************************************//** 00214 * @brief Requests the motor to move to the mark position 00215 * @param[in] shieldId (from 0 to 2) 00216 * @retval None 00217 **********************************************************/ 00218 void Easyspin::GoMark(uint8_t shieldId) 00219 { 00220 uint32_t mark; 00221 00222 mark = ConvertPosition(CmdGetParam(shieldId,Easyspin_MARK)); 00223 GoTo(shieldId,mark); 00224 } 00225 00226 /******************************************************//** 00227 * @brief Requests the motor to move to the specified position 00228 * @param[in] shieldId (from 0 to 2) 00229 * @param[in] targetPosition absolute position in steps 00230 * @retval None 00231 **********************************************************/ 00232 void Easyspin::GoTo(uint8_t shieldId, int32_t targetPosition) 00233 { 00234 dir_t direction; 00235 int32_t steps; 00236 00237 /* Eventually deactivate motor */ 00238 if (shieldPrm[shieldId].motionState != INACTIVE) { 00239 HardStop(shieldId); 00240 } 00241 00242 /* Get current position */ 00243 shieldPrm[shieldId].currentPosition = ConvertPosition(CmdGetParam(shieldId,Easyspin_ABS_POS)); 00244 00245 /* Compute the number of steps to perform */ 00246 steps = targetPosition - shieldPrm[shieldId].currentPosition; 00247 00248 if (steps >= 0) { 00249 shieldPrm[shieldId].stepsToTake = steps; 00250 direction = FORWARD; 00251 00252 } else { 00253 shieldPrm[shieldId].stepsToTake = -steps; 00254 direction = BACKWARD; 00255 } 00256 00257 if (steps != 0) { 00258 00259 shieldPrm[shieldId].commandExecuted = MOVE_CMD; 00260 00261 /* Direction setup */ 00262 SetDirection(shieldId,direction); 00263 00264 ComputeSpeedProfile(shieldId, shieldPrm[shieldId].stepsToTake); 00265 00266 /* Motor activation */ 00267 StartMovement(shieldId); 00268 } 00269 } 00270 00271 /******************************************************//** 00272 * @brief Immediatly stops the motor and disable the power bridge 00273 * @param[in] shieldId (from 0 to 2) 00274 * @retval None 00275 **********************************************************/ 00276 void Easyspin::HardStop(uint8_t shieldId) 00277 { 00278 /* Disable corresponding PWM */ 00279 PwmStop(shieldId); 00280 00281 /* Disable power stage */ 00282 CmdDisable(shieldId); 00283 00284 /* Set inactive state */ 00285 shieldPrm[shieldId].motionState = INACTIVE; 00286 shieldPrm[shieldId].commandExecuted = NO_CMD; 00287 shieldPrm[shieldId].stepsToTake = MAX_STEPS; 00288 00289 #ifdef _DEBUG_Easyspin 00290 Serial.println("Inactive\n"); 00291 #endif 00292 } 00293 00294 /******************************************************//** 00295 * @brief Moves the motor of the specified number of steps 00296 * @param[in] shieldId (from 0 to 2) 00297 * @param[in] direction FORWARD or BACKWARD 00298 * @param[in] stepCount Number of steps to perform 00299 * @retval None 00300 **********************************************************/ 00301 void Easyspin::Move(uint8_t shieldId, dir_t direction, uint32_t stepCount) 00302 { 00303 /* Eventually deactivate motor */ 00304 if (shieldPrm[shieldId].motionState != INACTIVE) { 00305 HardStop(shieldId); 00306 } 00307 00308 if (stepCount != 0) { 00309 shieldPrm[shieldId].stepsToTake = stepCount; 00310 00311 shieldPrm[shieldId].commandExecuted = MOVE_CMD; 00312 00313 shieldPrm[shieldId].currentPosition = ConvertPosition(CmdGetParam(shieldId,Easyspin_ABS_POS)); 00314 00315 /* Direction setup */ 00316 SetDirection(shieldId,direction); 00317 00318 ComputeSpeedProfile(shieldId, stepCount); 00319 00320 /* Motor activation */ 00321 StartMovement(shieldId); 00322 } 00323 } 00324 00325 00326 /******************************************************//** 00327 * @brief Turn left or right with the specified angle 00328 * @param[in] rotation RIGHT or LEFT 00329 * @param[in] angle in degrees 00330 * @retval None 00331 **********************************************************/ 00332 void Easyspin::Turn(rot_t rotation, uint16_t angle) 00333 { 00334 uint16_t nbStep = (10934*angle)/360; 00335 if(rotation==RIGHT) { 00336 Move(0, FORWARD, nbStep); 00337 Move(1, FORWARD, nbStep); 00338 } else { 00339 Move(0, BACKWARD, nbStep); 00340 Move(1, BACKWARD, nbStep); 00341 } 00342 } 00343 00344 /******************************************************//** 00345 * @brief Move forward or backward with the specified distance 00346 * @param[in] direction FORWARD or BACKWARD 00347 * @param[in] distance in cm 00348 * @retval None 00349 **********************************************************/ 00350 void Easyspin::Move_cm(dir_t direction, uint16_t distance) 00351 { 00352 uint16_t nbStep = (10000 * distance)/61; 00353 if(direction==FORWARD) { 00354 Move(0, FORWARD, nbStep); 00355 Move(1, BACKWARD, nbStep); 00356 } else { 00357 Move(0, BACKWARD, nbStep); 00358 Move(1, FORWARD, nbStep); 00359 } 00360 } 00361 00362 /******************************************************//** 00363 * @brief Resets all Easyspin shields 00364 * @param None 00365 * @retval None 00366 **********************************************************/ 00367 void Easyspin::ResetAllShields(void) 00368 { 00369 uint8_t loop; 00370 00371 for (loop = 0; loop < numberOfShields; loop++) { 00372 /* Stop movement and disable power stage*/ 00373 HardStop(loop); 00374 } 00375 Reset(); 00376 wait_us(20); // Reset pin must be forced low for at least 10us 00377 ReleaseReset(); 00378 } 00379 00380 /******************************************************//** 00381 * @brief Runs the motor. It will accelerate from the min 00382 * speed up to the max speed by using the shield acceleration. 00383 * @param[in] shieldId (from 0 to 2) 00384 * @param[in] direction FORWARD or BACKWARD 00385 * @retval None 00386 **********************************************************/ 00387 void Easyspin::Run(uint8_t shieldId, dir_t direction) 00388 { 00389 /* Eventually deactivate motor */ 00390 if (shieldPrm[shieldId].motionState != INACTIVE) { 00391 HardStop(shieldId); 00392 } 00393 00394 /* Direction setup */ 00395 SetDirection(shieldId,direction); 00396 00397 shieldPrm[shieldId].commandExecuted = RUN_CMD; 00398 00399 /* Motor activation */ 00400 StartMovement(shieldId); 00401 } 00402 00403 /******************************************************//** 00404 * @brief Changes the acceleration of the specified shield 00405 * @param[in] shieldId (from 0 to 2) 00406 * @param[in] newAcc New acceleration to apply in pps^2 00407 * @retval true if the command is successfully executed, else false 00408 * @note The command is not performed is the shield is executing 00409 * a MOVE or GOTO command (but it can be used during a RUN command) 00410 **********************************************************/ 00411 bool Easyspin::SetAcceleration(uint8_t shieldId,uint16_t newAcc) 00412 { 00413 bool cmdExecuted = false; 00414 if ((newAcc != 0)&& 00415 ((shieldPrm[shieldId].motionState == INACTIVE)|| 00416 (shieldPrm[shieldId].commandExecuted == RUN_CMD))) { 00417 shieldPrm[shieldId].acceleration = newAcc; 00418 cmdExecuted = true; 00419 } 00420 return cmdExecuted; 00421 } 00422 00423 /******************************************************//** 00424 * @brief Changes the deceleration of the specified shield 00425 * @param[in] shieldId (from 0 to 2) 00426 * @param[in] newDec New deceleration to apply in pps^2 00427 * @retval true if the command is successfully executed, else false 00428 * @note The command is not performed is the shield is executing 00429 * a MOVE or GOTO command (but it can be used during a RUN command) 00430 **********************************************************/ 00431 bool Easyspin::SetDeceleration(uint8_t shieldId, uint16_t newDec) 00432 { 00433 bool cmdExecuted = false; 00434 if ((newDec != 0)&& 00435 ((shieldPrm[shieldId].motionState == INACTIVE)|| 00436 (shieldPrm[shieldId].commandExecuted == RUN_CMD))) { 00437 shieldPrm[shieldId].deceleration = newDec; 00438 cmdExecuted = true; 00439 } 00440 return cmdExecuted; 00441 } 00442 00443 /******************************************************//** 00444 * @brief Set current position to be the Home position (ABS pos set to 0) 00445 * @param[in] shieldId (from 0 to 2) 00446 * @retval None 00447 **********************************************************/ 00448 void Easyspin::SetHome(uint8_t shieldId) 00449 { 00450 CmdSetParam(shieldId, Easyspin_ABS_POS, 0); 00451 } 00452 00453 /******************************************************//** 00454 * @brief Sets current position to be the Mark position 00455 * @param[in] shieldId (from 0 to 2) 00456 * @retval None 00457 **********************************************************/ 00458 void Easyspin::SetMark(uint8_t shieldId) 00459 { 00460 uint32_t mark = CmdGetParam(shieldId,Easyspin_ABS_POS); 00461 CmdSetParam(shieldId,Easyspin_MARK, mark); 00462 } 00463 00464 /******************************************************//** 00465 * @brief Changes the max speed of the specified shield 00466 * @param[in] shieldId (from 0 to 2) 00467 * @param[in] newMaxSpeed New max speed to apply in pps 00468 * @retval true if the command is successfully executed, else false 00469 * @note The command is not performed is the shield is executing 00470 * a MOVE or GOTO command (but it can be used during a RUN command). 00471 **********************************************************/ 00472 bool Easyspin::SetMaxSpeed(uint8_t shieldId, uint16_t newMaxSpeed) 00473 { 00474 bool cmdExecuted = false; 00475 if ((newMaxSpeed > Easyspin_MIN_PWM_FREQ)&& 00476 (newMaxSpeed <= Easyspin_MAX_PWM_FREQ) && 00477 (shieldPrm[shieldId].minSpeed <= newMaxSpeed) && 00478 ((shieldPrm[shieldId].motionState == INACTIVE)|| 00479 (shieldPrm[shieldId].commandExecuted == RUN_CMD))) { 00480 shieldPrm[shieldId].maxSpeed = newMaxSpeed; 00481 cmdExecuted = true; 00482 } 00483 return cmdExecuted; 00484 } 00485 00486 /******************************************************//** 00487 * @brief Changes the min speed of the specified shield 00488 * @param[in] shieldId (from 0 to 2) 00489 * @param[in] newMinSpeed New min speed to apply in pps 00490 * @retval true if the command is successfully executed, else false 00491 * @note The command is not performed is the shield is executing 00492 * a MOVE or GOTO command (but it can be used during a RUN command). 00493 **********************************************************/ 00494 bool Easyspin::SetMinSpeed(uint8_t shieldId, uint16_t newMinSpeed) 00495 { 00496 bool cmdExecuted = false; 00497 if ((newMinSpeed >= Easyspin_MIN_PWM_FREQ)&& 00498 (newMinSpeed < Easyspin_MAX_PWM_FREQ) && 00499 (newMinSpeed <= shieldPrm[shieldId].maxSpeed) && 00500 ((shieldPrm[shieldId].motionState == INACTIVE)|| 00501 (shieldPrm[shieldId].commandExecuted == RUN_CMD))) { 00502 shieldPrm[shieldId].minSpeed = newMinSpeed; 00503 cmdExecuted = true; 00504 } 00505 return cmdExecuted; 00506 } 00507 00508 /******************************************************//** 00509 * @brief Stops the motor by using the shield deceleration 00510 * @param[in] shieldId (from 0 to 2) 00511 * @retval true if the command is successfully executed, else false 00512 * @note The command is not performed is the shield is in INACTIVE state. 00513 **********************************************************/ 00514 bool Easyspin::SoftStop(uint8_t shieldId) 00515 { 00516 bool cmdExecuted = false; 00517 if (shieldPrm[shieldId].motionState != INACTIVE) { 00518 shieldPrm[shieldId].commandExecuted = SOFT_STOP_CMD; 00519 cmdExecuted = true; 00520 } 00521 return (cmdExecuted); 00522 } 00523 00524 /******************************************************//** 00525 * @brief Locks until the shield state becomes Inactive 00526 * @param[in] shieldId (from 0 to 2) 00527 * @retval None 00528 **********************************************************/ 00529 void Easyspin::WaitWhileActive(uint8_t shieldId) 00530 { 00531 /* Wait while motor is running */ 00532 while (GetShieldState(shieldId) != INACTIVE); 00533 } 00534 00535 /******************************************************//** 00536 * @brief Issue the Disable command to the Easyspin of the specified shield 00537 * @param[in] shieldId (from 0 to 2) 00538 * @retval None 00539 **********************************************************/ 00540 void Easyspin::CmdDisable(uint8_t shieldId) 00541 { 00542 SendCommand(shieldId, Easyspin_DISABLE); 00543 } 00544 00545 /******************************************************//** 00546 * @brief Issues the Enable command to the Easyspin of the specified shield 00547 * @param[in] shieldId (from 0 to 2) 00548 * @retval None 00549 **********************************************************/ 00550 void Easyspin::CmdEnable(uint8_t shieldId) 00551 { 00552 SendCommand(shieldId, Easyspin_ENABLE); 00553 } 00554 00555 /******************************************************//** 00556 * @brief Issues the GetParam command to the Easyspin of the specified shield 00557 * @param[in] shieldId (from 0 to 2) 00558 * @param[in] param Register adress (Easyspin_ABS_POS, Easyspin_MARK,...) 00559 * @retval Register value 00560 **********************************************************/ 00561 uint32_t Easyspin::CmdGetParam(uint8_t shieldId, Easyspin_Registers_t param) 00562 { 00563 uint32_t i; 00564 uint32_t spiRxData; 00565 uint8_t maxArgumentNbBytes = 0; 00566 uint8_t spiIndex = numberOfShields - shieldId - 1; 00567 bool itDisable = false; 00568 00569 do { 00570 spiPreemtionByIsr = false; 00571 if (itDisable) { 00572 /* re-enable interrupts if disable in previous iteration */ 00573 flag.enable_irq(); 00574 itDisable = false; 00575 } 00576 00577 for (i = 0; i < numberOfShields; i++) { 00578 spiTxBursts[0][i] = Easyspin_NOP; 00579 spiTxBursts[1][i] = Easyspin_NOP; 00580 spiTxBursts[2][i] = Easyspin_NOP; 00581 spiTxBursts[3][i] = Easyspin_NOP; 00582 spiRxBursts[1][i] = 0; 00583 spiRxBursts[2][i] = 0; 00584 spiRxBursts[3][i] = 0; 00585 } 00586 switch (param) { 00587 case Easyspin_ABS_POS: 00588 ; 00589 case Easyspin_MARK: 00590 spiTxBursts[0][spiIndex] = ((uint8_t)Easyspin_GET_PARAM )| (param); 00591 maxArgumentNbBytes = 3; 00592 break; 00593 case Easyspin_EL_POS: 00594 ; 00595 case Easyspin_CONFIG: 00596 ; 00597 case Easyspin_STATUS: 00598 spiTxBursts[1][spiIndex] = ((uint8_t)Easyspin_GET_PARAM )| (param); 00599 maxArgumentNbBytes = 2; 00600 break; 00601 default: 00602 spiTxBursts[2][spiIndex] = ((uint8_t)Easyspin_GET_PARAM )| (param); 00603 maxArgumentNbBytes = 1; 00604 } 00605 00606 /* Disable interruption before checking */ 00607 /* pre-emption by ISR and SPI transfers*/ 00608 flag.disable_irq(); 00609 itDisable = true; 00610 } while (spiPreemtionByIsr); // check pre-emption by ISR 00611 00612 for (i = Easyspin_CMD_ARG_MAX_NB_BYTES-1-maxArgumentNbBytes; 00613 i < Easyspin_CMD_ARG_MAX_NB_BYTES; 00614 i++) { 00615 WriteBytes(&spiTxBursts[i][0], 00616 &spiRxBursts[i][0]); 00617 } 00618 00619 spiRxData = ((uint32_t)spiRxBursts[1][spiIndex] << 16)| 00620 (spiRxBursts[2][spiIndex] << 8) | 00621 (spiRxBursts[3][spiIndex]); 00622 00623 /* re-enable interrupts after SPI transfers*/ 00624 flag.enable_irq(); 00625 00626 return (spiRxData); 00627 } 00628 00629 /******************************************************//** 00630 * @brief Issues the GetStatus command to the Easyspin of the specified shield 00631 * @param[in] shieldId (from 0 to 2) 00632 * @retval Status Register value 00633 * @note Once the GetStatus command is performed, the flags of the status register 00634 * are reset. This is not the case when the status register is read with the 00635 * GetParam command (via the functions ReadStatusRegister or CmdGetParam). 00636 **********************************************************/ 00637 uint16_t Easyspin::CmdGetStatus(uint8_t shieldId) 00638 { 00639 uint32_t i; 00640 uint16_t status; 00641 uint8_t spiIndex = numberOfShields - shieldId - 1; 00642 bool itDisable = false; 00643 00644 do { 00645 spiPreemtionByIsr = false; 00646 if (itDisable) { 00647 /* re-enable interrupts if disable in previous iteration */ 00648 flag.enable_irq(); 00649 itDisable = false; 00650 } 00651 00652 for (i = 0; i < numberOfShields; i++) { 00653 spiTxBursts[0][i] = Easyspin_NOP; 00654 spiTxBursts[1][i] = Easyspin_NOP; 00655 spiTxBursts[2][i] = Easyspin_NOP; 00656 spiRxBursts[1][i] = 0; 00657 spiRxBursts[2][i] = 0; 00658 } 00659 spiTxBursts[0][spiIndex] = Easyspin_GET_STATUS; 00660 00661 /* Disable interruption before checking */ 00662 /* pre-emption by ISR and SPI transfers*/ 00663 flag.disable_irq(); 00664 itDisable = true; 00665 } while (spiPreemtionByIsr); // check pre-emption by ISR 00666 00667 for (i = 0; i < Easyspin_CMD_ARG_NB_BYTES_GET_STATUS + Easyspin_RSP_NB_BYTES_GET_STATUS; i++) { 00668 WriteBytes(&spiTxBursts[i][0], &spiRxBursts[i][0]); 00669 } 00670 status = (spiRxBursts[1][spiIndex] << 8) | (spiRxBursts[2][spiIndex]); 00671 00672 /* re-enable interrupts after SPI transfers*/ 00673 flag.enable_irq(); 00674 00675 return (status); 00676 } 00677 00678 /******************************************************//** 00679 * @brief Issues the Nop command to the Easyspin of the specified shield 00680 * @param[in] shieldId (from 0 to 2) 00681 * @retval None 00682 **********************************************************/ 00683 void Easyspin::CmdNop(uint8_t shieldId) 00684 { 00685 SendCommand(shieldId, Easyspin_NOP); 00686 } 00687 00688 /******************************************************//** 00689 * @brief Issues the SetParam command to the Easyspin of the specified shield 00690 * @param[in] shieldId (from 0 to 2) 00691 * @param[in] param Register adress (Easyspin_ABS_POS, Easyspin_MARK,...) 00692 * @param[in] value Value to set in the register 00693 * @retval None 00694 **********************************************************/ 00695 void Easyspin::CmdSetParam(uint8_t shieldId, 00696 Easyspin_Registers_t param, 00697 uint32_t value) 00698 { 00699 uint32_t i; 00700 uint8_t maxArgumentNbBytes = 0; 00701 uint8_t spiIndex = numberOfShields - shieldId - 1; 00702 bool itDisable = false; 00703 do { 00704 spiPreemtionByIsr = false; 00705 if (itDisable) { 00706 /* re-enable interrupts if disable in previous iteration */ 00707 flag.enable_irq();//interrupts(); 00708 itDisable = false; 00709 } 00710 for (i = 0; i < numberOfShields; i++) { 00711 spiTxBursts[0][i] = Easyspin_NOP; 00712 spiTxBursts[1][i] = Easyspin_NOP; 00713 spiTxBursts[2][i] = Easyspin_NOP; 00714 spiTxBursts[3][i] = Easyspin_NOP; 00715 } 00716 switch (param) { 00717 case Easyspin_ABS_POS: 00718 ; 00719 case Easyspin_MARK: 00720 spiTxBursts[0][spiIndex] = param; 00721 spiTxBursts[1][spiIndex] = (uint8_t)(value >> 16); 00722 spiTxBursts[2][spiIndex] = (uint8_t)(value >> 8); 00723 maxArgumentNbBytes = 3; 00724 break; 00725 case Easyspin_EL_POS: 00726 ; 00727 case Easyspin_CONFIG: 00728 spiTxBursts[1][spiIndex] = param; 00729 spiTxBursts[2][spiIndex] = (uint8_t)(value >> 8); 00730 maxArgumentNbBytes = 2; 00731 break; 00732 default: 00733 spiTxBursts[2][spiIndex] = param; 00734 maxArgumentNbBytes = 1; 00735 } 00736 spiTxBursts[3][spiIndex] = (uint8_t)(value); 00737 00738 /* Disable interruption before checking */ 00739 /* pre-emption by ISR and SPI transfers*/ 00740 flag.disable_irq(); 00741 itDisable = true; 00742 } while (spiPreemtionByIsr); // check pre-emption by ISR 00743 00744 /* SPI transfer */ 00745 for (i = Easyspin_CMD_ARG_MAX_NB_BYTES-1-maxArgumentNbBytes; 00746 i < Easyspin_CMD_ARG_MAX_NB_BYTES; 00747 i++) { 00748 WriteBytes(&spiTxBursts[i][0],&spiRxBursts[i][0]); 00749 } 00750 /* re-enable interrupts after SPI transfers*/ 00751 flag.enable_irq(); 00752 } 00753 00754 /******************************************************//** 00755 * @brief Reads the Status Register value 00756 * @param[in] shieldId (from 0 to 2) 00757 * @retval Status register valued 00758 * @note The status register flags are not cleared 00759 * at the difference with CmdGetStatus() 00760 **********************************************************/ 00761 uint16_t Easyspin::ReadStatusRegister(uint8_t shieldId) 00762 { 00763 return (CmdGetParam(shieldId,Easyspin_STATUS)); 00764 } 00765 00766 /******************************************************//** 00767 * @brief Releases the Easyspin reset (pin set to High) of all shields 00768 * @param None 00769 * @retval None 00770 **********************************************************/ 00771 void Easyspin::ReleaseReset(void) 00772 { 00773 reset = 1; 00774 } 00775 00776 /******************************************************//** 00777 * @brief Resets the Easyspin (reset pin set to low) of all shields 00778 * @param None 00779 * @retval None 00780 **********************************************************/ 00781 void Easyspin::Reset(void) 00782 { 00783 reset = 0; 00784 } 00785 00786 /******************************************************//** 00787 * @brief Set the stepping mode 00788 * @param[in] shieldId (from 0 to 2) 00789 * @param[in] stepMod from full step to 1/16 microstep as specified in enum Easyspin_STEP_SEL_t 00790 * @retval None 00791 **********************************************************/ 00792 void Easyspin::SelectStepMode(uint8_t shieldId, Easyspin_STEP_SEL_t stepMod) 00793 { 00794 uint8_t stepModeRegister; 00795 00796 /* Eventually deactivate motor */ 00797 if (shieldPrm[shieldId].motionState != INACTIVE) { 00798 HardStop(shieldId); 00799 } 00800 00801 /* Read Step mode register and clear STEP_SEL field */ 00802 stepModeRegister = (uint8_t)(0xF8 & CmdGetParam(shieldId,Easyspin_STEP_MODE)) ; 00803 00804 /* Apply new step mode */ 00805 CmdSetParam(shieldId, Easyspin_STEP_MODE, stepModeRegister | (uint8_t)stepMod); 00806 00807 /* Reset abs pos register */ 00808 SetHome(shieldId); 00809 } 00810 00811 /******************************************************//** 00812 * @brief Specifies the direction 00813 * @param[in] shieldId (from 0 to 2) 00814 * @param[in] dir FORWARD or BACKWARD 00815 * @note The direction change is only applied if the shield 00816 * is in INACTIVE state 00817 * @retval None 00818 **********************************************************/ 00819 void Easyspin::SetDirection(uint8_t shieldId, dir_t dir) 00820 { 00821 if (shieldPrm[shieldId].motionState == INACTIVE) { 00822 shieldPrm[shieldId].direction = dir; 00823 00824 switch (shieldId) { 00825 case 2: 00826 dir3 = dir; 00827 break; 00828 case 1: 00829 dir2 = dir; 00830 break; 00831 case 0: 00832 dir1 = dir; 00833 break; 00834 default: 00835 ; 00836 } 00837 } 00838 } 00839 00840 /******************************************************//** 00841 * @brief Gets the pointer to the Easyspin instance 00842 * @param None 00843 * @retval Pointer to the instance of Easyspin 00844 **********************************************************/ 00845 class Easyspin* Easyspin::GetInstancePtr(void) 00846 { 00847 return (class Easyspin*)instancePtr; 00848 } 00849 00850 /******************************************************//** 00851 * @brief Handles the shield state machine at each ste 00852 * @param[in] shieldId (from 0 to 2) 00853 * @retval None 00854 * @note Must only be called by the timer ISR 00855 **********************************************************/ 00856 void Easyspin::StepClockHandler(uint8_t shieldId) 00857 { 00858 /* Set isr flag */ 00859 isrFlag = true; 00860 00861 /* Incrementation of the relative position */ 00862 shieldPrm[shieldId].relativePos++; 00863 00864 /* Periodically check that estimated position is correct */ 00865 if ((shieldPrm[shieldId].commandExecuted != RUN_CMD) && 00866 ((shieldPrm[shieldId].relativePos % 10) == 00)) { 00867 uint32_t AbsPos= ConvertPosition(CmdGetParam(shieldId,Easyspin_ABS_POS)); 00868 00869 /* Correct estimated position if needed */ 00870 if (AbsPos != 0) { 00871 if ((shieldPrm[shieldId].direction == FORWARD) && 00872 (AbsPos != shieldPrm[shieldId].currentPosition + shieldPrm[shieldId].relativePos)) { 00873 #ifdef _DEBUG_Easyspin 00874 snprintf(EasyspinStrOut, DEBUG_BUFFER_SIZE, "F EstPos:%ld RealPos: %ld\n",shieldPrm[shieldId].relativePos,(AbsPos - shieldPrm[shieldId].currentPosition)); 00875 Serial.println(EasyspinStrOut); 00876 #endif 00877 shieldPrm[shieldId].relativePos = AbsPos - shieldPrm[shieldId].currentPosition; 00878 00879 } else if ((shieldPrm[shieldId].direction == BACKWARD) && 00880 (AbsPos != shieldPrm[shieldId].currentPosition - shieldPrm[shieldId].relativePos)) { 00881 #ifdef _DEBUG_Easyspin 00882 snprintf(EasyspinStrOut, DEBUG_BUFFER_SIZE, "B EstPos:%ld RealPos: %ld\n",shieldPrm[shieldId].relativePos,(AbsPos - shieldPrm[shieldId].currentPosition)); 00883 Serial.println(EasyspinStrOut); 00884 #endif 00885 shieldPrm[shieldId].relativePos = shieldPrm[shieldId].currentPosition - AbsPos; 00886 } 00887 } 00888 } 00889 00890 switch (shieldPrm[shieldId].motionState) { 00891 case ACCELERATING: { 00892 if ((shieldPrm[shieldId].commandExecuted == SOFT_STOP_CMD)|| 00893 ((shieldPrm[shieldId].commandExecuted != RUN_CMD)&& 00894 (shieldPrm[shieldId].relativePos == shieldPrm[shieldId].startDecPos))) { 00895 shieldPrm[shieldId].motionState = DECELERATING; 00896 shieldPrm[shieldId].accu = 0; 00897 #ifdef _DEBUG_Easyspin 00898 snprintf(EasyspinStrOut, DEBUG_BUFFER_SIZE, "Acc->Dec: speed: %u relativepos: %ld \n",shieldPrm[shieldId].speed,shieldPrm[shieldId].relativePos); 00899 Serial.println(EasyspinStrOut); 00900 #endif 00901 } else if ((shieldPrm[shieldId].speed >= shieldPrm[shieldId].maxSpeed)|| 00902 ((shieldPrm[shieldId].commandExecuted != RUN_CMD)&& 00903 (shieldPrm[shieldId].relativePos == shieldPrm[shieldId].endAccPos))) { 00904 shieldPrm[shieldId].motionState = STEADY; 00905 #ifdef _DEBUG_Easyspin 00906 snprintf(EasyspinStrOut, DEBUG_BUFFER_SIZE, "Acc->Steady: speed: %u relativepos: %ld \n",shieldPrm[shieldId].speed,shieldPrm[shieldId].relativePos); 00907 Serial.println(EasyspinStrOut); 00908 #endif 00909 } else { 00910 bool speedUpdated = false; 00911 /* Go on accelerating */ 00912 shieldPrm[shieldId].accu += ((uint32_t)shieldPrm[shieldId].acceleration << 16) / shieldPrm[shieldId].speed; 00913 while (shieldPrm[shieldId].accu >= (0X10000L)) { 00914 shieldPrm[shieldId].accu -= (0X10000L); 00915 shieldPrm[shieldId].speed +=1; 00916 speedUpdated = true; 00917 } 00918 00919 if (speedUpdated) { 00920 ApplySpeed(shieldId, shieldPrm[shieldId].speed); 00921 } 00922 } 00923 break; 00924 } 00925 case STEADY: { 00926 if ((shieldPrm[shieldId].commandExecuted == SOFT_STOP_CMD)|| 00927 ((shieldPrm[shieldId].commandExecuted != RUN_CMD)&& 00928 (shieldPrm[shieldId].relativePos >= (shieldPrm[shieldId].startDecPos))) || 00929 ((shieldPrm[shieldId].commandExecuted == RUN_CMD)&& 00930 (shieldPrm[shieldId].speed > shieldPrm[shieldId].maxSpeed))) { 00931 shieldPrm[shieldId].motionState = DECELERATING; 00932 shieldPrm[shieldId].accu = 0; 00933 } else if ((shieldPrm[shieldId].commandExecuted == RUN_CMD)&& 00934 (shieldPrm[shieldId].speed < shieldPrm[shieldId].maxSpeed)) { 00935 shieldPrm[shieldId].motionState = ACCELERATING; 00936 shieldPrm[shieldId].accu = 0; 00937 } 00938 break; 00939 } 00940 case DECELERATING: { 00941 if (((shieldPrm[shieldId].commandExecuted == SOFT_STOP_CMD)&&(shieldPrm[shieldId].speed <= shieldPrm[shieldId].minSpeed))|| 00942 ((shieldPrm[shieldId].commandExecuted != RUN_CMD)&& 00943 (shieldPrm[shieldId].relativePos >= shieldPrm[shieldId].stepsToTake))) { 00944 /* Motion process complete */ 00945 HardStop(shieldId); 00946 #ifdef _DEBUG_Easyspin 00947 snprintf(EasyspinStrOut, DEBUG_BUFFER_SIZE, "Dec->Stop: speed: %u relativepos: %ld \n",shieldPrm[shieldId].speed,shieldPrm[shieldId].relativePos ); 00948 Serial.println(EasyspinStrOut); 00949 #endif 00950 } else if ((shieldPrm[shieldId].commandExecuted == RUN_CMD)&& 00951 (shieldPrm[shieldId].speed <= shieldPrm[shieldId].maxSpeed)) { 00952 shieldPrm[shieldId].motionState = STEADY; 00953 #ifdef _DEBUG_Easyspin 00954 snprintf(EasyspinStrOut, DEBUG_BUFFER_SIZE, "Dec->Steady: speed: %u relativepos: %ld \n",shieldPrm[shieldId].speed,shieldPrm[shieldId].relativePos); 00955 Serial.println(EasyspinStrOut); 00956 #endif 00957 } else { 00958 /* Go on decelerating */ 00959 if (shieldPrm[shieldId].speed > shieldPrm[shieldId].minSpeed) { 00960 bool speedUpdated = false; 00961 shieldPrm[shieldId].accu += ((uint32_t)shieldPrm[shieldId].deceleration << 16) / shieldPrm[shieldId].speed; 00962 while (shieldPrm[shieldId].accu >= (0X10000L)) { 00963 shieldPrm[shieldId].accu -= (0X10000L); 00964 shieldPrm[shieldId].speed -=1; 00965 speedUpdated = true; 00966 } 00967 if (speedUpdated) { 00968 ApplySpeed(shieldId, shieldPrm[shieldId].speed); 00969 } 00970 } 00971 } 00972 break; 00973 } 00974 default: { 00975 break; 00976 } 00977 } 00978 /* Set isr flag */ 00979 isrFlag = false; 00980 } 00981 00982 /******************************************************//** 00983 * @brief Updates the current speed of the shield 00984 * @param[in] shieldId (from 0 to 2) 00985 * @param[in] newSpeed in pps 00986 * @retval None 00987 **********************************************************/ 00988 void Easyspin::ApplySpeed(uint8_t shieldId, uint16_t newSpeed) 00989 { 00990 if (newSpeed < Easyspin_MIN_PWM_FREQ) { 00991 newSpeed = Easyspin_MIN_PWM_FREQ; 00992 } 00993 if (newSpeed > Easyspin_MAX_PWM_FREQ) { 00994 newSpeed = Easyspin_MAX_PWM_FREQ; 00995 } 00996 00997 shieldPrm[shieldId].speed = newSpeed; 00998 00999 switch (shieldId) { 01000 case 0: 01001 Pwm1SetFreq(newSpeed); 01002 break; 01003 case 1: 01004 Pwm2SetFreq(newSpeed); 01005 break; 01006 case 2: 01007 Pwm3SetFreq(newSpeed); 01008 break; 01009 default: 01010 break; //ignore error 01011 } 01012 } 01013 01014 /******************************************************//** 01015 * @brief Computes the speed profile according to the number of steps to move 01016 * @param[in] shieldId (from 0 to 2) 01017 * @param[in] nbSteps number of steps to perform 01018 * @retval None 01019 * @note Using the acceleration and deceleration of the shield, 01020 * this function determines the duration in steps of the acceleration, 01021 * steady and deceleration phases. 01022 * If the total number of steps to perform is big enough, a trapezoidal move 01023 * is performed (i.e. there is a steady phase where the motor runs at the maximum 01024 * speed. 01025 * Else, a triangular move is performed (no steady phase: the maximum speed is never 01026 * reached. 01027 **********************************************************/ 01028 void Easyspin::ComputeSpeedProfile(uint8_t shieldId, uint32_t nbSteps) 01029 { 01030 uint32_t reqAccSteps; 01031 uint32_t reqDecSteps; 01032 01033 /* compute the number of steps to get the targeted speed */ 01034 reqAccSteps = (shieldPrm[shieldId].maxSpeed - shieldPrm[shieldId].minSpeed); 01035 reqAccSteps *= (shieldPrm[shieldId].maxSpeed + shieldPrm[shieldId].minSpeed); 01036 reqDecSteps = reqAccSteps; 01037 reqAccSteps /= (uint32_t)shieldPrm[shieldId].acceleration; 01038 reqAccSteps /= 2; 01039 01040 /* compute the number of steps to stop */ 01041 reqDecSteps /= (uint32_t)shieldPrm[shieldId].deceleration; 01042 reqDecSteps /= 2; 01043 01044 if(( reqAccSteps + reqDecSteps ) > nbSteps) { 01045 /* Triangular move */ 01046 /* reqDecSteps = (Pos * Dec) /(Dec+Acc) */ 01047 01048 reqDecSteps = ((uint32_t) shieldPrm[shieldId].deceleration * nbSteps) / (shieldPrm[shieldId].acceleration + shieldPrm[shieldId].deceleration); 01049 if (reqDecSteps > 1) { 01050 reqAccSteps = reqDecSteps - 1; 01051 if(reqAccSteps == 0) { 01052 reqAccSteps = 1; 01053 } 01054 } else { 01055 reqAccSteps = 0; 01056 } 01057 shieldPrm[shieldId].endAccPos = reqAccSteps; 01058 shieldPrm[shieldId].startDecPos = reqDecSteps; 01059 } else { 01060 /* Trapezoidal move */ 01061 /* accelerating phase to endAccPos */ 01062 /* steady phase from endAccPos to startDecPos */ 01063 /* decelerating from startDecPos to stepsToTake*/ 01064 shieldPrm[shieldId].endAccPos = reqAccSteps; 01065 shieldPrm[shieldId].startDecPos = nbSteps - reqDecSteps - 1; 01066 } 01067 } 01068 01069 /******************************************************//** 01070 * @brief Converts the ABS_POSITION register value to a 32b signed integer 01071 * @param[in] abs_position_reg value of the ABS_POSITION register 01072 * @retval operation_result 32b signed integer corresponding to the absolute position 01073 **********************************************************/ 01074 int32_t Easyspin::ConvertPosition(uint32_t abs_position_reg) 01075 { 01076 int32_t operation_result; 01077 01078 if (abs_position_reg & Easyspin_ABS_POS_SIGN_BIT_MASK) { 01079 /* Negative register value */ 01080 abs_position_reg = ~abs_position_reg; 01081 abs_position_reg += 1; 01082 01083 operation_result = (int32_t) (abs_position_reg & Easyspin_ABS_POS_VALUE_MASK); 01084 operation_result = -operation_result; 01085 } else { 01086 operation_result = (int32_t) abs_position_reg; 01087 } 01088 return operation_result; 01089 } 01090 01091 /******************************************************//** 01092 * @brief Handlers of the flag interrupt which calls the user callback (if defined) 01093 * @param None 01094 * @retval None 01095 **********************************************************/ 01096 void Easyspin::FlagInterruptHandler(void) 01097 { 01098 if (flagInterruptCallback != NULL) { 01099 /* Set isr flag */ 01100 isrFlag = true; 01101 01102 flagInterruptCallback(); 01103 01104 /* Reset isr flag */ 01105 isrFlag = false; 01106 } 01107 } 01108 01109 /******************************************************//** 01110 * @brief Sends a command without arguments to the Easyspin via the SPI 01111 * @param[in] shieldId (from 0 to 2) 01112 * @param[in] param Command to send 01113 * @retval None 01114 **********************************************************/ 01115 void Easyspin::SendCommand(uint8_t shieldId, uint8_t param) 01116 { 01117 uint8_t spiIndex = numberOfShields - shieldId - 1; 01118 bool itDisable = false; 01119 01120 do { 01121 spiPreemtionByIsr = false; 01122 if (itDisable) { 01123 /* re-enable interrupts if disable in previous iteration */ 01124 flag.enable_irq(); 01125 itDisable = false; 01126 } 01127 01128 for (uint32_t i = 0; i < numberOfShields; i++) { 01129 spiTxBursts[3][i] = Easyspin_NOP; 01130 } 01131 spiTxBursts[3][spiIndex] = param; 01132 01133 /* Disable interruption before checking */ 01134 /* pre-emption by ISR and SPI transfers*/ 01135 flag.disable_irq(); 01136 itDisable = true; 01137 } while (spiPreemtionByIsr); // check pre-emption by ISR 01138 01139 WriteBytes(&spiTxBursts[3][0], &spiRxBursts[3][0]); 01140 01141 /* re-enable interrupts after SPI transfers*/ 01142 flag.enable_irq(); 01143 } 01144 01145 /******************************************************//** 01146 * @brief Sets the registers of the Easyspin to their predefined values 01147 * from Easyspin_target_config.h 01148 * @param[in] shieldId (from 0 to 2) 01149 * @retval None 01150 **********************************************************/ 01151 void Easyspin::SetRegisterToPredefinedValues(uint8_t shieldId) 01152 { 01153 CmdSetParam(shieldId, 01154 Easyspin_ABS_POS, 01155 0); 01156 CmdSetParam(shieldId, 01157 Easyspin_EL_POS, 01158 0); 01159 CmdSetParam(shieldId, 01160 Easyspin_MARK, 01161 0); 01162 switch (shieldId) { 01163 case 0: 01164 CmdSetParam(shieldId, 01165 Easyspin_TVAL, 01166 Tval_Current_to_Par(Easyspin_CONF_PARAM_TVAL_SHIELD_0)); 01167 CmdSetParam(shieldId, 01168 Easyspin_T_FAST, 01169 (uint8_t)Easyspin_CONF_PARAM_TOFF_FAST_SHIELD_0 | 01170 (uint8_t)Easyspin_CONF_PARAM_FAST_STEP_SHIELD_0); 01171 CmdSetParam(shieldId, 01172 Easyspin_TON_MIN, 01173 Tmin_Time_to_Par(Easyspin_CONF_PARAM_TON_MIN_SHIELD_0)); 01174 CmdSetParam(shieldId, 01175 Easyspin_TOFF_MIN, 01176 Tmin_Time_to_Par(Easyspin_CONF_PARAM_TOFF_MIN_SHIELD_0)); 01177 CmdSetParam(shieldId, 01178 Easyspin_OCD_TH, 01179 Easyspin_CONF_PARAM_OCD_TH_SHIELD_0); 01180 CmdSetParam(shieldId, 01181 Easyspin_STEP_MODE, 01182 (uint8_t)Easyspin_CONF_PARAM_STEP_SEL_SHIELD_0 | 01183 (uint8_t)Easyspin_CONF_PARAM_SYNC_SEL_SHIELD_0); 01184 CmdSetParam(shieldId, 01185 Easyspin_ALARM_EN, 01186 Easyspin_CONF_PARAM_ALARM_EN_SHIELD_0); 01187 CmdSetParam(shieldId, 01188 Easyspin_CONFIG, 01189 (uint16_t)Easyspin_CONF_PARAM_CLOCK_SETTING_SHIELD_0 | 01190 (uint16_t)Easyspin_CONF_PARAM_TQ_REG_SHIELD_0 | 01191 (uint16_t)Easyspin_CONF_PARAM_OC_SD_SHIELD_0 | 01192 (uint16_t)Easyspin_CONF_PARAM_SR_SHIELD_0 | 01193 (uint16_t)Easyspin_CONF_PARAM_TOFF_SHIELD_0); 01194 break; 01195 case 1: 01196 CmdSetParam(shieldId, 01197 Easyspin_TVAL, 01198 Tval_Current_to_Par(Easyspin_CONF_PARAM_TVAL_SHIELD_1)); 01199 CmdSetParam(shieldId, 01200 Easyspin_T_FAST, 01201 (uint8_t)Easyspin_CONF_PARAM_TOFF_FAST_SHIELD_1 | 01202 (uint8_t)Easyspin_CONF_PARAM_FAST_STEP_SHIELD_1); 01203 CmdSetParam(shieldId, 01204 Easyspin_TON_MIN, 01205 Tmin_Time_to_Par(Easyspin_CONF_PARAM_TON_MIN_SHIELD_1)); 01206 CmdSetParam(shieldId, 01207 Easyspin_TOFF_MIN, 01208 Tmin_Time_to_Par(Easyspin_CONF_PARAM_TOFF_MIN_SHIELD_1)); 01209 CmdSetParam(shieldId, 01210 Easyspin_OCD_TH, 01211 Easyspin_CONF_PARAM_OCD_TH_SHIELD_1); 01212 CmdSetParam(shieldId, 01213 Easyspin_STEP_MODE, 01214 (uint8_t)Easyspin_CONF_PARAM_STEP_SEL_SHIELD_1 | 01215 (uint8_t)Easyspin_CONF_PARAM_SYNC_SEL_SHIELD_1); 01216 CmdSetParam(shieldId, 01217 Easyspin_ALARM_EN, 01218 Easyspin_CONF_PARAM_ALARM_EN_SHIELD_1); 01219 CmdSetParam(shieldId, 01220 Easyspin_CONFIG, 01221 (uint16_t)Easyspin_CONF_PARAM_CLOCK_SETTING_SHIELD_1 | 01222 (uint16_t)Easyspin_CONF_PARAM_TQ_REG_SHIELD_1 | 01223 (uint16_t)Easyspin_CONF_PARAM_OC_SD_SHIELD_1 | 01224 (uint16_t)Easyspin_CONF_PARAM_SR_SHIELD_1 | 01225 (uint16_t)Easyspin_CONF_PARAM_TOFF_SHIELD_1); 01226 break; 01227 case 2: 01228 CmdSetParam(shieldId, 01229 Easyspin_TVAL, 01230 Tval_Current_to_Par(Easyspin_CONF_PARAM_TVAL_SHIELD_2)); 01231 CmdSetParam(shieldId, 01232 Easyspin_T_FAST, 01233 (uint8_t)Easyspin_CONF_PARAM_TOFF_FAST_SHIELD_2 | 01234 (uint8_t)Easyspin_CONF_PARAM_FAST_STEP_SHIELD_2); 01235 CmdSetParam(shieldId, 01236 Easyspin_TON_MIN, 01237 Tmin_Time_to_Par(Easyspin_CONF_PARAM_TON_MIN_SHIELD_2)); 01238 CmdSetParam(shieldId, 01239 Easyspin_TOFF_MIN, 01240 Tmin_Time_to_Par(Easyspin_CONF_PARAM_TOFF_MIN_SHIELD_2)); 01241 CmdSetParam(shieldId, 01242 Easyspin_OCD_TH, 01243 Easyspin_CONF_PARAM_OCD_TH_SHIELD_2); 01244 CmdSetParam(shieldId, 01245 Easyspin_STEP_MODE, 01246 (uint8_t)Easyspin_CONF_PARAM_STEP_SEL_SHIELD_2 | 01247 (uint8_t)Easyspin_CONF_PARAM_SYNC_SEL_SHIELD_2); 01248 CmdSetParam(shieldId, 01249 Easyspin_ALARM_EN, 01250 Easyspin_CONF_PARAM_ALARM_EN_SHIELD_2); 01251 CmdSetParam(shieldId, 01252 Easyspin_CONFIG, 01253 (uint16_t)Easyspin_CONF_PARAM_CLOCK_SETTING_SHIELD_2 | 01254 (uint16_t)Easyspin_CONF_PARAM_TQ_REG_SHIELD_2 | 01255 (uint16_t)Easyspin_CONF_PARAM_OC_SD_SHIELD_2 | 01256 (uint16_t)Easyspin_CONF_PARAM_SR_SHIELD_2 | 01257 (uint16_t)Easyspin_CONF_PARAM_TOFF_SHIELD_2); 01258 break; 01259 default: 01260 ; 01261 } 01262 } 01263 01264 /******************************************************//** 01265 * @brief Sets the registers of the Easyspin to their predefined values 01266 * from Easyspin_target_config.h 01267 * @param[in] shieldId (from 0 to 2) 01268 * @retval None 01269 **********************************************************/ 01270 void Easyspin::WriteBytes(uint8_t *pByteToTransmit, uint8_t *pReceivedByte) 01271 { 01272 CS = 0; 01273 for (uint32_t i = 0; i < numberOfShields; i++) { 01274 *pReceivedByte = spi.write(*pByteToTransmit); 01275 pByteToTransmit++; 01276 pReceivedByte++; 01277 } 01278 CS = 1; 01279 if (isrFlag) { 01280 spiPreemtionByIsr = true; 01281 } 01282 } 01283 01284 /******************************************************//** 01285 * @brief Initialises the PWM uses by the specified shield 01286 * @param[in] shieldId (from 0 to 2) 01287 * @retval None 01288 * @note Shield 0 uses PW1 based on timer 1 01289 * Shield 1 uses PWM 2 based on timer 2 01290 * Shield 2 uses PWM3 based timer 0 01291 **********************************************************/ 01292 void Easyspin::PwmInit(uint8_t shieldId) 01293 { 01294 switch (shieldId) { 01295 case 0: 01296 /* PWM1 uses timer 1 */ 01297 /* Initialise timer by setting waveform generation mode 01298 to PWM phase and Frequency correct: mode = 8 01299 (WGM10 = 0, WGM11 = 0, WGM12 = 0, WGM13 = 1) */ 01300 01301 /* Stop timer1 by clearing CSS bits and set WGM13 and WGM12 */ 01302 //TCCR1B = 0x10; 01303 01304 /* Set WGM10 and WGM11 */ 01305 //TCCR1A = 0x00; 01306 01307 /* Disable Timer1 interrupt */ 01308 //TIMSK1 = 0; 01309 //pwm1.period_us(400); 01310 //pwm1.pulsewidth_us(200); 01311 01312 break; 01313 case 1: 01314 /* PWM2 uses timer 2 */ 01315 /* Initialise timer by setting waveform generation mode 01316 to PWM phase correct: mode = 5 01317 (WGM0 = 1, WGM21 = 0, WGM22 = 1) */ 01318 01319 /* Stop timer2 by clearing CSS bits and set WGM22 */ 01320 //TCCR2B = 0x08; 01321 01322 /* Set WGM20 and WGM21 */ 01323 //TCCR2A = 0x01; 01324 01325 /* Disable Timer2 interrupt */ 01326 //TIMSK2 = 0; 01327 //pwm2.period_us(500); 01328 //pwm2.pulsewidth_us(100); 01329 break; 01330 01331 01332 case 2: 01333 /* PWM3 uses timer 0 */ 01334 /* !!!!! Caution: Calling this configuration will break */ 01335 /* all default Arduino's timing functions as delay(),millis()... */ 01336 01337 /* Initialise timer by setting waveform generation mode 01338 to PWM phase correct: mode = 5 01339 (WGM0 = 1, WGM21 = 0, WGM22 = 1) */ 01340 01341 /* Stop timer0 by clearing CSS bits and set WGM22 */ 01342 //TCCR0B = 0x08; 01343 01344 /* Set WGM00 and WGM01 */ 01345 //TCCR0A = 0x01; 01346 01347 /* Disable Timer0 interrupt */ 01348 //TIMSK0 = 0; 01349 //pwm3.period_ms(10); 01350 //pwm3.pulsewidth_ms(1); 01351 break; 01352 default: 01353 break;//ignore error 01354 } 01355 } 01356 01357 /******************************************************//** 01358 * @brief Ticker1 01359 * @param[in] 01360 * @retval 01361 **********************************************************/ 01362 void Easyspin::tick1() 01363 { 01364 class Easyspin* instancePtr = Easyspin::GetInstancePtr(); 01365 pwm1 = !pwm1; 01366 if (instancePtr != NULL) { 01367 if (instancePtr->GetShieldState(0) != INACTIVE) { 01368 instancePtr->StepClockHandler(0); 01369 } 01370 } 01371 } 01372 01373 /******************************************************//** 01374 * @brief Ticker2 01375 * @param[in] 01376 * @retval 01377 **********************************************************/ 01378 void Easyspin::tick2() 01379 { 01380 class Easyspin* instancePtr = Easyspin::GetInstancePtr(); 01381 pwm2 = !pwm2; 01382 if (instancePtr != NULL) { 01383 if (instancePtr->GetShieldState(1) != INACTIVE) { 01384 instancePtr->StepClockHandler(1); 01385 } 01386 } 01387 } 01388 01389 /******************************************************//** 01390 * @brief Sets the frequency of PWM1 used by shield 0 01391 * @param[in] newFreq in Hz 01392 * @retval None 01393 * @note The frequency is directly the current speed of the shield 01394 **********************************************************/ 01395 void Easyspin::Pwm1SetFreq(uint16_t newFreq) 01396 { 01397 uint16_t us; 01398 us = (1000000 / (newFreq * 2)); 01399 ticker1.attach_us(this, &Easyspin::tick1, us); 01400 } 01401 01402 /******************************************************//** 01403 * @brief Sets the frequency of PWM2 used by shield 1 01404 * @param[in] newFreq in Hz 01405 * @retval None 01406 * @note The frequency is directly the current speed of the shield 01407 **********************************************************/ 01408 void Easyspin::Pwm2SetFreq(uint16_t newFreq) 01409 { 01410 uint16_t us; 01411 us = (1000000 / (newFreq * 2)); 01412 ticker2.attach_us(this, &Easyspin::tick2, us); 01413 } 01414 01415 /******************************************************//** 01416 * @brief Sets the frequency of PWM3 used by shield 2 01417 * @param[in] newFreq in Hz 01418 * @retval None 01419 * @note The frequency is directly the current speed of the shield 01420 **********************************************************/ 01421 void Easyspin::Pwm3SetFreq(uint16_t newFreq) 01422 { 01423 01424 } 01425 01426 /******************************************************//** 01427 * @brief Stops the PWM uses by the specified shield 01428 * @param[in] shieldId (from 0 to 2) 01429 * @retval None 01430 **********************************************************/ 01431 void Easyspin::PwmStop(uint8_t shieldId) 01432 { 01433 switch (shieldId) { 01434 case 0: 01435 ticker1.detach(); 01436 break; 01437 case 1: 01438 ticker2.detach(); 01439 break; 01440 case 2: 01441 ticker3.detach(); 01442 break; 01443 default: 01444 break;//ignore error 01445 } 01446 } 01447 01448 /******************************************************//** 01449 * @brief Sets the parameters of the shield to predefined values 01450 * from Easyspin_target_config.h 01451 * @param None 01452 * @retval None 01453 **********************************************************/ 01454 void Easyspin::SetShieldParamsToPredefinedValues(void) 01455 { 01456 shieldPrm[0].acceleration = Easyspin_CONF_PARAM_ACC_SHIELD_0; 01457 shieldPrm[0].deceleration = Easyspin_CONF_PARAM_DEC_SHIELD_0; 01458 shieldPrm[0].maxSpeed = Easyspin_CONF_PARAM_MAX_SPEED_SHIELD_0; 01459 shieldPrm[0].minSpeed = Easyspin_CONF_PARAM_MIN_SPEED_SHIELD_0; 01460 01461 shieldPrm[1].acceleration = Easyspin_CONF_PARAM_ACC_SHIELD_1; 01462 shieldPrm[1].deceleration = Easyspin_CONF_PARAM_DEC_SHIELD_1; 01463 shieldPrm[1].maxSpeed = Easyspin_CONF_PARAM_MAX_SPEED_SHIELD_1; 01464 shieldPrm[1].minSpeed = Easyspin_CONF_PARAM_MIN_SPEED_SHIELD_1; 01465 01466 shieldPrm[2].acceleration = Easyspin_CONF_PARAM_ACC_SHIELD_2; 01467 shieldPrm[2].deceleration = Easyspin_CONF_PARAM_DEC_SHIELD_2; 01468 shieldPrm[2].maxSpeed = Easyspin_CONF_PARAM_MAX_SPEED_SHIELD_2; 01469 shieldPrm[2].minSpeed = Easyspin_CONF_PARAM_MIN_SPEED_SHIELD_2; 01470 01471 for (uint8_t i = 0; i < numberOfShields; i++) { 01472 SetRegisterToPredefinedValues(i); 01473 } 01474 } 01475 01476 /******************************************************//** 01477 * @brief Initialises the bridge parameters to start the movement 01478 * and enable the power bridge 01479 * @param[in] shieldId (from 0 to 2) 01480 * @retval None 01481 **********************************************************/ 01482 void Easyspin::StartMovement(uint8_t shieldId) 01483 { 01484 /* Enable Easyspin powerstage */ 01485 CmdEnable(shieldId); 01486 01487 if (shieldPrm[shieldId].endAccPos != 0) { 01488 shieldPrm[shieldId].motionState = ACCELERATING;; 01489 } else { 01490 shieldPrm[shieldId].motionState = DECELERATING; 01491 } 01492 01493 shieldPrm[shieldId].accu = 0; 01494 shieldPrm[shieldId].relativePos = 0; 01495 ApplySpeed(shieldId, shieldPrm[shieldId].minSpeed); 01496 #ifdef _DEBUG_Easyspin 01497 snprintf(EasyspinStrOut, DEBUG_BUFFER_SIZE, "Stop->Acc: speed: %u relPos: %ld\n", shieldPrm[shieldId].minSpeed, shieldPrm[shieldId].relativePos) ; 01498 Serial.println(EasyspinStrOut); 01499 #endif 01500 } 01501 01502 /******************************************************//** 01503 * @brief Converts mA in compatible values for TVAL register 01504 * @param[in] Tval 01505 * @retval TVAL values 01506 **********************************************************/ 01507 inline uint8_t Easyspin::Tval_Current_to_Par(double Tval) 01508 { 01509 return ((uint8_t)(((Tval - 31.25)/31.25)+0.5)); 01510 } 01511 01512 /******************************************************//** 01513 * @brief Convert time in us in compatible values 01514 * for TON_MIN register 01515 * @param[in] Tmin 01516 * @retval TON_MIN values 01517 **********************************************************/ 01518 inline uint8_t Easyspin::Tmin_Time_to_Par(double Tmin) 01519 { 01520 return ((uint8_t)(((Tmin - 0.5)*2)+0.5)); 01521 }
Generated on Tue Jul 12 2022 21:33:48 by 1.7.2