mirror of
https://github.com/eddyem/scorpio.git
synced 2025-12-06 18:55:19 +03:00
161 lines
4.7 KiB
C
161 lines
4.7 KiB
C
/*
|
|
* stepper.c
|
|
*
|
|
* Copyright 2014 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "ports_definition.h"
|
|
#include "uart.h"
|
|
#include "stepper.h"
|
|
|
|
volatile U8 chk_esw = 0; // need 2 check end-switches
|
|
|
|
U8 usteps[8] = {0b1000, 0b1010, 0b0010, 0b0110, 0b0100, 0b0101, 0b0001, 0b1001};
|
|
|
|
// numbers of motors in inner system:
|
|
// MOTOR6=5, MOTOR5=4, MOTOR4=0, MOTOR3=1, MOTOR2=2, MOTOR1=3
|
|
static motors_numbers[7] = {0,3,2,1,0,4,5};
|
|
// array of end-switches for appropriate motor number
|
|
// M1=e1, M2=e4, M3=e3, M4=e0, M5=e2, M6=e5
|
|
static U8 esw_arr[7] = {0, 1, 4, 3, 0, 2, 5};
|
|
#define ESW_SELECT(NUM) do{register U8 nsw = esw_arr[NUM]; register U8 C=PC_ODR & ~ESW_SEL_PINS; C |= ((nsw)<<5); PC_ODR = C;}while(0)
|
|
|
|
volatile int Steps_left = 0; // Number of steps
|
|
volatile char Dir = 0; // direction of moving: 0/1
|
|
U16 Stepper_speed = 0; // length of one MICROstep in us
|
|
U8 cur_motor = 7;
|
|
/**
|
|
* Setup pins of stepper motor (all - PP out)
|
|
*/
|
|
void setup_stepper_pins(){
|
|
// Push-pull for outputs
|
|
// PB0..3
|
|
PORT(STP_PORT, DDR) |= STP_PINS;
|
|
PORT(STP_PORT, CR1) |= STP_PINS;
|
|
PORT(STP_PORT, CR2) |= STP_PINS;
|
|
// PD0..4
|
|
PORT(STP_SEL_PORT, DDR) |= STP_SEL_PINS;
|
|
PORT(STP_SEL_PORT, CR1) |= STP_SEL_PINS;
|
|
PORT(STP_SEL_PORT, CR2) |= STP_SEL_PINS;
|
|
|
|
STPRS_OFF();
|
|
}
|
|
|
|
U8 stepper_ch_speed(char *spd){
|
|
int newval;
|
|
if(readInt(spd, &newval)){
|
|
if(newval > -9 && newval < 0x7fff){
|
|
U16 O = 0xffff / (newval + 10);
|
|
if(O < MIN_STEP_LENGTH) return 0;
|
|
Stepper_speed = O;
|
|
// Configure timer 2 to generate signals for CLK
|
|
TIM2_PSCR = 4; // 1MHz
|
|
TIM2_ARRH = O >> 8; // set speed
|
|
TIM2_ARRL = O & 0xff;
|
|
TIM2_IER = TIM_IER_UIE; // update interrupt enable
|
|
TIM2_CR1 |= TIM_CR1_APRE | TIM_CR1_URS; // auto reload + interrupt on overflow & RUN
|
|
#ifdef EBUG
|
|
uart_write("Speed changed to ");
|
|
printUint((U8*)&O, 2);
|
|
uart_write("\n");
|
|
#endif
|
|
return 1;
|
|
}else DBG("Bad speed value\n");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Check endswitches
|
|
* @return 0 if none pressed, 1 if "-", 2 if "+"
|
|
*/
|
|
U8 check_endsw(){
|
|
// A1 - "+", A2 - "-"
|
|
U8 pc = PORT(ESW_PORT, IDR);
|
|
if(0 == (pc & ESW_MINUS)) return 1;
|
|
if(0 == (pc & ESW_PLUS)) return 2;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* move stepper number Nmotor by Nsteps steps
|
|
* @return 1 if all OK, 0 if error occured
|
|
*/
|
|
U8 stepper_move(U8 Nmotor, int Nsteps){
|
|
U8 c, nm;
|
|
if(!Nmotor || Nmotor > 6 || !Nsteps || Steps_left) return 0;
|
|
nm = motors_numbers[Nmotor];
|
|
IWDG_KR = KEY_REFRESH; // refresh watchdog
|
|
|
|
if(Nsteps < 0){
|
|
Dir = 1;
|
|
Nsteps *= -1;
|
|
}else
|
|
Dir = 0;
|
|
Steps_left = Nsteps;
|
|
// select endswitch
|
|
ESW_SELECT(Nmotor);
|
|
// turn all motors OFF
|
|
STPRS_OFF();
|
|
// turn on the motor we need
|
|
PORT(STP_SEL_PORT, ODR) |= (1 << (nm/2));
|
|
if(nm & 1) PORT(STP_SEL_PORT, ODR) &= ~GPIO_PIN4;
|
|
else PORT(STP_SEL_PORT, ODR) &= ~GPIO_PIN3;
|
|
c = check_endsw();
|
|
cur_motor = Nmotor;
|
|
if(c){
|
|
if(c == 1){if(!Dir) c = 0;}
|
|
else if(Dir) c = 0;
|
|
}
|
|
if(c){
|
|
stop_motor();
|
|
return 0; // already at end-switch in given direction
|
|
}
|
|
DBG("stepper_move\n");
|
|
TIM2_CR1 |= TIM_CR1_CEN; // turn on timer
|
|
return 1;
|
|
}
|
|
|
|
void stop_motor(){
|
|
TIM2_CR1 &= ~TIM_CR1_CEN; // Turn off timer
|
|
// turn all motors OFF
|
|
STPRS_OFF();
|
|
Ustep = 0;
|
|
Steps_left = 0;
|
|
chk_esw = 1;
|
|
DBG("stop\n");
|
|
}
|
|
|
|
/**
|
|
* get end-switches state for all motors or only Nth
|
|
* @param Nmotor - number of given motor
|
|
*/
|
|
void stepper_get_esw(U8 Nmotor){
|
|
U8 sw;
|
|
char str[] = "[2 0 St=0]\n"; // 3 - motor number, 5 - endswitch (3 if none)
|
|
IWDG_KR = KEY_REFRESH; // refresh watchdog
|
|
if(Nmotor == 0 || Nmotor > 6) return; // no running motor
|
|
ESW_SELECT(Nmotor);
|
|
str[3] = Nmotor + '0';
|
|
sw = check_endsw();
|
|
if(sw == 0) sw = 3;
|
|
str[8] = sw + '0';
|
|
uart_write(str);
|
|
cur_motor = 0;
|
|
}
|