Advertisement
PiotrProkopowicz

Untitled

Mar 26th, 2019
566
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 24.38 KB | None | 0 0
  1. /*************************************************************
  2.  INCLUDES
  3. **************************************************************/
  4. #include <avr/io.h>
  5. #include "A4988-stepperDriver.h"
  6. #include <util/delay.h>
  7. #define MS_PIN1          2
  8. #define MS_PIN2          24
  9. #define MS_PIN3          26
  10. /*************************************************************
  11.  SETUP
  12. **************************************************************/
  13. void setup() {
  14.   pinMode(MS_PIN1,     OUTPUT);
  15.   pinMode(MS_PIN2,     OUTPUT);
  16.   pinMode(MS_PIN3,     OUTPUT);
  17.   digitalWrite(MS_PIN1,LOW);
  18.   digitalWrite(MS_PIN2,LOW);
  19.   digitalWrite(MS_PIN3,LOW);
  20. }
  21. /*************************************************************
  22.  MAIN FUNCTION
  23. **************************************************************/
  24. int main(void){
  25.  // A4988 setup
  26.  A4988_stepperSetup();
  27.  
  28.  while(1){
  29. // Turn left
  30. A4988_stepperDirection(TURN_LEFT);
  31.  
  32. // Make 100 steps with 800 microseconds delay between each step
  33. A4988_stepMicroseconds(300, 2000);
  34.  
  35. // Wait until the rotation ends
  36. A4988_isBusy();
  37.  
  38. // Add a small delay when changing the direction of rotation to prevent
  39. // mechanical shock. The value can be changed depending on the speed
  40. _delay_ms(100);
  41.  
  42. // A delay just to see when a rotation stops and the other begins
  43. //_delay_ms(2000);
  44.  
  45. // Turn right
  46. A4988_stepperDirection(TURN_RIGHT);
  47.  
  48. // Make 50 steps with 800 microseconds delay between each step
  49. A4988_stepMicroseconds(300, 2000);
  50.  
  51. // Wait until the rotation ends
  52. A4988_isBusy();
  53.  
  54. _delay_ms(100);
  55. // A delay just to see when a rotation stops and the other begins
  56. //_delay_ms(2000);
  57. }
  58.  
  59.   // Do other stuff
  60.  }
  61.  
  62.  
  63. -------------------------------------------------
  64.  
  65. /*_______________________________________________________________________________
  66.  
  67. A4988-stepperDriver v1.0
  68.  
  69. Copyright (c) 2017 Istrate Liviu
  70.  
  71. NOTICE
  72. --------
  73. NO PART OF THIS WORK CAN BE COPIED, DISTRIBUTED OR PUBLISHED WITHOUT A
  74. WRITTEN PERMISSION FROM THE AUTHOR. THE LIBRARY, NOR ANY PART
  75. OF IT CAN BE USED IN COMMERCIAL APPLICATIONS. IT IS INTENDED TO BE USED FOR
  76. HOBBY, LEARNING AND EDUCATIONAL PURPOSE ONLY. IF YOU WANT TO USE THEM IN
  77. COMMERCIAL APPLICATION PLEASE WRITE TO THE AUTHOR.
  78.  
  79. AUTHOR: Istrate Liviu
  80. CONTACT: istrateliviu24@yahoo.com
  81. __________________________________________________________________________________*/
  82. // Uncomment MATH_LIB = -lm in your MAKE file for the compiler to use the math lib from libc not libm.
  83. // The one from libc in about three times larger.
  84.  
  85. #ifndef A4988_STEPPER_DRIVER_H
  86. #define A4988_STEPPER_DRIVER_H
  87.  
  88. /*************************************************************
  89.   INCLUDES
  90. **************************************************************/
  91. #include <avr/io.h>
  92. #include <avr/interrupt.h>
  93. #include <util/delay.h>
  94.  
  95.  
  96.  
  97. /*************************************************************
  98.   SETUP FOR USER
  99. **************************************************************/
  100. ///////////////////    DIGITAL CONTROL PINS SETUP
  101. /* Step Pin */
  102. #define STEP_DDR DDRE
  103. #define STEP_PORT PORTE
  104. #define STEP_PIN PD5
  105.  
  106. /* Direction Pin (Optional) */
  107. #define USE_DIRECTION_PIN   1
  108. #define DIR_DDR DDRG
  109. #define DIR_PORT PORTG
  110. #define DIR_PIN PD5
  111.  
  112. /* Enable Pin (Optional) */
  113. #define USE_ENABLE_PIN      1
  114. #define ENABLE_DDR        DDRD
  115. #define ENABLE_PORT       PORTD
  116. #define ENABLE_PIN        PD6
  117.  
  118. /* Sleep Pin (Optional) */
  119. #define USE_SLEEP_PIN     1
  120. #define SLEEP_DDR       DDRB
  121. #define SLEEP_PORT        PORTB
  122. #define SLEEP_PIN       PB2
  123.  
  124. /* Reset Pin (Optional) */
  125. #define USE_RESET_PIN     1
  126. #define RESET_DDR       DDRC
  127. #define RESET_PORT        PORTC
  128. #define RESET_PIN       PC5
  129.  
  130. /* Microstepping Resolution Pins (Optional) */
  131. #define USE_MICROSTEPPING     0
  132. // If total duration of spinning doesn't matter, set this to 0. This will allow using smaller delays between steps
  133. // at a higher microstepping resolution.
  134. #define MICROSTEPPING_DIVIDE_TIME 0
  135. #define MS1_DDR           DDRD
  136. #define MS1_PORT          PORTD
  137. #define MS1_PIN           PD2
  138.  
  139. #define MS2_DDR           DDRD
  140. #define MS2_PORT          PORTD
  141. #define MS2_PIN           PD3
  142.  
  143. #define MS3_DDR           DDRD
  144. #define MS3_PORT          PORTD
  145. #define MS3_PIN           PD4
  146.  
  147. ///////////////////    SELECT THE TIMER (put 1 to the one you want to use and 0 to the rest)
  148. #define USE_TIMER0          0
  149. #define USE_TIMER1          1
  150.  
  151. ///////////////////    ACTIVATE/DEACTIVATE FANCY FUNCTIONS (to save space)
  152. #define USE_stepperRotateToDegree 0 // disable acceleration when setting this to 1 or the motor will be slow
  153. #define IMPROVE_TIME_PRECISION    1
  154.  
  155. ///////////////////    STEPPER MOTOR TYPE SETUP
  156. #define STEPPER_DEGREES     1.8
  157.  
  158. ///////////////////    MICROSTEPPING TIME THRESHOLD
  159. #define FULL_STEP_THRESHOLD     200   // in microseconds
  160. #define HALF_STEP_THRESHOLD     500   // (1/2) microseconds
  161. #define QUARTER_STEP_THRESHOLD    800   // (1/4) microseconds
  162. #define EIGHTH_STEP_THRESHOLD   10000   // (1/8) microseconds
  163. #define SIXTEENTH_STEP_THRESHOLD  1000000 // (1/16) microseconds
  164.  
  165. ///////////////////    ACCELERATION, DECELERATION (from 0 to 100 percents)
  166. #define USE_ACCELERATION        1
  167. #define ACCELERATION          20 // acceleration and deceleration should add up to maximum 100
  168. #define DECELERATION          20 //
  169. #define ACCELERATION_STARTING_SPEED   5000 // in microseconds
  170.  
  171. ///////////////////   IF TRUE THE MOTOR WILL SPIN ENDLESSLY (or until you stop it)
  172. #define PERPETUAL_MOTION        0
  173.  
  174.  
  175.  
  176. /*************************************************************
  177.   MACROS
  178. **************************************************************/
  179. /* STEPPER DIRECTION */
  180. #define TURN_RIGHT          1 // turn clockwise
  181. #define TURN_LEFT         0 // turn counter-clockwise
  182.  
  183. /* ENABLE Pin */
  184. // This input turns on or off all of the FET outputs.
  185. // The translator inputs STEP, DIR, and MSx, as well as the internal sequencing logic,
  186. // all remain active, independent of the ENABLE input state. Disable when the load doesn't need the holding torque.
  187. #define A4988_stepperEnable()   (ENABLE_PORT &= ~(1 << ENABLE_PIN))
  188. #define A4988_stepperDisable()    (ENABLE_PORT |= (1 << ENABLE_PIN))
  189.  
  190. /* SLEEP Pin */
  191. // To minimize power consumption when the motor is not in use, this input disables much of the
  192. // internal circuitry including the output FETs, current regulator, and charge pump.
  193. // When emerging from Sleep mode, in order to allow the charge pump to stabilize, provide a delay of 1 ms
  194. // before issuing a Step command. Sleep during long delays, wake up time is 1ms.
  195. #define A4988_stepperSleep()    (SLEEP_PORT &= ~(1 << SLEEP_PIN))
  196. #define A4988_stepperWakeUp(){\
  197.   SLEEP_PORT |= (1 << SLEEP_PIN);\
  198.   _delay_ms(1);\
  199. }
  200.  
  201. /* RESET Pin */
  202. // The RESET input sets the translator to a predefined Home state, and turns off all of the FET outputs.
  203. // All STEP inputs are ignored until the RESET input is set to high.
  204. #define A4988_stepperReset(){\
  205.   RESET_PORT &= ~(1 << RESET_PIN);\
  206.   _delay_ms(1);\
  207.   RESET_PORT |= (1 << RESET_PIN);\
  208. }
  209.  
  210. /* OTHER PARAMETERS */
  211. #define STEPS_PER_REVOLUTION      360 / STEPPER_DEGREES
  212. // Calculate timer 0 TOP value for 10 microseconds resolution
  213. #define FIXED_PRESCALER         1
  214. #define TIMER0_RESOLUTION       10 // microseconds
  215. #define TIMER1_RESOLUTION       10 // microseconds
  216. #if USE_TIMER0 == 1
  217.   #define OCR0A_TIMER0_TOP        (F_CPU / (FIXED_PRESCALER * (1.0 / (TIMER0_RESOLUTION / 1000000.0)))) - 1 // (TIMER0_RESOLUTION / 1000000) converts us to s
  218. #endif
  219. #if USE_TIMER1 == 1
  220.   #define OCR1A_TIMER1_TOP        (F_CPU / (FIXED_PRESCALER * (1.0 / (TIMER1_RESOLUTION / 1000000.0)))) - 1 // (TIMER0_RESOLUTION / 1000000) converts us to s
  221. #endif
  222.  
  223.  
  224.  
  225. /*************************************************************
  226.   GLOBAL VARIABLES
  227. **************************************************************/
  228. static volatile uint16_t ticksPassed = 0;
  229. static volatile uint16_t ticksPerPulse = 0;
  230. static volatile uint16_t numberOfPulsesMade = 0;
  231. static volatile uint32_t numberOfPulsesNecessary = 0;
  232. static volatile uint8_t microTime = 0;
  233. static uint8_t useMicrosteppingGlobalVar = 1;
  234. #if USE_stepperRotateToDegree == 1
  235. float currentDegreePosition = 0;
  236. #endif
  237. #if USE_ACCELERATION == 1
  238. static volatile uint8_t useAcceleration = 1;
  239. static volatile uint16_t stepsToAccelerate = 0;
  240. static volatile uint16_t stepsToDecelerate = 0;
  241. static volatile uint16_t decelerationStep = 0;
  242. static volatile float accelerationPerStep = 0;
  243. static volatile float decelerationPerStep = 0;
  244. static volatile float accelerationPerStepInteger = 0;
  245. static volatile float decelerationPerStepInteger = 0;
  246. #endif
  247. #if IMPROVE_TIME_PRECISION == 1 && USE_ACCELERATION == 0
  248. static volatile uint8_t pulsesAfterTickIsAdded = 0;
  249. static volatile uint8_t countCorrectionPulses = 0;
  250. static volatile uint32_t ticksPerPulseBuffer = 0;
  251. static volatile uint8_t correctionNeeded = 1;
  252. #endif
  253. static volatile uint8_t sregSave;
  254.  
  255.  
  256.  
  257. /*************************************************************
  258.   FUNCTION PROTOTYPES
  259. **************************************************************/
  260. uint8_t A4988_isNotBusy(void);
  261. void A4988_isBusy(void);
  262. void A4988_stepperSetup(void);
  263. void A4988_stepMicroseconds(uint16_t nr_of_steps, uint16_t delay_between_steps_us);
  264. void A4988_stepMilliseconds(uint16_t nr_of_steps, uint32_t delay_between_steps_ms);
  265. #if USE_DIRECTION_PIN == 1
  266. void A4988_stepperDirection(uint8_t direction);
  267. #endif
  268. void A4988_stepperRotateNTimes(uint16_t nr_of_rotations, uint16_t total_duration_ms);
  269. #if USE_stepperRotateToDegree == 1
  270. void A4988_stepperRotateToDegree(float degree, uint16_t delay_between_steps_us);
  271. #endif
  272. void A4988_stepperStop(void);
  273. #if PERPETUAL_MOTION == 1
  274. void A4988_stepperIncreaseSpeed(uint8_t speed);
  275. void A4988_stepperDecreaseSpeed(uint8_t speed);
  276. #endif
  277.  
  278.  
  279.  
  280. /*************************************************************
  281.   FUNCTIONS
  282. **************************************************************/
  283. ///////////////////    PUBLIC
  284.  
  285. void A4988_stepperSetup(){
  286.   // Wait 1 ms for the pump to charge
  287.   _delay_ms(1);
  288.  
  289.   /* I/O Setup */
  290.   STEP_DDR |= 1 << STEP_PIN;
  291.   STEP_PORT &= ~(1 << STEP_PIN);
  292.  
  293.   #if USE_DIRECTION_PIN == 1
  294.   DIR_DDR |= 1 << DIR_DDR;
  295.   #endif
  296.  
  297.   #if USE_ENABLE_PIN == 1
  298.   ENABLE_DDR |= 1 << ENABLE_PIN;
  299.   ENABLE_PORT &= ~(1 << ENABLE_PIN);
  300.   #endif
  301.  
  302.   #if USE_SLEEP_PIN == 1
  303.   SLEEP_DDR |= 1 << SLEEP_PIN;
  304.   SLEEP_PORT |= (1 << SLEEP_PIN);
  305.   #endif
  306.  
  307.   #if USE_RESET_PIN == 1
  308.   RESET_DDR |= 1 << RESET_PIN;
  309.   RESET_PORT |= (1 << RESET_PIN);
  310.   A4988_stepperReset();
  311.   #endif
  312.  
  313.   #if USE_MICROSTEPPING == 1
  314.   MS1_DDR |= 1 << MS1_PIN;
  315.   MS2_DDR |= 1 << MS2_PIN;
  316.   MS3_DDR |= 1 << MS3_PIN;
  317.   #endif
  318.  
  319.   /* Timer Interrupt Setup */
  320.   #if USE_TIMER0 == 1
  321.     // Timer0 in Fast PWM mode, OCR0A as TOP
  322.     TCCR0A  |= (1 << WGM01) | (1 << WGM00);
  323.     TCCR0B  |= (1 << WGM02);
  324.     // Set the ISR COMPA vect - TIMER0_COMPA_vect
  325.     TIMSK0 |= (1 << OCIE0A);
  326.   #endif
  327.  
  328.   #if USE_TIMER1 == 1
  329.     // Timer1 in Fast PWM mode, OCR1A as TOP
  330.     TCCR1A |= (1 << WGM10) | (1 << WGM11);
  331.     TCCR1B |= (1 << WGM12) | (1 << WGM13);
  332.     // Set the ISR COMPA vect - TIMER1_COMPA_vect
  333.     TIMSK1 |= (1 << OCIE1A);
  334.   #endif
  335. }
  336.  
  337. void A4988_isBusy(void){
  338.   while(numberOfPulsesNecessary);
  339. }
  340.  
  341. uint8_t A4988_isNotBusy(void){
  342.   if(numberOfPulsesNecessary == 0) return 1; // is ready
  343.   else return 0; // is not
  344. }
  345.  
  346. void A4988_stepperStop(void){
  347.   // Stop timer
  348.   #if USE_TIMER0 == 1
  349.     TCCR0B &= ~((1 << CS02) |  (1 << CS01) | (1 << CS00));
  350.    
  351.     // Clear timer
  352.     TCNT0 = 0;
  353.   #endif
  354.   #if USE_TIMER1 == 1
  355.     TCCR1B &= ~((1 << CS12) |  (1 << CS11) | (1 << CS10));
  356.    
  357.     // Clear timer
  358.     TCNT1 = 0;
  359.   #endif
  360.  
  361.   // Leave STEP pin LOW
  362.   STEP_PORT &= ~(1 << STEP_PIN);
  363.  
  364.   // Restore SREG (Status Register)
  365.   SREG = sregSave;
  366.  
  367.   // Reset some global variables
  368.   ticksPassed = 0;
  369.   numberOfPulsesNecessary = 0;
  370.   numberOfPulsesMade = 0;
  371.   #if USE_ACCELERATION == 1
  372.   useAcceleration = 1;
  373.   #endif
  374. }
  375.  
  376. #if PERPETUAL_MOTION == 1
  377. void A4988_stepperDecreaseSpeed(uint8_t speed){
  378.   ticksPerPulse += speed;
  379. }
  380.  
  381. void A4988_stepperIncreaseSpeed(uint8_t speed){
  382.   int16_t newTicksPerPulseValue = ticksPerPulse - speed;
  383.  
  384.   if(newTicksPerPulseValue > 0){
  385.     ticksPerPulse = newTicksPerPulseValue;
  386.   }else{
  387.     ticksPerPulse = 1;
  388.   }
  389. }
  390. #endif
  391.  
  392. void A4988_stepMicroseconds(uint16_t nr_of_steps, uint16_t delay_between_steps_us){
  393.   microTime = 1;
  394.   A4988_stepMilliseconds(nr_of_steps, delay_between_steps_us);
  395. }
  396.  
  397. void A4988_stepMilliseconds(uint16_t nr_of_steps, uint32_t delay_between_steps_ms){
  398.   if(nr_of_steps > 0){
  399.     /* Local variables */
  400.     float halfCycleDelay;
  401.    
  402.     /* The function can receive ms or us values so we check the microTime flag
  403.     to convert to microseconds if is necessary */
  404.    
  405.     #if USE_ACCELERATION == 1
  406.       // Save desired speed in buffer
  407.       uint32_t cruising_speed = delay_between_steps_ms;
  408.      
  409.       // Convert milliseconds to microseconds if it is the case
  410.       if(microTime == 0){
  411.         cruising_speed *= 1000;
  412.       }
  413.      
  414.       // Set new speed to a lower predefined speed only if the cruising speed is greater.
  415.       // There is no need for acceleration if the speed is slow.
  416.       if(cruising_speed >= ACCELERATION_STARTING_SPEED){
  417.         useAcceleration = 0;
  418.       }else{
  419.         delay_between_steps_ms = ACCELERATION_STARTING_SPEED;
  420.        
  421.         // Set microTime to true because ACCELERATION_STARTING_SPEED is in microseconds
  422.         microTime = 1;
  423.       }
  424.      
  425.       float halfCycleDelay_cruising = cruising_speed / 2.0;
  426.     #endif
  427.    
  428.     // Convert milliseconds to microseconds if it is the case
  429.     if(microTime == 0){
  430.       delay_between_steps_ms *= 1000;
  431.     }
  432.    
  433.     // Divide the delay between steps by 2 to double the speed because the ISR needs to trigger 2 times for 1 step
  434.     halfCycleDelay = delay_between_steps_ms / 2.0;
  435.    
  436.     // Set the number of ticks for the ISR. Multiply by 2 because for one step is necessary a low
  437.     // pulse and a high pulse
  438.     numberOfPulsesNecessary = nr_of_steps * 2;
  439.    
  440.     /* Set microstepping */
  441.     #if USE_MICROSTEPPING == 1
  442.     if(useMicrosteppingGlobalVar){
  443.       if(delay_between_steps_ms < FULL_STEP_THRESHOLD){
  444.         // Full Step
  445.         MS1_PORT &= ~(1 << MS1_PIN);
  446.         MS2_PORT &= ~(1 << MS2_PIN);
  447.         MS3_PORT &= ~(1 << MS3_PIN);
  448.       }else if(delay_between_steps_ms < HALF_STEP_THRESHOLD){
  449.         // 1/2 Step
  450.         MS1_PORT |= (1 << MS1_PIN);
  451.         MS2_PORT &= ~(1 << MS2_PIN);
  452.         MS3_PORT &= ~(1 << MS3_PIN);
  453.        
  454.         numberOfPulsesNecessary = nr_of_steps * 2 * 2;
  455.        
  456.         #if MICROSTEPPING_DIVIDE_TIME == 1
  457.           halfCycleDelay /= 2;
  458.          
  459.           #if USE_ACCELERATION == 1
  460.             halfCycleDelay_cruising /= 2;
  461.           #endif
  462.         #endif
  463.       }else if(delay_between_steps_ms < QUARTER_STEP_THRESHOLD){
  464.         // 1/4 Step
  465.         MS1_PORT &= ~(1 << MS1_PIN);
  466.         MS2_PORT |= (1 << MS2_PIN);
  467.         MS3_PORT &= ~(1 << MS3_PIN);
  468.        
  469.         numberOfPulsesNecessary = nr_of_steps * 2 * 4;
  470.        
  471.         #if MICROSTEPPING_DIVIDE_TIME == 1
  472.           halfCycleDelay /= 4;
  473.          
  474.           #if USE_ACCELERATION == 1
  475.             halfCycleDelay_cruising /= 4;
  476.           #endif
  477.         #endif
  478.       }else if(delay_between_steps_ms < EIGHTH_STEP_THRESHOLD){
  479.         // 1/8 Step
  480.         MS1_PORT |= (1 << MS1_PIN);
  481.         MS2_PORT |= (1 << MS2_PIN);
  482.         MS3_PORT &= ~(1 << MS3_PIN);
  483.        
  484.         numberOfPulsesNecessary = nr_of_steps * 2 * 8;
  485.        
  486.         #if MICROSTEPPING_DIVIDE_TIME == 1
  487.           halfCycleDelay /= 8;
  488.          
  489.           #if USE_ACCELERATION == 1
  490.             halfCycleDelay_cruising /= 8;
  491.           #endif
  492.         #endif
  493.       }else if(delay_between_steps_ms < SIXTEENTH_STEP_THRESHOLD){
  494.         // 1/16 Step
  495.         MS1_PORT |= (1 << MS1_PIN);
  496.         MS2_PORT |= (1 << MS2_PIN);
  497.         MS3_PORT |= (1 << MS3_PIN);
  498.        
  499.         numberOfPulsesNecessary = nr_of_steps * 2 * 16;
  500.        
  501.         #if MICROSTEPPING_DIVIDE_TIME == 1
  502.           halfCycleDelay /= 16;
  503.          
  504.           #if USE_ACCELERATION == 1
  505.             halfCycleDelay_cruising /= 16;
  506.           #endif
  507.         #endif
  508.       }
  509.      
  510.     }else{
  511.       #if USE_stepperRotateToDegree == 1
  512.       if(useMicrosteppingGlobalVar == 0){
  513.         // 1/16 Step
  514.         MS1_PORT |= (1 << MS1_PIN);
  515.         MS2_PORT |= (1 << MS2_PIN);
  516.         MS3_PORT |= (1 << MS3_PIN);
  517.        
  518.         //halfCycleDelay /= 16;
  519.        
  520.         #if USE_ACCELERATION == 1
  521.           halfCycleDelay_cruising /= 16;
  522.         #endif
  523.       }
  524.       #endif
  525.      
  526.       // Reset the flag
  527.       useMicrosteppingGlobalVar = 1;
  528.     }
  529.     #endif
  530.    
  531.    
  532.     // Reset the flag
  533.     if(microTime){
  534.       microTime = 0;
  535.     }
  536.    
  537.     // Save SREG (Status Register) and enable global interrupts
  538.     sregSave = SREG;
  539.     sei();
  540.    
  541.     #if USE_TIMER0 == 1
  542.       // TOP value for Timer0
  543.       OCR0A = OCR0A_TIMER0_TOP;
  544.     #endif
  545.     #if USE_TIMER1 == 1
  546.       // TOP value for Timer1
  547.       OCR1A = OCR1A_TIMER1_TOP;
  548.     #endif
  549.    
  550.     // Calculate how many times the ISR must trigger to reach the desired time based on current timer resolution
  551.     #if USE_TIMER0 == 1
  552.     float ticksPerPulse_buffer = halfCycleDelay / TIMER0_RESOLUTION;
  553.     #endif
  554.     #if USE_TIMER1 == 1
  555.     float ticksPerPulse_buffer = halfCycleDelay / TIMER1_RESOLUTION;
  556.     #endif
  557.     ticksPerPulse = ticksPerPulse_buffer;
  558.    
  559.     #if IMPROVE_TIME_PRECISION == 1 && USE_ACCELERATION == 0
  560.     // ticksPerPulse_buffer (float) - ticksPerPulse (integer) e.g. 6.25 - 6 = 0.25
  561.     // This is used to account for conversion from float to integer and added to ticksPerPulse
  562.     float ticksPerPulse_diff = ticksPerPulse_buffer - ticksPerPulse;
  563.     if(ticksPerPulse_diff == 0){
  564.       correctionNeeded = 0;
  565.     }else{
  566.       pulsesAfterTickIsAdded = 1 / ticksPerPulse_diff;
  567.       correctionNeeded = 1;
  568.     }
  569.     ticksPerPulseBuffer = ticksPerPulse;
  570.     #endif
  571.    
  572.     // Acceleration, deceleration
  573.     #if USE_ACCELERATION == 1
  574.     if(useAcceleration){
  575.       // Same as ticksPerPulse but used for cruising speed
  576.       uint16_t ticks_per_pulse_cruising = halfCycleDelay_cruising / TIMER0_RESOLUTION;
  577.      
  578.       // Difference in time (ticks) between the acceleration speed and the cruising speed
  579.       // The acceleration speed is used for the deceleration speed as well
  580.       float start_end_diff = ticksPerPulse - ticks_per_pulse_cruising;
  581.      
  582.       // How many steps are used to accelerate/decelerate based on a percentage set by the user
  583.       stepsToAccelerate = (numberOfPulsesNecessary * ACCELERATION) / 100;
  584.       stepsToDecelerate = (numberOfPulsesNecessary * DECELERATION) / 100;
  585.      
  586.       // How much to accelerate/decelerate per step based on the number of steps
  587.       accelerationPerStep = start_end_diff / stepsToAccelerate;
  588.       decelerationPerStep = start_end_diff / stepsToDecelerate;
  589.      
  590.       // accelerationPerStep/decelerationPerStep may be less than 1 so accelerationPerStepInteger/decelerationPerStepInteger
  591.       // are used by the ISR to sum the floats to 1
  592.       accelerationPerStepInteger = accelerationPerStep;
  593.       decelerationPerStepInteger = decelerationPerStep;
  594.      
  595.       // The step number after the cruising ends and deceleration starts
  596.       decelerationStep = numberOfPulsesNecessary - stepsToDecelerate;
  597.     }
  598.     #endif
  599.    
  600.     // Set the prescaler and start Timer
  601.     #if FIXED_PRESCALER == 1
  602.       #if USE_TIMER0 == 1
  603.         // Set prescaler to 1 and start the timer
  604.         TCCR0B |= (1 << CS00);
  605.       #endif
  606.       #if USE_TIMER1 == 1
  607.         // Set prescaler to 1 and start the timer
  608.         TCCR1B |= (1 << CS10);
  609.       #endif
  610.     #elif FIXED_PRESCALER == 8
  611.       #if USE_TIMER0 == 1
  612.         // Set prescaler to 8 and start the timer
  613.         TCCR0B |= (1 << CS01);
  614.       #endif
  615.       #if USE_TIMER1 == 1
  616.         // Set prescaler to 8 and start the timer
  617.         TCCR1B |= (1 << CS11);
  618.       #endif
  619.     #elif FIXED_PRESCALER == 64
  620.       #if USE_TIMER0 == 1
  621.         // Set prescaler to 64 and start the timer
  622.         TCCR0B |= (1 << CS00) | (1 << CS01);
  623.       #endif
  624.       #if USE_TIMER1 == 1
  625.         // Set prescaler to 64 and start the timer
  626.         TCCR1B |= (1 << CS10) | (1 << CS11);
  627.       #endif
  628.     #elif FIXED_PRESCALER == 256
  629.       #if USE_TIMER0 == 1
  630.         // Set prescaler to 256 and start the timer
  631.         TCCR0B |= (1 << CS02);
  632.       #endif
  633.       #if USE_TIMER1 == 1
  634.         // Set prescaler to 256 and start the timer
  635.         TCCR1B |= (1 << CS12);
  636.       #endif
  637.     #elif FIXED_PRESCALER == 1024
  638.       #if USE_TIMER0 == 1
  639.         // Set prescaler to 1024 and start the timer
  640.         TCCR0B |= (1 << CS00) | (1 << CS02);
  641.       #endif
  642.       #if USE_TIMER1 == 1
  643.         // Set prescaler to 1024 and start the timer
  644.         TCCR1B |= (1 << CS10) | (1 << CS12);
  645.       #endif
  646.     #endif
  647.   }
  648. }
  649.  
  650. #if USE_DIRECTION_PIN == 1
  651. void A4988_stepperDirection(uint8_t direction){
  652.   if(direction)
  653.     DIR_PORT |= 1 << DIR_PIN; // turn clockwise
  654.   else
  655.     DIR_PORT &= ~(1 << DIR_PIN); // turn counter-clockwise
  656. }
  657. #endif
  658.  
  659. void A4988_stepperRotateNTimes(uint16_t nr_of_rotations, uint16_t total_duration_ms){
  660.   uint16_t total_steps = STEPS_PER_REVOLUTION * nr_of_rotations;
  661.   uint32_t millisToMicro = 1000;
  662.   millisToMicro = total_duration_ms * millisToMicro; // convert to us
  663.   millisToMicro = (millisToMicro / total_steps);
  664.   microTime = 1;
  665.   A4988_stepMilliseconds(total_steps, millisToMicro);
  666. }
  667.  
  668. #if USE_stepperRotateToDegree == 1
  669. void A4988_stepperRotateToDegree(float degree, uint16_t delay_between_steps_us){
  670.   microTime = 1;
  671.   useMicrosteppingGlobalVar = 0;
  672.   #if USE_ACCELERATION == 1
  673.   //useAcceleration = 0;
  674.   #endif
  675.  
  676.   float micro_degree = STEPPER_DEGREES / 16.0;
  677.   int16_t degrees_to_move = degree - currentDegreePosition;
  678.   if(degrees_to_move < 0) degrees_to_move *= -1; // Convert negative number to positive
  679.   uint16_t steps_to_make = degrees_to_move / micro_degree;
  680.  
  681.   // Set direction
  682.   if(degree > currentDegreePosition){
  683.     A4988_stepperDirection(TURN_RIGHT);
  684.   }else{
  685.     A4988_stepperDirection(TURN_LEFT);
  686.   }
  687.  
  688.   currentDegreePosition = degree;
  689.   A4988_stepMilliseconds(steps_to_make, delay_between_steps_us);
  690. }
  691. #endif
  692.  
  693.  
  694.  
  695. /*************************************************************
  696.   INTERRUPTS
  697. **************************************************************/
  698. #if USE_TIMER0 == 1
  699. ISR(TIMER0_COMPA_vect){
  700. #endif
  701. #if USE_TIMER1 == 1
  702. ISR(TIMER1_COMPA_vect){
  703. #endif
  704.   // Half cycle has passed
  705.   if(ticksPassed >= ticksPerPulse){
  706.     STEP_PORT ^= (1 << STEP_PIN);
  707.    
  708.     // Acceleration, deceleration
  709.     #if USE_ACCELERATION == 1
  710.     if(useAcceleration){
  711.       uint16_t new_trigger_time = 0;
  712.       // Accelerate
  713.       if(numberOfPulsesMade < stepsToAccelerate){
  714.         if(accelerationPerStepInteger < 1){
  715.           accelerationPerStepInteger += accelerationPerStep;
  716.         }else{
  717.           new_trigger_time = ticksPerPulse - (uint16_t)accelerationPerStepInteger;
  718.           accelerationPerStepInteger = 0;
  719.          
  720.           if(new_trigger_time > 0){
  721.             ticksPerPulse = new_trigger_time;
  722.           }
  723.         }
  724.       }else{
  725.         #if PERPETUAL_MOTION == 0
  726.         // Decelerate
  727.         if(numberOfPulsesMade > decelerationStep){
  728.           if(decelerationPerStepInteger < 1){
  729.             decelerationPerStepInteger += decelerationPerStep;
  730.           }else{
  731.             ticksPerPulse += (uint16_t)decelerationPerStepInteger;
  732.             decelerationPerStepInteger = 0;
  733.           }
  734.         }
  735.         #else
  736.           // Keep the numberOfPulsesMade = with stepsToAccelerate to prevent further acceleration
  737.           numberOfPulsesMade = stepsToAccelerate;
  738.         #endif
  739.       }
  740.     }
  741.     #else
  742.       #if IMPROVE_TIME_PRECISION == 1
  743.         if(countCorrectionPulses == pulsesAfterTickIsAdded && correctionNeeded){
  744.           ticksPerPulse++;
  745.           countCorrectionPulses = 0;
  746.         }else{
  747.           ticksPerPulse = ticksPerPulseBuffer;
  748.           countCorrectionPulses++;
  749.         }
  750.       #endif
  751.     #endif
  752.    
  753.     numberOfPulsesMade++; // Two of these is one step for the motor
  754.     ticksPassed = 0;
  755.    
  756.     // When the steps have been made, stop the timer interrupt, unless the PERPETUAL_MOTION is activated
  757.     #if PERPETUAL_MOTION == 0
  758.       if(numberOfPulsesMade >= numberOfPulsesNecessary){
  759.         A4988_stepperStop();
  760.       }
  761.     #endif
  762.   }
  763.  
  764.   // Count the number of times the ISR has been triggered
  765.   ticksPassed++;
  766. }
  767.  
  768. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement