Skip to content

Commit fdae078

Browse files
committed
add initial version
0 parents  commit fdae078

File tree

10 files changed

+1009
-0
lines changed

10 files changed

+1009
-0
lines changed

AFMotor_R4.cpp

Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
/* AFMotor_R4.cpp - Implementation for Arduino R4 WiFi compatible AFMotor library
2+
* Compatible replacement for the Adafruit Motor Shield V1 library
3+
*
4+
* This library replicates the original AFMotor library API while being
5+
* compatible with Arduino R4 WiFi and other non-AVR boards.
6+
*/
7+
8+
#include "AFMotor_R4.h"
9+
10+
// Global variables
11+
uint8_t latch_state = 0; // Current state of the shift register
12+
bool motor_controller_initialized = false;
13+
14+
// Microstep curve for smooth stepping
15+
uint8_t microstepcurve[] = {0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225, 236, 244, 250, 253, 255};
16+
17+
// Function to send data to the shift register
18+
void latch_tx() {
19+
digitalWrite(DIR_LATCH, LOW);
20+
shiftOut(DIR_SER, DIR_CLK, MSBFIRST, latch_state);
21+
digitalWrite(DIR_LATCH, HIGH);
22+
}
23+
24+
// Initialize the motor controller
25+
void initMotorController() {
26+
if (!motor_controller_initialized) {
27+
// Initialize control pins for the shift register
28+
pinMode(DIR_EN, OUTPUT);
29+
pinMode(DIR_SER, OUTPUT);
30+
pinMode(DIR_LATCH, OUTPUT);
31+
pinMode(DIR_CLK, OUTPUT);
32+
33+
// Enable the shift register outputs (active LOW)
34+
digitalWrite(DIR_EN, LOW);
35+
36+
// Reset latch state
37+
latch_state = 0;
38+
latch_tx();
39+
40+
motor_controller_initialized = true;
41+
}
42+
}
43+
44+
// AF_DCMotor class implementation
45+
AF_DCMotor::AF_DCMotor(uint8_t num, uint8_t freq) { // freq parameter for compatibility, not used
46+
motornum = num;
47+
48+
// Initialize motor controller if not done already
49+
initMotorController();
50+
51+
// Set PWM pins and direction bits based on motor number
52+
switch(num) {
53+
case 1:
54+
pwm_pin = PWM2A; // Pin 11
55+
motor_a_bit = MOTOR1_A;
56+
motor_b_bit = MOTOR1_B;
57+
break;
58+
case 2:
59+
pwm_pin = PWM2B; // Pin 3
60+
motor_a_bit = MOTOR2_A;
61+
motor_b_bit = MOTOR2_B;
62+
break;
63+
case 3:
64+
pwm_pin = PWM0A; // Pin 6
65+
motor_a_bit = MOTOR3_A;
66+
motor_b_bit = MOTOR3_B;
67+
break;
68+
case 4:
69+
pwm_pin = PWM0B; // Pin 5
70+
motor_a_bit = MOTOR4_A;
71+
motor_b_bit = MOTOR4_B;
72+
break;
73+
default:
74+
return;
75+
}
76+
77+
// Initialize PWM pin
78+
pinMode(pwm_pin, OUTPUT);
79+
80+
// Set both motor direction bits to 0 initially
81+
latch_state &= ~(1 << motor_a_bit) & ~(1 << motor_b_bit);
82+
latch_tx();
83+
}
84+
85+
void AF_DCMotor::run(uint8_t cmd) {
86+
switch(cmd) {
87+
case FORWARD:
88+
latch_state |= (1 << motor_a_bit); // Set A bit
89+
latch_state &= ~(1 << motor_b_bit); // Clear B bit
90+
break;
91+
case BACKWARD:
92+
latch_state &= ~(1 << motor_a_bit); // Clear A bit
93+
latch_state |= (1 << motor_b_bit); // Set B bit
94+
break;
95+
case BRAKE:
96+
latch_state |= (1 << motor_a_bit); // Set both bits for brake
97+
latch_state |= (1 << motor_b_bit);
98+
break;
99+
case RELEASE:
100+
latch_state &= ~(1 << motor_a_bit); // Clear both bits
101+
latch_state &= ~(1 << motor_b_bit);
102+
break;
103+
}
104+
latch_tx();
105+
}
106+
107+
void AF_DCMotor::setSpeed(uint8_t speed) {
108+
analogWrite(pwm_pin, speed);
109+
}
110+
111+
// AF_Stepper class implementation
112+
AF_Stepper::AF_Stepper(uint16_t steps, uint8_t num) {
113+
revsteps = steps;
114+
steppernum = num;
115+
currentstep = 0;
116+
usperstep = 0;
117+
steppingcounter = 0;
118+
119+
// Initialize motor controller if not done already
120+
initMotorController();
121+
122+
if (steppernum == 1) {
123+
// Stepper 1 uses motors M1 and M2
124+
latch_state &= ~(1 << MOTOR1_A) & ~(1 << MOTOR1_B) &
125+
~(1 << MOTOR2_A) & ~(1 << MOTOR2_B);
126+
latch_tx();
127+
128+
// Enable PWM pins for stepper 1
129+
pinMode(PWM2A, OUTPUT); // Pin 11 for M1
130+
pinMode(PWM2B, OUTPUT); // Pin 3 for M2
131+
digitalWrite(PWM2A, HIGH);
132+
digitalWrite(PWM2B, HIGH);
133+
134+
} else if (steppernum == 2) {
135+
// Stepper 2 uses motors M3 and M4
136+
latch_state &= ~(1 << MOTOR3_A) & ~(1 << MOTOR3_B) &
137+
~(1 << MOTOR4_A) & ~(1 << MOTOR4_B);
138+
latch_tx();
139+
140+
// Enable PWM pins for stepper 2
141+
pinMode(PWM0A, OUTPUT); // Pin 6 for M3
142+
pinMode(PWM0B, OUTPUT); // Pin 5 for M4
143+
digitalWrite(PWM0A, HIGH);
144+
digitalWrite(PWM0B, HIGH);
145+
}
146+
}
147+
148+
void AF_Stepper::setSpeed(uint16_t rpm) {
149+
usperstep = 60000000L / ((uint32_t)revsteps * (uint32_t)rpm);
150+
steppingcounter = 0;
151+
}
152+
153+
void AF_Stepper::release(void) {
154+
if (steppernum == 1) {
155+
latch_state &= ~(1 << MOTOR1_A) & ~(1 << MOTOR1_B) &
156+
~(1 << MOTOR2_A) & ~(1 << MOTOR2_B);
157+
} else if (steppernum == 2) {
158+
latch_state &= ~(1 << MOTOR3_A) & ~(1 << MOTOR3_B) &
159+
~(1 << MOTOR4_A) & ~(1 << MOTOR4_B);
160+
}
161+
latch_tx();
162+
}
163+
164+
void AF_Stepper::step(uint16_t steps, uint8_t dir, uint8_t style) {
165+
uint32_t uspers = usperstep;
166+
uint8_t ret = 0;
167+
168+
if (style == INTERLEAVE) {
169+
uspers /= 2;
170+
} else if (style == MICROSTEP) {
171+
uspers /= MICROSTEPS;
172+
steps *= MICROSTEPS;
173+
}
174+
175+
while (steps--) {
176+
ret = onestep(dir, style);
177+
if (uspers > 16383) { // Delay longer than 16ms
178+
delay(uspers / 1000);
179+
delayMicroseconds(uspers % 1000);
180+
} else {
181+
delayMicroseconds(uspers);
182+
}
183+
184+
steppingcounter += (uspers % 1000);
185+
if (steppingcounter >= 1000) {
186+
delay(1);
187+
steppingcounter -= 1000;
188+
}
189+
}
190+
191+
if (style == MICROSTEP) {
192+
while ((ret != 0) && (ret != MICROSTEPS)) {
193+
ret = onestep(dir, style);
194+
if (uspers > 16383) {
195+
delay(uspers / 1000);
196+
delayMicroseconds(uspers % 1000);
197+
} else {
198+
delayMicroseconds(uspers);
199+
}
200+
201+
steppingcounter += (uspers % 1000);
202+
if (steppingcounter >= 1000) {
203+
delay(1);
204+
steppingcounter -= 1000;
205+
}
206+
}
207+
}
208+
}
209+
210+
uint8_t AF_Stepper::onestep(uint8_t dir, uint8_t style) {
211+
uint8_t a, b, c, d;
212+
uint8_t ocra = 255, ocrb = 255;
213+
214+
if (steppernum == 1) {
215+
a = (1 << MOTOR1_A);
216+
b = (1 << MOTOR2_A);
217+
c = (1 << MOTOR1_B);
218+
d = (1 << MOTOR2_B);
219+
} else if (steppernum == 2) {
220+
a = (1 << MOTOR3_A);
221+
b = (1 << MOTOR4_A);
222+
c = (1 << MOTOR3_B);
223+
d = (1 << MOTOR4_B);
224+
} else {
225+
return 0;
226+
}
227+
228+
// Handle different stepping styles
229+
if (style == SINGLE) {
230+
if ((currentstep / (MICROSTEPS / 2)) % 2) {
231+
if (dir == FORWARD) {
232+
currentstep += MICROSTEPS / 2;
233+
} else {
234+
currentstep -= MICROSTEPS / 2;
235+
}
236+
} else {
237+
if (dir == FORWARD) {
238+
currentstep += MICROSTEPS;
239+
} else {
240+
currentstep -= MICROSTEPS;
241+
}
242+
}
243+
} else if (style == DOUBLE) {
244+
if (!(currentstep / (MICROSTEPS / 2) % 2)) {
245+
if (dir == FORWARD) {
246+
currentstep += MICROSTEPS / 2;
247+
} else {
248+
currentstep -= MICROSTEPS / 2;
249+
}
250+
} else {
251+
if (dir == FORWARD) {
252+
currentstep += MICROSTEPS;
253+
} else {
254+
currentstep -= MICROSTEPS;
255+
}
256+
}
257+
} else if (style == INTERLEAVE) {
258+
if (dir == FORWARD) {
259+
currentstep += MICROSTEPS / 2;
260+
} else {
261+
currentstep -= MICROSTEPS / 2;
262+
}
263+
}
264+
265+
if (style == MICROSTEP) {
266+
if (dir == FORWARD) {
267+
currentstep++;
268+
} else {
269+
currentstep--;
270+
}
271+
272+
currentstep += MICROSTEPS * 4;
273+
currentstep %= MICROSTEPS * 4;
274+
275+
ocra = ocrb = 0;
276+
if ((currentstep >= 0) && (currentstep < MICROSTEPS)) {
277+
ocra = microstepcurve[MICROSTEPS - currentstep];
278+
ocrb = microstepcurve[currentstep];
279+
} else if ((currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS * 2)) {
280+
ocra = microstepcurve[currentstep - MICROSTEPS];
281+
ocrb = microstepcurve[MICROSTEPS * 2 - currentstep];
282+
} else if ((currentstep >= MICROSTEPS * 2) && (currentstep < MICROSTEPS * 3)) {
283+
ocra = microstepcurve[MICROSTEPS * 3 - currentstep];
284+
ocrb = microstepcurve[currentstep - MICROSTEPS * 2];
285+
} else if ((currentstep >= MICROSTEPS * 3) && (currentstep < MICROSTEPS * 4)) {
286+
ocra = microstepcurve[currentstep - MICROSTEPS * 3];
287+
ocrb = microstepcurve[MICROSTEPS * 4 - currentstep];
288+
}
289+
}
290+
291+
currentstep += MICROSTEPS * 4;
292+
currentstep %= MICROSTEPS * 4;
293+
294+
// Set PWM values for microstepping
295+
if (steppernum == 1) {
296+
analogWrite(PWM2A, ocra);
297+
analogWrite(PWM2B, ocrb);
298+
} else if (steppernum == 2) {
299+
analogWrite(PWM0A, ocra);
300+
analogWrite(PWM0B, ocrb);
301+
}
302+
303+
// Clear all motor bits
304+
latch_state &= ~a & ~b & ~c & ~d;
305+
306+
// Set appropriate motor bits based on step position
307+
if (style == MICROSTEP) {
308+
if ((currentstep >= 0) && (currentstep < MICROSTEPS))
309+
latch_state |= a | b;
310+
if ((currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS * 2))
311+
latch_state |= b | c;
312+
if ((currentstep >= MICROSTEPS * 2) && (currentstep < MICROSTEPS * 3))
313+
latch_state |= c | d;
314+
if ((currentstep >= MICROSTEPS * 3) && (currentstep < MICROSTEPS * 4))
315+
latch_state |= d | a;
316+
} else {
317+
switch (currentstep / (MICROSTEPS / 2)) {
318+
case 0:
319+
latch_state |= a; // energize coil 1 only
320+
break;
321+
case 1:
322+
latch_state |= a | b; // energize coil 1+2
323+
break;
324+
case 2:
325+
latch_state |= b; // energize coil 2 only
326+
break;
327+
case 3:
328+
latch_state |= b | c; // energize coil 2+3
329+
break;
330+
case 4:
331+
latch_state |= c; // energize coil 3 only
332+
break;
333+
case 5:
334+
latch_state |= c | d; // energize coil 3+4
335+
break;
336+
case 6:
337+
latch_state |= d; // energize coil 4 only
338+
break;
339+
case 7:
340+
latch_state |= d | a; // energize coil 1+4
341+
break;
342+
}
343+
}
344+
345+
latch_tx();
346+
return currentstep;
347+
}

0 commit comments

Comments
 (0)