Fixed buffer size (see issue 12)
[hackover2013-badge-firmware.git] / drivers / motor / stepper / stepper.c
1 /**************************************************************************/
2 /*!
3 @file stepper.c
4 @author Based on original code by Tom Igoe
5 Modified by K. Townsend (microBuilder.eu)
6
7 @brief Simple bi-polar stepper motor controller, based on the
8 Arduino stepper library by Tom Igoe. Includes simple
9 position handling methods to keep track of the motor's
10 relative position and the spindle's current rotation.
11
12 @section Example
13
14 @code
15
16 #include "sysinit.h"
17 #include "core/systick/systick.h"
18 #include "drivers/motor/stepper/stepper.h"
19
20 ...
21
22 systemInit(); // Configure cpu and mandatory peripherals
23
24 stepperInit(200); // Initialise driver for 200-step motor
25 stepperSetSpeed(60); // Set speed to 60 rpm (1 revolution per second)
26
27 while (1)
28 {
29 stepperStep(400); // Move forward 400 steps
30 stepperStep(-200); // Move backward 200 steps
31 systickDelay(1000); // Wait one second
32
33 // Move 'home' after 10 loops (current position = 2000)
34 if (stepperGetPosition() == 2000)
35 {
36 stepperMoveHome(); // Move back to the starting position
37 systickDelay(1000); // Wait one second
38 }
39 }
40
41 @endcode
42
43 @section LICENSE
44
45 Software License Agreement (BSD License)
46
47 Copyright (c) 2010, microBuilder SARL
48 All rights reserved.
49
50 Redistribution and use in source and binary forms, with or without
51 modification, are permitted provided that the following conditions are met:
52 1. Redistributions of source code must retain the above copyright
53 notice, this list of conditions and the following disclaimer.
54 2. Redistributions in binary form must reproduce the above copyright
55 notice, this list of conditions and the following disclaimer in the
56 documentation and/or other materials provided with the distribution.
57 3. Neither the name of the copyright holders nor the
58 names of its contributors may be used to endorse or promote products
59 derived from this software without specific prior written permission.
60
61 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
62 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
65 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
66 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
67 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
68 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
69 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
70 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
71 */
72 /**************************************************************************/
73 #include <stdlib.h>
74
75 #include "stepper.h"
76 #include "core/gpio/gpio.h"
77 #include "core/timer32/timer32.h"
78
79 static int64_t stepperPosition = 0; // The current position (in steps) relative to 'Home'
80 static uint32_t stepperStepNumber = 0; // The current position (in steps) relative to 0°
81 static uint32_t stepperStepsPerRotation = 0; // Number of steps in a full 360° rotation
82 static uint32_t stepperStepDelay = 0; // Delay in CPU ticks between individual steps
83
84 /**************************************************************************/
85 /*!
86 Private - Cause the motor to step forward or backward one step
87 */
88 /**************************************************************************/
89 void stepMotor(uint32_t thisStep)
90 {
91 switch (thisStep)
92 {
93 case 0: // 1010
94 gpioSetValue(STEPPER_IN1_PORT, STEPPER_IN1_PIN, 1);
95 gpioSetValue(STEPPER_IN2_PORT, STEPPER_IN2_PIN, 0);
96 gpioSetValue(STEPPER_IN3_PORT, STEPPER_IN3_PIN, 1);
97 gpioSetValue(STEPPER_IN4_PORT, STEPPER_IN4_PIN, 0);
98 break;
99 case 1: // 0110
100 gpioSetValue(STEPPER_IN1_PORT, STEPPER_IN1_PIN, 0);
101 gpioSetValue(STEPPER_IN2_PORT, STEPPER_IN2_PIN, 1);
102 gpioSetValue(STEPPER_IN3_PORT, STEPPER_IN3_PIN, 1);
103 gpioSetValue(STEPPER_IN4_PORT, STEPPER_IN4_PIN, 0);
104 break;
105 case 2: // 0101
106 gpioSetValue(STEPPER_IN1_PORT, STEPPER_IN1_PIN, 0);
107 gpioSetValue(STEPPER_IN2_PORT, STEPPER_IN2_PIN, 1);
108 gpioSetValue(STEPPER_IN3_PORT, STEPPER_IN3_PIN, 0);
109 gpioSetValue(STEPPER_IN4_PORT, STEPPER_IN4_PIN, 1);
110 break;
111 case 3: // 1001
112 gpioSetValue(STEPPER_IN1_PORT, STEPPER_IN1_PIN, 1);
113 gpioSetValue(STEPPER_IN2_PORT, STEPPER_IN2_PIN, 0);
114 gpioSetValue(STEPPER_IN3_PORT, STEPPER_IN3_PIN, 0);
115 gpioSetValue(STEPPER_IN4_PORT, STEPPER_IN4_PIN, 1);
116 break;
117 }
118 }
119
120 /**************************************************************************/
121 /*!
122 @brief Initialises the GPIO pins and delay timer and sets any
123 default values.
124
125 @param[in] steps
126 The number of steps per rotation (typically 200 or 400)
127 */
128 /**************************************************************************/
129 void stepperInit(uint32_t steps)
130 {
131 // Setup motor control pins
132 gpioSetDir(STEPPER_IN1_PORT, STEPPER_IN1_PIN, 1);
133 gpioSetDir(STEPPER_IN2_PORT, STEPPER_IN2_PIN, 1);
134 gpioSetDir(STEPPER_IN3_PORT, STEPPER_IN3_PIN, 1);
135 gpioSetDir(STEPPER_IN4_PORT, STEPPER_IN4_PIN, 1);
136
137 gpioSetValue(STEPPER_IN1_PORT, STEPPER_IN1_PIN, 0);
138 gpioSetValue(STEPPER_IN2_PORT, STEPPER_IN2_PIN, 0);
139 gpioSetValue(STEPPER_IN3_PORT, STEPPER_IN3_PIN, 0);
140 gpioSetValue(STEPPER_IN4_PORT, STEPPER_IN4_PIN, 0);
141
142 // Set the number of steps per rotation
143 stepperStepsPerRotation = steps;
144
145 // Set the default speed (2 rotations per second)
146 stepperSetSpeed(120);
147 }
148
149 /**************************************************************************/
150 /*!
151 @brief Gets the current position (in steps) relative to 'Home'.
152
153 @return The difference (in steps) of the motor's current position
154 from the original 'Home' position. Value can be negative or
155 positive depending on the direction of previous movements.
156 */
157 /**************************************************************************/
158 int64_t stepperGetPosition()
159 {
160 return stepperPosition;
161 }
162
163 /**************************************************************************/
164 /*!
165 @brief Gets the motor's current rotation (in steps) relative to
166 the spindle's 'Zero' position.
167
168 @return The current step (0 .. steps per rotation) on the motor's
169 spindle relative to 0°. Value is always positive.
170 */
171 /**************************************************************************/
172 uint32_t stepperGetRotation()
173 {
174 return stepperStepNumber;
175 }
176
177 /**************************************************************************/
178 /*!
179 @brief Sets the motor's current position to 'Home', meaning that
180 any future movement will be relative to the current
181 position.
182 */
183 /**************************************************************************/
184 void stepperSetHome()
185 {
186 stepperPosition = 0;
187 }
188
189 /**************************************************************************/
190 /*!
191 @brief Moves the motor back to the original 'Home' position.
192 */
193 /**************************************************************************/
194 void stepperMoveHome()
195 {
196 stepperStep(stepperPosition * -1);
197 }
198
199 /**************************************************************************/
200 /*!
201 @brief Saves the spindle's current angle/position as 0°. Each
202 step the spindle takes will now be relative to the spindle's
203 current position.
204 */
205 /**************************************************************************/
206 void stepperSetZero()
207 {
208 stepperStepNumber = 0;
209 }
210
211 /**************************************************************************/
212 /*!
213 @brief Moves the motor to its original rotation value. For example,
214 if a 200-step motor is currently rotated to step 137, it
215 will move the motor forward 63 steps to end at step 0 or 0°.
216 */
217 /**************************************************************************/
218 void stepperMoveZero()
219 {
220 if (!stepperStepNumber)
221 {
222 stepperStep(stepperStepsPerRotation - stepperStepNumber);
223 }
224 }
225
226 /**************************************************************************/
227 /*!
228 @brief Sets the motor speed in rpm, meaning the number of times the
229 motor will fully rotate in a one minute period.
230
231 @param[in] rpm
232 Motor speed in revolutions per minute (RPM)
233
234 @warning Not all motors will function at all speeds, and some trial
235 and error may be required to find an appropriate speed for
236 the motor.
237 */
238 /**************************************************************************/
239 void stepperSetSpeed(uint32_t rpm)
240 {
241 uint32_t ticksOneRPM = ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / stepperStepsPerRotation) * 60;
242
243 // Set stepper RPM
244 stepperStepDelay = ticksOneRPM / rpm;
245
246 // Initialise 32-bit timer 0 with the appropriate delay
247 timer32Init(0, stepperStepDelay);
248 timer32Enable(0);
249 }
250
251 /**************************************************************************/
252 /*!
253 @brief Moves the motor forward or backward the specified number
254 of steps. A positive number moves the motor forward,
255 while a negative number moves the motor backwards.
256
257 @param[in] steps
258 The number of steps to move foreward (positive) or
259 backward (negative)
260 */
261 /**************************************************************************/
262 void stepperStep(int32_t steps)
263 {
264 uint32_t stepsLeft = abs(steps); // Force number to be positive
265
266 while (stepsLeft > 0)
267 {
268 // Wait 1 tick between individual steps
269 timer32Delay(0, 1);
270
271 // Increment or decrement step counters (depending on direction)
272 if (steps > 0)
273 {
274 stepperPosition++; // Increment global position counter
275 stepperStepNumber++; // Increment single rotation counter
276 if (stepperStepNumber == stepperStepsPerRotation)
277 {
278 stepperStepNumber = 0;
279 }
280 }
281 else
282 {
283 stepperPosition--; // Decrement global position counter
284 if (stepperStepNumber == 0)
285 {
286 stepperStepNumber = stepperStepsPerRotation;
287 }
288 stepperStepNumber--; // Decrement single rotation counter
289 }
290
291 // Decrement number of remaining steps
292 stepsLeft--;
293
294 // Step the motor one step
295 stepMotor(stepperStepNumber % 4);
296 }
297 }
298
299
300
This page took 0.113931 seconds and 5 git commands to generate.