beta-version, tested @ breadbord

This commit is contained in:
eddyem 2017-12-14 15:19:08 +03:00
parent 025d323135
commit 23396af35b
12 changed files with 456 additions and 119 deletions

View File

@ -9,18 +9,129 @@ Based on STM32F030F4P6
|:---|:----:|:------------------------| |:---|:----:|:------------------------|
|PA0 | AIN | Steppers current | |PA0 | AIN | Steppers current |
|PA1 | AIN | Input voltage 12V | |PA1 | AIN | Input voltage 12V |
|PA2 | AIN | EndSwitch2 of motor1 | |PA2 | AIN | EndSwitch1 of motor0 |
|PA3 | AIN | EndSwitch1 of motor1 | |PA3 | AIN | EndSwitch0 of motor0 |
|PA4 | PUPD | Tim14Ch1 - motor1 steps | |PA4 | PUPD | Tim14Ch1 - motor0 steps |
|PA5 | PUPD | Motor2 enable | |PA5 | PUPD | Motor1 enable |
|PA6 | PUPD | Tim3Ch1 - motor2 steps | |PA6 | PUPD | Tim3Ch1 - motor1 steps |
|PA7 | PUPD | Motor2 direction | |PA7 | PUPD | Motor1 direction |
|PA9 | OD | USART1 Tx | |PA9 | OD | USART1 Tx |
|PA10| FIN | USART1 Rx | |PA10| FIN | USART1 Rx |
|PA13| AIN | EndSwitch1 of motor2 | |PA13| FIN | EndSwitch0 of motor1 |
|PA14| AIN | EndSwitch2 of motor2 | |PA14| FIN | EndSwitch1 of motor1 |
|PB1 | PUPD | Turn off motors' power | |PB1 | PUPD | Turn off current sensor |
|PF0 | PUPD | Motor1 enable | |PF0 | PUPD | Motor0 enable |
|PF1 | PUPD | Motor1 direction | |PF1 | PUPD | Motor0 direction |
## Protocol ## Protocol
Any command have format "# CMD", where # is device ID (the_conf.devID) or "-1" if there's
only one device at the bus. After it can be any number of spaces and command symbols.
### First symbol of commands
* (nothing except spaces) - *ping* command, device with given ID answers: `ALIVE`
* **G** - one of the *Getters* (depending on next text)
* **S** - one of the *Setters*
* **R** - make *MCU software reboot* (next `status` getter will return `SOFTRESET=1`)
* **W** - *write flash* command, use it to save new configuration data
All wrong commands will return `BADCMD`, commands with bad format or wrong number return `ERR`.
Commands with lot of output ends with `DATAEND`. Some commands (like flash write) will return
just `ALL OK` if succeed.
### Getters
Getters returning more than one field ends with `DATAEND` meaning that's all data.
* **A** - get *ADC value*
* **D** - Vdd value (*100 Volts), e.g. `VDD=330`
* **I** - total motors' current (*100 Amperes), e.g. `IMOT=123`
* **M** - motor's voltage (*100 Volts), e.g. `VMOT=1193`
* **C** - get *current configuration*, e.g.
```
CONFSZ=36
DEVID=0
V12NUM=1
V12DEN=10
I12NUM=1
I12DEN=1
V33NUM=1
V33DEN=1
ESWTHR=150
MOT0SPD=60
MOT1SPD=60
USARTSPD=115200
REVERSE0=0
REVERSE1=0
MAXSTEPS0=0
MAXSTEPS1=0
DATAEND
```
All variables here are fields of `user_conf` struct.
* **R** - get *raw ADC* values, e.g.
```
ADC[0]=1991
ADC[1]=124
ADC[2]=1351
ADC[3]=1909
ADC[4]=0
ADC[5]=0
ADC[6]=1707
ADC[7]=1531
DATAEND
```
* **S** - get *motors' status*, e.g.
```
SOFTRESET=1
MOTOR0=STOP
POS0=-1
ESW00=ERR
ESW01=BTN
MOTOR1=STOPPOS1=-1
ESW10=HALL
ESW11=HALL
```
* **T** - get *MCU temperature*, e.g. `TEMP=365`
### Setters
Change of any setter takes place in MCU RAM immediately. To store them permanently run
*write flash* command.
* **C#num** - set current *speed* to *num* for motor #
* **D num** - set *denominator* to number *num*
* **E num** - set *numerator*
* **I num** - set *device ID*
* **M#num** - set maxsteps (*num* is 1..65535) for motor `#`
* **R#num** - set reverse for motor # (*num* == 0 turns reverse off, *num* == 1 turns it on)
* **S#num** - set *speed* (`motspd`) to *num* for motor #
* **T num** - set *end-switches threshold* (in ADU, near 0 for Hall switch, 2048 for user button
and 4096 for released state)
* **U num** - set *USART speed* to *num* bits per second
### Motor speed setters
To set motor speed to **N** steps per second, give command `C` or `S` with argument equal to
3000/N. E.g. to set current speed for DevID=0, motor0 to 50 steps per second give command `0SC050`.
### Denominator and numerator setters
Have naxt letter similar to ADC getter (**D** - Vdd, **I** - motors' I, or **M** - motors' U).
The value of numerator shouldn't be very large as uint32_t used in multiplications.
### Device ID setter
After this command device will immediately change it's ID, if you "lost" device after this
procedure you should reboot it or (if there's only one device on the bus) call it by "universal ID"
(-1).
### USART speed setter
The USART speed will be changed after next reset (e.g. by *MCU software reboot* command), so it
don't work without storing in the flash. Check it twice before writing as wrong numbers can make device
lost until next re-flashing.

View File

@ -36,10 +36,8 @@ static uint32_t VddValue = 0; // value of Vdd * 100 (for more precision measurem
* 1 - Input voltage 12V * 1 - Input voltage 12V
* 2 - EndSwitch2 of motor1 * 2 - EndSwitch2 of motor1
* 3 - EndSwitch1 of motor1 * 3 - EndSwitch1 of motor1
* 4 - EndSwitch1 of motor2 * 4 - inner temperature
* 5 - EndSwitch2 of motor2 * 5 - vref
* 6 - inner temperature
* 7 - vref
*/ */
uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS]; uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS];
@ -67,14 +65,13 @@ void adc_setup(){
}while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* (2) */; }while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* (2) */;
/* (1) Select HSI14 by writing 00 in CKMODE (reset value) */ /* (1) Select HSI14 by writing 00 in CKMODE (reset value) */
/* (2) Select the continuous mode */ /* (2) Select the continuous mode */
/* (3) Select CHSEL0..3, 13,14, 16,17 */ /* (3) Select CHSEL0..3, 16,17 */
/* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us */ /* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us */
/* (5) Wake-up the VREFINT and Temperature sensor (only for VBAT, Temp sensor and VRefInt) */ /* (5) Wake-up the VREFINT and Temperature sensor (only for VBAT, Temp sensor and VRefInt) */
// ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */ // ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */
ADC1->CFGR1 |= ADC_CFGR1_CONT; /* (2)*/ ADC1->CFGR1 |= ADC_CFGR1_CONT; /* (2)*/
ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL2 | ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL2 |
ADC_CHSELR_CHSEL3 | ADC_CHSELR_CHSEL13 | ADC_CHSELR_CHSEL14 | ADC_CHSELR_CHSEL3 | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL17; /* (3)*/
ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL17; /* (3)*/
ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* (4) */ ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* (4) */
ADC->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN; /* (5) */ ADC->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN; /* (5) */
// DMA for AIN // DMA for AIN
@ -99,7 +96,8 @@ void adc_setup(){
int32_t getTemp(){ int32_t getTemp(){
CHKVDDTIME(); CHKVDDTIME();
// make correction on Vdd value // make correction on Vdd value
int32_t temperature = (int32_t)ADC_array[6] * VddValue / 330; int32_t temperature = (int32_t)ADC_array[4] * VddValue / 330;
/*
write2trbuf("getTemp()\ncal30="); write2trbuf("getTemp()\ncal30=");
put_uint(*TEMP30_CAL_ADDR); put_uint(*TEMP30_CAL_ADDR);
write2trbuf(", cal110="); write2trbuf(", cal110=");
@ -107,72 +105,87 @@ put_uint(*TEMP110_CAL_ADDR);
write2trbuf(", t="); write2trbuf(", t=");
put_int(temperature); put_int(temperature);
SENDBUF(); SENDBUF();
*/
temperature = (int32_t) *TEMP30_CAL_ADDR - temperature; temperature = (int32_t) *TEMP30_CAL_ADDR - temperature;
/*
put_int(temperature); put_int(temperature);
SENDBUF(); SENDBUF();
*/
temperature *= (int32_t)(1100 - 300); temperature *= (int32_t)(1100 - 300);
/*
put_int(temperature); put_int(temperature);
SENDBUF(); SENDBUF();
*/
temperature = temperature / (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR); temperature = temperature / (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR);
/*
put_int(temperature); put_int(temperature);
SENDBUF(); SENDBUF();
*/
temperature += 300; temperature += 300;
return(temperature); return(temperature);
} }
//static uint32_t calval = 0; // return Vdd * 100 (V)
// return Vdd * 10 (V)
uint32_t getVdd(){ uint32_t getVdd(){
#define ARRSZ (10) #define ARRSZ (10)
static uint16_t arr[ARRSZ] = {0}; static uint16_t arr[ARRSZ] = {0};
static int arridx = 0; static int arridx = 0;
uint32_t v = ADC_array[7]; uint32_t v = ADC_array[5];
int i; int i;
/*
write2trbuf("getVdd(), val="); write2trbuf("getVdd(), val=");
put_uint(v); put_uint(v);
write2trbuf(", cal="); write2trbuf(", cal=");
put_uint(*VREFINT_CAL_ADDR); put_uint(*VREFINT_CAL_ADDR);
SENDBUF(); SENDBUF();
*/
if(arr[0] == 0){ // first run - fill all with current data if(arr[0] == 0){ // first run - fill all with current data
/*
write2trbuf("1st run"); write2trbuf("1st run");
SENDBUF(); SENDBUF();
*/
for(i = 0; i < ARRSZ; ++i) arr[i] = (uint16_t) v; for(i = 0; i < ARRSZ; ++i) arr[i] = (uint16_t) v;
}else{ }else{
/*
write2trbuf("arridx="); write2trbuf("arridx=");
put_int(arridx); put_int(arridx);
SENDBUF(); SENDBUF();
*/
arr[arridx++] = v; arr[arridx++] = v;
v = 0; // now v is mean v = 0; // now v is mean
if(arridx > ARRSZ-1) arridx = 0; if(arridx > ARRSZ-1) arridx = 0;
// calculate mean // calculate mean
for(i = 0; i < ARRSZ; ++i){ for(i = 0; i < ARRSZ; ++i){
/*
write2trbuf("arr["); put2trbuf('0'+i); write2trbuf("]="); write2trbuf("arr["); put2trbuf('0'+i); write2trbuf("]=");
put_uint(arr[i]); put_uint(arr[i]);
SENDBUF(); SENDBUF();
*/
v += arr[i]; v += arr[i];
} }
v /= ARRSZ; v /= ARRSZ;
/*
write2trbuf("mean value: "); write2trbuf("mean value: ");
put_uint(v); put_uint(v);
SENDBUF(); SENDBUF();
*/
} }
/* if(!calval){
calval = ((uint32_t) *VREFINT_CAL_ADDR) * VDD_CALIB;
calval /= VDD_APPLI;
} */
uint32_t vdd = ((uint32_t) *VREFINT_CAL_ADDR) * (uint32_t)330 * the_conf.v33numerator; // 3.3V uint32_t vdd = ((uint32_t) *VREFINT_CAL_ADDR) * (uint32_t)330 * the_conf.v33numerator; // 3.3V
/*
put_uint(vdd); put_uint(vdd);
SENDBUF(); SENDBUF();
//vdd /= calval * the_conf.v33denominator; */
vdd /= v * the_conf.v33denominator; vdd /= v * the_conf.v33denominator;
/*
put_uint(vdd); put_uint(vdd);
SENDBUF(); SENDBUF();
*/
lastVddtime = Tms; lastVddtime = Tms;
VddValue = vdd; VddValue = vdd;
return vdd/10; return vdd;
} }
// return value of 12V * 10 (V) // return value of 12V * 100 (V)
uint32_t getVmot(){ uint32_t getVmot(){
CHKVDDTIME(); CHKVDDTIME();
uint32_t vmot = ADC_array[1] * VddValue * the_conf.v12numerator; uint32_t vmot = ADC_array[1] * VddValue * the_conf.v12numerator;
@ -195,12 +208,17 @@ uint32_t getImot(){
// @param eswnum - switch number (0,1) // @param eswnum - switch number (0,1)
ESW_status eswStatus(int motnum, int eswnum){ ESW_status eswStatus(int motnum, int eswnum){
int idx; int idx;
if(motnum){ // motor 1 if(motnum){ // motor 1 have no ADC - just 0 or 1
if(eswnum) idx = 5; if(eswnum){ // ESW11 - PA14
else idx = 4; if(GPIOA->IDR & 1<<14) return ESW_RELEASED;
else return ESW_HALL;
}else{ // ESW10 - PA13
if(GPIOA->IDR & 1<<13) return ESW_RELEASED;
else return ESW_HALL;
}
}else{ // motor 0 }else{ // motor 0
if(eswnum) idx = 3; if(eswnum) idx = 2;
else idx = 2; else idx = 3;
} }
uint16_t thres = the_conf.ESW_thres, val = ADC_array[idx]; uint16_t thres = the_conf.ESW_thres, val = ADC_array[idx];
// low sighal: 0..threshold - Hall activated // low sighal: 0..threshold - Hall activated

View File

@ -26,7 +26,7 @@
#define __ADC_H__ #define __ADC_H__
// 8 channels (including inttemp & vrefint) // 8 channels (including inttemp & vrefint)
#define NUMBER_OF_ADC_CHANNELS (8) #define NUMBER_OF_ADC_CHANNELS (6)
extern uint16_t ADC_array[]; extern uint16_t ADC_array[];
void adc_setup(); void adc_setup();

View File

@ -35,15 +35,15 @@ user_conf the_conf = {
.userconf_sz = sizeof(user_conf) .userconf_sz = sizeof(user_conf)
,.devID = 0 ,.devID = 0
,.v12numerator = 1 ,.v12numerator = 1
,.v12denominator = 10 ,.v12denominator = 1
,.i12numerator = 1 ,.i12numerator = 1
,.i12denominator = 1 ,.i12denominator = 1
,.v33denominator = 1 ,.v33denominator = 1
,.v33numerator = 1 ,.v33numerator = 1
,.ESW_thres = 150 ,.ESW_thres = 500
,.usartspd = (uint32_t)115200 ,.usartspd = (uint32_t)115200
,.motspd = {60, 60} // max speed: 3000/60 = 50 steps per second ,.motspd = {10, 10} // max speed: 300 steps per second
,.maxsteps = {0, 0} // max steps from point to point - infinity ,.maxsteps = {50000, 50000} // max steps from point to point
,.reverse = {0,0} // set DIR to this value when moving to '+' ,.reverse = {0,0} // set DIR to this value when moving to '+'
}; };

View File

@ -37,7 +37,7 @@ typedef struct{
uint16_t v33numerator; // 3.3V (vref) uint16_t v33numerator; // 3.3V (vref)
uint16_t v33denominator; uint16_t v33denominator;
uint32_t usartspd; // usartspeed uint32_t usartspd; // usartspeed
uint16_t motspd[2]; // motors speed dividers (3kHz/motxspd per step) uint16_t motspd[2]; // max motor speed ([3000 / motspd] steps per second)
uint16_t maxsteps[2]; // maximum amount of steps for each motor (0 - infinity) uint16_t maxsteps[2]; // maximum amount of steps for each motor (0 - infinity)
uint8_t reverse[2]; // == 1 if positive direction when DIR is low uint8_t reverse[2]; // == 1 if positive direction when DIR is low
} user_conf; } user_conf;

View File

@ -45,15 +45,17 @@ void sys_tick_handler(void){
static void gpio_setup(void){ static void gpio_setup(void){
// Enable clocks to the GPIO subsystems // Enable clocks to the GPIO subsystems
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOFEN; RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOFEN;
// PA0..3, PA13, PA14 - AIN; PA4..7 - PUPD; // prepare levels @ ~EN pins (1 disable drivers)
GPIOA->MODER = GPIO_MODER_MODER0_AI | GPIO_MODER_MODER1_AI | GPIO_MODER_MODER2_AI | stp_disable();
GPIO_MODER_MODER3_AI | GPIO_MODER_MODER13_AI | GPIO_MODER_MODER14_AI | // PA0..3, PA13, PA14 - floating input with pullup; PA5,7 - PUPD; PA4,6 - AF
GPIO_MODER_MODER4_O | GPIO_MODER_MODER5_O | GPIO_MODER_MODER6_O | GPIO_MODER_MODER7_O;
GPIOA->OSPEEDR = 0; // all low speed GPIOA->OSPEEDR = 0; // all low speed
GPIOA->PUPDR = 0; // clear pull-down for PA14&PA13 GPIOA->PUPDR = GPIO_PUPDR_PUPDR13_0 | GPIO_PUPDR_PUPDR14_0;
// PA4 - Tim14Ch1 (AF4), PA6 - Tim3Ch1 (AF1) // PA4 - Tim14Ch1 (AF4), PA6 - Tim3Ch1 (AF1)
GPIOA->AFR[0] = (GPIOA->AFR[0] &~ (GPIO_AFRL_AFRL4 | GPIO_AFRL_AFRL6))\ GPIOA->AFR[0] = (GPIOA->AFR[0] &~ (GPIO_AFRL_AFRL4 | GPIO_AFRL_AFRL6))\
| (4 << (4 * 4)) | (1 << (6 * 4)); | (4 << (4 * 4)) | (1 << (6 * 4));
GPIOA->MODER = GPIO_MODER_MODER0_AI | GPIO_MODER_MODER1_AI | GPIO_MODER_MODER2_AI |
GPIO_MODER_MODER3_AI | GPIO_MODER_MODER4_AF | GPIO_MODER_MODER5_O |
GPIO_MODER_MODER6_AF | GPIO_MODER_MODER7_O;
// PB1 - PUPD // PB1 - PUPD
GPIOB->MODER = GPIO_MODER_MODER1_O; GPIOB->MODER = GPIO_MODER_MODER1_O;
// PF0, PF1 - PUPD // PF0, PF1 - PUPD
@ -102,9 +104,10 @@ int main(void){
while (1){ while (1){
IWDG->KR = IWDG_REFRESH; // refresh watchdog IWDG->KR = IWDG_REFRESH; // refresh watchdog
if(lastT > Tms || Tms - lastT > 499){ if(lastT > Tms || Tms - lastT > 499){
#ifdef EBUG /* #ifdef EBUG
pin_toggle(GPIOA, 1<<4); // blink by onboard LED once per second pin_toggle(GPIOA, 1<<4); // blink by onboard LED once per second
#endif #endif
*/
lastT = Tms; lastT = Tms;
} }
if(usart1rx()){ // usart1 received data, store in in buffer if(usart1rx()){ // usart1 received data, store in in buffer

View File

@ -41,6 +41,7 @@ static const char *err = "ERR";
static char *getnum(char *buf, int32_t *N); static char *getnum(char *buf, int32_t *N);
static char *get_something(char *str); static char *get_something(char *str);
static char *set_something(char *str); static char *set_something(char *str);
static char *motor_cmd(char *str);
static char *get_status(); static char *get_status();
static char *get_conf(); static char *get_conf();
@ -52,7 +53,8 @@ static char *setDenEn(uint8_t De, char *str);
static char *setDevId(char *str); static char *setDevId(char *str);
static char *setESWthres(char *str); static char *setESWthres(char *str);
static char *setUSARTspd(char *str); static char *setUSARTspd(char *str);
static char *setmotvals(char v, char *str);
static char *setMotSpeed(int cur, char *str);
#define omitwsp(str) do{register char nxt; while((nxt = *str)){if(nxt != ' ' && nxt != '\t') break; else ++str;}}while(0) #define omitwsp(str) do{register char nxt; while((nxt = *str)){if(nxt != ' ' && nxt != '\t') break; else ++str;}}while(0)
@ -78,6 +80,9 @@ char* process_command(char *cmdbuf){
case 'G': // get something case 'G': // get something
return get_something(str); return get_something(str);
break; break;
case 'M': // motors' management
return motor_cmd(str);
break;
case 'R': case 'R':
NVIC_SystemReset(); NVIC_SystemReset();
break; break;
@ -147,7 +152,7 @@ static char *get_something(char *str){
case 'S': // get motors' status case 'S': // get motors' status
return get_status(); return get_status();
break; break;
case 'T': case 'T': // get MCU temperature
return get_temper(); return get_temper();
break; break;
} }
@ -158,21 +163,52 @@ static char *get_status(){
int i, j; int i, j;
char str[3] = {0, '=', 0}; char str[3] = {0, '=', 0};
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
write2trbuf("WDGRESET=1"); write2trbuf("WDGRESET=1\n");
} }
if(RCC->CSR & RCC_CSR_SFTRSTF){ // software reset occured if(RCC->CSR & RCC_CSR_SFTRSTF){ // software reset occured
write2trbuf("SOFTRESET=1"); write2trbuf("SOFTRESET=1\n");
} }
RCC->CSR = RCC_CSR_RMVF; // clear reset flags RCC->CSR = RCC_CSR_RMVF; // clear reset flags
for(i = 0; i < 2; ++i){ for(i = 0; i < 2; ++i){
write2trbuf("MOTOR"); str[0] = '0' + i; write2trbuf("MOTOR"); str[0] = '0' + i;
write2trbuf(str); write2trbuf(str);
if(stp_isactive(i)){ stp_state stt = stp_getstate(i);
write2trbuf("MOV\nSTEPSLEFT"); if(STP_SLEEP != stt){
char *s;
switch(stt){
case STP_ACCEL:
s = "ACCEL";
break;
case STP_DECEL:
s = "DECEL";
break;
case STP_MOVE:
s = "MOVE";
break;
case STP_MOVE0:
s = "MOVETO0";
break;
case STP_MOVE1:
s = "MOVETO1";
break;
case STP_MVSLOW:
s = "MVSLOW";
break;
case STP_STOP:
s = "STOP";
break;
case STP_STOPZERO:
s = "STOPZERO";
break;
default:
s = "UNKNOWN";
}
write2trbuf(s);
write2trbuf("\nSTEPSLEFT");
write2trbuf(str); write2trbuf(str);
put_uint(stp_stepsleft(i)); put_uint(stp_stepsleft(i));
}else write2trbuf("STOP"); }else write2trbuf("SLEEP");
write2trbuf("POS"); write2trbuf("\nPOS");
write2trbuf(str); write2trbuf(str);
put_int(stp_position(i)); put_int(stp_position(i));
SENDBUF(); SENDBUF();
@ -218,6 +254,8 @@ static const user_conf_descr descrarr[] = {
{"ESWTHR", &the_conf.ESW_thres}, {"ESWTHR", &the_conf.ESW_thres},
{"MOT0SPD",&the_conf.motspd[0]}, {"MOT0SPD",&the_conf.motspd[0]},
{"MOT1SPD",&the_conf.motspd[1]}, {"MOT1SPD",&the_conf.motspd[1]},
{"MAXSTEPS0",&the_conf.maxsteps[0]},
{"MAXSTEPS1",&the_conf.maxsteps[1]},
{NULL, NULL} {NULL, NULL}
}; };
@ -236,6 +274,7 @@ static char *get_conf(){
put_uint(the_conf.reverse[0]); put_uint(the_conf.reverse[0]);
write2trbuf("\nREVERSE1="); write2trbuf("\nREVERSE1=");
put_uint(the_conf.reverse[1]); put_uint(the_conf.reverse[1]);
SENDBUF();
return EODATA; return EODATA;
} }
@ -284,6 +323,9 @@ static char *get_temper(){
static char *set_something(char *str){ static char *set_something(char *str){
switch(*str++){ switch(*str++){
case 'C': // set current speed
return setMotSpeed(1, str);
break;
case 'D': // set denominator case 'D': // set denominator
return setDenEn(1, str); return setDenEn(1, str);
break; break;
@ -293,6 +335,15 @@ static char *set_something(char *str){
case 'I': // set device ID case 'I': // set device ID
return setDevId(str); return setDevId(str);
break; break;
case 'M': // set maxsteps
setmotvals('M', str);
break;
case 'R': // set reverse
setmotvals('R', str);
break;
case 'S': // set speed
return setMotSpeed(0, str);
break;
case 'T': // set endsw threshold case 'T': // set endsw threshold
return setESWthres(str); return setESWthres(str);
break; break;
@ -347,3 +398,82 @@ static char *setUSARTspd(char *str){
the_conf.usartspd = (uint32_t) N32; the_conf.usartspd = (uint32_t) N32;
return ALLOK; return ALLOK;
} }
// if cur == 1 set current speed else set global motspd
static char *setMotSpeed(int cur, char *str){
omitwsp(str);
uint8_t Num = *str++ - '0';
if(Num > 1) return ERR;
int32_t spd;
omitwsp(str);
if(!getnum(str, &spd)) return ERR;
if(spd < 2 || spd > 6553) return "BadSpd";
if(cur){ // change current speed
stp_chARR(Num, spd);
}else{
the_conf.motspd[Num] = spd;
stp_chspd();
}
return ALLOK;
}
// set other motor values
static char *setmotvals(char v, char *str){
omitwsp(str);
uint8_t Num = *str++ - '0';
if(Num > 1) return ERR;
omitwsp(str);
int32_t val;
if(!getnum(str, &val)) return ERR;
if(val < 0 || val > 0xffff) return "BadUINT16";
switch(v){
case 'M': // maxsteps
if(val == 0) return ERR;
the_conf.maxsteps[Num] = val;
break;
case 'R': // reverse
if(val && val != 1) return ERR;
the_conf.reverse[Num] = val;
break;
default: return ERR;
}
return ALLOK;
}
// process motor command: start/stop
static char *motor_cmd(char *str){
omitwsp(str);
uint8_t Num = *str++ - '0';
int32_t steps;
stp_status st;
if(Num > 1) return "Num>1";
omitwsp(str);
switch(*str++){
case 'M':
omitwsp(str);
if(!getnum(str, &steps)) return "BadSteps";
st = stp_move(Num, steps);
switch(st){
case STPS_ACTIVE:
return "IsMoving";
break;
case STPS_ONESW:
return "OnEndSwitch";
break;
case STPS_ZEROMOVE:
return "ZeroMove";
break;
case STPS_TOOBIG:
return "TooBigNumber";
break;
default:
return ALLOK;
}
break;
case 'S':
stp_stop(Num);
return ALLOK;
break;
}
return ERR;
}

Binary file not shown.

View File

@ -24,6 +24,7 @@
#include "steppers.h" #include "steppers.h"
#include "flash.h" #include "flash.h"
#include "adc.h" #include "adc.h"
#include "usart.h"
// amount of steps need for full acceleration/deceleration cycle // amount of steps need for full acceleration/deceleration cycle
#define ACCDECSTEPS (50) #define ACCDECSTEPS (50)
@ -31,8 +32,8 @@
#define USTEPS (16) #define USTEPS (16)
static GPIO_TypeDef* const MPORT[2] = {GPIOF, GPIOA}; static GPIO_TypeDef* const MPORT[2] = {GPIOF, GPIOA};
static const uint16_t MENPIN[2] = { 0, 1 << 5}; // enable pins: PF0 and PA5 static const uint16_t MENPIN[2] = { 1<<0, 1 << 5}; // enable pins: PF0 and PA5
static const uint16_t MDIRPIN[2] = { 1, 1 << 7}; // direction pins: PF1 and PA7 static const uint16_t MDIRPIN[2] = { 1<<1, 1 << 7}; // direction pins: PF1 and PA7
int32_t mot_position[2] = {-1, -1}; // current position of motor (from zero endswitch, -1 means inactive) int32_t mot_position[2] = {-1, -1}; // current position of motor (from zero endswitch, -1 means inactive)
uint32_t steps_left[2] = {0,0}; // amount of steps left uint32_t steps_left[2] = {0,0}; // amount of steps left
@ -42,35 +43,48 @@ static uint16_t stplowarr[2], stphigharr[2], stpsteparr[2];
static int8_t dir[2] = {0,0}; // moving direction: -1 (negative) or 1 (positive) static int8_t dir[2] = {0,0}; // moving direction: -1 (negative) or 1 (positive)
// return 1 if motor is in active state // return 1 if motor is in active state
int stp_isactive(int motnum){ stp_state stp_getstate(int motnum){
if(state[motnum] == STP_SLEEP) return 0; return state[motnum];
return 1; }
// turn ~EN to 1 for both motors
void stp_disable(){
pin_set(MPORT[0], MENPIN[0]);
pin_set(MPORT[1], MENPIN[1]);
} }
void stp_chspd(){ void stp_chspd(){
int i; int i;
for(i = 0; i < 2; ++i){ for(i = 0; i < 2; ++i){
uint16_t spd = the_conf.motspd[i] << 4; uint16_t spd = the_conf.motspd[i];
if(spd && spd < 6553){
stplowarr[i] = spd; stplowarr[i] = spd;
stphigharr[i] = spd * 10; stphigharr[i] = spd * 10;
stpsteparr[i] = (spd * 9) / ACCDECSTEPS + 1; stpsteparr[i] = (spd * 9) / ACCDECSTEPS + 1;
} }
} }
}
// Tim3_ch1 - PA6, Tim14ch1 - PA4; 48MHz -> 48kHz // Tim3_ch1 - PA6, Tim14ch1 - PA4; 48MHz -> 48kHz
static void timers_setup(){ static void timers_setup(){
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN; // enable clocking RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN; // enable clocking
TIM3->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // PWM mode 1: acive->inactive, preload enable //TIM3->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; // PWM mode 2: inacive->active, preload enable
TIM3->CCMR1 = TIM_CCMR1_OC1M_2; // Force inactive
TIM3->PSC = 999; // 48kHz TIM3->PSC = 999; // 48kHz
TIM3->CCER = TIM_CCER_CC1P | TIM_CCER_CC1E; // turn it on, active low //TIM3->CCER = TIM_CCER_CC1P | TIM_CCER_CC1E; // turn it on, active low
TIM3->DIER = TIM_DIER_UIE; // update interrupt TIM3->CCER = TIM_CCER_CC1E; // turn it on, active high
TIM14->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; TIM3->CCR1 = 1; // 20.8us for pulse duration, according to datasheet 1.9us is enough
TIM3->ARR = 1000; // starting ARR value
//TIM14->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0;
TIM14->CCMR1 = TIM_CCMR1_OC1M_2;
TIM14->PSC = 999; TIM14->PSC = 999;
TIM14->CCER = TIM_CCER_CC1P | TIM_CCER_CC1E; //TIM14->CCER = TIM_CCER_CC1P | TIM_CCER_CC1E;
TIM14->DIER = TIM_DIER_UIE; TIM14->CCER = TIM_CCER_CC1E;
// enable IRQ TIM14->CCR1 = 1;
TIM14->ARR = 1000;
// enable IRQ & update values
TIM3->EGR = TIM_EGR_UG;
TIM14->EGR = TIM_EGR_UG;
TIM3->DIER = TIM_DIER_CC1IE; // allow CC interrupt (we should count steps)
TIM14->DIER = TIM_DIER_CC1IE;
NVIC_EnableIRQ(TIM3_IRQn); NVIC_EnableIRQ(TIM3_IRQn);
NVIC_SetPriority(TIM3_IRQn, 0); NVIC_SetPriority(TIM3_IRQn, 0);
NVIC_EnableIRQ(TIM14_IRQn); NVIC_EnableIRQ(TIM14_IRQn);
@ -79,49 +93,90 @@ static void timers_setup(){
// setup timers // setup timers
void stp_setup(){ void stp_setup(){
timers_setup();
stp_chspd(); stp_chspd();
timers_setup();
} }
// check end-switches for stepper motors // check end-switches for stepper motors
void stp_process(){ void stp_process(){
static uint16_t lastbtnpressed = 0; // anticlash counter static uint16_t lastbtnpressed = 0; // anticlash counter
int i = 0; int i = 0;
for(i = 0; i < 2; ++i){
stp_state curst = state[i];
ESW_status esw[2]; ESW_status esw[2];
// check ESW0 for buttons
esw[0] = eswStatus(0, 0);
esw[1] = eswStatus(0, 1);
if(esw[0] == ESW_BUTTON || esw[1] == ESW_BUTTON){
if(lastbtnpressed++ == 3){ // stop all motors @ button
//~ write2trbuf("1stpress");
//~ SENDBUF();
uint8_t stopped = 0;
if(state[0] != STP_SLEEP){
//~ write2trbuf("stopmot0");
//~ SENDBUF();
state[0] = STP_STOP;
stopped = 1;
}
if(state[1] != STP_SLEEP){
//~ write2trbuf("stopmot1");
//~ SENDBUF();
state[1] = STP_STOP;
stopped = 1;
}
if(stopped) lastbtnpressed = 111; // override value
}else if(lastbtnpressed == 100){ // one or both buttons pressed, run only after ~100ms
//~ write2trbuf("lastbtnpressed");
//~ SENDBUF();
if(esw[0] == ESW_BUTTON && esw[1] == ESW_BUTTON){
//~ write2trbuf("both");
//~ SENDBUF();
// both buttons pressed - move MOTOR1 to zero
state[1] = STP_MOVE0;
}else{ // move motor 0 to 0 or 1
//~ write2trbuf("single");
//~ SENDBUF();
if(esw[0] == ESW_BUTTON) state[0] = STP_MOVE0;
else state[0] = STP_MOVE1;
}
}
}else lastbtnpressed = 0;
for(i = 0; i < 2; ++i){ // check motors' status
stp_state curst = state[i];
esw[0] = eswStatus(i, 0); esw[0] = eswStatus(i, 0);
esw[1] = eswStatus(i, 1); esw[1] = eswStatus(i, 1);
if(esw[0] == ESW_RELEASED && esw[1] == ESW_RELEASED) continue;
uint8_t anybtn = 0; // any button pressed
if(esw[0] == ESW_BUTTON || esw[1] == ESW_BUTTON){
if(lastbtnpressed++ == 0) anybtn = 1;
}else lastbtnpressed = 0;
switch(curst){ switch(curst){
case STP_MOVE0: // move towards zero endswitch case STP_MOVE0: // move towards zero endswitch
state[i] = STP_SLEEP;
stp_move(i, -the_conf.maxsteps[i]); // won't move if the_conf.maxsteps == 0 stp_move(i, -the_conf.maxsteps[i]); // won't move if the_conf.maxsteps == 0
//~ write2trbuf("MOTOR");
//~ put2trbuf('0'+i);
//~ write2trbuf(" move0");
//~ SENDBUF();
break; break;
case STP_MOVE1: case STP_MOVE1:
state[i] = STP_SLEEP;
stp_move(i, the_conf.maxsteps[i]); stp_move(i, the_conf.maxsteps[i]);
//~ write2trbuf("MOTOR");
//~ put2trbuf('0'+i);
//~ write2trbuf(" move1");
//~ SENDBUF();
break; break;
case STP_ACCEL: // @ any move check esw case STP_ACCEL: // @ any move check esw
case STP_DECEL: case STP_DECEL:
case STP_MOVE: case STP_MOVE:
case STP_MVSLOW: case STP_MVSLOW: // check end-switches status
if(anybtn) state[i] = STP_STOP; // stop at the pressing moment if(esw[0] == ESW_HALL && dir[i] == -1){
else{ // check end-switches status
if( (esw[0] == ESW_HALL && dir[i] == -1) ||
(esw[1] == ESW_HALL && dir[i] == 1))
state[i] = STP_STOPZERO; // stop @ end-switch state[i] = STP_STOPZERO; // stop @ end-switch
} //~ write2trbuf("MOTOR");
break; //~ put2trbuf('0'+i);
case STP_SLEEP: //~ write2trbuf(" stop on zero end-switch");
if(lastbtnpressed > 30){ // one or both buttons pressed, run only after ~30ms //~ SENDBUF();
if(esw[0] == ESW_BUTTON && esw[1] == ESW_BUTTON){ }else{ if(esw[1] == ESW_HALL && dir[i] == 1){
// both buttons pressed state[i] = STP_STOP; // stop @ end-switch 1
}else{ //~ write2trbuf("MOTOR");
if(esw[0] == ESW_BUTTON) state[i] = STP_MOVE0; //~ put2trbuf('0'+i);
else state[i] = STP_MOVE1; //~ write2trbuf(" stop on sw1");
//~ SENDBUF();
} }
} }
break; break;
@ -134,7 +189,7 @@ void stp_process(){
// move motor `nmotor` to `steps` steps, @return 0 if all OK // move motor `nmotor` to `steps` steps, @return 0 if all OK
stp_status stp_move(int nmotor, int32_t steps){ stp_status stp_move(int nmotor, int32_t steps){
stp_state st = state[nmotor]; stp_state st = state[nmotor];
if(st != STP_SLEEP || st != STP_MOVE0 || st != STP_MOVE1) return STPS_ACTIVE; if(st != STP_SLEEP && st != STP_MOVE0 && st != STP_MOVE1) return STPS_ACTIVE;
if(steps == 0) if(steps == 0)
return STPS_ZEROMOVE; return STPS_ZEROMOVE;
int8_t d; int8_t d;
@ -149,33 +204,50 @@ stp_status stp_move(int nmotor, int32_t steps){
dir[nmotor] = d; dir[nmotor] = d;
// change value of DIR pin // change value of DIR pin
if(the_conf.reverse[nmotor]){ if(the_conf.reverse[nmotor]){
if(d) if(d>0)
pin_set(MPORT[nmotor], MDIRPIN[nmotor]); pin_set(MPORT[nmotor], MDIRPIN[nmotor]);
else else
pin_clear(MPORT[nmotor], MDIRPIN[nmotor]); pin_clear(MPORT[nmotor], MDIRPIN[nmotor]);
}else{ }else{
if(d) if(d>0)
pin_clear(MPORT[nmotor], MDIRPIN[nmotor]); pin_clear(MPORT[nmotor], MDIRPIN[nmotor]);
else else
pin_set(MPORT[nmotor], MDIRPIN[nmotor]); pin_set(MPORT[nmotor], MDIRPIN[nmotor]);
} }
// turn on EN pin // turn on EN pin (0)
pin_set(MPORT[nmotor], MENPIN[nmotor]); pin_clear(MPORT[nmotor], MENPIN[nmotor]);
steps_left[nmotor] = steps; steps_left[nmotor] = steps;
// setup timer & start it // setup timer & start it
TIM_TypeDef *TIMx = nmotor ? TIM3 : TIM14; TIM_TypeDef *TIMx = nmotor ? TIM3 : TIM14;
TIMx->ARR = stphigharr[nmotor]; // set minimal speed TIMx->ARR = stphigharr[nmotor];
TIMx->CCR1 = stphigharr[nmotor] >> 1; TIMx->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // PWM mode 1: active->inacive, preload enable
TIMx->CR1 |= TIM_CR1_CEN; TIMx->CR1 |= TIM_CR1_CEN;
if(steps < ACCDECSTEPS*2) state[nmotor] = STP_MVSLOW; // move without acceleration if(steps < ACCDECSTEPS*2) state[nmotor] = STP_MVSLOW; // move without acceleration
else state[nmotor] = STP_ACCEL; // move with acceleration else state[nmotor] = STP_ACCEL; // move with acceleration
return STPS_ALLOK; return STPS_ALLOK;
} }
// change ARR and for given stepper
void stp_chARR(int n, int32_t val){
TIM_TypeDef *TIMx = n ? TIM3 : TIM14;
if(val < 2) val = 2;
TIMx->ARR = val;
}
void stp_stop(int n){ // stop motor by demand or @ end-switch void stp_stop(int n){ // stop motor by demand or @ end-switch
if(state[n] == STP_SLEEP) return; switch(state[n]){
case STP_SLEEP:
return;
break;
case STP_MOVE0:
case STP_MOVE1:
state[n] = STP_SLEEP;
break;
default:
state[n] = STP_STOP; state[n] = STP_STOP;
} }
}
// timer interrupt // timer interrupt
static void stpr_int(int n){ static void stpr_int(int n){
@ -184,12 +256,13 @@ static void stpr_int(int n){
uint16_t tmp, arrval; uint16_t tmp, arrval;
if(USTEPS == ++ustep[n]){ // prevent stop @ not full step if(USTEPS == ++ustep[n]){ // prevent stop @ not full step
ustep[n] = 0; ustep[n] = 0;
if(0 == --steps_left[n]) state[n] = STP_STOP;
if(state[n] == STP_STOPZERO) if(state[n] == STP_STOPZERO)
mot_position[n] = 0; mot_position[n] = 0;
else else{
if(0 == --steps_left[n]) state[n] = STP_STOP;
mot_position[n] += dir[n]; mot_position[n] += dir[n];
} }
}else return;
switch(state[n]){ switch(state[n]){
case STP_ACCEL: // acceleration phase case STP_ACCEL: // acceleration phase
arrval = TIMx->ARR - stpsteparr[n]; arrval = TIMx->ARR - stpsteparr[n];
@ -199,7 +272,6 @@ static void stpr_int(int n){
state[n] = STP_MOVE; // end of acceleration phase state[n] = STP_MOVE; // end of acceleration phase
} }
TIMx->ARR = arrval; TIMx->ARR = arrval;
TIMx->CCR1 = arrval >> 1;
break; break;
case STP_DECEL: // deceleration phase case STP_DECEL: // deceleration phase
arrval = TIMx->ARR + stpsteparr[n]; arrval = TIMx->ARR + stpsteparr[n];
@ -209,7 +281,6 @@ static void stpr_int(int n){
state[n] = STP_MVSLOW; // end of deceleration phase, move @ lowest speed state[n] = STP_MVSLOW; // end of deceleration phase, move @ lowest speed
} }
TIMx->ARR = arrval; TIMx->ARR = arrval;
TIMx->CCR1 = arrval >> 1;
break; break;
case STP_MOVE: // moving with constant speed phases case STP_MOVE: // moving with constant speed phases
if(steps_left[n] <= ACCDECSTEPS) state[n] = STP_DECEL; // change moving status to decelerate if(steps_left[n] <= ACCDECSTEPS) state[n] = STP_DECEL; // change moving status to decelerate
@ -219,8 +290,9 @@ static void stpr_int(int n){
break; break;
default: // STP_STOP, STP_STOPZERO default: // STP_STOP, STP_STOPZERO
ustep[n] = 0; ustep[n] = 0;
TIMx->CCMR1 = TIM_CCMR1_OC1M_2; // Force inactive
TIMx->CR1 &= ~TIM_CR1_CEN; // stop timer TIMx->CR1 &= ~TIM_CR1_CEN; // stop timer
pin_clear(MPORT[n], MENPIN[n]); // turn off motor power pin_set(MPORT[n], MENPIN[n]); // turn off motor power
dir[n] = 0; dir[n] = 0;
steps_left[n] = 0; steps_left[n] = 0;
state[n] = STP_SLEEP; state[n] = STP_SLEEP;
@ -228,13 +300,13 @@ static void stpr_int(int n){
} }
} }
// interrupt from stepper 0 timer // interrupt from stepper 1 timer
void tim3_isr(){ void tim3_isr(){
stpr_int(0); stpr_int(1);
TIM3->SR = 0; TIM3->SR = 0;
} }
// interrupt from stepper 1 timer // interrupt from stepper 0 timer
void tim14_isr(){ void tim14_isr(){
stpr_int(1); stpr_int(0);
TIM14->SR = 0; TIM14->SR = 0;
} }

View File

@ -53,11 +53,13 @@ typedef enum{
#define stp_position(n) (mot_position[n]) #define stp_position(n) (mot_position[n])
#define stp_stepsleft(n) (steps_left[n]) #define stp_stepsleft(n) (steps_left[n])
int stp_isactive(int motnum); stp_state stp_getstate(int motnum);
void stp_setup(); void stp_setup();
void stp_chspd(); void stp_chspd();
stp_status stp_move(int nmotor, int32_t steps); stp_status stp_move(int nmotor, int32_t steps);
void stp_stop(int n); void stp_stop(int n);
void stp_process(); void stp_process();
void stp_disable();
void stp_chARR(int n, int32_t val);
#endif // __STEPPERS_H__ #endif // __STEPPERS_H__

View File

@ -1,4 +1,4 @@
update=Пн 27 ноя 2017 21:22:37 update=Вт 12 дек 2017 11:12:17
last_client=kicad last_client=kicad
[pcbnew] [pcbnew]
version=1 version=1

View File

@ -14,6 +14,7 @@ LIBS:texas
LIBS:transistors LIBS:transistors
LIBS:switches LIBS:switches
LIBS:drv8825 LIBS:drv8825
LIBS:a3212lh
LIBS:steppers-cache LIBS:steppers-cache
EELAYER 25 0 EELAYER 25 0
EELAYER END EELAYER END
@ -1154,7 +1155,7 @@ Tim3
Text Notes 6750 1800 0 60 ~ 0 Text Notes 6750 1800 0 60 ~ 0
ADC ADC
Text Notes 6750 2650 0 60 ~ 0 Text Notes 6750 2650 0 60 ~ 0
ADC Floating input
Text Notes 6850 2450 0 60 ~ 0 Text Notes 6850 2450 0 60 ~ 0
UART UART
Text Notes 6700 2100 0 60 ~ 0 Text Notes 6700 2100 0 60 ~ 0
@ -1713,7 +1714,7 @@ Wire Wire Line
9500 5150 9500 5300 9500 5150 9500 5300
Connection ~ 10200 5350 Connection ~ 10200 5350
$Comp $Comp
L LM1117-3.3 U1 L LM1117-3.3-RESCUE-steppers U1
U 1 1 5A2588E7 U 1 1 5A2588E7
P 2750 5100 P 2750 5100
F 0 "U1" H 2600 5225 50 0000 C CNN F 0 "U1" H 2600 5225 50 0000 C CNN