mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-07 03:05:15 +03:00
DRV8825 works, PCB should be rebuild for ability of encoder connection
This commit is contained in:
parent
8d6aeb8f00
commit
d8a4c99ec7
@ -1,5 +1,4 @@
|
||||
EESchema Schematic File Version 4
|
||||
LIBS:stm32-cache
|
||||
EELAYER 30 0
|
||||
EELAYER END
|
||||
$Descr A3 16535 11693
|
||||
@ -1888,4 +1887,6 @@ F 3 "" H 1600 2240 50 0000 C CNN
|
||||
$EndComp
|
||||
Text Label 1200 4540 2 60 ~ 0
|
||||
12Vin
|
||||
Text Notes 3850 5975 0 50 ~ 0
|
||||
TODO:\nESW0 & ESW2 should be @ encoder interface!\nTIM1: ch1 - PA8, ch2 - PA9\nTIM2: ch2 - PA1, PB3, \nTIM3: ch1 - PA6, PB4, ch2 - PA7, PB5
|
||||
$EndSCHEMATC
|
||||
|
||||
@ -445,7 +445,7 @@ L Device:D_Zener D7
|
||||
U 1 1 59684468
|
||||
P 9140 1520
|
||||
F 0 "D7" H 9140 1620 50 0000 C CNN
|
||||
F 1 "MM3Z3V9" H 9140 1420 50 0000 C CNN
|
||||
F 1 "MM3Z4V7" H 9140 1420 50 0000 C CNN
|
||||
F 2 "Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder" H 9140 1520 50 0001 C CNN
|
||||
F 3 "" H 9140 1520 50 0000 C CNN
|
||||
1 9140 1520
|
||||
@ -1056,7 +1056,7 @@ L Device:D_Zener D8
|
||||
U 1 1 5E7D7999
|
||||
P 10080 1510
|
||||
F 0 "D8" H 10080 1610 50 0000 C CNN
|
||||
F 1 "MM3Z3V9" H 10080 1410 50 0000 C CNN
|
||||
F 1 "MM3Z4V7" H 10080 1410 50 0000 C CNN
|
||||
F 2 "Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder" H 10080 1510 50 0001 C CNN
|
||||
F 3 "" H 10080 1510 50 0000 C CNN
|
||||
1 10080 1510
|
||||
|
||||
Binary file not shown.
@ -48,10 +48,10 @@ static uint32_t maxCnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
||||
.userconf_sz = sizeof(user_conf) \
|
||||
,.defflags.reverse = 0 \
|
||||
,.CANspeed = 100 \
|
||||
,.driver_type = DRV_NONE \
|
||||
,.driver_type = DRV_8825 \
|
||||
,.microsteps = 16 \
|
||||
,.accdecsteps = 100 \
|
||||
,.motspd = 10 \
|
||||
,.accdecsteps = 25 \
|
||||
,.motspd = 1000 \
|
||||
,.maxsteps = 50000 \
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ typedef struct __attribute__((packed, aligned(4))){
|
||||
uint16_t CANspeed; // default CAN speed
|
||||
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)
|
||||
uint16_t motspd; // max motor speed (steps per second)
|
||||
defflags_t defflags; // default flags
|
||||
uint8_t driver_type; // user's settings: type of stepper's driver
|
||||
} user_conf;
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
*/
|
||||
|
||||
#include "hardware.h"
|
||||
#include "proto.h"
|
||||
#include "steppers.h"
|
||||
|
||||
TIM_TypeDef *TIMx = TIM15; // stepper's timer
|
||||
|
||||
@ -117,20 +119,30 @@ void gpio_setup(){
|
||||
brdADDR = READ_BRD_ADDR();
|
||||
}
|
||||
|
||||
// PA3 (STEP): TIM15_CH2; 48MHz -> 48kHz
|
||||
// PA3 (STEP): TIM15_CH2; 48MHz -> 1MHz
|
||||
void timer_setup(){
|
||||
// PA3 - Tim15Ch2 (AF0)
|
||||
GPIOA->AFR[0] = (GPIOA->AFR[0] & ~GPIO_AFRL_AFRL3);
|
||||
GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODER3) | GPIO_MODER_MODER3_AF; // set alternate output
|
||||
RCC->APB2ENR |= RCC_APB2ENR_TIM15EN; // enable clocking
|
||||
TIM15->CR1 &= ~TIM_CR1_CEN; // turn off timer
|
||||
TIM15->CR1 = 0; // 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;
|
||||
TIM15->PSC = TIM15PSC;
|
||||
TIM15->CCR2 = TIM15CCR2;
|
||||
TIM15->ARR = 1000; // this value will be changed later
|
||||
TIM15->CCER = TIM_CCER_CC2E; // enable PWM out
|
||||
TIM15->BDTR = TIM_BDTR_MOE; // enable main output
|
||||
// enable IRQ & update values
|
||||
TIM15->EGR = TIM_EGR_UG;
|
||||
TIM15->DIER = TIM_DIER_CC2IE;
|
||||
NVIC_EnableIRQ(TIM15_IRQn);
|
||||
NVIC_SetPriority(TIM15_IRQn, 0);
|
||||
/*
|
||||
TIM15->CCMR1 = TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1; // PWM mode 1: active->inacive
|
||||
TIM15->BDTR = TIM_BDTR_MOE;
|
||||
TIM15->CR1 = TIM_CR1_CEN;
|
||||
*/
|
||||
MSG("Timer is ON\n");
|
||||
}
|
||||
|
||||
uint8_t refreshBRDaddr(){
|
||||
|
||||
@ -68,12 +68,15 @@
|
||||
#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)
|
||||
// microstepping0 (PA7), 1 (PA5), ~reset (PA6) - PP config
|
||||
#define UST01_CFG_PP() do{GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER5|GPIO_MODER_MODER6|GPIO_MODER_MODER7)) | (GPIO_MODER_MODER5_O|GPIO_MODER_MODER6_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)
|
||||
// ~RESET pin (inverse), PA6
|
||||
#define DRV_RESET_ON() do{GPIOA->BRR = 1<<6;}while(0)
|
||||
#define DRV_RESET_OFF() do{GPIOA->BSRR = 1<<6;}while(0)
|
||||
// end-switches state
|
||||
#define ESW_STATE() ((GPIOB->IDR & 0x07) | ((GPIOB->IDR>>7) & 0x08))
|
||||
// configure ~CS as PP output
|
||||
|
||||
@ -102,9 +102,10 @@ int main(void){
|
||||
USB_setup();
|
||||
iwdg_setup();
|
||||
|
||||
while (1){
|
||||
while (1){
|
||||
IWDG->KR = IWDG_REFRESH; // refresh watchdog
|
||||
if(Tms - lastT > 499){
|
||||
sendbuf();
|
||||
lastT = Tms;
|
||||
}
|
||||
can_proc();
|
||||
|
||||
@ -218,7 +218,7 @@ TRUE_INLINE void setdefflags(char *txt){
|
||||
the_conf.defflags.reverse = U&1;
|
||||
break;
|
||||
default:
|
||||
SEND("\nFlag commands:"
|
||||
SEND("\nFlag commands:\n"
|
||||
"r - set/clear reverse\n"
|
||||
);
|
||||
}
|
||||
@ -230,7 +230,7 @@ TRUE_INLINE void setters(char *txt){
|
||||
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);
|
||||
const char *motspdshould = "Motor speed should be from 1 to " STR(10000);
|
||||
txt = omit_spaces(txt);
|
||||
if(!*txt){
|
||||
SEND("Setters need more arguments");
|
||||
@ -322,10 +322,11 @@ TRUE_INLINE void setters(char *txt){
|
||||
if(U != the_conf.maxsteps){
|
||||
the_conf.maxsteps = U;
|
||||
userconf_changed = 1;
|
||||
SEND("Set maxsteps to "); printu(U);
|
||||
}
|
||||
break;
|
||||
case 's': // motor speed
|
||||
if(nxt == txt + 1 || U < 2 || U > (0xffff/LOWEST_SPEED_DIV)){ // no number
|
||||
if(nxt == txt + 1 || U < 1 || U > MAX_SPEED){ // no number
|
||||
SEND(motspdshould); break;
|
||||
}
|
||||
if(the_conf.motspd != (uint16_t)U){
|
||||
@ -339,7 +340,7 @@ TRUE_INLINE void setters(char *txt){
|
||||
"a - set accdecsteps\n"
|
||||
"c - set default CAN speed\n"
|
||||
"d - set driver type\n"
|
||||
"F - set flags"
|
||||
"F - set flags\n"
|
||||
"m - set microsteps\n"
|
||||
"M - set maxsteps\n"
|
||||
"s - set motspd\n"
|
||||
@ -364,6 +365,17 @@ TRUE_INLINE void driver_commands(char *txt){
|
||||
char *nxt = getnum(txt, &U);
|
||||
stp_status st;
|
||||
switch(cmd){
|
||||
case '0':
|
||||
state = STP_MOVE0;
|
||||
stp_process();
|
||||
break;
|
||||
case '1':
|
||||
state = STP_MOVE1;
|
||||
stp_process();
|
||||
break;
|
||||
case 'd':
|
||||
SEND(stp_getdrvtype());
|
||||
break;
|
||||
case 'e':
|
||||
SEND("ESW=");
|
||||
printu(ESW_STATE());
|
||||
@ -371,8 +383,12 @@ TRUE_INLINE void driver_commands(char *txt){
|
||||
case 'i': // init
|
||||
initDriver();
|
||||
break;
|
||||
case 'l':
|
||||
SEND("Stepsleft=");
|
||||
printu(stpleft());
|
||||
break;
|
||||
case 'm':
|
||||
if(nxt == txt + 1 || U > (INT32_MAX-1)){
|
||||
if(nxt == txt || U > (INT32_MAX-1)){
|
||||
SEND("Give right steps amount: from -INT32_MAX to INT32_MAX");
|
||||
return;
|
||||
}
|
||||
@ -395,16 +411,32 @@ TRUE_INLINE void driver_commands(char *txt){
|
||||
SEND("Move to given steps amount");
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
SEND("Motpos=");
|
||||
if(stppos() < 0){
|
||||
U = (uint32_t) -stppos();
|
||||
bufputchar('-');
|
||||
}else U = (uint32_t) stppos();
|
||||
printu(U);
|
||||
break;
|
||||
case 's':
|
||||
stp_stop();
|
||||
SEND("Stop motor");
|
||||
break;
|
||||
case 'S':
|
||||
SEND(stp_getstate());
|
||||
break;
|
||||
default:
|
||||
SEND("\nDriver commands:\n"
|
||||
"0/1 - move to ESW0/ESW3 and stop there\n"
|
||||
"d - current driver type\n"
|
||||
"e - end-switches state\n"
|
||||
"i - init stepper driver (8825, 4988, 2130)\n"
|
||||
"l - steps left\n"
|
||||
"m - move N steps\n"
|
||||
"p - motor position\n"
|
||||
"s - stop\n"
|
||||
"S - state\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -448,6 +480,9 @@ void cmd_parser(char *txt, uint8_t isUSB){
|
||||
can_accept_one();
|
||||
SEND("Accept only my ID @CAN");
|
||||
break;
|
||||
case '1':
|
||||
timer_setup();
|
||||
break;
|
||||
case '@':
|
||||
can_accept_any();
|
||||
SEND("Accept any ID @CAN");
|
||||
@ -460,9 +495,6 @@ void cmd_parser(char *txt, uint8_t isUSB){
|
||||
sendbuf();
|
||||
Jump2Boot();
|
||||
break;
|
||||
case 'd':
|
||||
dump_userconf();
|
||||
break;
|
||||
case 'g':
|
||||
SEND("Board address: ");
|
||||
printuhex(refreshBRDaddr());
|
||||
@ -498,7 +530,6 @@ void cmd_parser(char *txt, uint8_t isUSB){
|
||||
"@ - accept any IDs\n"
|
||||
"a - get raw ADC values\n"
|
||||
"b - switch to bootloader\n"
|
||||
"d - dump userconf\n"
|
||||
"D? - stepper driver commands\n"
|
||||
"g - get board address\n"
|
||||
"j - get MCU temperature\n"
|
||||
|
||||
112
F0-nolib/CANbus_stepper/src/spi.c
Normal file
112
F0-nolib/CANbus_stepper/src/spi.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This file is part of the Stepper project.
|
||||
* Copyright 2020 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "hardware.h"
|
||||
#include "proto.h"
|
||||
#include "spi.h"
|
||||
|
||||
#include <string.h> // memcpy
|
||||
|
||||
// buffers for DMA rx/tx
|
||||
static uint8_t inbuff[SPIBUFSZ], outbuf[SPIBUFSZ];
|
||||
spiStatus SPI_status = SPI_NOTREADY;
|
||||
|
||||
//SPI: PA5 - SCK, PA6 -MISO, PA7 - MOSI, PC14 - ~CS
|
||||
void spi_setup(){
|
||||
/* (1) Select AF mode on PA5, PA6, PA7 */
|
||||
/* (2) AF0 for SPI1 signals */
|
||||
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER5 | GPIO_MODER_MODER6 | GPIO_MODER_MODER7)) |
|
||||
(GPIO_MODER_MODER5_AF | GPIO_MODER_MODER6_AF | GPIO_MODER_MODER7_AF); /* (1) */
|
||||
GPIOA->AFR[0] = (GPIOA->AFR[0] & (GPIO_AFRL_AFRL5 | GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7)); /* (2) */
|
||||
// Configure DMA SPI
|
||||
/* Enable the peripheral clock DMA11 */
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||
/* DMA1 Channel2 SPI1_RX config */
|
||||
/* (1) Peripheral address */
|
||||
/* (2) Memory address */
|
||||
/* (3) Data size */
|
||||
/* (4) Memory increment */
|
||||
/* Peripheral to memory */
|
||||
/* 8-bit transfer */
|
||||
DMA1_Channel2->CPAR = (uint32_t)&(SPI1->DR); /* (1) */
|
||||
DMA1_Channel2->CMAR = (uint32_t)inbuff; /* (2) */
|
||||
DMA1_Channel2->CNDTR = SPIBUFSZ; /* (3) */
|
||||
DMA1_Channel2->CCR |= DMA_CCR_MINC | DMA_CCR_EN; /* (4) */
|
||||
/* DMA1 Channel3 SPI1_TX config */
|
||||
/* (5) Peripheral address */
|
||||
/* (6) Memory address */
|
||||
/* (7) Memory increment */
|
||||
/* Memory to peripheral*/
|
||||
/* 8-bit transfer */
|
||||
/* Transfer complete IT */
|
||||
DMA1_Channel3->CPAR = (uint32_t)&(SPI1->DR); /* (5) */
|
||||
DMA1_Channel3->CMAR = (uint32_t)outbuf; /* (6) */
|
||||
DMA1_Channel3->CCR |= DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_DIR; /* (7) */
|
||||
/* Configure IT */
|
||||
/* (8) Set priority for DMA1_Channel2_3_IRQn */
|
||||
/* (9) Enable DMA1_Channel2_3_IRQn */
|
||||
NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0); /* (8) */
|
||||
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); /* (9) */
|
||||
// configure SPI (transmit only)
|
||||
/* Enable the peripheral clock SPI1 */
|
||||
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
|
||||
/* Configure SPI1 in master */
|
||||
/* (1) Master selection, BR: Fpclk/256 CPOL and CPHA at zero (rising first edge) */
|
||||
/* (2) TX and RX with DMA, slave select output enabled, 8-bit Rx fifo */
|
||||
/* (3) Enable SPI1 */
|
||||
SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR; /* (1) */
|
||||
SPI1->CR2 = SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; /* (2) */
|
||||
SPI1->CR1 |= SPI_CR1_SPE; /* (3) */
|
||||
SPI_status = SPI_READY;
|
||||
}
|
||||
|
||||
void dma1_channel2_3_isr(){
|
||||
if(DMA1->ISR & DMA_ISR_TCIF3){
|
||||
DMA1->IFCR |= DMA_IFCR_CTCIF3;
|
||||
SPI_status = SPI_READY;
|
||||
#ifdef EBUG
|
||||
SEND("rxCNDTR="); printu(DMA1_Channel2->CNDTR); SEND(", txCNDTR="); printu(DMA1_Channel3->CNDTR); newline(); sendbuf();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI_transmit - transmit data over SPI DMA
|
||||
* @param buf - data to transmit
|
||||
* @param len - its length
|
||||
* @return 0 if all OK
|
||||
*/
|
||||
uint8_t SPI_transmit(const uint8_t *buf, uint8_t len){
|
||||
if(!buf || !len || len > SPIBUFSZ) return 1; // bad data format
|
||||
if(SPI_status != SPI_READY) return 2; // spi not ready to transmit data
|
||||
DMA1_Channel3->CCR &=~ DMA_CCR_EN;
|
||||
memcpy(outbuf, buf, len);
|
||||
DMA1_Channel3->CNDTR = len;
|
||||
SPI_status = SPI_BUSY;
|
||||
#ifdef EBUG
|
||||
SEND("SPI tx "); printu(len); SEND(" bytes\n"); sendbuf();
|
||||
#endif
|
||||
DMA1_Channel3->CCR |= DMA_CCR_EN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
static uint8_t *SPI_receive(uint8_t *len){
|
||||
if(!len || SPI_status != SPI_READY) return NULL;
|
||||
*len =
|
||||
}*/
|
||||
38
F0-nolib/CANbus_stepper/src/spi.h
Normal file
38
F0-nolib/CANbus_stepper/src/spi.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of the Stepper project.
|
||||
* Copyright 2020 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef SPI_H__
|
||||
#define SPI_H__
|
||||
|
||||
#include "stm32f0.h"
|
||||
|
||||
#define SPIBUFSZ 64
|
||||
|
||||
typedef enum{
|
||||
SPI_NOTREADY,
|
||||
SPI_READY,
|
||||
SPI_BUSY
|
||||
} spiStatus;
|
||||
|
||||
extern spiStatus SPI_status;
|
||||
|
||||
void spi_setup();
|
||||
uint8_t SPI_transmit(const uint8_t *buf, uint8_t len);
|
||||
|
||||
#endif // SPI_H__
|
||||
@ -18,6 +18,7 @@
|
||||
#include "flash.h"
|
||||
#include "hardware.h"
|
||||
#include "proto.h"
|
||||
#include "spi.h"
|
||||
#include "steppers.h"
|
||||
|
||||
static drv_type driver = DRV_NONE;
|
||||
@ -32,11 +33,6 @@ static const uint16_t maxusteps[] = {
|
||||
[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
|
||||
@ -44,6 +40,7 @@ stp_state state = STP_SLEEP;// current state of motor
|
||||
static uint16_t stplowarr, stphigharr, stpsteparr;
|
||||
static int8_t dir = 0; // moving direction: -1 (negative) or 1 (positive)
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief checkDrv - test if driver connected
|
||||
*/
|
||||
@ -109,17 +106,19 @@ static void checkDrv(){
|
||||
ret:
|
||||
DRV_DISABLE();
|
||||
EN_CFG_OUT(); // return OUT conf
|
||||
SLEEP_OFF();
|
||||
SLEEP_ON();
|
||||
SLP_CFG_OUT();
|
||||
#ifdef EBUG
|
||||
sendbuf();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
static drv_type ini2130(){ // init 2130: SPI etc.
|
||||
if(driver != DRV_2130) return DRV_MAILF;
|
||||
;
|
||||
return DRV_MAILF;
|
||||
VIO_ON();
|
||||
spi_setup();
|
||||
CS_ACTIVE();
|
||||
return DRV_2130;
|
||||
}
|
||||
|
||||
static drv_type ini4988_8825(){ // init 4988 or 8825
|
||||
@ -135,7 +134,9 @@ static drv_type ini4988_8825(){ // init 4988 or 8825
|
||||
SEND("Configure microstepping first\n");
|
||||
return DRV_MAILF;
|
||||
}
|
||||
if(driver == DRV_4988) VIO_ON();
|
||||
// init microstepping pins and set config
|
||||
DRV_RESET_ON(); // reset counters
|
||||
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
|
||||
@ -153,6 +154,8 @@ static drv_type ini4988_8825(){ // init 4988 or 8825
|
||||
timer_setup();
|
||||
// recalculate defaults
|
||||
stp_chspd();
|
||||
DRV_RESET_OFF(); // normal mode
|
||||
SLEEP_OFF();
|
||||
SEND("Init OK\n");
|
||||
return driver;
|
||||
}
|
||||
@ -162,6 +165,10 @@ static drv_type ini4988_8825(){ // init 4988 or 8825
|
||||
* @return driver type
|
||||
*/
|
||||
drv_type initDriver(){
|
||||
stp_stop();
|
||||
DRV_DISABLE();
|
||||
VIO_OFF();
|
||||
SLEEP_ON();
|
||||
if(driver != DRV_NOTINIT){ // reset all settings
|
||||
MSG("clear GPIO & other setup\n");
|
||||
STEP_TIMER_OFF();
|
||||
@ -169,7 +176,8 @@ drv_type initDriver(){
|
||||
gpio_setup(); // reset pins control
|
||||
}
|
||||
driver = the_conf.driver_type;
|
||||
checkDrv();
|
||||
//checkDrv();
|
||||
state = STP_SLEEP;
|
||||
if(driver > DRV_MAX-1) return (driver = DRV_NONE);
|
||||
MSG("init pins\n");
|
||||
switch(driver){
|
||||
@ -192,14 +200,55 @@ uint16_t getMaxUsteps(){
|
||||
return maxusteps[driver];
|
||||
}
|
||||
|
||||
static const char *stpstates[] = {
|
||||
[STP_SLEEP] = "Relax"
|
||||
,[STP_ACCEL] = "Accelerated"
|
||||
,[STP_MOVE] = "Moving"
|
||||
,[STP_MVSLOW] = "Slowmoving"
|
||||
,[STP_DECEL] = "Decelerated"
|
||||
,[STP_STOP] = "Stopping"
|
||||
,[STP_STOPZERO] = "Stop0"
|
||||
,[STP_MOVE0] = "Moveto0"
|
||||
,[STP_MOVE1] = "Moveto1"
|
||||
};
|
||||
const char *stp_getstate(){
|
||||
return stpstates[state];
|
||||
}
|
||||
|
||||
static const char *drvtypes[] = {
|
||||
[DRV_NONE] = "Absent"
|
||||
,[DRV_NOTINIT] = "NotInit"
|
||||
,[DRV_MAILF] = "Mailfunction"
|
||||
,[DRV_8825] = "DRV8825"
|
||||
,[DRV_4988] = "A4988"
|
||||
,[DRV_2130] = "TMC2130"
|
||||
};
|
||||
const char *stp_getdrvtype(){
|
||||
return drvtypes[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;
|
||||
uint32_t arrval = DEFTICKSPERSEC / the_conf.motspd;
|
||||
arrval /= the_conf.microsteps;
|
||||
if(arrval > 0xffff){
|
||||
SEND("The speed is too little for this microstepping settings, set min available\n");
|
||||
arrval = 0xffff;
|
||||
}else if(arrval < TIM15ARRMIN){
|
||||
SEND("The speed is too big for this microstepping settings, set max available\n");
|
||||
arrval = TIM15ARRMIN;
|
||||
}
|
||||
stplowarr = (uint16_t)arrval;
|
||||
arrval *= LOW_SPEED_DIVISOR;
|
||||
if(arrval > 0xffff) arrval = 0xffff;
|
||||
stphigharr = (uint16_t)arrval;
|
||||
stpsteparr = (stphigharr - stplowarr) / ((uint16_t)the_conf.accdecsteps);
|
||||
if(stpsteparr < 1) stpsteparr = 1;
|
||||
#ifdef EBUG
|
||||
SEND("stplowarr="); printu(stplowarr);
|
||||
SEND("\nstphigharr="); printu(stphigharr);
|
||||
SEND("\nstpsteparr="); printu(stpsteparr);
|
||||
newline();
|
||||
#endif
|
||||
}
|
||||
|
||||
// check end-switches for stepper motors
|
||||
@ -221,8 +270,10 @@ void stp_process(){
|
||||
case STP_MVSLOW:
|
||||
if((esw&1) && dir == -1){ // move through ESW0
|
||||
state = STP_STOPZERO; // stop @ end-switch
|
||||
MSG("ESW0 active\n");
|
||||
}else if((esw&8) && dir == 1){ // move through ESW3
|
||||
state = STP_STOP; // stop @ ESW3
|
||||
MSG("ESW3 active\n");
|
||||
}
|
||||
break;
|
||||
default: // stopping states - do nothing
|
||||
@ -233,17 +284,26 @@ void stp_process(){
|
||||
// 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)
|
||||
if(steps == 0){
|
||||
MSG("Zero move\n");
|
||||
return STPS_ZEROMOVE;
|
||||
if(the_conf.maxsteps && steps > (int32_t)the_conf.maxsteps) return STPS_TOOBIG;
|
||||
}
|
||||
if(the_conf.maxsteps && steps > (int32_t)the_conf.maxsteps){
|
||||
MSG("Too much steps\n");
|
||||
return STPS_TOOBIG;
|
||||
}
|
||||
int8_t d;
|
||||
if(steps < 0){
|
||||
MSG("Negative direction\n");
|
||||
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
|
||||
if(((esw&1) && d == -1) || ((esw&8) && d == 1)){
|
||||
MSG("Stay @esw\n");
|
||||
return STPS_ONESW; // can't move through esw
|
||||
}
|
||||
dir = d;
|
||||
// change value of DIR pin
|
||||
if(the_conf.defflags.reverse){
|
||||
@ -264,14 +324,16 @@ stp_status stp_move(int32_t steps){
|
||||
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
|
||||
if(steps < the_conf.accdecsteps*2) state = STP_MVSLOW; // move without acceleration
|
||||
else state = STP_ACCEL; // move with acceleration
|
||||
MSG("Start moving\n");
|
||||
return STPS_ALLOK;
|
||||
}
|
||||
|
||||
// change ARR value
|
||||
void stp_chARR(uint32_t val){
|
||||
if(val < 2) val = 2;
|
||||
if(val < TIM15ARRMIN) val = TIM15ARRMIN;
|
||||
else if(val > 0xffff) val = 0xffff;
|
||||
TIMx->ARR = (uint32_t)val;
|
||||
}
|
||||
|
||||
@ -292,51 +354,67 @@ void stp_stop(){ // stop motor by demand or @ end-switch
|
||||
void timer_isr(){
|
||||
static uint16_t ustep = 0;
|
||||
uint16_t tmp, arrval;
|
||||
if(USTEPS == ++ustep){ // prevent stop @ not full step
|
||||
TIMx->SR = 0;
|
||||
if(the_conf.microsteps == ++ustep){ // prevent stop @ not full step
|
||||
ustep = 0;
|
||||
if(state == STP_STOPZERO)
|
||||
if(state == STP_STOPZERO){
|
||||
MSG("Stop @zero\n");
|
||||
mot_position = 0;
|
||||
else{
|
||||
if(0 == --steps_left) state = STP_STOP;
|
||||
}else{
|
||||
if(0 == --steps_left){
|
||||
MSG("End moving\n");
|
||||
state = STP_STOP;
|
||||
}
|
||||
mot_position += dir;
|
||||
}
|
||||
//SEND("Left ");printu(steps_left); newline(); sendbuf();
|
||||
}else return;
|
||||
//SEND("state="); printu(state); newline(); sendbuf();
|
||||
switch(state){
|
||||
case STP_ACCEL: // acceleration phase
|
||||
//SEND("ACC"); newline(); sendbuf();
|
||||
arrval = (uint16_t)TIMx->ARR - stpsteparr;
|
||||
tmp = stplowarr;
|
||||
if(arrval <= tmp || arrval > stphigharr){
|
||||
arrval = tmp;
|
||||
state = STP_MOVE; // end of acceleration phase
|
||||
MSG("Accel end\n");
|
||||
}
|
||||
TIMx->ARR = arrval;
|
||||
break;
|
||||
case STP_DECEL: // deceleration phase
|
||||
//SEND("DEC"); newline(); sendbuf();
|
||||
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
|
||||
MSG("Decel end\n");
|
||||
}
|
||||
TIMx->ARR = arrval;
|
||||
break;
|
||||
case STP_MOVE: // moving with constant speed phases
|
||||
if(steps_left <= ACCDECSTEPS){
|
||||
//SEND("MOVE"); newline(); sendbuf();
|
||||
if(steps_left <= the_conf.accdecsteps){
|
||||
MSG("Decel start\n");
|
||||
state = STP_DECEL; // change moving status to decelerate
|
||||
}
|
||||
break;
|
||||
case STP_MVSLOW:
|
||||
//SEND("MVSLOW"); newline(); sendbuf();
|
||||
// nothing to do here: all done before switch()
|
||||
break;
|
||||
default: // STP_STOP, STP_STOPZERO
|
||||
//SEND("DEFAULT"); newline(); sendbuf();
|
||||
ustep = 0;
|
||||
TIMx->CCMR1 = TIM_CCMR1_OC1M_2; // Force inactive
|
||||
TIMx->CCMR1 = TIM_CCMR1_OC2M_2; // Force inactive
|
||||
TIMx->CR1 &= ~TIM_CR1_CEN; // stop timer
|
||||
DRV_DISABLE();
|
||||
CLEAR_DIR();
|
||||
dir = 0;
|
||||
steps_left = 0;
|
||||
state = STP_SLEEP;
|
||||
MSG("Stop motor\n");
|
||||
break;
|
||||
}
|
||||
TIMx->SR = 0;
|
||||
}
|
||||
|
||||
@ -21,10 +21,20 @@
|
||||
|
||||
#include <stm32f0.h>
|
||||
|
||||
// the lowest speed equal to [max speed] / LOWEST_SPEED_DIV
|
||||
#define LOWEST_SPEED_DIV 30
|
||||
// TIM15->PSC for 4MHz (48MHz/(PSC+1))
|
||||
#define TIM15PSC 47
|
||||
// TIM15->CCR2: 20us for pulse duration, according to datasheet 1.9us is enough
|
||||
#define TIM15CCR2 20
|
||||
// TIM15->ARR minimum value
|
||||
#define TIM15ARRMIN (2*TIM15CCR2)
|
||||
// timer settings give DEFTICKSPERSEC ticks per second
|
||||
#define DEFTICKSPERSEC (48000000/(TIM15PSC+1))
|
||||
// max speed (steps per second)
|
||||
#define MAX_SPEED 10000
|
||||
// The lowest speed @acceleration (= current speed / LOW_SPEED_DIVISOR)
|
||||
#define LOW_SPEED_DIVISOR 30
|
||||
// min/max value of ACCDECSTEPS
|
||||
#define ACCDECSTEPS_MIN 30
|
||||
#define ACCDECSTEPS_MIN 1
|
||||
#define ACCDECSTEPS_MAX 2000
|
||||
|
||||
typedef enum{
|
||||
@ -59,14 +69,18 @@ typedef enum{
|
||||
} stp_status;
|
||||
|
||||
extern int32_t mot_position;
|
||||
#define stppos() (mot_position)
|
||||
extern uint32_t steps_left;
|
||||
#define stpleft() (steps_left)
|
||||
extern stp_state state;
|
||||
#define stp_getstate() (state)
|
||||
#define stpstate() (state)
|
||||
|
||||
drv_type initDriver();
|
||||
drv_type getDrvType();
|
||||
uint16_t getMaxUsteps();
|
||||
|
||||
const char *stp_getstate();
|
||||
const char *stp_getdrvtype();
|
||||
void stp_chspd();
|
||||
stp_status stp_move(int32_t steps);
|
||||
void stp_stop();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user