1 /*
2 * Author: Jon Trulson <jtrulson@ics.com>
3 * Copyright (c) 2015 Intel Corporation.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <iostream>
26 #include <string>
27 #include <stdexcept>
28
29 #include "uln200xa.h"
30
31 using namespace upm;
32 using namespace std;
33
ULN200XA(int stepsPerRev,int i1,int i2,int i3,int i4)34 ULN200XA::ULN200XA(int stepsPerRev, int i1, int i2, int i3, int i4)
35 {
36 m_stepsPerRev = stepsPerRev;
37 m_currentStep = 0;
38 m_stepDelay = 0;
39 m_stepDirection = 1; // default is forward
40
41 if ( !(m_stepI1 = mraa_gpio_init(i1)) )
42 {
43 throw std::invalid_argument(std::string(__FUNCTION__) +
44 ": mraa_gpio_init(i1) failed, invalid pin?");
45 return;
46 }
47 mraa_gpio_dir(m_stepI1, MRAA_GPIO_OUT);
48
49 if ( !(m_stepI2 = mraa_gpio_init(i2)) )
50 {
51 throw std::invalid_argument(std::string(__FUNCTION__) +
52 ": mraa_gpio_init(i2) failed, invalid pin?");
53 mraa_gpio_close(m_stepI1);
54 return;
55 }
56 mraa_gpio_dir(m_stepI2, MRAA_GPIO_OUT);
57
58 if ( !(m_stepI3 = mraa_gpio_init(i3)) )
59 {
60 throw std::invalid_argument(std::string(__FUNCTION__) +
61 ": mraa_gpio_init(i3) failed, invalid pin?");
62 mraa_gpio_close(m_stepI1);
63 mraa_gpio_close(m_stepI2);
64 return;
65 }
66 mraa_gpio_dir(m_stepI3, MRAA_GPIO_OUT);
67
68 if ( !(m_stepI4 = mraa_gpio_init(i4)) )
69 {
70 throw std::invalid_argument(std::string(__FUNCTION__) +
71 ": mraa_gpio_init(i4) failed, invalid pin?");
72 mraa_gpio_close(m_stepI1);
73 mraa_gpio_close(m_stepI2);
74 mraa_gpio_close(m_stepI3);
75
76 return;
77 }
78 mraa_gpio_dir(m_stepI4, MRAA_GPIO_OUT);
79
80 // set default speed to 1
81 setSpeed(1);
82 }
83
initClock()84 void ULN200XA::initClock()
85 {
86 gettimeofday(&m_startTime, NULL);
87 }
88
getMillis()89 uint32_t ULN200XA::getMillis()
90 {
91 struct timeval elapsed, now;
92 uint32_t elapse;
93
94 // get current time
95 gettimeofday(&now, NULL);
96
97 // compute the delta since m_startTime
98 if( (elapsed.tv_usec = now.tv_usec - m_startTime.tv_usec) < 0 )
99 {
100 elapsed.tv_usec += 1000000;
101 elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec - 1;
102 }
103 else
104 {
105 elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec;
106 }
107
108 elapse = (uint32_t)((elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000));
109
110 // never return 0
111 if (elapse == 0)
112 elapse = 1;
113
114 return elapse;
115 }
116
117
~ULN200XA()118 ULN200XA::~ULN200XA()
119 {
120 mraa_gpio_close(m_stepI1);
121 mraa_gpio_close(m_stepI2);
122 mraa_gpio_close(m_stepI3);
123 mraa_gpio_close(m_stepI4);
124 }
125
setSpeed(int speed)126 void ULN200XA::setSpeed(int speed)
127 {
128 m_stepDelay = 60 * 1000 / m_stepsPerRev / speed;
129 }
130
setDirection(ULN200XA_DIRECTION_T dir)131 void ULN200XA::setDirection(ULN200XA_DIRECTION_T dir)
132 {
133 switch (dir)
134 {
135 case DIR_CW:
136 m_stepDirection = 1;
137 break;
138 case DIR_CCW:
139 m_stepDirection = -1;
140 break;
141 }
142 }
143
stepperStep()144 void ULN200XA::stepperStep()
145 {
146 int step = m_currentStep % 8;
147
148 // This motor requires a different sequencing order in 8-steps than
149 // usual.
150
151 // Step I0 I1 I2 I3
152 // 1 0 0 0 1
153 // 2 0 0 1 1
154 // 3 0 0 1 0
155 // 4 0 1 1 0
156 // 5 0 1 0 0
157 // 6 1 1 0 0
158 // 7 1 0 0 0
159 // 8 1 0 0 1
160
161 switch (step)
162 {
163 case 0: // 0001
164 mraa_gpio_write(m_stepI1, 0);
165 mraa_gpio_write(m_stepI2, 0);
166 mraa_gpio_write(m_stepI3, 0);
167 mraa_gpio_write(m_stepI4, 1);
168 break;
169 case 1: // 0011
170 mraa_gpio_write(m_stepI1, 0);
171 mraa_gpio_write(m_stepI2, 0);
172 mraa_gpio_write(m_stepI3, 1);
173 mraa_gpio_write(m_stepI4, 1);
174 break;
175 case 2: // 0010
176 mraa_gpio_write(m_stepI1, 0);
177 mraa_gpio_write(m_stepI2, 0);
178 mraa_gpio_write(m_stepI3, 1);
179 mraa_gpio_write(m_stepI4, 0);
180 break;
181 case 3: // 0110
182 mraa_gpio_write(m_stepI1, 0);
183 mraa_gpio_write(m_stepI2, 1);
184 mraa_gpio_write(m_stepI3, 1);
185 mraa_gpio_write(m_stepI4, 0);
186 break;
187 case 4: // 0100
188 mraa_gpio_write(m_stepI1, 0);
189 mraa_gpio_write(m_stepI2, 1);
190 mraa_gpio_write(m_stepI3, 0);
191 mraa_gpio_write(m_stepI4, 0);
192 break;
193 case 5: // 1100
194 mraa_gpio_write(m_stepI1, 1);
195 mraa_gpio_write(m_stepI2, 1);
196 mraa_gpio_write(m_stepI3, 0);
197 mraa_gpio_write(m_stepI4, 0);
198 break;
199 case 6: // 1000
200 mraa_gpio_write(m_stepI1, 1);
201 mraa_gpio_write(m_stepI2, 0);
202 mraa_gpio_write(m_stepI3, 0);
203 mraa_gpio_write(m_stepI4, 0);
204 break;
205 case 7: // 1001
206 mraa_gpio_write(m_stepI1, 1);
207 mraa_gpio_write(m_stepI2, 0);
208 mraa_gpio_write(m_stepI3, 0);
209 mraa_gpio_write(m_stepI4, 1);
210 break;
211 }
212 }
213
stepperSteps(unsigned int steps)214 void ULN200XA::stepperSteps(unsigned int steps)
215 {
216 while (steps > 0)
217 {
218 if (getMillis() >= m_stepDelay)
219 {
220 // reset the clock
221 initClock();
222
223 m_currentStep += m_stepDirection;
224
225 if (m_stepDirection == 1)
226 {
227 if (m_currentStep >= m_stepsPerRev)
228 m_currentStep = 0;
229 }
230 else
231 {
232 if (m_currentStep <= 0)
233 m_currentStep = m_stepsPerRev;
234 }
235
236 steps--;
237 stepperStep();
238 }
239 }
240 }
241
release()242 void ULN200XA::release()
243 {
244 mraa_gpio_write(m_stepI1, 0);
245 mraa_gpio_write(m_stepI2, 0);
246 mraa_gpio_write(m_stepI3, 0);
247 mraa_gpio_write(m_stepI4, 0);
248 }
249