Skip to content
This repository was archived by the owner on Feb 4, 2023. It is now read-only.

Commit c9117a8

Browse files
authored
v1.0.1 to add PWM_StepperControl example
### Releases v1.0.1 1. Add example [PWM_StepperControl](https://github.com/khoih-prog/STM32_PWM/tree/main/examples/PWM_StepperControl) to demo how to control Stepper Motor using PWM
1 parent 4932e4b commit c9117a8

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed

Diff for: examples/PWM_StepperControl/PWM_StepperControl.ino

+214
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
/****************************************************************************************************************************
2+
PWM_StepperControl.ino
3+
4+
For STM32F/L/H/G/WB/MP1 boards
5+
Written by Khoi Hoang
6+
7+
Built by Khoi Hoang https://github.com/khoih-prog/STM32_PWM
8+
Licensed under MIT license
9+
10+
Hardware-based multi-channel PWM wrapper library for STM32F/L/H/G/WB/MP1 boards
11+
12+
Credits of Paul van Dinther (https://github.com/dinther). Check https://github.com/khoih-prog/RP2040_PWM/issues/16
13+
*****************************************************************************************************************************/
14+
15+
// Use with Stepper-Motor driver, such as TMC2209
16+
17+
#if !( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \
18+
defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \
19+
defined(STM32WB) || defined(STM32MP1) || defined(STM32L5))
20+
#error This code is designed to run on STM32F/L/H/G/WB/MP1 platform! Please check your Tools->Board setting.
21+
#endif
22+
23+
// These define's must be placed at the beginning before #include "ESP32_PWM.h"
24+
// _PWM_LOGLEVEL_ from 0 to 4
25+
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
26+
#define _PWM_LOGLEVEL_ 4
27+
28+
#define USING_MICROS_RESOLUTION true //false
29+
30+
#include "STM32_PWM.h"
31+
32+
/////////////////////////////////////////////////
33+
34+
// Change the pin according to your STM32 board. There is no single definition for all boards.
35+
#define pin0 PA0
36+
#define pin1 D1
37+
#define pin2 D2
38+
#define pin3 D3
39+
#define pin4 D4
40+
#define pin5 D5
41+
#define pin6 D6
42+
#define pin7 D7
43+
44+
#define pin8 D8
45+
#define pin9 D9
46+
#define pin10 D10
47+
#define pin11 D11
48+
#define pin12 D12
49+
#define pin13 D13
50+
#define pin14 D14
51+
#define pin15 D15
52+
#define pin16 D16
53+
54+
//////////////////////////////////////////////////////
55+
56+
// Change the pin according to your STM32 board. There is no single definition for all boards.
57+
58+
#if ( defined(STM32F1) && ( defined(ARDUINO_BLUEPILL_F103CB) || defined(ARDUINO_BLUEPILL_F103C8) ) )
59+
60+
#warning Using BLUEPILL_F103CB / BLUEPILL_F103C8 pins
61+
62+
// For F103CB => pin0, pin4, pin10 ============>> TimerIndex = 1, 2, 0
63+
#define STEP_PIN pin3
64+
65+
#elif ( defined(STM32F7) && defined(ARDUINO_NUCLEO_F767ZI) )
66+
67+
#warning Using NUCLEO_F767ZI pins
68+
69+
// For F767ZI => pin0, pin3, pin9/10 ============>> TimerIndex = 1, 0, 3
70+
#define STEP_PIN pin3
71+
72+
#elif ( defined(STM32L5) && defined(ARDUINO_NUCLEO_L552ZE_Q) )
73+
74+
#warning Using NUCLEO_L552ZE_Q pins
75+
76+
// For NUCLEO_L552ZE_Q => pin0, pin3, pin9/10 ============>> TimerIndex = 1, 0, 3
77+
#define STEP_PIN pin3
78+
79+
#elif ( defined(STM32H7) && defined(ARDUINO_NUCLEO_H743ZI2) )
80+
81+
#warning Using NUCLEO_H743ZI2 pins
82+
83+
// For NUCLEO_L552ZE_Q => pin0, pin3, pin9/10 ============>> TimerIndex = 1, 0, 3
84+
#define STEP_PIN pin3
85+
86+
#else
87+
88+
// For ??? => pin0, pin3, pin9/10 ============>> TimerIndex = 1, 0, 3
89+
#define STEP_PIN pin3
90+
91+
#endif
92+
93+
//////////////////////////////////////////////////////
94+
95+
#define DIR_PIN pin1
96+
97+
TIM_TypeDef *stepperTimer;
98+
99+
HardwareTimer *stepper;
100+
101+
uint32_t channel;
102+
103+
int previousSpeed = 0;
104+
105+
// The Stepper RPM will be ( speed * 60 ) / steps-per-rev
106+
// For example, 28BYJ-48 Stepper Motor (https://lastminuteengineers.com/28byj48-stepper-motor-arduino-tutorial/) has 32 Steps/Rev
107+
// Speed = 640 Hz => Stepper RPM = (640 * 60 / 32) = 1200 RPM
108+
void setSpeed(int speed)
109+
{
110+
// Do nothing if same speed
111+
if (speed == previousSpeed)
112+
return;
113+
114+
Serial.print(F("setSpeed = "));
115+
Serial.println(speed);
116+
117+
// Create new instance for new speed
118+
if (stepper)
119+
delete stepper;
120+
121+
stepper = new HardwareTimer(stepperTimer);
122+
123+
if (speed == 0)
124+
{
125+
// Use DC = 0 to stop stepper
126+
stepper->setPWM(channel, STEP_PIN, 500, 0, nullptr);
127+
}
128+
else
129+
{
130+
// Set the frequency of the PWM output and a duty cycle of 50%
131+
digitalWrite(DIR_PIN, (speed < 0));
132+
stepper->setPWM(channel, STEP_PIN, abs(speed), 50, nullptr);
133+
}
134+
135+
previousSpeed = speed;
136+
}
137+
138+
void initPWM(uint32_t step_pin)
139+
{
140+
// Using pin = PA0, PA1, etc.
141+
PinName pinNameToUse = digitalPinToPinName(step_pin);
142+
143+
// Automatically retrieve TIM instance and channel associated to pin
144+
// This is used to be compatible with all STM32 series automatically.
145+
stepperTimer = (TIM_TypeDef *) pinmap_peripheral(pinNameToUse, PinMap_PWM);
146+
147+
if (stepperTimer != nullptr)
148+
{
149+
uint8_t timerIndex = get_timer_index(stepperTimer);
150+
151+
// pin => 0, 1, etc
152+
channel = STM_PIN_CHANNEL(pinmap_function( pinNameToUse, PinMap_PWM));
153+
154+
Serial.print("stepperTimer = 0x");
155+
Serial.print( (uint32_t) stepperTimer, HEX);
156+
Serial.print(", channel = ");
157+
Serial.print(channel);
158+
Serial.print(", TimerIndex = ");
159+
Serial.print(get_timer_index(stepperTimer));
160+
Serial.print(", PinName = ");
161+
Serial.println( pinNameToUse );
162+
163+
stepper = new HardwareTimer(stepperTimer);
164+
165+
// SetPWM object and passed just a random frequency of 500 steps/s
166+
// The Stepper RPM will be ( speed * 60 ) / steps-per-revolution
167+
// The duty cycle is how you turn the motor on and off
168+
previousSpeed = 500;
169+
stepper->setPWM(channel, step_pin, previousSpeed, 0, nullptr);
170+
}
171+
else
172+
{
173+
Serial.println("ERROR => Wrong pin, You have to select another one. Skip NULL stepperTimer");
174+
}
175+
}
176+
177+
void setup()
178+
{
179+
pinMode(STEP_PIN, OUTPUT);
180+
digitalWrite(STEP_PIN, LOW);
181+
pinMode(DIR_PIN, OUTPUT);
182+
digitalWrite(DIR_PIN, LOW);
183+
184+
Serial.begin(115200);
185+
186+
while (!Serial && millis() < 5000);
187+
188+
delay(100);
189+
190+
Serial.print(F("\nStarting PWM_StepperControl on "));
191+
Serial.println(BOARD_NAME);
192+
Serial.println(STM32_PWM_VERSION);
193+
194+
initPWM(STEP_PIN);
195+
}
196+
197+
void loop()
198+
{
199+
// The Stepper RPM will be ( speed * 60 ) / steps-per-rev
200+
setSpeed(2000);
201+
delay(3000);
202+
203+
// Stop before reversing
204+
setSpeed(0);
205+
delay(3000);
206+
207+
// Reversing
208+
setSpeed(-1000);
209+
delay(3000);
210+
211+
// Stop before reversing
212+
setSpeed(0);
213+
delay(3000);
214+
}

0 commit comments

Comments
 (0)