Last active
June 17, 2022 07:22
-
-
Save TiNredmc/9727586ca05a2c2ecc853d74b5502c2c to your computer and use it in GitHub Desktop.
control 2-phase stepper motor with Timer interrupt.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 500us Timer interrupt to drive stepper motor. | |
// Coded by TinLethax 2022/6/17 +7 | |
#define full_rev_step 200 | |
#define motor_pulse 2 | |
volatile uint8_t pulse_tog = 0; | |
volatile uint16_t pulse_cnt = 0; | |
#define motor_dir 3 | |
uint8_t dir = 0; | |
#define motor_en 4 | |
#define motor_on digitalWrite(motor_en, 0) | |
#define motor_off digitalWrite(motor_en, 1) | |
volatile uint8_t pulse_gate = 0; | |
// timer interrupt handler | |
ISR(TIMER1_COMPA_vect) { | |
TCNT1 = 0; //First, set the timer back to 0 so it resets for next interrupt | |
pulse_tog = !pulse_tog; //Invert LED state | |
pulse_cnt = pulse_gate ? pulse_cnt + 1 : 0;// step counter | |
digitalWrite(motor_pulse, pulse_tog & pulse_gate); //Write new state to the LED on pin D5 | |
} | |
// Timer interrupt set up. | |
void timer_init() { | |
cli(); | |
TCCR1A = 0;// Reset entire TCCR1A to 0 | |
TCCR1B = 0;// Reset entire TCCR1B to 0 | |
TCCR1B |= B00000100;// Set CS12 to prescalar 256 | |
TIMSK1 |= B00000010;// Set OCIE1A to 1 so we enable compare match A | |
OCR1A = 31;// motor speed here. 62500 * interval in second uint = OCR1A number. in this case it's roughtly 500us | |
sei();// enable interrupt | |
} | |
// Set stepper motor direction | |
// 0 - | |
// 1 - | |
void set_dir(uint8_t set_dir){ | |
// sanity check | |
if(set_dir > 1) | |
return; | |
dir = set_dir; | |
digitalWrite(motor_dir, dir); | |
} | |
// Steps to rotate (note, code blocking). | |
// input 0 will be invalid. | |
void set_step_blocking(uint16_t steps){ | |
if(steps == 0)// sanity check | |
return; | |
motor_on; | |
pulse_gate = 1; | |
while (pulse_cnt < steps); | |
TCNT1 = 0; | |
motor_off; | |
pulse_gate = 0; | |
} | |
// rotate motor with angle (Degree) input. (note, code blocking). | |
// input 0 will be invalid. | |
void set_angle_blocking(int16_t degree){ | |
//sanity check | |
if(degree == 0) | |
return; | |
set_dir(degree > 0 ? 1 : 0);// set direction | |
degree = degree < 0 ? (degree * -1) : degree;// absolute value | |
degree = map(degree, 0, 360, 0, 200);// remap 0-360 degree to 0-200 steps | |
set_step_blocking(degree * (uint8_t)((degree/360) + 1));// rotate | |
} | |
void setup() { | |
// GPIOs | |
pinMode(motor_pulse, OUTPUT); | |
pinMode(motor_dir, OUTPUT); | |
pinMode(motor_en, OUTPUT); | |
dir = 1; | |
digitalWrite(motor_en, 1);// enable is active low, turn it on later. | |
// Debug | |
Serial.begin(9600); | |
} | |
void loop() { | |
Serial.println("Start"); | |
set_angle_blocking(45); | |
delay(1000); | |
Serial.println("Stop"); | |
delay(1000); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment