diff --git a/README.md b/README.md index e595a5e120be88a366c659d9ab18b195b278ff42..8f19ef431a186dadd0d554795e6a3095eca9b643 100644 --- a/README.md +++ b/README.md @@ -24,14 +24,8 @@ This stepdriver is part of another project on networked machine control (I am ca A-la [Mechaduino](http://tropical-labs.com/index.php/mechaduino) and many other solutions, this beckons to be mounted on the arse-side of the motor it is responsible for... that way, it looks neat, and we can just glue a magnet on the back of the shaft to read position with our encoder. In the future, I really want to also control NEMA8 and NEMA11 motors (because they're cute as heck) but for the immediate future NEMA17s are OK and I can always use a laser-cut adapter to mount the same board onto a NEMA23. OK, again, simplicity wins, we go for the NEMA17 board, but spec drivers to NEMA23 size. -# Board Design +# Currently -OK, normally I get really longwinded about this. Not today! I drew *this* board after a major revision of another version using the TMC262 and some small P-and-NFET H-Bridges, which were a cool part, but obsoleted for me now that I discovered the TMC2660. Really should have looked harder for that. +Working through firmware setup (and requisite firmware tools / libs for ATSAMD51, will be used on BLDC, etc). Nearly there! - - - - -# Board Fab - -I had this manufactured, and got the solder stencil, so that just left me to place components and reflow. Somewhere along the way I royally screwed up my reflow profile. Next time I fab a set, I'll put an image here, and start the programming folder. + \ No newline at end of file diff --git a/circuit/README.md b/circuit/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e8cf60184b38f6011fcd304bd1a981f624b08d85 --- /dev/null +++ b/circuit/README.md @@ -0,0 +1,13 @@ +# Board Design + +OK, normally I get really longwinded about this. Not today! I drew *this* board after a major revision of another version using the TMC262 and some small P-and-NFET H-Bridges, which were a cool part, but obsoleted for me now that I discovered the TMC2660. Really should have looked harder for that. + + + + + +# Board Fab + +I had this manufactured, and got the solder stencil, so that just left me to place components and reflow. Somewhere along the way I royally screwed up my reflow profile. Next time I fab a set, I'll put an image here, and start the programming folder. + + \ No newline at end of file diff --git a/circuit/mkstepper/eagle.epf b/circuit/mkstepper/eagle.epf index d40b9de98a08535aebf4e8f775e7fb9a4948eef3..1a2929fd56818e5b0012a908c54d95e22901fd21 100644 --- a/circuit/mkstepper/eagle.epf +++ b/circuit/mkstepper/eagle.epf @@ -32,12 +32,6 @@ UsedLibrary="C:/EAGLE 8.3.2/lbr/ltspice/rload.lbr" UsedLibrary="C:/EAGLE 8.3.2/lbr/ltspice/sym.lbr" [Win_1] -Type="Control Panel" -Loc="0 0 1919 1016" -State=1 -Number=0 - -[Win_2] Type="Board Editor" Loc="0 0 1919 1016" State=3 @@ -83,13 +77,13 @@ AddLevel=2 PadsSameType=0 Layer=16 -[Win_3] +[Win_2] Type="Schematic Editor" -Loc="0 0 1919 1016" +Loc="-1928 -8 -9 1008" State=1 Number=1 File="mkstepper.sch" -View="48.0247 158.394 176.435 240.944" +View="37.2579 86.1909 222.169 205.063" WireWidths=" 0.0762 0.1016 0.127 0.15 0.2 0.2032 0.254 0.3048 0.4064 0.508 0.6096 0.8128 1.016 1.27 2.54 0.1524" PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" PadDrills=" 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6" @@ -128,9 +122,15 @@ ArcDirection=0 AddLevel=2 PadsSameType=0 Layer=91 -Views=" 1: 48.0247 158.394 176.435 240.944" +Views=" 1: 37.2579 86.1909 222.169 205.063" Sheet="1" +[Win_3] +Type="Control Panel" +Loc="0 0 1919 1016" +State=1 +Number=0 + [Desktop] Screen="3840 1080" Window="Win_1" diff --git a/embedded/README.md b/embedded/README.md index 7ca92e990067c0d78eb48e58368a93b533405fd7..45fc919af907b6395ee8fb1b3d38a5538dff8031 100644 --- a/embedded/README.md +++ b/embedded/README.md @@ -308,14 +308,26 @@ void uart_txhandler(uartport_t *uart){ Next I'm going to try to get some steps to happen. I guess we're ready for this! -I found [this](https://github.com/trinamic/TMC26XStepper) library. +I found [this](https://github.com/trinamic/TMC26XStepper) library, which will save me from re-writing all of the registers and addresses. Bless. -# the end of this day +SPI commands and responses are all 20-bits long. Each 20-bit command is met with a 20-bit status word. Those 20-bit 'commands' are registers - the first three bits of each word denote the address of which register we are re-writing. This means that we have to keep track of each entire register-state in the microcontroller, or should. -- dinner -- tell anna you can't handle meeting b/c NSF -- setup to be doing NSF only tomorrow -- get whatever you can get done today -- maybe kill / handle: dome ... anything else you feel is 'loose' - - lots of emails - - cleaning up \ No newline at end of file +Most likely, operation will consist of starting up with sending all 5 registers sequentially in the setup config, and then occasionally polling one to get the response (which, it looks like, contains useful things like relative loads!). + +Late on, when I try to make a closed loop stepper with the AS5147, I'll be writing coil currents directly into these registers (I think?) to commutate the motor based on encoder input and a tiny PID loop. That, later - but for now I see that in the DRVCTRL register has two 8-bit words for Current in A and Current in B. Noice. + +Another thing I like is that I can set both step edges to signify a step. Normally, step drivers have a 'minimum on time' and only count the positive edge, so the microcode has to do a tiny wait (normally not long enough to warrant an interrupt-to-turn-off). This way I'll just toggle the step pin whenever I want to step, and I can forget about it. + +So, first I'll try to figure out how to send a 20-bit word with the SPI peripheral, and verify that I get any kind of response from the TMC. + +The ATSAMD51 only allows an 8, 9, or 32 bit word, so 32 it is - I'll just keep the last 12 set to 0 and hope that suffices. + +OK, here's a classic debugging moment: I take ~45 minutes (or was it two hours? would rather not count) trying to get my SPI setup correctly. Nothing returns. Welp. I pull my hair out. I take a break, decide to plug in some motor power, because why not? Of course, now, data returns. Heck. + +To solve that 20-bit word problem, I'm taking over manual control of the chip select pin, issuing 3 8-bit words (which I'll have to bit-splice myself) and then sending those on one CSN low cycle. + +Great, now we unfux the hacked together code, and try to send some data, then some steps, I guess? + +I think I'm actually going to try writing this library from the datasheet. Let's see how that goes. + +Er, how about we just write some values down manually and send those? Sounds good. \ No newline at end of file diff --git a/embedded/mkstepper-v011/.vs/mkstepper-v011/v14/.atsuo b/embedded/mkstepper-v011/.vs/mkstepper-v011/v14/.atsuo index b14b68e3dd1cd02342db41b3d6c09b1e92b2ab3d..c07e4635da7580fbeaa3150c81ae549f11bceb7d 100644 Binary files a/embedded/mkstepper-v011/.vs/mkstepper-v011/v14/.atsuo and b/embedded/mkstepper-v011/.vs/mkstepper-v011/v14/.atsuo differ diff --git a/embedded/mkstepper-v011/mkstepper-v011/Debug/Makefile b/embedded/mkstepper-v011/mkstepper-v011/Debug/Makefile index 7d21dd26e9fed5522a9bceb34794fbf12d185169..dcfb0ff20c80a840272fbda62995bac462a99369 100644 --- a/embedded/mkstepper-v011/mkstepper-v011/Debug/Makefile +++ b/embedded/mkstepper-v011/mkstepper-v011/Debug/Makefile @@ -44,6 +44,7 @@ C_SRCS += \ ../pin.c \ ../ringbuffer.c \ ../spiport.c \ +../tmc2660.c \ ../uartport.c @@ -60,6 +61,7 @@ main.o \ pin.o \ ringbuffer.o \ spiport.o \ +tmc2660.o \ uartport.o OBJS_AS_ARGS += \ @@ -69,6 +71,7 @@ main.o \ pin.o \ ringbuffer.o \ spiport.o \ +tmc2660.o \ uartport.o C_DEPS += \ @@ -78,6 +81,7 @@ main.d \ pin.d \ ringbuffer.d \ spiport.d \ +tmc2660.d \ uartport.d C_DEPS_AS_ARGS += \ @@ -87,6 +91,7 @@ main.d \ pin.d \ ringbuffer.d \ spiport.d \ +tmc2660.d \ uartport.d OUTPUT_FILE_PATH +=mkstepper-v011.elf @@ -120,6 +125,8 @@ LINKER_SCRIPT_DEP+= \ + + Device_Startup/%.o: ../Device_Startup/%.c @echo Building file: $< @echo Invoking: ARM/GNU C Compiler : 6.3.1 diff --git a/embedded/mkstepper-v011/mkstepper-v011/Debug/makedep.mk b/embedded/mkstepper-v011/mkstepper-v011/Debug/makedep.mk index bd15a2469d53d98789bff4058882d0f7bb3b206d..72ec45f8addabeaabf32c2f925395d9b88a919b0 100644 --- a/embedded/mkstepper-v011/mkstepper-v011/Debug/makedep.mk +++ b/embedded/mkstepper-v011/mkstepper-v011/Debug/makedep.mk @@ -14,5 +14,7 @@ ringbuffer.c spiport.c +tmc2660.c + uartport.c diff --git a/embedded/mkstepper-v011/mkstepper-v011/hardware.h b/embedded/mkstepper-v011/mkstepper-v011/hardware.h index ad2481e0014308b57205b60a8d89f920d20738cd..7d369f2ae65c2c1d12704a1c079bb0bb746d8a96 100644 --- a/embedded/mkstepper-v011/mkstepper-v011/hardware.h +++ b/embedded/mkstepper-v011/mkstepper-v011/hardware.h @@ -13,6 +13,7 @@ #include "uartport.h" #include "spiport.h" #include "ringbuffer.h" +#include "tmc2660.h" pin_t stlr; pin_t stlb; @@ -27,4 +28,11 @@ uartport_t up2; spiport_t spi_tmc; +pin_t step_pin; +pin_t dir_pin; +pin_t en_pin; +pin_t sg_pin; + +tmc2260_t tmc; + #endif /* HARDWARE_H_ */ \ No newline at end of file diff --git a/embedded/mkstepper-v011/mkstepper-v011/main.c b/embedded/mkstepper-v011/mkstepper-v011/main.c index c68636a84cc8906fb0da2de391f466458b1702fc..6e4553574414df6005e1d68164738cf072904471 100644 --- a/embedded/mkstepper-v011/mkstepper-v011/main.c +++ b/embedded/mkstepper-v011/mkstepper-v011/main.c @@ -125,13 +125,29 @@ int main(void) // spi spi_tmc = spi_new(SERCOM0, &PORT->Group[0], 4, 7, 5, 6, HARDWARE_IS_APBA, HARDWARE_ON_PERIPHERAL_D); MCLK->APBAMASK.reg |= MCLK_APBAMASK_SERCOM0; - spi_init(&spi_tmc, 8, SERCOM0_GCLK_ID_CORE, 126, 0, 2); - - // -> DO SPI, talk to the TMC ! - + spi_init(&spi_tmc, 8, SERCOM0_GCLK_ID_CORE, 126, 0, 2, 0, 0, 1, 0); + + // TMC + // STEP PB08 + // DIR PB09 + // EN PB07 + // SG PB06 + + step_pin = pin_new(&PORT->Group[1], 8); + dir_pin = pin_new(&PORT->Group[1], 9); + en_pin = pin_new(&PORT->Group[1], 7); + sg_pin = pin_new(&PORT->Group[1], 6); + + tmc = tmc2660_new(&spi_tmc, &step_pin, &dir_pin, &en_pin, &sg_pin); + tmc2660_init(&tmc); + while (1) { - // spi_txchar_polled(&spitmc, 'x'); + tmc2660_init(&tmc); + // delay + for(int i=0; i < 500; i++){ + pin_toggle(&stlr); + } // find TMC registers now, try to read! } diff --git a/embedded/mkstepper-v011/mkstepper-v011/mkstepper-v011.cproj b/embedded/mkstepper-v011/mkstepper-v011/mkstepper-v011.cproj index 0f4e9d1b7a328cf1558fde1d1588409ef956d570..1c7366ff6e0a0fcd327d5e89c4cd2337c5b4f89c 100644 --- a/embedded/mkstepper-v011/mkstepper-v011/mkstepper-v011.cproj +++ b/embedded/mkstepper-v011/mkstepper-v011/mkstepper-v011.cproj @@ -190,6 +190,12 @@ <Compile Include="spiport.h"> <SubType>compile</SubType> </Compile> + <Compile Include="tmc2660.c"> + <SubType>compile</SubType> + </Compile> + <Compile Include="tmc2660.h"> + <SubType>compile</SubType> + </Compile> <Compile Include="uartport.c"> <SubType>compile</SubType> </Compile> diff --git a/embedded/mkstepper-v011/mkstepper-v011/spiport.c b/embedded/mkstepper-v011/mkstepper-v011/spiport.c index 8fe8b5615f2cc94ccaeb6af2793ee4b98a2f1078..a291180c545e9da0050870125a457b844b669cd6 100644 --- a/embedded/mkstepper-v011/mkstepper-v011/spiport.c +++ b/embedded/mkstepper-v011/mkstepper-v011/spiport.c @@ -28,7 +28,8 @@ spiport_t spi_new(Sercom *com, PortGroup *port, uint32_t miso_pin, uint32_t mosi return spi; } -void spi_init(spiport_t *spi, uint32_t gclknum, uint32_t gclkidcore, uint8_t baud, uint32_t dipo, uint32_t dopo){ +void spi_init(spiport_t *spi, uint32_t gclknum, uint32_t gclkidcore, uint8_t baud, uint8_t dipo, uint8_t dopo, uint8_t csnhardware, uint8_t cpha, uint8_t cpol, uint8_t lsbfirst){ + // to add to this lib: doc, cleaning, options properly enumerated: do when doing AS5147 // clk is unmasked (external to this lib) // do pin configs spi->port->DIRCLR.reg |= spi->miso_bm; @@ -36,7 +37,17 @@ void spi_init(spiport_t *spi, uint32_t gclknum, uint32_t gclkidcore, uint8_t bau spi->port->DIRSET.reg |= spi->mosi_bm | spi->sck_bm | spi->csn_bm; spi->port->PINCFG[spi->mosi_pin].bit.PMUXEN = 1; spi->port->PINCFG[spi->sck_pin].bit.PMUXEN = 1; - spi->port->PINCFG[spi->csn_pin].bit.PMUXEN = 1; + + if(csnhardware){ + spi->port->PINCFG[spi->csn_pin].bit.PMUXEN = 1; + if(spi->csn_pin % 2){ // yes if odd + spi->port->PMUX[spi->csn_pin >> 1].reg |= PORT_PMUX_PMUXO(spi->peripheral); + } else { + spi->port->PMUX[spi->csn_pin >> 1].reg |= PORT_PMUX_PMUXE(spi->peripheral); + } + }else{ + spi->port->OUTSET.reg = spi->csn_bm; // set hi to start! - this should properly depend on our CPHA ! + } if(spi->miso_pin % 2){ // yes if odd spi->port->PMUX[spi->miso_pin >> 1].reg |= PORT_PMUX_PMUXO(spi->peripheral); @@ -56,31 +67,39 @@ void spi_init(spiport_t *spi, uint32_t gclknum, uint32_t gclkidcore, uint8_t bau spi->port->PMUX[spi->sck_pin >> 1].reg |= PORT_PMUX_PMUXE(spi->peripheral); } - if(spi->csn_pin % 2){ // yes if odd - spi->port->PMUX[spi->csn_pin >> 1].reg |= PORT_PMUX_PMUXO(spi->peripheral); - } else { - spi->port->PMUX[spi->csn_pin >> 1].reg |= PORT_PMUX_PMUXE(spi->peripheral); - } - // build a clock for GCLK->GENCTRL[gclknum].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL) | GCLK_GENCTRL_GENEN; while(GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL(gclknum)); GCLK->PCHCTRL[gclkidcore].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclknum); // now some SERCOM + // tmc spi is clock inactive hi + // tmc spi latches data on the rising edge of sck and drives data out on the next falling edge spi->com->SPI.CTRLA.bit.ENABLE = 0; // master, data in pinout, data out pinout spi->com->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_MODE(0x03); - //SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_CPHA | SERCOM_SPI_CTRLA_CPOL; + if(cpol){ + spi->com->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_CPOL; + } + if(cpha){ + spi->com->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_CPHA; + } + if(lsbfirst){ + SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_DORD; // 0 MSB, 1 LSB + } spi->com->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_DIPO(dipo) | SERCOM_SPI_CTRLA_DOPO(dopo); // these to defaults, but here for show - //SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_DORD; // 0 MSB, 1 LSB //SERCOM0->SPI.CTRLB.reg |= SERCOM_SPI_CTRLB_CHSIZE(0x0); // 8 bits character - 0x0, so no need to set // BAUD // f_baud = f_ref / (2 * (BAUD +1)) so BAUD = f_ref / (2 * f_baud) - 1 spi->com->SPI.BAUD.reg |= SERCOM_SPI_BAUD_BAUD(baud); // use hardware slave select, enable receiver - spi->com->SPI.CTRLB.reg |= SERCOM_SPI_CTRLB_MSSEN | SERCOM_SPI_CTRLB_RXEN; + spi->com->SPI.CTRLB.reg |= SERCOM_SPI_CTRLB_RXEN; //SERCOM_SPI_CTRLB_MSSEN | + // 8 or 32 bits + // do if(bits) + //spi->com->SPI.CTRLC.reg |= SERCOM_SPI_CTRLC_DATA32B; + //spi->com->SPI.LENGTH.reg |= SERCOM_SPI_LENGTH_LENEN | SERCOM_SPI_LENGTH_LEN(20); + // turnt it up spi->com->SPI.CTRLA.bit.ENABLE = 1; } @@ -90,6 +109,15 @@ void spi_txchar_polled(spiport_t *spi, uint8_t data){ spi->com->SPI.DATA.reg = SERCOM_SPI_DATA_DATA(data); } +void spi_txchars_polled(spiport_t *spi, uint8_t *data, uint8_t length){ + spi->port->OUTCLR.reg = spi->csn_bm; + for(int i = 0; i < length; i ++){ + spi_txchar_polled(spi, data[0]); + } + while(!spi->com->SPI.INTFLAG.bit.TXC); // wait for complete before + spi->port->OUTSET.reg = spi->csn_bm; +} + void spi_txrxchar_polled(spiport_t *spi, uint8_t data, uint8_t *rxdata){ // how to read? } \ No newline at end of file diff --git a/embedded/mkstepper-v011/mkstepper-v011/spiport.h b/embedded/mkstepper-v011/mkstepper-v011/spiport.h index c433d455c67762125889c83fa82d3700d0326642..d4ac77554e0a8ff4121a40302dde67619c4cae83 100644 --- a/embedded/mkstepper-v011/mkstepper-v011/spiport.h +++ b/embedded/mkstepper-v011/mkstepper-v011/spiport.h @@ -31,8 +31,10 @@ typedef struct{ spiport_t spi_new(Sercom *com, PortGroup *port, uint32_t miso_pin, uint32_t mosi_pin, uint32_t sck_pin, uint32_t csn_pin, uint32_t apbx, uint32_t peripheral); -void spi_init(spiport_t *spi, uint32_t gclknum, uint32_t gclkidcore, uint8_t baud, uint32_t dipo, uint32_t dopo); +void spi_init(spiport_t *spi, uint32_t gclknum, uint32_t gclkidcore, uint8_t baud, uint8_t dipo, uint8_t dopo, uint8_t csnhardware, uint8_t cpha, uint8_t cpol, uint8_t lsbfirst); // bits: 0: 8, 1: 32 + void spi_txchar_polled(spiport_t *spi, uint8_t data); +void spi_txchars_polled(spiport_t *spi, uint8_t *data, uint8_t length); void spi_txrxchar_polled(spiport_t *spi, uint8_t data, uint8_t *rxdata); #endif /* SPIPORT_H_ */ \ No newline at end of file diff --git a/embedded/mkstepper-v011/mkstepper-v011/tmc2660.c b/embedded/mkstepper-v011/mkstepper-v011/tmc2660.c new file mode 100644 index 0000000000000000000000000000000000000000..5a883f02a1eb32f721e91ca0c9b99ea2530283f5 --- /dev/null +++ b/embedded/mkstepper-v011/mkstepper-v011/tmc2660.c @@ -0,0 +1,29 @@ +/* + * tmc2660.c + * + * Created: 2/7/2018 10:17:39 PM + * Author: Jake + */ + +#include "tmc2660.h" + +tmc2260_t tmc2660_new(spiport_t *spi, pin_t *step, pin_t *dir, pin_t *en, pin_t *sg){ + tmc2260_t tmc; + + tmc.spi = spi; + tmc.step_pin = step; + tmc.dir_pin = dir; + tmc.en_pin = en; + tmc.sg_pin = sg; + + return tmc; +} + +void tmc2660_init(tmc2260_t *tmc){ + // lots + // pins are also init externally + // spi is init externally, godbless + uint8_t data[3] = {8, 9, 10}; + spi_txchars_polled(tmc->spi, data, 3); +} + diff --git a/embedded/mkstepper-v011/mkstepper-v011/tmc2660.h b/embedded/mkstepper-v011/mkstepper-v011/tmc2660.h new file mode 100644 index 0000000000000000000000000000000000000000..0025e10c66ea2e5192957959dac0f129456b4e7a --- /dev/null +++ b/embedded/mkstepper-v011/mkstepper-v011/tmc2660.h @@ -0,0 +1,32 @@ +/* + * tmc2660.h + * + * Created: 2/7/2018 10:17:49 PM + * Author: Jake + */ + + +#ifndef TMC2660_H_ +#define TMC2660_H_ + +#include "sam.h" +#include "spiport.h" +#include "pin.h" + +typedef struct{ + spiport_t *spi; + + pin_t *step_pin; + pin_t *dir_pin; + pin_t *en_pin; + + pin_t *sg_pin; +}tmc2260_t; + +tmc2260_t tmc2660_new(spiport_t *spi, pin_t *step, pin_t *dir, pin_t *en, pin_t *sg); + +void tmc2660_init(tmc2260_t *tmc); + +void tmc2660_step_once(tmc2260_t *tmc, uint8_t dir); + +#endif /* TMC2660_H_ */ \ No newline at end of file diff --git a/images/fabbed-v011.jpg b/images/fabbed-v011.jpg new file mode 100644 index 0000000000000000000000000000000000000000..49b1ad4a496e5257accda7833fcbbf29b0459553 Binary files /dev/null and b/images/fabbed-v011.jpg differ