mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-07 19:25:19 +03:00
Fix error in CAN speed calculation
This commit is contained in:
parent
131f6fab44
commit
bc7a9aacc5
@ -145,7 +145,7 @@ void CAN_setup(uint16_t speed){
|
||||
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
|
||||
CAN->MCR |= CAN_MCR_ABOM; /* allow automatically bus-off */
|
||||
|
||||
CAN->BTR |= 2 << 20 | 3 << 16 | (6000/speed) << 0; /* (4) */
|
||||
CAN->BTR |= 2 << 20 | 3 << 16 | (6000/speed - 1); /* (4) */
|
||||
CAN->MCR &=~ CAN_MCR_INRQ; /* (5) */
|
||||
tmout = 16000000;
|
||||
while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK) if(--tmout == 0) break; /* (6) */
|
||||
|
||||
Binary file not shown.
@ -46,9 +46,13 @@ static uint32_t maxCnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
||||
|
||||
#define USERCONF_INITIALIZER { \
|
||||
.userconf_sz = sizeof(user_conf) \
|
||||
,.defflags = 0 \
|
||||
,.defflags.reverse = 0 \
|
||||
,.CANspeed = 100 \
|
||||
,.driver_type = DRV_NONE \
|
||||
,.microsteps = 16 \
|
||||
,.accdecsteps = 100 \
|
||||
,.motspd = 10 \
|
||||
,.maxsteps = 50000 \
|
||||
}
|
||||
|
||||
static int erase_flash(const void*, const void*);
|
||||
@ -214,7 +218,6 @@ static int erase_flash(const void *start, const void *end){
|
||||
void dump_userconf(){
|
||||
SEND("userconf_addr="); printuhex((uint32_t)Flash_Data);
|
||||
SEND("\nuserconf_sz="); printu(the_conf.userconf_sz);
|
||||
SEND("\nflags="); printuhex(the_conf.defflags);
|
||||
SEND("\nCANspeed="); printu(the_conf.CANspeed);
|
||||
SEND("\ndriver_type=");
|
||||
const char *p = "NONE";
|
||||
@ -230,6 +233,12 @@ void dump_userconf(){
|
||||
break;
|
||||
}
|
||||
SEND(p);
|
||||
SEND("\nmicrosteps="); printu(the_conf.microsteps);
|
||||
SEND("\naccdecsteps="); printu(the_conf.accdecsteps);
|
||||
SEND("\nmotspd="); printu(the_conf.motspd);
|
||||
SEND("\nmaxsteps="); printu(the_conf.maxsteps);
|
||||
//flags
|
||||
SEND("\nreverse="); bufputchar('0' + the_conf.defflags.reverse);
|
||||
newline();
|
||||
sendbuf();
|
||||
}
|
||||
|
||||
@ -30,13 +30,21 @@
|
||||
#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7CC)
|
||||
#define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG)
|
||||
|
||||
typedef struct{
|
||||
uint8_t reverse : 1;
|
||||
} defflags_t;
|
||||
|
||||
/*
|
||||
* struct to save user configurations
|
||||
*/
|
||||
typedef struct __attribute__((packed, aligned(4))){
|
||||
uint32_t maxsteps; // maximal amount of steps from ESW0 to EWS3
|
||||
uint16_t userconf_sz; // "magick number"
|
||||
uint16_t CANspeed; // default CAN speed
|
||||
uint8_t defflags; // default flags
|
||||
uint16_t microsteps; // microsteps amount per step
|
||||
uint16_t accdecsteps; // amount of steps need for full acceleration/deceleration cycle
|
||||
uint16_t motspd; // max motor speed ([3000 / motspd] steps per second)
|
||||
defflags_t defflags; // default flags
|
||||
uint8_t driver_type; // user's settings: type of stepper's driver
|
||||
} user_conf;
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
TIM_TypeDef *TIMx = TIM15; // stepper's timer
|
||||
|
||||
static uint8_t brdADDR = 0;
|
||||
|
||||
void Jump2Boot(){
|
||||
@ -81,7 +83,7 @@ void gpio_setup(){
|
||||
| RCC_AHBENR_DMAEN;
|
||||
// setup pins need @start: Vio_ON (PF0, opendrain), ~FAULT (PF1, floating IN),
|
||||
// ~SLEEP (PC15, pushpull), DIR (PA4, pushpull), ~EN (PC13, pushpull)
|
||||
// ~CS, microstepping2, (PC14, pushpull
|
||||
// ~CS, microstepping2, (PC14, pushpull)
|
||||
// PA8 - Tx/Rx
|
||||
// PB12..15 - board address, pullup input; PB0..2, PB10 - ESW, pullup inputs (inverse)
|
||||
VIO_OFF();
|
||||
@ -115,6 +117,22 @@ void gpio_setup(){
|
||||
brdADDR = READ_BRD_ADDR();
|
||||
}
|
||||
|
||||
// PA3 (STEP): TIM15_CH2; 48MHz -> 48kHz
|
||||
void timer_setup(){
|
||||
RCC->APB2ENR |= RCC_APB2ENR_TIM15EN; // enable clocking
|
||||
TIM15->CR1 &= ~TIM_CR1_CEN; // turn off timer
|
||||
TIM15->CCMR1 = TIM_CCMR1_OC2M_2; // Force inactive
|
||||
TIM15->PSC = 999;
|
||||
TIM15->CCER = TIM_CCER_CC2E;
|
||||
TIM15->CCR1 = 1; // very short pulse
|
||||
TIM15->ARR = 1000;
|
||||
// enable IRQ & update values
|
||||
TIM15->EGR = TIM_EGR_UG;
|
||||
TIM15->DIER = TIM_DIER_CC2IE;
|
||||
NVIC_EnableIRQ(TIM15_IRQn);
|
||||
NVIC_SetPriority(TIM15_IRQn, 0);
|
||||
}
|
||||
|
||||
uint8_t refreshBRDaddr(){
|
||||
return (brdADDR = READ_BRD_ADDR());
|
||||
}
|
||||
|
||||
@ -68,14 +68,28 @@
|
||||
#define RESET_UST2() do{GPIOC->BRR = 1<<14;}while(0)
|
||||
#define CS_ACTIVE() do{GPIOC->BRR = 1<<14;}while(0)
|
||||
#define CS_PASSIVE() do{GPIOC->BSRR = 1<<14;}while(0)
|
||||
// microstepping0 (PA7), 1 (PA5) - set PP
|
||||
#define UST01_CFG_PP() do{GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER5|GPIO_MODER_MODER7)) | (GPIO_MODER_MODER5_O|GPIO_MODER_MODER7_O);}while(0)
|
||||
#define SET_UST0() do{GPIOA->BSRR = 1<<7;}while(0)
|
||||
#define SET_UST1() do{GPIOA->BSRR = 1<<5;}while(0)
|
||||
#define RESET_UST0() do{GPIOA->BRR = 1<<7;}while(0)
|
||||
#define RESET_UST1() do{GPIOA->BRR = 1<<5;}while(0)
|
||||
// end-switches state
|
||||
#define ESW_STATE() ((GPIOB->IDR & 0x07) | ((GPIOB->IDR>>7) & 0x08))
|
||||
// configure ~CS as PP output
|
||||
//#define CS_CFG_OUT() do{GPIOC->MODER = (GPIOC->MODER&~GPIO_MODER_MODER14) | GPIO_MODER_MODER14_O; }while(0)
|
||||
// ~CS as floating input
|
||||
;
|
||||
// Vio_ON, PF0 (inverse)
|
||||
#define VIO_ON() do{GPIOF->BRR = 1;}while(0)
|
||||
#define VIO_OFF() do{GPIOF->BSRR = 1;}while(0)
|
||||
|
||||
// turn off timer of STEPS pin
|
||||
#define STEP_TIMER_OFF() do{TIM15->CR1 &= ~TIM_CR1_CEN;}while(0)
|
||||
|
||||
// timer for stepper
|
||||
extern TIM_TypeDef *TIMx;
|
||||
#define timer_isr tim15_isr
|
||||
|
||||
extern volatile uint32_t Tms;
|
||||
|
||||
void Jump2Boot();
|
||||
@ -84,4 +98,6 @@ void iwdg_setup();
|
||||
uint8_t getBRDaddr();
|
||||
uint8_t refreshBRDaddr();
|
||||
void sleep(uint16_t ms);
|
||||
void timer_setup();
|
||||
|
||||
#endif // __HARDWARE_H__
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "flash.h"
|
||||
#include "hardware.h"
|
||||
#include "proto.h"
|
||||
#include "steppers.h"
|
||||
#include "usart.h"
|
||||
#include "usb.h"
|
||||
#include "usb_lib.h"
|
||||
@ -81,7 +82,7 @@ static char *get_USB(){
|
||||
}
|
||||
|
||||
int main(void){
|
||||
uint32_t lastT = 0;
|
||||
uint32_t lastT = 0, ostctr = 0;
|
||||
sysreset();
|
||||
SysTick_Config(6000, 1);
|
||||
gpio_setup(); // + read board address
|
||||
@ -120,6 +121,11 @@ int main(void){
|
||||
}
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
can_messages_proc();
|
||||
if(ostctr != Tms){ // check steppers not more than once in 1ms
|
||||
ostctr = Tms;
|
||||
stp_process();
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -192,14 +192,45 @@ TRUE_INLINE void userconf_manip(char *txt){
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SEND("Wrong argument of userconf manipulation: ");
|
||||
SEND(txt);
|
||||
SEND("\nUserconf commands:\n"
|
||||
"d - userconf dump\n"
|
||||
"s - userconf store\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TRUE_INLINE void setdefflags(char *txt){
|
||||
const char *needar = "Need argument 0 or 1 for flag";
|
||||
txt = omit_spaces(txt);
|
||||
char ch = *txt;
|
||||
++txt;
|
||||
uint32_t U;
|
||||
if(txt == getnum(txt, &U)){
|
||||
SEND(needar);
|
||||
return;
|
||||
}
|
||||
switch(ch){
|
||||
case 'r':
|
||||
if(U > 1){
|
||||
SEND(needar);
|
||||
return;
|
||||
}
|
||||
the_conf.defflags.reverse = U&1;
|
||||
break;
|
||||
default:
|
||||
SEND("\nFlag commands:"
|
||||
"r - set/clear reverse\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// a set of setters for user_conf
|
||||
TRUE_INLINE void setters(char *txt){
|
||||
uint32_t U;
|
||||
uint8_t u8;
|
||||
const char *drvshould = "Driver type should be one of: 2130, 4988, 8825";
|
||||
const char *usshould = "Microsteps amount is a power of two: 1..512";
|
||||
const char *motspdshould = "Motor speed should be from 2 to " STR(0xffff/LOWEST_SPEED_DIV);
|
||||
txt = omit_spaces(txt);
|
||||
if(!*txt){
|
||||
SEND("Setters need more arguments");
|
||||
@ -207,6 +238,21 @@ TRUE_INLINE void setters(char *txt){
|
||||
}
|
||||
char *nxt = getnum(txt + 1, &U);
|
||||
switch(*txt){
|
||||
case 'a': // accdecsteps
|
||||
if(nxt == txt + 1){
|
||||
SEND("No accdecsteps value given");
|
||||
return;
|
||||
}
|
||||
if(U < ACCDECSTEPS_MIN || U > ACCDECSTEPS_MAX){
|
||||
SEND("The value should be from" STR(ACCDECSTEPS_MIN) " to " STR(ACCDECSTEPS_MAX));
|
||||
return;
|
||||
}
|
||||
if(the_conf.accdecsteps != (uint16_t) U){
|
||||
the_conf.accdecsteps = (uint16_t) U;
|
||||
userconf_changed = 1;
|
||||
SEND("Set accdecsteps to "); printu(U);
|
||||
}
|
||||
break;
|
||||
case 'c': // set CAN speed
|
||||
if(nxt == txt + 1){
|
||||
SEND("No CAN speed given");
|
||||
@ -222,54 +268,144 @@ TRUE_INLINE void setters(char *txt){
|
||||
}
|
||||
if(the_conf.CANspeed != (uint16_t)U){
|
||||
the_conf.CANspeed = (uint16_t)U;
|
||||
SEND("Set CAN speed to "); printu(U);
|
||||
userconf_changed = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SEND("Wrong argument of setters: ");
|
||||
SEND(txt);
|
||||
}
|
||||
}
|
||||
|
||||
TRUE_INLINE void driver_commands(char *txt){
|
||||
uint32_t U;
|
||||
char *nxt;
|
||||
const char *drvshould = "Driver type should be one of: 2130, 4988, 8825";
|
||||
txt = omit_spaces(txt);
|
||||
if(!*txt){
|
||||
SEND("Driver commands need more arguments");
|
||||
return;
|
||||
}
|
||||
switch(*txt){
|
||||
case 'i': // init
|
||||
initDriver();
|
||||
break;
|
||||
case 's': // set type
|
||||
nxt = getnum(txt + 1, &U);
|
||||
case 'd': // set driver type
|
||||
if(nxt == txt+1){
|
||||
SEND(drvshould);
|
||||
break;
|
||||
}
|
||||
u8 = DRV_NONE;
|
||||
switch(U){
|
||||
case 2130:
|
||||
the_conf.driver_type = DRV_2130;
|
||||
u8 = DRV_2130;
|
||||
SEND("TMC2130");
|
||||
break;
|
||||
case 4988:
|
||||
the_conf.driver_type = DRV_4988;
|
||||
u8 = DRV_4988;
|
||||
SEND("A4988");
|
||||
break;
|
||||
case 8825:
|
||||
the_conf.driver_type = DRV_8825;
|
||||
u8 = DRV_8825;
|
||||
SEND("DRV8825");
|
||||
break;
|
||||
default:
|
||||
SEND(drvshould);
|
||||
}
|
||||
if(the_conf.driver_type != u8){
|
||||
the_conf.driver_type = u8;
|
||||
userconf_changed = 1;
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
setdefflags(txt+1);
|
||||
break;
|
||||
case 'm': // microsteps
|
||||
if(nxt == txt + 1){ // no number
|
||||
SEND(usshould); break;
|
||||
}
|
||||
if(U < 1 || U > getMaxUsteps() || (U & (U-1)) != 0){ // U over of range or not power of two
|
||||
SEND(usshould); break;
|
||||
}
|
||||
if(the_conf.microsteps != (uint16_t)U){
|
||||
the_conf.microsteps = (uint16_t)U;
|
||||
userconf_changed = 1;
|
||||
SEND("Set microsteps to "); printu(U);
|
||||
}
|
||||
break;
|
||||
case 'M': // maxsteps
|
||||
if(nxt == txt + 1 || U > INT32_MAX){
|
||||
SEND("Enter number from 0 (infinity) to INT32_MAX"); break;
|
||||
}
|
||||
if(U != the_conf.maxsteps){
|
||||
the_conf.maxsteps = U;
|
||||
userconf_changed = 1;
|
||||
}
|
||||
break;
|
||||
case 's': // motor speed
|
||||
if(nxt == txt + 1 || U < 2 || U > (0xffff/LOWEST_SPEED_DIV)){ // no number
|
||||
SEND(motspdshould); break;
|
||||
}
|
||||
if(the_conf.motspd != (uint16_t)U){
|
||||
the_conf.motspd = (uint16_t)U;
|
||||
userconf_changed = 1;
|
||||
SEND("Set motspd to "); printu(U);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SEND("Wrong argument of driver commands: ");
|
||||
SEND(txt);
|
||||
SEND("\nSetters commands:\n"
|
||||
"a - set accdecsteps\n"
|
||||
"c - set default CAN speed\n"
|
||||
"d - set driver type\n"
|
||||
"F - set flags"
|
||||
"m - set microsteps\n"
|
||||
"M - set maxsteps\n"
|
||||
"s - set motspd\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TRUE_INLINE void driver_commands(char *txt){
|
||||
txt = omit_spaces(txt);
|
||||
if(!*txt){
|
||||
SEND("Driver commands need more arguments");
|
||||
return;
|
||||
}
|
||||
char cmd = *txt++;
|
||||
txt = omit_spaces(txt);
|
||||
uint32_t U;
|
||||
int8_t sign = 1;
|
||||
if(*txt == '-'){
|
||||
++txt;
|
||||
sign = -1;
|
||||
}
|
||||
char *nxt = getnum(txt, &U);
|
||||
stp_status st;
|
||||
switch(cmd){
|
||||
case 'e':
|
||||
SEND("ESW=");
|
||||
printu(ESW_STATE());
|
||||
break;
|
||||
case 'i': // init
|
||||
initDriver();
|
||||
break;
|
||||
case 'm':
|
||||
if(nxt == txt + 1 || U > (INT32_MAX-1)){
|
||||
SEND("Give right steps amount: from -INT32_MAX to INT32_MAX");
|
||||
return;
|
||||
}
|
||||
if(sign > 0) st = stp_move((int32_t)U);
|
||||
else st = stp_move(-(int32_t)U);
|
||||
switch(st){
|
||||
case STPS_ACTIVE:
|
||||
SEND("IsMoving");
|
||||
break;
|
||||
case STPS_ONESW:
|
||||
SEND("OnEndSwitch");
|
||||
break;
|
||||
case STPS_ZEROMOVE:
|
||||
SEND("ZeroMove");
|
||||
break;
|
||||
case STPS_TOOBIG:
|
||||
SEND("TooBigNumber");
|
||||
break;
|
||||
default:
|
||||
SEND("Move to given steps amount");
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
stp_stop();
|
||||
SEND("Stop motor");
|
||||
break;
|
||||
default:
|
||||
SEND("\nDriver commands:\n"
|
||||
"e - end-switches state\n"
|
||||
"i - init stepper driver (8825, 4988, 2130)\n"
|
||||
"m - move N steps\n"
|
||||
"s - stop\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,18 +499,16 @@ void cmd_parser(char *txt, uint8_t isUSB){
|
||||
"a - get raw ADC values\n"
|
||||
"b - switch to bootloader\n"
|
||||
"d - dump userconf\n"
|
||||
"Di - init stepper driver (8825, 4988, 2130)\n"
|
||||
"Ds - set driver type\n"
|
||||
"D? - stepper driver commands\n"
|
||||
"g - get board address\n"
|
||||
"j - get MCU temperature\n"
|
||||
"k - get U values\n"
|
||||
"m - start/stop monitoring CAN bus\n"
|
||||
"s - send data over CAN: s ID [byte0..7]\n"
|
||||
"S? - parameter setters\n"
|
||||
"t - send test sequence over RS-485\n"
|
||||
"T - print current time\n"
|
||||
"Sc - set default CAN speed\n"
|
||||
"Ud - userconf dump\n"
|
||||
"Us - userconf store\n"
|
||||
"U? - options for user configuration\n"
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -22,6 +22,28 @@
|
||||
|
||||
static drv_type driver = DRV_NONE;
|
||||
|
||||
// maximum number of microsteps per driver
|
||||
static const uint16_t maxusteps[] = {
|
||||
[DRV_NONE] = 0,
|
||||
[DRV_NOTINIT] = 0,
|
||||
[DRV_MAILF] = 0,
|
||||
[DRV_8825] = 32,
|
||||
[DRV_4988] = 16,
|
||||
[DRV_2130] = 256
|
||||
};
|
||||
|
||||
// amount of steps need for full acceleration/deceleration cycle
|
||||
#define ACCDECSTEPS (the_conf.accdecsteps)
|
||||
// amount of microsteps in each step
|
||||
#define USTEPS (the_conf.microsteps)
|
||||
|
||||
int32_t mot_position = -1; // current position of motor (from zero endswitch, -1 means inactive)
|
||||
uint32_t steps_left = 0; // amount of steps left
|
||||
stp_state state = STP_SLEEP;// current state of motor
|
||||
// ARR register values: low (max speed), high (min speed = 10% from max), step (1/50(hi-lo))
|
||||
static uint16_t stplowarr, stphigharr, stpsteparr;
|
||||
static int8_t dir = 0; // moving direction: -1 (negative) or 1 (positive)
|
||||
|
||||
/**
|
||||
* @brief checkDrv - test if driver connected
|
||||
*/
|
||||
@ -42,12 +64,16 @@ static void checkDrv(){
|
||||
sleep(2);
|
||||
// Check is ~SLEEP is in air
|
||||
oldstate = SLP_STATE();
|
||||
#ifdef EBUG
|
||||
if(oldstate) MSG("SLP=1\n"); else MSG("SLP=0\n");
|
||||
#endif
|
||||
SLEEP_OFF(); SLP_CFG_OUT(); // sleep -> 1
|
||||
sleep(2);
|
||||
SLP_CFG_IN();
|
||||
sleep(2);
|
||||
#ifdef EBUG
|
||||
if(SLP_STATE()) MSG("SLP=1\n"); else MSG("SLP=0\n");
|
||||
#endif
|
||||
if(SLP_STATE() != oldstate){
|
||||
MSG("~SLP is in air\n");
|
||||
if(driver != DRV_2130){
|
||||
@ -63,13 +89,17 @@ static void checkDrv(){
|
||||
EN_CFG_IN();
|
||||
sleep(2);
|
||||
oldstate = EN_STATE();
|
||||
#ifdef EBUG
|
||||
if(oldstate) MSG("EN=1\n"); else MSG("EN=0\n");
|
||||
#endif
|
||||
DRV_DISABLE(); // EN->1
|
||||
EN_CFG_OUT();
|
||||
sleep(2);
|
||||
EN_CFG_IN();
|
||||
sleep(2);
|
||||
#ifdef EBUG
|
||||
if(EN_STATE()) MSG("EN=1\n"); else MSG("EN=0\n");
|
||||
#endif
|
||||
if(oldstate != EN_STATE()){
|
||||
MSG("~EN is in air\n");
|
||||
driver = DRV_NONE;
|
||||
@ -86,6 +116,47 @@ ret:
|
||||
#endif
|
||||
}
|
||||
|
||||
static drv_type ini2130(){ // init 2130: SPI etc.
|
||||
if(driver != DRV_2130) return DRV_MAILF;
|
||||
;
|
||||
return DRV_MAILF;
|
||||
}
|
||||
|
||||
static drv_type ini4988_8825(){ // init 4988 or 8825
|
||||
if(driver != DRV_4988 && driver != DRV_8825){
|
||||
MSG("Wrong drv\n");
|
||||
return DRV_MAILF;
|
||||
}
|
||||
if(the_conf.microsteps > maxusteps[driver]){
|
||||
SEND("Wrong microstepping settings\n");
|
||||
return DRV_MAILF;
|
||||
}
|
||||
if(the_conf.microsteps == 0){
|
||||
SEND("Configure microstepping first\n");
|
||||
return DRV_MAILF;
|
||||
}
|
||||
// init microstepping pins and set config
|
||||
UST01_CFG_PP();
|
||||
uint8_t PINS = 0;
|
||||
if(the_conf.microsteps == 16 && driver == DRV_4988) PINS = 7; // microstepping settings for 4988 in 1/16 differs from 8825
|
||||
else PINS = (uint8_t)__builtin_ctz(the_conf.microsteps);
|
||||
#ifdef EBUG
|
||||
SEND("Microstep PINS=");
|
||||
printu(PINS);
|
||||
newline(); sendbuf();
|
||||
#endif
|
||||
// now PINS is M0..M2 settings
|
||||
if(PINS & 1) SET_UST0(); else RESET_UST0();
|
||||
if(PINS & 2) SET_UST1(); else RESET_UST1();
|
||||
if(PINS & 4) SET_UST2(); else RESET_UST2();
|
||||
// turn on timer
|
||||
timer_setup();
|
||||
// recalculate defaults
|
||||
stp_chspd();
|
||||
SEND("Init OK\n");
|
||||
return driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initDriver - try to init driver
|
||||
* @return driver type
|
||||
@ -93,12 +164,179 @@ ret:
|
||||
drv_type initDriver(){
|
||||
if(driver != DRV_NOTINIT){ // reset all settings
|
||||
MSG("clear GPIO & other setup\n");
|
||||
STEP_TIMER_OFF();
|
||||
// TODO: turn off SPI & timer
|
||||
gpio_setup(); // reset pins control
|
||||
}
|
||||
driver = the_conf.driver_type;
|
||||
checkDrv();
|
||||
if(driver == DRV_NONE) return driver;
|
||||
// TODO: some stuff here
|
||||
if(driver > DRV_MAX-1) return (driver = DRV_NONE);
|
||||
MSG("init pins\n");
|
||||
switch(driver){
|
||||
case DRV_2130:
|
||||
return ini2130();
|
||||
break;
|
||||
case DRV_4988:
|
||||
case DRV_8825:
|
||||
return ini4988_8825();
|
||||
break;
|
||||
default:
|
||||
SEND("Set driver type in config\n");
|
||||
return driver; // bad driver type
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
|
||||
uint16_t getMaxUsteps(){
|
||||
if(driver > DRV_MAX-1) return 0;
|
||||
return maxusteps[driver];
|
||||
}
|
||||
|
||||
void stp_chspd(){
|
||||
int i;
|
||||
for(i = 0; i < 2; ++i){
|
||||
uint16_t spd = the_conf.motspd;
|
||||
stplowarr = spd;
|
||||
stphigharr = spd * LOWEST_SPEED_DIV;
|
||||
stpsteparr = (spd * (LOWEST_SPEED_DIV - 1)) / ((uint16_t)ACCDECSTEPS) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// check end-switches for stepper motors
|
||||
void stp_process(){
|
||||
// check end-switches; ESW0&ESW3 stops motor
|
||||
uint8_t esw = ESW_STATE();
|
||||
switch(state){
|
||||
case STP_MOVE0: // move towards ESW0
|
||||
state = STP_SLEEP;
|
||||
stp_move(-the_conf.maxsteps); // won't move if the_conf.maxsteps == 0
|
||||
break;
|
||||
case STP_MOVE1: // move towards ESW3
|
||||
state = STP_SLEEP;
|
||||
stp_move(the_conf.maxsteps);
|
||||
break;
|
||||
case STP_ACCEL: // @ any move check esw
|
||||
case STP_DECEL:
|
||||
case STP_MOVE:
|
||||
case STP_MVSLOW:
|
||||
if((esw&1) && dir == -1){ // move through ESW0
|
||||
state = STP_STOPZERO; // stop @ end-switch
|
||||
}else if((esw&8) && dir == 1){ // move through ESW3
|
||||
state = STP_STOP; // stop @ ESW3
|
||||
}
|
||||
break;
|
||||
default: // stopping states - do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// move motor to `steps` steps, @return 0 if all OK
|
||||
stp_status stp_move(int32_t steps){
|
||||
if(state != STP_SLEEP && state != STP_MOVE0 && state != STP_MOVE1) return STPS_ACTIVE;
|
||||
if(steps == 0)
|
||||
return STPS_ZEROMOVE;
|
||||
if(the_conf.maxsteps && steps > (int32_t)the_conf.maxsteps) return STPS_TOOBIG;
|
||||
int8_t d;
|
||||
if(steps < 0){
|
||||
d = -1;
|
||||
steps = -steps;
|
||||
}else d = 1; // positive direction
|
||||
// check end-switches
|
||||
uint8_t esw = ESW_STATE();
|
||||
if(((esw&1) && d == -1) || ((esw&8) && d == 1)) return STPS_ONESW; // can't move through esw
|
||||
dir = d;
|
||||
// change value of DIR pin
|
||||
if(the_conf.defflags.reverse){
|
||||
if(d>0)
|
||||
SET_DIR();
|
||||
else
|
||||
CLEAR_DIR();
|
||||
}else{
|
||||
if(d>0)
|
||||
CLEAR_DIR();
|
||||
else
|
||||
SET_DIR();
|
||||
}
|
||||
// turn on driver, EN=0
|
||||
DRV_ENABLE();
|
||||
steps_left = (uint32_t)steps;
|
||||
// setup timer & start it
|
||||
TIMx->ARR = stphigharr;
|
||||
TIMx->CCMR1 = TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1; // PWM mode 1: active->inacive, preload enable
|
||||
TIMx->CR1 |= TIM_CR1_CEN;
|
||||
if(steps < ACCDECSTEPS*2) state = STP_MVSLOW; // move without acceleration
|
||||
else state = STP_ACCEL; // move with acceleration
|
||||
return STPS_ALLOK;
|
||||
}
|
||||
|
||||
// change ARR value
|
||||
void stp_chARR(uint32_t val){
|
||||
if(val < 2) val = 2;
|
||||
TIMx->ARR = (uint32_t)val;
|
||||
}
|
||||
|
||||
void stp_stop(){ // stop motor by demand or @ end-switch
|
||||
switch(state){
|
||||
case STP_SLEEP:
|
||||
return;
|
||||
break;
|
||||
case STP_MOVE0:
|
||||
case STP_MOVE1:
|
||||
state = STP_SLEEP;
|
||||
break;
|
||||
default:
|
||||
state = STP_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_isr(){
|
||||
static uint16_t ustep = 0;
|
||||
uint16_t tmp, arrval;
|
||||
if(USTEPS == ++ustep){ // prevent stop @ not full step
|
||||
ustep = 0;
|
||||
if(state == STP_STOPZERO)
|
||||
mot_position = 0;
|
||||
else{
|
||||
if(0 == --steps_left) state = STP_STOP;
|
||||
mot_position += dir;
|
||||
}
|
||||
}else return;
|
||||
switch(state){
|
||||
case STP_ACCEL: // acceleration phase
|
||||
arrval = (uint16_t)TIMx->ARR - stpsteparr;
|
||||
tmp = stplowarr;
|
||||
if(arrval <= tmp || arrval > stphigharr){
|
||||
arrval = tmp;
|
||||
state = STP_MOVE; // end of acceleration phase
|
||||
}
|
||||
TIMx->ARR = arrval;
|
||||
break;
|
||||
case STP_DECEL: // deceleration phase
|
||||
arrval = (uint16_t)TIMx->ARR + stpsteparr;
|
||||
tmp = stphigharr;
|
||||
if(arrval >= tmp || arrval < stplowarr){
|
||||
arrval = tmp;
|
||||
state = STP_MVSLOW; // end of deceleration phase, move @ lowest speed
|
||||
}
|
||||
TIMx->ARR = arrval;
|
||||
break;
|
||||
case STP_MOVE: // moving with constant speed phases
|
||||
if(steps_left <= ACCDECSTEPS){
|
||||
state = STP_DECEL; // change moving status to decelerate
|
||||
}
|
||||
break;
|
||||
case STP_MVSLOW:
|
||||
// nothing to do here: all done before switch()
|
||||
break;
|
||||
default: // STP_STOP, STP_STOPZERO
|
||||
ustep = 0;
|
||||
TIMx->CCMR1 = TIM_CCMR1_OC1M_2; // Force inactive
|
||||
TIMx->CR1 &= ~TIM_CR1_CEN; // stop timer
|
||||
DRV_DISABLE();
|
||||
dir = 0;
|
||||
steps_left = 0;
|
||||
state = STP_SLEEP;
|
||||
break;
|
||||
}
|
||||
TIMx->SR = 0;
|
||||
}
|
||||
|
||||
@ -21,16 +21,61 @@
|
||||
|
||||
#include <stm32f0.h>
|
||||
|
||||
// the lowest speed equal to [max speed] / LOWEST_SPEED_DIV
|
||||
#define LOWEST_SPEED_DIV 30
|
||||
// min/max value of ACCDECSTEPS
|
||||
#define ACCDECSTEPS_MIN 30
|
||||
#define ACCDECSTEPS_MAX 2000
|
||||
|
||||
typedef enum{
|
||||
DRV_NONE, // driver is absent
|
||||
DRV_NOTINIT,// not initialized
|
||||
DRV_MAILF, // mailfunction - no Vdd when Vio_ON activated
|
||||
DRV_8825, // DRV8825 connected
|
||||
DRV_4988, // A4988 connected
|
||||
DRV_2130 // TMC2130 connected
|
||||
DRV_2130, // TMC2130 connected
|
||||
DRV_MAX // amount of records in enum
|
||||
} drv_type;
|
||||
|
||||
// stepper states
|
||||
typedef enum{
|
||||
STP_SLEEP, // don't moving
|
||||
STP_ACCEL, // start moving with acceleration
|
||||
STP_MOVE, // moving with constant speed
|
||||
STP_MVSLOW, // moving with slowest constant speed
|
||||
STP_DECEL, // moving with deceleration
|
||||
STP_STOP, // stop motor right now (by demand)
|
||||
STP_STOPZERO, // stop motor and zero its position (on end-switch)
|
||||
STP_MOVE0, // move towards 0 endswitch (negative direction)
|
||||
STP_MOVE1, // move towards 1 endswitch (positive direction)
|
||||
} stp_state;
|
||||
|
||||
typedef enum{
|
||||
STPS_ALLOK, // no errors
|
||||
STPS_ACTIVE, // motor is still moving
|
||||
STPS_TOOBIG, // amount of steps too big
|
||||
STPS_ZEROMOVE, // give 0 steps to move
|
||||
STPS_ONESW // staying on end-switch & try to move further
|
||||
} stp_status;
|
||||
|
||||
extern int32_t mot_position;
|
||||
extern uint32_t steps_left;
|
||||
extern stp_state state;
|
||||
#define stp_getstate() (state)
|
||||
|
||||
drv_type initDriver();
|
||||
drv_type getDrvType();
|
||||
uint16_t getMaxUsteps();
|
||||
|
||||
void stp_chspd();
|
||||
stp_status stp_move(int32_t steps);
|
||||
void stp_stop();
|
||||
void stp_process();
|
||||
void stp_chARR(uint32_t val);
|
||||
|
||||
#endif // STEPPERS_H__
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -165,7 +165,7 @@ void CAN_setup(uint16_t speed){
|
||||
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
|
||||
CAN->MCR |= CAN_MCR_ABOM; /* allow automatically bus-off */
|
||||
|
||||
CAN->BTR |= 2 << 20 | 3 << 16 | (6000/speed) << 0; /* (4) */
|
||||
CAN->BTR |= 2 << 20 | 3 << 16 | (6000/speed - 1); /* (4) */
|
||||
CAN->MCR &=~ CAN_MCR_INRQ; /* (5) */
|
||||
tmout = 16000000;
|
||||
while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK) if(--tmout == 0) break; /* (6) */
|
||||
|
||||
@ -544,8 +544,13 @@ void printu(uint32_t val){
|
||||
void printuhex(uint32_t val){
|
||||
addtobuf("0x");
|
||||
uint8_t *ptr = (uint8_t*)&val + 3;
|
||||
int8_t i, j;
|
||||
int8_t i, j, z=1;
|
||||
for(i = 0; i < 4; ++i, --ptr){
|
||||
if(*ptr == 0){ // omit leading zeros
|
||||
if(i == 3) z = 0;
|
||||
if(z) continue;
|
||||
}
|
||||
else z = 0;
|
||||
for(j = 1; j > -1; --j){
|
||||
uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
||||
if(half < 10) bufputchar(half + '0');
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user