Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define F_CPU 16000000L
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <util/delay.h>
- #define nop() do { __asm__ __volatile__ ("nop"); } while (0)
- // steppe port
- #define sport PORTB
- // externals
- #define cport PORTD
- // pins
- #define enable_pin PB3
- #define step_pin PB1
- #define dir_pin PB2
- #define enable_b_pin PD4
- #define home_pin PD2
- #define error_pin PD3
- // work cycle
- #define stop 0
- #define search_home 1
- #define duty_cycle 2
- #define move_in_home 3
- volatile unsigned int current_state = 0;
- // forced home position
- volatile unsigned int force_at_home = 0;
- // duty cycle speed
- unsigned int step = 0x047D;
- // search home speed
- unsigned int step_home = 0x047D;
- // steps per revolution
- unsigned int steps_per_rev = 800;
- // revolution length in mm
- unsigned int revolution_length = 25;
- // duty cycle length in mm
- unsigned int duty_length = 220;
- // duty cycle length in steps
- unsigned long int duty_steps = 0;
- // current position in steps
- volatile unsigned long int position = 0;
- // steps to make when home first reached
- unsigned int steps_in_home = 800;
- // home state
- inline int at_home(void) {
- if ((PIND & (1 << home_pin)) == 0) {
- return force_at_home;
- } else {
- return 1;
- }
- }
- // enable button
- int enabled(void) {
- if ((PIND & (1 << enable_b_pin)) == 0) {
- return 1;
- } else {
- return 0;
- }
- }
- ISR(INT0_vect) {
- _delay_ms(10);
- if (current_state == search_home)
- if (at_home()) {
- current_state = move_in_home;
- position = steps_in_home;
- // move forward from home
- sport |= (1 << dir_pin);
- };
- }
- ISR(INT1_vect) {
- // active if level is high
- if ((PIND & (1 << error_pin)) != 0) {
- // this is error
- // stop everything
- TIMSK1 = 0;
- TCCR1A = 0;
- TCCR1B = 0;
- OCR1AH = 0;
- OCR1AL = 0;
- EIMSK = 0;
- PCICR = 0;
- PCMSK0 = 0;
- // turn off diode on arduino pin 13
- PORTB &= ~(1 << PB5);
- }
- }
- // level change on enable button pin
- ISR(PCINT2_vect) {
- _delay_ms(50);
- if (enabled()) {
- PORTB |= (1 << PB5);
- // enable button pressed step enabled
- PORTB |= (1 << enable_pin);
- TCCR1B |= (1 << CS11);
- if (at_home()) {
- // duty cycle begin
- OCR1A = step;
- sport |= (1 << dir_pin);
- current_state = duty_cycle;
- position = duty_steps;
- force_at_home = 0;
- } else {
- // go home
- OCR1A = step_home;
- sport &= ~(1 << dir_pin);
- current_state = search_home;
- };
- TIMSK1 |= (1 << OCIE1A);
- } else {
- PORTB &= ~(1 << PB5);
- // enable button released - step disabled
- PORTB &= ~(1 << enable_pin);
- TCCR1B &= ~(1 << CS11);
- TIMSK1 &= ~(1 << OCIE1A);
- };
- };
- ISR(TIMER1_COMPA_vect) {
- if (current_state == duty_cycle) {
- position--;
- if (position == 0) {
- _delay_ms(10);
- OCR1A = step_home;
- sport &= ~(1 << dir_pin);
- current_state = search_home;
- }
- }
- else if (current_state == move_in_home) {
- position--;
- if (position == 0) {
- // step disabled at home
- PORTB &= ~(1 << enable_pin);
- TCCR1B &= ~(1 << CS11);
- TIMSK1 &= ~(1 << OCIE1A);
- force_at_home = 1;
- }
- };
- }
- int main(void) {
- _delay_ms(500);
- // step and dir pins - output
- // enable, home and error pins - input
- // activate pull-ups
- PORTB = 0xFF;
- PORTC = 0xFF;
- PORTD = 0xFF;
- DDRB = 0;
- DDRC = 0;
- DDRD = 0;
- nop();
- // step enable, step and dir to output
- sport &= ~((1 << step_pin) | (1 << dir_pin) | (1 << enable_pin));
- DDRB |= (1 << step_pin) | (1 << dir_pin) | (1 << enable_pin) | (1 << PB5);
- nop();
- // step
- // phase and frequency correct PWM and /8 divider
- TCCR1A = (0 << COM1A1) | (1 << COM1A0) | (0 << WGM11) | (1 << WGM10);
- TCCR1B = (1 << WGM13) | (0 << WGM12) | (0 << CS12) | (0 << CS11) | (0 << CS10);
- // 125(0x7d) is 8kHz (raise + fall) == 4 kHz total frequency
- OCR1A = step;
- // step will be enabled on button pressed
- TIMSK1 &= ~(1 << OCIE1A);
- // home switch on INT0
- // interrupt on any logical change for int0/1: ISC00 = 1 ISC01 = 0 ISC10 = 1 ISC11 = 0
- EICRA = (1 << ISC00) | (1 << ISC10);
- EIMSK |= (1 << INT0);
- // error switch on INT1
- EIMSK |= (1 << INT1);
- // enable button on PCINT0
- PCICR |= (1 << PCIE2);
- PCMSK2 |= (1 << PCINT20);
- duty_steps = (duty_length / revolution_length) * steps_per_rev * 2;
- sei();
- // diode on pb5 on
- PORTB |= (1 << PB5);
- while(1)
- {
- nop();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement