Skip to content

Instantly share code, notes, and snippets.

@TiNredmc
Last active June 17, 2022 07:22
Show Gist options
  • Save TiNredmc/9727586ca05a2c2ecc853d74b5502c2c to your computer and use it in GitHub Desktop.
Save TiNredmc/9727586ca05a2c2ecc853d74b5502c2c to your computer and use it in GitHub Desktop.
control 2-phase stepper motor with Timer interrupt.
// 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