diff --git a/circuit/atkbldcdriver/atkbldcdriver.brd b/circuit/atkbldcdriver/atkbldcdriver.brd index 0d0bc312f6f55da37359d91c53a2169de053e662..fc5a79f4a7a6a09554cd870ee49b04f7885b9c05 100644 --- a/circuit/atkbldcdriver/atkbldcdriver.brd +++ b/circuit/atkbldcdriver/atkbldcdriver.brd @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE eagle SYSTEM "eagle.dtd"> -<eagle version="9.1.1"> +<eagle version="9.0.0"> <drawing> <settings> <setting alwaysvectorfont="no"/> @@ -962,9 +962,6 @@ design rules under a new name.</description> <param name="checkRestrict" value="1"/> <param name="checkStop" value="0"/> <param name="checkValues" value="0"/> -<param name="checkNames" value="1"/> -<param name="checkWireStubs" value="1"/> -<param name="checkPolygonWidth" value="0"/> <param name="useDiameter" value="13"/> <param name="maxErrors" value="50"/> </designrules> @@ -3641,13 +3638,6 @@ design rules under a new name.</description> <wire x1="51.2308" y1="51.1808" x2="50.4" y2="50.35" width="0.1524" layer="1"/> </signal> </signals> -<mfgpreviewcolors> -<mfgpreviewcolor name="soldermaskcolor" color="0xC8008000"/> -<mfgpreviewcolor name="silkscreencolor" color="0xFFFEFEFE"/> -<mfgpreviewcolor name="backgroundcolor" color="0xFF282828"/> -<mfgpreviewcolor name="coppercolor" color="0xFFFFBF00"/> -<mfgpreviewcolor name="substratecolor" color="0xFF786E46"/> -</mfgpreviewcolors> </board> </drawing> <compatibility> diff --git a/circuit/atkbldcdriver/eagle.epf b/circuit/atkbldcdriver/eagle.epf index 5db0460885a3f79be0605e77e152056e237fe0c6..e04a85b1a1c47aa0d45d630c7e4002ff865ab5a2 100644 --- a/circuit/atkbldcdriver/eagle.epf +++ b/circuit/atkbldcdriver/eagle.epf @@ -42,7 +42,7 @@ UsedLibrary="D:/Dropbox (Personal)/CBA/doc/libraries_jake/eagle/sparkfun/SparkFu Type="Board Editor" Number=1 File="atkbldcdriver.brd" -View="46.6255 23.8801 69.1125 42.6084" +View="41.6112 50.1586 52.4556 59.1904" WireWidths=" 0.0762 0.127 0.15 0.508 0.6096 0.8128 2.54 1.016 1.27 0.3048 0.254 0.2 0.4064 0.1016 0.2032 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.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6 0.3" @@ -86,7 +86,7 @@ Layer=1 Type="Schematic Editor" Number=3 File="atkbldcdriver.sch" -View="-280.35 -76.1712 223.851 152.676" +View="-250.34 -67.9039 169.828 122.802" 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" @@ -125,7 +125,7 @@ ArcDirection=0 AddLevel=2 PadsSameType=0 Layer=91 -Views=" 1: -280.35 -76.1712 223.851 152.676" +Views=" 1: -250.34 -67.9039 169.828 122.802" Sheet="1" [Win_3] diff --git a/embedded/README.md b/embedded/README.md index 7b6fd78b28dcbf8098af889cfaf8dd601af4da95..6b77b7762745bac473d5b59a6aee447ef104fd5d 100644 --- a/embedded/README.md +++ b/embedded/README.md @@ -32,4 +32,6 @@ In any case, I'd say it's enough to start trying to cut things, with some more c I know I can do this if I can manage to read my encoder successfully. I could also probably do it with the ADC, but I would want an oscilloscope to go down that path, and I don't have one here. -So, we use a logic analyzer to try reading this AMS5047 \ No newline at end of file +So, we use a logic analyzer to try reading this AMS5047 + +Got this running, feels pretty mediocre. I need to understand commutation a bit better, and do this with a fan setup etc. I perhaps just have not counted my poles properly, but I wamt to do this with an oscilloscope, and understand how we might search for those offsets etc. \ No newline at end of file diff --git a/embedded/atkbldcdriver/atkbldcdriver/ams5047.c b/embedded/atkbldcdriver/atkbldcdriver/ams5047.c index 651c21bb183d85ed85c48811728ead301ae1aa30..c19ebcd2cc73288f76919a5a82733cbc7965abb2 100644 --- a/embedded/atkbldcdriver/atkbldcdriver/ams5047.c +++ b/embedded/atkbldcdriver/atkbldcdriver/ams5047.c @@ -7,34 +7,20 @@ #include "ams5047.h" -void ams5047_init(ams5047_t *ams, spiport_t *spi, pin_t *en, pin_t *sg){ +void ams5047_init(ams5047_t *ams, spiport_t *spi){ ams->spi = spi; - ams->en_pin = en; - ams->sg_pin = sg; + ams5047_readOp = (1 << 15) | (1 << 14) | 0x3FFF; // parity bit, 1 for read / notwrite, 1s for read-op address + ams5047_readBytes[0] = ams5047_readOp >> 8; + ams5047_readBytes[1] = (uint8_t)ams5047_readOp; + ams5047_noOp = (1 << 15); // parity bit, 0's for no-op + ams5047_noOpBytes[0] = ams5047_noOp >> 8; + ams5047_noOpBytes[1] = (uint8_t)ams5047_noOp; } -void ams5047_write(ams5047_t *ams, uint32_t word){ - // ? - uint8_t bytes[3]; - bytes[0] = word >> 16;// | 0b11110000; // top 4 & mask for visibility - bytes[1] = word >> 8; // middle 8 - bytes[2] = word; // last 4 and 0's - spi_txchars_polled(ams->spi, bytes, 3); -} - -void ams5047_start(ams5047_t *ams){ - // -} - -void ams5047_update(ams5047_t *ams){ - uint32_t smarten = 0b10100000000000000000; - ams5047_write(ams, smarten); -} - -void ams5047_enable(ams5047_t *ams){ - pin_clear(ams->en_pin); -} - -void ams5047_disable(ams5047_t *ams){ - pin_set(ams->en_pin); +void ams5047_read(ams5047_t *ams, uint16_t *result){ + // at baud, takes ~ 20us (bauda = 12, baudb = 0) so max 50kHz + spi_txchars_polled(ams->spi, ams5047_readBytes, 2); + // issue noop, read rx'd on this tx (one step back) + spi_txrxchars_polled(ams->spi, ams5047_readBytes, ams5047_resultBytes, 2); + *result = ((ams5047_resultBytes[0] & 0b00111111) << 8) | ams5047_resultBytes[1]; } \ No newline at end of file diff --git a/embedded/atkbldcdriver/atkbldcdriver/ams5047.h b/embedded/atkbldcdriver/atkbldcdriver/ams5047.h index 3b560b2f4bc5511679d94e47a4593958c118dfdb..04c695d302612b8f49b382e4c6ce21097f8d1d73 100644 --- a/embedded/atkbldcdriver/atkbldcdriver/ams5047.h +++ b/embedded/atkbldcdriver/atkbldcdriver/ams5047.h @@ -18,21 +18,17 @@ typedef struct{ spiport_t *spi; - - pin_t *en_pin; - pin_t *sg_pin; }ams5047_t; -void ams5047_init(ams5047_t *ams, spiport_t *spi, pin_t *en, pin_t *sg); +uint16_t ams5047_readOp; +uint16_t ams5047_noOp; +uint8_t ams5047_readBytes[2]; +uint8_t ams5047_noOpBytes[2]; -void ams5047_write(ams5047_t *ams, uint32_t word); +uint8_t ams5047_resultBytes[2]; -void ams5047_start(ams5047_t *ams); +void ams5047_init(ams5047_t *ams, spiport_t *spi); -void ams5047_update(ams5047_t *ams); - -void ams5047_enable(ams5047_t *ams); - -void ams5047_disable(ams5047_t *ams); +void ams5047_read(ams5047_t *ams, uint16_t *result); #endif /* AMS5047_H_ */ \ No newline at end of file diff --git a/embedded/atkbldcdriver/atkbldcdriver/main.c b/embedded/atkbldcdriver/atkbldcdriver/main.c index 2669daf701f7411ecf08257a96b94c6103cf995c..06de01e01aced7d936959b696b037a988df0fb7b 100644 --- a/embedded/atkbldcdriver/atkbldcdriver/main.c +++ b/embedded/atkbldcdriver/atkbldcdriver/main.c @@ -43,9 +43,12 @@ void atkps_init(void){ } void encoder_init(void){ + // startup SPI pin_init(&spiEncCsPin, &PORTD, PIN4_bm, 4, 1); spi_init(&spiEncoder, &USARTD1, &PORTD, PIN6_bm, PIN7_bm, PIN5_bm, &spiEncCsPin); - spi_start(&spiEncoder, 0); + spi_start(&spiEncoder, 1); + // startup object + ams5047_init(&ams5047, &spiEncoder); } void pwm_periods(uint16_t peru, uint16_t perv, uint16_t perw){ @@ -135,8 +138,7 @@ void tickers_init(void){ // sets up two timers // compare and capture at value - // this is a low-speed-start friendly value, to start the commutation ticker with - uint16_t perStartSpeed = 2400; + uint16_t perStartSpeed = 150; // 75 should be 10kHz for commutation, 150 for 5kHz // write low first, bc bussing / xmega 8-bit oddities cc datasheet @ 3.11 uint8_t perSl = (uint8_t) perStartSpeed; uint8_t perSh = (uint8_t) (perStartSpeed >> 8); @@ -149,6 +151,7 @@ void tickers_init(void){ // set cca interrupt on TCD0.INTCTRLA = TC_OVFINTLVL_HI_gc; + /* // and a reasonable speed for acceleration ticking uint16_t perAccelRate = 800; @@ -161,6 +164,7 @@ void tickers_init(void){ TCD1.PERBUFH = perAh; TCD1.INTCTRLA = TC_OVFINTLVL_HI_gc; + */ } int main(void) @@ -178,33 +182,28 @@ int main(void) pin_set(&stlerr); pin_set(&stlclk); - //pin_init(&tstpin1, &PORTC, PIN5_bm, 5, 1); - //pin_init(&tstpin2, &PORTC, PIN3_bm, 3, 1); - + // startup encoder + encoder_init(); // start timers for commutation, accel tickers tickers_init(); - // startup encoder - //encoder_init(); // start pwm system pwm_init(); // initialize the bldc state structure bldc_init(&bldc); - // on startup speed and duty - bldc_setTargetSpeed(&bldc, 1000); - bldc_setDuty(&bldc, 10); + // on startup, speed (if clcomm) and duty + //bldc_setTargetSpeed(&bldc, 1000); + bldc_setDuty(&bldc, 40); // startup the driver drv_init(); // and enable the gate drv_enable(); - // now we should be spinning at 500 eRPM, so we can set an accel... later // runtime globals uint32_t tck = 0; while (1) { - //ams5047_write(&ams5047, 1200); atkport_scan(&atkp0, 2); // just... as fast as we can tck++; @@ -216,10 +215,6 @@ int main(void) } } -ISR(TCC0_OVF_vect){ - pin_toggle(&hi1); -} - int8_t comTable[6][3] = { {1,-1,0}, {1,0,-1}, @@ -229,9 +224,48 @@ int8_t comTable[6][3] = { {0,-1,1} }; +#define ENC_RESOLUTION 16834 + +// a handful of constants, probably need many less +// divisor is # of poles on motor / 2 (for each n/s pair, one set of 3 coils per full rotation) +const static uint16_t enc_resolution = ENC_RESOLUTION; +const static uint8_t enc_reverse = 0; // 1 or 0, for reverse op +const static uint16_t enc_modulo = ENC_RESOLUTION / 4; // 2805 in this case: divisor is # poles / 2 +const static uint16_t enc_offset = 60; // start at midpoint - adjust -ve or +ve from +const static uint16_t enc_steplength = ENC_RESOLUTION / 4 / 6; +static uint16_t enc_reading = 0; +static uint16_t enc_adjusted = 0; +static uint16_t enc_phase = 0; +static uint16_t enc_target = 0; +// 2^14 = 16,384 + // commutation timer ISR(TCD0_OVF_vect){ - // commutate? + // CL 6-step Commutate + + // get encoder reading + ams5047_read(&ams5047, &enc_reading); + // offset and modulo to bring to in-phase relative location + if(enc_reverse){ + enc_adjusted = enc_resolution - enc_reading; + } + enc_adjusted += enc_offset; // add offset + enc_adjusted %= enc_resolution; // wrap to resolution + enc_adjusted %= enc_modulo; // break into phase relative + // so this should represent the phase (0-5) that we're currently in + enc_phase = enc_adjusted / enc_steplength; + // if dir, phase + 2 to go forwards, else + 4, effectively - 2, and wrap past circle + (bldc.comDir) ? (enc_target = (enc_phase + 2) % 6) : (enc_target = (enc_phase + 4) % 6); + //uint8_t dout[6] = {6,0,5,254,255,enc_target}; + //uart_sendchars_buffered(&up0, dout, 6); + // now we can set PWMs accordingly + pwm_by_offset( comTable[enc_target][0] * bldc.comDuty, + comTable[enc_target][1] * bldc.comDuty, + comTable[enc_target][2] * bldc.comDuty + ); + + // OL Commutate + /* (bldc.comDir) ? (bldc.comState ++) : (bldc.comState --); if(bldc.comState > 5){ bldc.comState = 0; @@ -241,10 +275,15 @@ ISR(TCD0_OVF_vect){ comTable[bldc.comState][1] * bldc.comDuty, comTable[bldc.comState][2] * bldc.comDuty ); + */ } // acceleration timer ISR(TCD1_OVF_vect){ + // CL Commutate: PID Speed Loop + + // OL Commutate: Acceleration to Speed + /* if(bldc.currentSpeed != bldc.targetSpeed){ if(bldc.currentSpeed < bldc.targetSpeed){ bldc.currentSpeed ++; @@ -254,6 +293,7 @@ ISR(TCD1_OVF_vect){ bldc_setSpeed(&bldc, bldc.currentSpeed); } } + */ } ISR(USARTE1_RXC_vect){ diff --git a/embedded/atkbldcdriver/atkbldcdriver/spiport.c b/embedded/atkbldcdriver/atkbldcdriver/spiport.c index a7698bc628f04f00f6730ef8df697754c951b9ed..b59d12b3c58b753d68c818f45e551c01f859dc64 100644 --- a/embedded/atkbldcdriver/atkbldcdriver/spiport.c +++ b/embedded/atkbldcdriver/atkbldcdriver/spiport.c @@ -23,8 +23,8 @@ void spi_start(spiport_t *spi, uint8_t cpha){ spi->port->DIRCLR = spi->miso_bm; // want BSEL 7 and BSCALE -4 - spi->com->BAUDCTRLA = 0; //130; - spi->com->BAUDCTRLB = 1; //USART_BSCALE3_bm | USART_BSCALE2_bm | USART_BSCALE1_bm | USART_BSCALE0_bm; + spi->com->BAUDCTRLA = 12; //130; + spi->com->BAUDCTRLB = 0; //USART_BSCALE3_bm | USART_BSCALE2_bm | USART_BSCALE1_bm | USART_BSCALE0_bm; spi->com->CTRLB = USART_TXEN_bm | USART_RXEN_bm; @@ -42,13 +42,23 @@ void spi_txchar_polled(spiport_t *spi, uint8_t data){ void spi_txchars_polled(spiport_t *spi, uint8_t *data, uint8_t length){ pin_clear(spi->csn); for(int i = 0; i < length; i ++){ + spi->com->STATUS |= USART_TXCIF_bm; // clear transmit complete flag spi_txchar_polled(spi, data[i]); - spi->com->STATUS |= USART_TXCIF_bm; // clear transmit complete flag } while(!(spi->com->STATUS & USART_TXCIF_bm)); // wait for complete before pin_set(spi->csn); } -void spi_txrxchar_polled(spiport_t *spi, uint8_t data, uint8_t *rxdata){ - // how to read? +void spi_txrxchars_polled(spiport_t *spi, uint8_t *data, uint8_t *result, uint8_t length){ + pin_clear(spi->csn); + for(int i = 0; i < length; i ++){ + // rm'd extra clear of txcomplete flag + while(!(spi->com->STATUS & USART_DREIF_bm)); // wait for data register empty + spi->com->STATUS |= USART_TXCIF_bm; // clear transmit complete flag + spi->com->DATA = data[i]; // tx this + while(!(spi->com->STATUS & USART_TXCIF_bm)); // wait for complete before + while(!(spi->com->STATUS & USART_RXCIF_bm)); // wait for rx complete + result[i] = spi->com->DATA; // this is incoming (when read DATA reg, rx, when write, TX) + } + pin_set(spi->csn); } \ No newline at end of file diff --git a/embedded/atkbldcdriver/atkbldcdriver/spiport.h b/embedded/atkbldcdriver/atkbldcdriver/spiport.h index cd5e5aa10ae4d4a5f85c73acd785d2b727d67650..dd4f013cdb1f39c086a435fbc171466a81e6da47 100644 --- a/embedded/atkbldcdriver/atkbldcdriver/spiport.h +++ b/embedded/atkbldcdriver/atkbldcdriver/spiport.h @@ -30,6 +30,7 @@ void spi_start(spiport_t *spi, uint8_t cpha); // 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); +void spi_txrxchars_polled(spiport_t *spi, uint8_t *data, uint8_t *result, uint8_t length); #endif /* SPIPORT_H_ */ \ No newline at end of file