From d8a4c99ec72e5ed043cdf4ffd46f88d805eb6fdc Mon Sep 17 00:00:00 2001 From: eddyem Date: Mon, 27 Jul 2020 20:58:18 +0300 Subject: [PATCH] DRV8825 works, PCB should be rebuild for ability of encoder connection --- F0-nolib/CANbus_stepper/kicad/stm32.sch | 3 +- F0-nolib/CANbus_stepper/kicad/stm32.sch-bak | 4 +- F0-nolib/CANbus_stepper/src/canstepper.bin | Bin 16036 -> 18204 bytes F0-nolib/CANbus_stepper/src/flash.c | 6 +- F0-nolib/CANbus_stepper/src/flash.h | 2 +- F0-nolib/CANbus_stepper/src/hardware.c | 24 +++- F0-nolib/CANbus_stepper/src/hardware.h | 7 +- F0-nolib/CANbus_stepper/src/main.c | 3 +- F0-nolib/CANbus_stepper/src/proto.c | 49 +++++-- F0-nolib/CANbus_stepper/src/spi.c | 112 ++++++++++++++++ F0-nolib/CANbus_stepper/src/spi.h | 38 ++++++ F0-nolib/CANbus_stepper/src/steppers.c | 134 ++++++++++++++++---- F0-nolib/CANbus_stepper/src/steppers.h | 22 +++- 13 files changed, 347 insertions(+), 57 deletions(-) create mode 100644 F0-nolib/CANbus_stepper/src/spi.c create mode 100644 F0-nolib/CANbus_stepper/src/spi.h diff --git a/F0-nolib/CANbus_stepper/kicad/stm32.sch b/F0-nolib/CANbus_stepper/kicad/stm32.sch index 493bf7c..fee8ebb 100644 --- a/F0-nolib/CANbus_stepper/kicad/stm32.sch +++ b/F0-nolib/CANbus_stepper/kicad/stm32.sch @@ -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 diff --git a/F0-nolib/CANbus_stepper/kicad/stm32.sch-bak b/F0-nolib/CANbus_stepper/kicad/stm32.sch-bak index 1b283e8..493bf7c 100644 --- a/F0-nolib/CANbus_stepper/kicad/stm32.sch-bak +++ b/F0-nolib/CANbus_stepper/kicad/stm32.sch-bak @@ -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 diff --git a/F0-nolib/CANbus_stepper/src/canstepper.bin b/F0-nolib/CANbus_stepper/src/canstepper.bin index b2c1abe7c9e30b703aac60bedd0611fbb536b405..0a5b9491e82dfb210ada178ca0fd3350fb13c647 100755 GIT binary patch delta 8731 zcmb_h4Rlk-m7ez`+d{@5EC{x2oF~Z!V;S%-7~6o5j3VpFhG5bVLlVihKmvmmTLcHv zNcroUB%1=SZ5%skl7{Xffi~2Rx9Qo^ux;9q)3lX<^k8UO8IVQWq*bzXWy{Zg`;80< zG~3lv!^?$ z!2gDZ1^>GYwef)NZ^_LiiX{s_@61*Zg?8EZexza9_axy0Tf{DwgjAW1oi7PRvRqan z4O(TJ8TN?^;ahUYd~evo-(k<|Dd@=ySojxBB(x{I&bCg-PFcXOvGvPCo^mO)Xw{UdtaL;msuWuamc%Y6fX}9n*MTj9zV~fpktLZ5uQhcjKrIv{Q679Wdl6?ddM*BCIY#2BX7%PRxlwQAP;v+=l{kU{{UL#@% zL8KKYNrcR#N>-wn3pzG*x24hYTgy6&gAWfm8gtx^^<{3hW~Ey&-Sr_;R_0JMTWu;2 zNv%7_L7o$p_DcE4ZLT<@tFQXI5!d&I;~;g;^wD$Q3+h+2F6g)7E3T zv;I)sGZuTj(b8s-J5)Vcfz$3Z7&z@tHEHpiViJQJENt0n2U~t<-5*0FKcHR9*I6|l zrCHF7$0wpo)1V?Irc+m2^Tx@ z$f7Z+LaZMOOeNCTd34=RL*?!qW^0tme<6As{JoT5@}G;&1@~dXW}&K=9ZdeSST4Fu zbb07f5sppf2VEwbBUvkmLeFepckIBQe=)Y4C?pxGB$kmbaSz(3ffoSP5Z#Ub6N&uf zPOY7w8}hY;-u`kAiK!=aXniXY2A?s(fqx-!dB3dY;s9$foL^w;C%s7H!-*X9d^N#g zcPA3r;147m;IAd-gMU2nGWb6w=7Ilmf^(DD)r1=S-o(rMPoGs^;{vnm9w0Ip%z)`4yU+5j)`FhG_MZp&EC_z&vNq^Ngj>QzJO z##35#i`p%5Pn(S^)6Hr}KtIp6g*}AADmaNw&Hq%ZaRhW{m_Fw+U0+L1bzf^jcbHsg zQRy@-0bM5B+{WmdowBkEkW%m)Wg5(@dGllD<_)Qs!Xx9Vlcy}wY@`XQ4ly!DGD1?q z8xVTo+N}JYtWE7^%GD0<9n-~z(Z+^;YoRH$&awvyq;c=DV&^)V-A|rijm-{?yVJ@V zHJ}e9X|vl4I-6^DT-foL`9h0k=PvrZmFW5$%{!kmH@EJvsY>TS-y^&k7sB56%rHkC8T)Km=sq|uID#2o=3e{n_yyt6H@%$DWWF=Bk;U^ z{qq((Z*Sm>_LoGVn~A+8%JXuAL|^EZ z-Nh8MAz8QIU=K1et7vfNWH;w!b}QMUrNYxHt-su{#ggMDhB+a#rQ9LKOT`*D=@U#p z3W5quj34^}&Y-|pjhhipMrB8t*w%5PmGzR?k?}~Bw`{Z+9BcGy2XD#gRvOL)GYqm2 zZ`lI=mqFgbXss5RKw{61zZbQx`{^)KRp^ju=UJK9+Y>}D6Mn=*h5R{n)>?KtJ-k?> zv7y;Kt?{bREc>j6+3ROFlJIKB;%?N)n0A~g91G5DB>D=6!8>-6=w~#_?PYF`sJ%?= z_=Ip`&L*}Kr+cQ3?U)dXGOIFcB(tS9JJ&H1)#6lPVpqllU*=a-Pe{zFlG4RqjwrQE zEIuVD)f?HFCgDEy8UFx3Xd7(QILf=9JRv6;gcz70PN1nb_yu0FgoGXs>)~HY=v!f? zf^sDEVwf|G4L5;%CCm@sW#B@s-7UFP=5&}TQzvD9l9XvPkl<@!DL#(6CB+j{&+)ye zS>=$RW3)}BoR}%RF*iNq*-K0Td+hM~U8Y{kVd34m1%^*YcIFlb)0U7AnM-WHWFW)L zrTurw2~!!3*1@XlQfqEoHz`gF`GxuO?($z0+5TQrf2cT*1b0TCi*B<@@fA}&QD#v| zE&Ey_xiTQdqf_Q$GW`6A14n<(Jug{Wv2ILojb87)7t-9+1JTxQ7v>=k6@-~e1H9A* zIm7sHdoJ@DhXd{1DMPmfb!Q2@=^VKemFMi{mn>a|%+PwjeL6H7aN;=u!k9pSt- znElJ7C0Y;q$)qW21^sw(b@T~bv-XWJ{p)P^mjSyXtG(be!q ztHvwEe?7_cB2T9BlRDprPR(_l!y_x8b7xX#Uew72{7#) zS(c>RN0uh(eIrZY(6=XvKHnDFPY3^G^lTTS%jGrRk4CAJT^O*`K+f+R$)_5_ts@!? z8tS347e_hk*?<&(l8&a1$0ixwEGPy?cXg8`RiXJKLhQCI|2u0@ENh6uhrMnz62%i$ zMDaY1fB71sxQadwboL@bXmQ=TnkasiM#%A66jL=J59tWms34?v6;ZsEPDmkW0gRK- z@30rSC1b;Ea$WvolKT3GaOV;d91gR6Oc5Er9A>zm*Ry`()B7JctIbb$?N3hV?J(1i zEqvkM!tdDTxSxhv$Ee!D=zh%qI2pRzlA(KavMnk7!nAa#H%wwf2?iUCoH-nB&Qs&E z`fT`3gknxI{tcsQg#UZ|K+?uFk*?YOlcrIH&i@8NLSnCowWDde<4L|>Tt12eReTMx z|D9MedKC1cc$A)eh2+AkVfNtE=#y~FA7*=B<$F#0&oj$N&}bsDu?e=2guWMUAC`fB zJ1oaG`)0Tw`u`@*9PI=BzSsvlQd~PJ#~4=OP=d^5sSOt0TOtY1d(Aw1nIz7}B$D?@w1ZxmmRJP6t-z7*L5Y7_e-K2VF8qJL?$ z6Wm%+rtcel09>so*MEJq1KbL+C$bx~Tzn#8G_n4JOHg>eEV8|KjqbqXLh+%92Q**Y z6LEub;scTGpt<6%2rU^|q9@`4oh!N`ZJ;XA8EFNbDc&2Q<$?r9BKqzU6agEGz=x50 zuNMI+K5xt(QEHoUB3~7;kfF)&X6X526Kf-P+wZpOyPHi-YxPL!=)`oX_$1r}f$&6W zWGY@G%E<<_h9|flDPAWwfpYI6p#5$&c~$+JrohT=-R( z)~CW`ZLk)EHo8q zigHNDFj6iL$JI=vupFpB-;^ZzPgUd2190ebgAzHhwnIJ(GW5c3G|eV+k;eWK{JaSx z73iFaT)zhX8Q@JQJq)yix1u&w(fR<;T0aqdSK9vQ39&`g}?MhtCP*3Ip z^z|YJ+ju!soCgg9SApOfqEWmI<^<3K+<4JqkM&ye1Svb)pM_icRQz2;>Cp+Mf(G~g z33>6yq5H06B1SVNGLz}lHSwh@Q*qv#j6KQKEcvSBlGUh+JFo&g= zMD>pBhMbI?6m?6MExW$SBQrNSv-lSs!;YCAc%< z?)U;c%q6U`1o#bjtfPdxWSF2|hO*p;X92wmJARH^HI$7Kr8;@1JHwi8ZbAi}iQ*>3 zA4sJ0o82gA2^xtVi5bb(IozzVAra;Ei7Qb8`zk~Q_A-(K=AuCd6#{v4{R^<86lS7e zd6_Mzn_lj{chDVpy6)CzRIU(;-l0YIMb=jiFtO@{7Qf#aFR&dnEkD1gaPhFdLB`~0 z3IkgRJ-pPUZy-x^dt+I^2|0Zt&mI`y0;I4gmjR-E zO(&WTG%Xgw>3r%qa2%6-3pfopfVqHo$iKURUOeQ%v>L{+;ylqCya64v(8C|b`+>*i zv46u!-wFC!^xcd>5u`Qid*j=1#~;L|nTns3h_1EqKlT@S_1+W%J4`qome~QRZ;tD` zWrjIt<%YS#DTa&?qq~dmYmwq_O$BrtdAxnJq;S8FruZ@7&!Trh;Va`@_eiwKb`L2z z@Kp0-IQkwB)57*-SZ-(z9xO2GKTbK;VsP7S8tmPRjM{8)s0yob@or6|lAjLT0UK@O zC8$fk8mG(u-Eq|LaaJeS7a0x4-=}dO9MlH5_fmSCq-aU-ppMg?Njc>769XR#;3`8s znu;HkP=lp|dZX@QN*`uk$Y-););=dnA>2D0y>6oA!>9qnEg6?%px)$gdoi4PJfJ_; z@^H;{<1N7`qs!tC7WB2;aDKrp&c71U(6dT8o(3~}l4dr+Ol%BhoQ|4fa6myFa}MAW z5fXoly;2o-L zkQ4uBtIshwVZ0|v@jbzk#`5G#3n^ZGacO;;PT@)SD6|)6q#IeI+MI1l4=#o~Z;Z*g z(detDKVDdb)={|hyC|bCu&KQR`_-n>;6c6WdK9&EH??rQ)|Ttg@|it3Zbo~d}bSO(u_(s&py$8$FA-_J?fnYO|G zbG%umU)&g^<^AX^NNyXGaW6(`RA>a~AyJ1k9zz6juSbd=AT%TL(cgwXe=dH`Lm-d8 z-InFa_Ncp6LurOZ!3F1;8ks?NUZH<)Mz)cu$uctLpQp(`xDBsQTLzf&yr4p#ZpsX1 zPPehc<>e}?8jk0WrG*uEIU#zrHzQfkc}azrDYbV7T1Jx;H%tE+P1UDS=>_qOu~?LP zO1-9D9)&~H`yNn1ygk=XJ7PmWvyg&@Mlw|Hw%Zpt?d$bD)d!gJ{((M|ET|92@#QCW z(#jVEdhx25YG@By8j9RZb&-P<8H088bvA`Nv-=6l#(|bPrGquJ1#^aFhRZ>@p*>XQ zUd@MgU{0G&KuDp>s0)oC0#wyE8JS!6PB}IYOPCmkVOIQ zq5zX$?tYJX-kI$t+$%U~0$PqgfHpRe_F{_v`4+Q9<<0WuT9={X?34~fH88ean$0h8 zm@(VlXga^|K#sc)C1XFn8BN9Sk>qee?e#@d8d7cVN9kf0A&NAtG@5i1RDh@9rlpZ? z2wE!NSw|E{fF}T&R&oozwxpqP1rV&-idn@}3aA2VS>Y*dEwfd4SG!=wX*?iRjPZTp zW9?unZ56Y^zvzB8?|s^VQ!RPA(Jv+tIxRe^zd!pFdP)FeQkdGCw)>7St~aM$Hz;)E z?_o1!!f5^@tWiF=tzZ_TG|F*7k`YcN6CPREa&z+!3t!LMfSynAfxcl8KGXv@q-!x@ zXbdc>PNk1BWP_hBN@Y^3z;BibQ-zmUkV}jAfehYP^h>6Z8v5$ng!uiEM5W#azX{KX zgBUl1jsZp(rPdgHX|p3*GEfJo7dQe0fp#F@GPtiekI_;+Dvx`OB>j2X?rPZhuo%}Y zYE$^ZlKZJ6nx$owG%j78HyO7{Qz&-iV-mJPmH_8qlk#=)!Pl2QCR?3~^`f|%MihSn zt^s3!2%G@u|AY93)(gB090A@0-T_Wm4(=#JSZ`bjtt*7b%AfLY>U@avb#SguXP1lf zI=8zxJ=xao>~b${o#sw-YigA34<2u4A~eK-o-S^EqY~F=1$j6Ns{<5g|HI+`KO5Ej z1DsI7#;3^%`9Gi0M>oyzH{g%n)c)E{d=L0d^RYi+%qa#0K9{$v-L=iPO2}OPR9Zua z&)dGBXD#G<*pm{8mFHsy~zhiS`MRnXwgu1B~?1S%BCda^tqHo zxNXIEm8G-*m6hPH1;Q^^e8MP&x2v**^HuFtO)ej|%h^3W4rJ)GFb^2*^158`)!nhD zy^U*eaoajOc5z8NrLZHkuY3?@F0HH_%&I=Z4F0kvmk~aywfj4}&5d=NHYVd!%=tcR zeS}NMH9!PDua87QNA|ipyQVA6igHw%)^?Y(le=R>{d#U8*Fgitb-8?dyvbsCt9(@% zT`R#gjK8Nmle~2xLuyzoby4ar`_4ojsSi^v&FOh7B&BMHD~wDY6xVP&)eRCGTMn~ zDA90xwxh7p)^wY?c%yyGyvnLjx4C9lXGd}i(TU&Mzmm>-6K1h%PpjL1eM5XfXa$5C zUE7^LY%H$L(>Z;#z}hXw%1h{>(&TeK#2H;(d%rMPc^N&R(BFyBbUf(Uy`75OWW!HS zvE<6pea<;?fIWz~-7-koisdjeodVbUXW}X}7vO+GpaL)gc3=~*68;L}FE33-0BLL7hei3T2>R{i%jpTZ4!QkVfNq(6c@;H~^pSJz zZu?@0lk1uE@o)6gC7AB-q6=|LbmtY?D@y5F)5*XCWG_Y#j<5Ow{<4UVT9RbM3^)9Q S{$;ui$R<~1L?#4Q=l>U-t(7kT delta 6666 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 Xc&jR8BU<+c`R3f2gbvEmBv 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(){ diff --git a/F0-nolib/CANbus_stepper/src/hardware.h b/F0-nolib/CANbus_stepper/src/hardware.h index bf434d3..ecdc62b 100644 --- a/F0-nolib/CANbus_stepper/src/hardware.h +++ b/F0-nolib/CANbus_stepper/src/hardware.h @@ -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 diff --git a/F0-nolib/CANbus_stepper/src/main.c b/F0-nolib/CANbus_stepper/src/main.c index aced506..e99a1e6 100644 --- a/F0-nolib/CANbus_stepper/src/main.c +++ b/F0-nolib/CANbus_stepper/src/main.c @@ -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(); diff --git a/F0-nolib/CANbus_stepper/src/proto.c b/F0-nolib/CANbus_stepper/src/proto.c index cd5c3ca..c0373f2 100644 --- a/F0-nolib/CANbus_stepper/src/proto.c +++ b/F0-nolib/CANbus_stepper/src/proto.c @@ -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" diff --git a/F0-nolib/CANbus_stepper/src/spi.c b/F0-nolib/CANbus_stepper/src/spi.c new file mode 100644 index 0000000..9dbddf2 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/spi.c @@ -0,0 +1,112 @@ +/* + * This file is part of the Stepper project. + * Copyright 2020 Edward V. Emelianov . + * + * 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 . + */ + +#include "hardware.h" +#include "proto.h" +#include "spi.h" + +#include // 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 = +}*/ diff --git a/F0-nolib/CANbus_stepper/src/spi.h b/F0-nolib/CANbus_stepper/src/spi.h new file mode 100644 index 0000000..f7c39a6 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/spi.h @@ -0,0 +1,38 @@ +/* + * This file is part of the Stepper project. + * Copyright 2020 Edward V. Emelianov . + * + * 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 . + */ + +#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__ diff --git a/F0-nolib/CANbus_stepper/src/steppers.c b/F0-nolib/CANbus_stepper/src/steppers.c index 9a21a29..6e4b597 100644 --- a/F0-nolib/CANbus_stepper/src/steppers.c +++ b/F0-nolib/CANbus_stepper/src/steppers.c @@ -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; } diff --git a/F0-nolib/CANbus_stepper/src/steppers.h b/F0-nolib/CANbus_stepper/src/steppers.h index 9635696..70606e4 100644 --- a/F0-nolib/CANbus_stepper/src/steppers.h +++ b/F0-nolib/CANbus_stepper/src/steppers.h @@ -21,10 +21,20 @@ #include -// 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();