diff --git a/circuit/mkbldcdriver/eagle.epf b/circuit/mkbldcdriver/eagle.epf index b7dc703852c482ce7f222a541fd910b85f304f70..9a391b0c0cc194ecfc00627dcbf807296753bba3 100644 --- a/circuit/mkbldcdriver/eagle.epf +++ b/circuit/mkbldcdriver/eagle.epf @@ -36,11 +36,11 @@ UsedLibrary="D:/Dropbox (Personal)/CBA/doc/libraries_jake/eagle/sparkfun/SparkFu [Win_1] Type="Schematic Editor" -Loc="0 0 1919 1016" +Loc="-1928 -8 -9 1008" State=1 Number=2 File="mkbldcdriver.sch" -View="-133.101 -16.4054 69.9278 60.3757" +View="-191.238 -0.355913 101.124 110.209" 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" @@ -79,7 +79,7 @@ ArcDirection=0 AddLevel=2 PadsSameType=0 Layer=91 -Views=" 1: -133.101 -16.4054 69.9278 60.3757" +Views=" 1: -191.238 -0.355913 101.124 110.209" Sheet="1" [Win_2] @@ -88,7 +88,7 @@ Loc="0 0 1919 1016" State=1 Number=1 File="mkbldcdriver.brd" -View="13.5716 56.9498 32.0603 57.5241" +View="21.1469 45.1135 67.1527 46.5425" WireWidths=" 0.0762 0.1016 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.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" diff --git a/circuit/mkbldcdriver/mkbldcdriver.brd b/circuit/mkbldcdriver/mkbldcdriver.brd index 7f9ddeede93d93d5a8554d2b75518ac863da2ebb..ccf6ab2fff04d8543d6d681aab1e23ae48123968 100644 --- a/circuit/mkbldcdriver/mkbldcdriver.brd +++ b/circuit/mkbldcdriver/mkbldcdriver.brd @@ -173,8 +173,8 @@ <text x="35.052" y="20.193" size="0.6096" layer="21" font="vector">V-W</text> <text x="35.052" y="22.86" size="0.6096" layer="21" font="vector">V-V</text> <text x="35.052" y="25.273" size="0.6096" layer="21" font="vector">V-U</text> -<text x="35.052" y="30.48" size="0.6096" layer="21" font="vector">C-V</text> -<text x="35.052" y="27.813" size="0.6096" layer="21" font="vector">C-W</text> +<text x="35.052" y="30.48" size="0.6096" layer="21" font="vector">I-V</text> +<text x="35.052" y="27.813" size="0.6096" layer="21" font="vector">I-W</text> <text x="35.052" y="33.02" size="0.6096" layer="21" font="vector">3V3</text> <text x="35.052" y="35.56" size="0.6096" layer="21" font="vector">GND</text> <text x="35.052" y="37.973" size="0.6096" layer="21" font="vector">LO3</text> diff --git a/embedded/README.md b/embedded/README.md index 506601ec60c362b12b01cc992c6b30b6e08a27ac..03d2adcb5b9c1f14fb1ebc48c457206fcdf46a04 100644 --- a/embedded/README.md +++ b/embedded/README.md @@ -517,3 +517,42 @@ OK! Properly, I should do this on a timer. I'm going to do it in the while() loop for now, just to check that I'm having the output on the PWMs that I want. +Great - I have this running in the open while() loop. It commutates! I suppose I shouldn't be surprised at this stuff anymore. + +I set up my logic analyzer so that I can start on this commutation debug cycle. I have three pins on the lo-sides of the PWMs, three on the voltage sense pinse, and two on the current sense pins. + +I'm hearing this 'tick' every so often as the motor commutates. Here's what it looks like on the analyzer: + + + +So I think that one of the PWM registers is occasionally being written to 100% in error. My suspicion is that this has something to do with my fast-and-loose commutation scheme, which I'm about to improve. + +While I did notice that this was only occuring while the motor driver's gates where enabled (so, 'stuff was happening'), I tried using the ATSAMD's PWM Capture-Compare Buffer (capture-compare is the value the pwm timer checks to switch-or-not-switch the output). The buffer let's me write into the PWM registers when I'm sure they're not being read by the peripheral. This eliminated the problem. I also pushed the PWM frequency to 22kHZ and it's all silky smooth sounding now. + +OK, some current / voltage waveforms: + +Channels: Fault, PWM Hi U, Pwm Hi V, Pwm Hi W, Current V, Current W, Voltage V, Voltage W. + + + + + +I set this up to accept a commanded 'torque' (just PWM duty cycle) and direction, so next step here is doing some network integration as well. + + + +Then, a longer list of development: + +# Next: + +## Firmware + - Closed-Loop Speed Control (maybe using simple 6-step commutation?) + - Search for Encoder Offset + - Closed-Loop Position Control + - Probably just Sinusoid PWM Commutation + - The Big Bite: FOC + +## Hardware + - I have a list of incremental improvements... mostly: + - Go to 2oz copper so that I dont' blow up any traces when the power hits + - Discrete LEDs and more indication (there's an overcurrent / overtemp warning I want to break out) \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/Debug/Makefile b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/Debug/Makefile index 08c97de7fef9c1933b750b651dc16bf28e0ab7f0..dd50fc2eebf3e8794f8818aebb106861a35e2c47 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/Debug/Makefile +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/Debug/Makefile @@ -38,8 +38,10 @@ SUBDIRS := \ # Add inputs and outputs from these tool invocations to the build variables C_SRCS += \ +../bldc_pfoc.c \ ../Device_Startup/startup_samd51.c \ ../Device_Startup/system_samd51.c \ +../encoder.c \ ../main.c \ ../pin.c \ ../pwm_foc.c \ @@ -55,8 +57,10 @@ ASM_SRCS += OBJS += \ +bldc_pfoc.o \ Device_Startup/startup_samd51.o \ Device_Startup/system_samd51.o \ +encoder.o \ main.o \ pin.o \ pwm_foc.o \ @@ -65,8 +69,10 @@ spiport.o \ uartport.o OBJS_AS_ARGS += \ +bldc_pfoc.o \ Device_Startup/startup_samd51.o \ Device_Startup/system_samd51.o \ +encoder.o \ main.o \ pin.o \ pwm_foc.o \ @@ -75,8 +81,10 @@ spiport.o \ uartport.o C_DEPS += \ +bldc_pfoc.d \ Device_Startup/startup_samd51.d \ Device_Startup/system_samd51.d \ +encoder.d \ main.d \ pin.d \ pwm_foc.d \ @@ -85,8 +93,10 @@ spiport.d \ uartport.d C_DEPS_AS_ARGS += \ +bldc_pfoc.d \ Device_Startup/startup_samd51.d \ Device_Startup/system_samd51.d \ +encoder.d \ main.d \ pin.d \ pwm_foc.d \ @@ -127,14 +137,18 @@ LINKER_SCRIPT_DEP+= \ -Device_Startup/%.o: ../Device_Startup/%.c + + + + +./%.o: .././%.c @echo Building file: $< @echo Invoking: ARM/GNU C Compiler : 6.3.1 $(QUOTE)C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\arm\arm-gnu-toolchain\bin\arm-none-eabi-gcc.exe$(QUOTE) -x c -mthumb -D__SAMD51J18A__ -DDEBUG -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\arm\CMSIS\5.0.1\CMSIS\Include" -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\SAMD51_DFP\1.0.70\include" -O1 -ffunction-sections -mlong-calls -g3 -Wall -mcpu=cortex-m4 -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<" @echo Finished building: $< -./%.o: .././%.c +Device_Startup/%.o: ../Device_Startup/%.c @echo Building file: $< @echo Invoking: ARM/GNU C Compiler : 6.3.1 $(QUOTE)C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\arm\arm-gnu-toolchain\bin\arm-none-eabi-gcc.exe$(QUOTE) -x c -mthumb -D__SAMD51J18A__ -DDEBUG -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\arm\CMSIS\5.0.1\CMSIS\Include" -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\SAMD51_DFP\1.0.70\include" -O1 -ffunction-sections -mlong-calls -g3 -Wall -mcpu=cortex-m4 -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<" diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/Debug/makedep.mk b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/Debug/makedep.mk index d58c0ac36fd33ca578c91a5c9483ee4acf23fb42..48ac82f043585d6ba80915c4985fb8604fa8b45a 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/Debug/makedep.mk +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/Debug/makedep.mk @@ -2,10 +2,14 @@ # Automatically-generated file. Do not edit or delete the file ################################################################################ +bldc_pfoc.c + Device_Startup\startup_samd51.c Device_Startup\system_samd51.c +encoder.c + main.c pin.c diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/bldc_pfoc.c b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/bldc_pfoc.c new file mode 100644 index 0000000000000000000000000000000000000000..9e00465bf03795e20d069de6cf13d0ed951f7c02 --- /dev/null +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/bldc_pfoc.c @@ -0,0 +1,78 @@ +/* + * bldc_pfoc.c + * + * Created: 2/19/2018 10:40:54 AM + * Author: Jake + */ + +#include "bldc_pfoc.h" +#include "encoder.h" +#include "sinelut.h" +#include "pwm_foc.h" +#include "hardware.h" + +void bldc_init(bldc_t *bldc, uint32_t resolution, uint32_t modulo, uint32_t offset, uint32_t reverse){ + bldc->resolution = resolution; + bldc->modulo = modulo; + bldc->offset = offset; + bldc->reverse = reverse; + bldc->modmap = modulo / 1024; +} + +// super simple throttle +void bldc_command(bldc_t *bldc, uint32_t scalar, uint32_t dir){ + if(scalar > BLDC_MAX_SCALAR){ + bldc->scalar = BLDC_MAX_SCALAR; + } else { + bldc->scalar = scalar; + } + bldc->dir = dir; +} + +void bldc_update(bldc_t *bldc){ + // read encoder, where 0 - 2^14 is 0 - 2*PI rads mechanical phase + encoder_read(&bldc->reading); + // reverse the reading if that flag is set + if(bldc->reverse){ + bldc->reading = bldc->resolution - bldc->reading; + } + + // electric position and offsetting + // one modulo is one full electric phase, is some division of full rotations + // so, elecpos is 0 - modulo (uint) describing 0 - 2*PI rads of an electric phase + bldc->elecpos = (bldc->reading + bldc->offset) % bldc->modulo; + + // now we map the phases from 0 - modulo (uint) -> 0 - 1024 (uint) + // this is the depth of our lookup table for sin() + // we computed this value at init, as modulo / lut_depth; + // we compute the modpos once + bldc->modpos = bldc->elecpos / bldc->modmap; + if(bldc->dir){ + bldc->phaseu = bldc->modpos; + bldc->phasev = bldc->modpos + 341; // + 120* in lut phase + bldc->phasew = bldc->modpos + 682; // + 240* + } else { + bldc->phaseu = bldc->modpos + 682; + bldc->phasev = bldc->modpos + 341; // + 120* in lut phase + bldc->phasew = bldc->modpos; // + 240* + } + + + // now we check for wrap arounds in the lut phase + (bldc->phaseu > 1023) ? (bldc->phaseu -= 1023) : (0); + (bldc->phasev > 1023) ? (bldc->phasev -= 1023) : (0); + (bldc->phasew > 1023) ? (bldc->phasew -= 1023) : (0); + + // and set the pwm value to be the sin of it's current electric phase, + // where the sinelut returns a value 0 - 255 + // midpoint (0 volts, equal time on / off) being 128 + // and multiply that value by a scalar + bldc->pwmu = (sinelut[bldc->phaseu] * bldc->scalar) / 255; + bldc->pwmv = sinelut[bldc->phasev] * bldc->scalar / 255; + bldc->pwmw = sinelut[bldc->phasew] * bldc->scalar / 255; + + // finally, sending new pwm values + // we assert the minimum value to be 5 and the max to be 250 + // this leaves some time for deadtime insertion (set with TCC_WEXCTRL_DTHS(1) in PWM setup) + pwmupdate_foc(bldc->pwmu,bldc->pwmv,bldc->pwmw); +} \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/bldc_pfoc.h b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/bldc_pfoc.h new file mode 100644 index 0000000000000000000000000000000000000000..a46ee934e4b43a847e3260a56114e1d39dce7932 --- /dev/null +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/bldc_pfoc.h @@ -0,0 +1,46 @@ +/* + * bldc_pfoc.h + * + * Created: 2/19/2018 10:40:36 AM + * Author: Jake + */ + + +#ifndef BLDC_PFOC_H_ +#define BLDC_PFOC_H_ + +#include "sam.h" + +#define BLDC_MAX_SCALAR 255 +#define BLDC_INIT_OFFSET 700 +#define BLDC_RESOLUTION 16834 +#define BLDC_MODULO 2340 +#define BLDC_REVERSE 1 + +// struct to wrap commutation information +typedef struct{ + uint32_t resolution; + uint32_t modulo; + uint32_t offset; + uint32_t reverse; + uint32_t modmap; + + uint32_t scalar; + uint32_t dir; + + uint32_t reading; + uint32_t elecpos; + uint32_t modpos; + + uint32_t phaseu, pwmu; + uint32_t phasev, pwmv; + uint32_t phasew, pwmw; +}bldc_t; + +void bldc_init(bldc_t *bldc, uint32_t resolution, uint32_t modulo, uint32_t offset, uint32_t reverse); + +void bldc_command(bldc_t *bldc, uint32_t scalar, uint32_t dir); + +void bldc_update(bldc_t *bldc); + +#endif /* BLDC_PFOC_H_ */ \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/encoder.c b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/encoder.c new file mode 100644 index 0000000000000000000000000000000000000000..9e2114269ea6c5582e1a330c3972b9cd870ff39c --- /dev/null +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/encoder.c @@ -0,0 +1,19 @@ +/* + * encoder.c + * + * Created: 2/19/2018 11:11:57 AM + * Author: Jake + */ + +#include "encoder.h" +#include "hardware.h" + +void encoder_read(uint32_t *data_return){ + uint8_t data_tx[2] = {0xFF, 0xFF}; // read command: 1s, noop: 0s + uint8_t data_rx[2]; + spi_txrxchars_polled(&spi_encoder, data_tx, 2, data_rx); + data_tx[0] = 0x00; + data_tx[1] = 0x00; + spi_txrxchars_polled(&spi_encoder, data_tx, 2, data_rx); + * data_return = (data_rx[0] & 0b00111111) << 8 | data_rx[1]; +} \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/encoder.h b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..4bc3d48c7e9b00171e87c70d6da55517ed9db116 --- /dev/null +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/encoder.h @@ -0,0 +1,16 @@ +/* + * encoder.h + * + * Created: 2/19/2018 11:11:23 AM + * Author: Jake + */ + + +#ifndef ENCODER_H_ +#define ENCODER_H_ + +#include "sam.h" + +void encoder_read(uint32_t *data_return); + +#endif /* ENCODER_H_ */ \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/hardware.h b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/hardware.h index 1566dda3d369e8e5cb02c7eca5fa801c27ebef5a..54e7ff6a0dcace4359c17bccc90076a9c3def94c 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/hardware.h +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/hardware.h @@ -13,6 +13,8 @@ #include "ringbuffer.h" #include "uartport.h" #include "spiport.h" +#include "bldc_pfoc.h" +#include "pwm_foc.h" pin_t stlb; @@ -33,4 +35,8 @@ pin_t m_gain; pin_t fault; pin_t octw; +bldc_t bldc; + +pin_t testp; + #endif /* HARDWARE_H_ */ \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/main.c b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/main.c index 4cbb5f5cac5daf6de3696bf3b2acdc5986690d38..cd5bedc5a712c7d6c272d76eed79f33febb86e72 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/main.c +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/main.c @@ -7,27 +7,42 @@ #include "sam.h" -#include "pwm_foc.h" -#include "pin.h" -#include "ringbuffer.h" -#include "uartport.h" -#include "spiport.h" #include "hardware.h" -#include "sinelut.h" +#include "encoder.h" #include <stdio.h> -// stlb is PA23 - -uint32_t encoder_read(void){ - uint8_t data_tx[2] = {0xFF, 0xFF}; // read command: 1s, noop: 0s - uint8_t data_rx[2]; - spi_txrxchars_polled(&spi_encoder, data_tx, 2, data_rx); - data_tx[0] = 0x00; - data_tx[1] = 0x00; - spi_txrxchars_polled(&spi_encoder, data_tx, 2, data_rx); - - uint32_t data = (data_rx[0] & 0b00111111) << 8 | data_rx[1]; - return data; +void comticker_init(uint32_t cc){ + // Timers: in 32 bit mode we pair two - obscure datasheet reading later, they pair in a predefined way: 0 with 1... + // a word of warning: with the same code, a 16-bit timer was not working. I am mystified. + TC2->COUNT32.CTRLA.bit.ENABLE = 0; + TC3->COUNT32.CTRLA.bit.ENABLE = 0; + // unmask clocks + MCLK->APBBMASK.reg |= MCLK_APBBMASK_TC2 | MCLK_APBBMASK_TC3; // at 15.8.9 + // generate a gclk + GCLK->GENCTRL[11].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL) | GCLK_GENCTRL_GENEN; + while(GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL(11)); + // ship gclk to their channels + GCLK->PCHCTRL[TC2_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(11); + GCLK->PCHCTRL[TC3_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(11); + // turn on in mode, presync + TC2->COUNT32.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCSYNC_PRESC | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_CAPTEN0;// | TC_CTRLA_CAPTEN1; + TC3->COUNT32.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCSYNC_PRESC | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_CAPTEN0;// | TC_CTRLA_CAPTEN1; + // do frequency match + TC2->COUNT32.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ; + TC3->COUNT32.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ; + // allow interrupt to trigger on this event (compare channel 0) + TC2->COUNT32.INTENSET.bit.MC0 = 1; + TC2->COUNT32.INTENSET.bit.MC1 = 1; // don't know why, but had to turn this on to get the interrupts + // set period + while(TC2->COUNT32.SYNCBUSY.bit.CC0); + TC2->COUNT32.CC[0].reg = 165; + while(TC2->COUNT32.SYNCBUSY.bit.CC1); + TC2->COUNT32.CC[1].reg = 165; + // enable, sync for enable write + TC2->COUNT32.CTRLA.bit.ENABLE = 1; + while(TC2->COUNT32.SYNCBUSY.bit.ENABLE); + TC3->COUNT32.CTRLA.bit.ENABLE = 1; + while(TC3->COUNT32.SYNCBUSY.bit.ENABLE); } int main(void) @@ -46,6 +61,7 @@ int main(void) NVIC_EnableIRQ(SERCOM4_2_IRQn); //up1rx NVIC_EnableIRQ(SERCOM5_0_IRQn); NVIC_EnableIRQ(SERCOM5_2_IRQn); + NVIC_EnableIRQ(TC2_IRQn); // Rinbuffers for UARTs rb_init(&up1_rbrx); @@ -103,11 +119,10 @@ int main(void) // OCTW PA22: input, open drain when active, use pullup fault = pin_new(&PORT->Group[0], 21); pin_input(&fault); + pin_pullup(&fault); octw = pin_new(&PORT->Group[0], 22); pin_input(&octw); - - // do closed loop sinucommutate, following old ATSAMS70 code - // do BLDC closed, open loop + pin_pullup(&octw); // enable or don't //pin_clear(&en_gate); @@ -118,61 +133,31 @@ int main(void) pin_clear(&m_gain); pin_clear(&dc_cal); - uint32_t resolution = 16384; - uint32_t modulo = 2340; - uint32_t offset = 800; - uint32_t reverse = 1; - uint32_t scalar = 42; // of 255 + bldc_init(&bldc, BLDC_RESOLUTION, BLDC_MODULO, BLDC_INIT_OFFSET, BLDC_REVERSE); + bldc_command(&bldc, 90, 1); - uint32_t reading; - uint32_t elecpos; - - uint32_t phaseu, pwmu; - uint32_t phasev, pwmv; - uint32_t phasew, pwmw; + // startup timer for 5khz commutation loop + comticker_init(64); while (1) { - // read encoder & get electric position (relative phase period, not rotation period) - reading = encoder_read(); - if(reverse){ - reading = resolution - reading; + if(!pin_read(&octw)){ + pin_clear(&stlb); } - elecpos = (reading + offset) % modulo; - - // not LUT'd yet - phaseu = elecpos / (modulo / 1024); - phasev = elecpos / (modulo / 1024) + 341; - phasew = elecpos / (modulo / 1024) + 682; - - (phaseu > 1023) ? (phaseu -= 1023) : (0); - (phasev > 1023) ? (phasev -= 1023) : (0); - (phasew > 1023) ? (phasew -= 1023) : (0); - - pwmu = sinelut[phaseu] * scalar / 255 + 1; - pwmv = sinelut[phasev] * scalar / 255 + 1; - pwmw = sinelut[phasew] * scalar / 255 + 1; - - pwmupdate_foc(pwmu,pwmv,pwmw); + // timer should be running, doing bldc things + // use these while() loops to handle network } } -// ok, we're commutating -/* - - ticking: it's a PWM update error, occasionally setting some values to 100% - - implement a timer to commutate at a set frequency - - work through the mess of values above, go faster, cleaner - - basic search for reverse, offset, modulo etc would be cool, hard (probably) - - verify all gates are opening -*/ - uint8_t loopcnt; void SysTick_Handler(void){ - pin_toggle(&stlb); + pin_set(&stlb); loopcnt ++; uart_sendchar_buffered(&up1, loopcnt); - uint32_t reading = encoder_read(); + uint32_t reading; + //encoder_read(&reading); + reading = bldc.reading; uint8_t d1 = reading >> 8; uint8_t d2 = reading; uart_sendchar_buffered(&up1, d1); @@ -194,3 +179,9 @@ void SERCOM5_0_Handler(void){ void SERCOM5_2_Handler(void){ uart_rxhandler(&up2); } + +void TC2_Handler(void){ + TC2->COUNT32.INTFLAG.bit.MC0 = 1; + TC2->COUNT32.INTFLAG.bit.MC1 = 1; + bldc_update(&bldc); +} \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/mkbldcdriver-v03.cproj b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/mkbldcdriver-v03.cproj index afe85b64ef67f91c5fd6183067a3f0b530010b38..fc8e8ed7f97fb9073b2607668c73b307ff32f261 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/mkbldcdriver-v03.cproj +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/mkbldcdriver-v03.cproj @@ -159,12 +159,24 @@ </ToolchainSettings> </PropertyGroup> <ItemGroup> + <Compile Include="bldc_pfoc.c"> + <SubType>compile</SubType> + </Compile> + <Compile Include="bldc_pfoc.h"> + <SubType>compile</SubType> + </Compile> <Compile Include="Device_Startup\startup_samd51.c"> <SubType>compile</SubType> </Compile> <Compile Include="Device_Startup\system_samd51.c"> <SubType>compile</SubType> </Compile> + <Compile Include="encoder.c"> + <SubType>compile</SubType> + </Compile> + <Compile Include="encoder.h"> + <SubType>compile</SubType> + </Compile> <Compile Include="hardware.h"> <SubType>compile</SubType> </Compile> diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pin.c b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pin.c index 6bf2a5e55b0893e0b4b4052a31436964ebcbce3a..9912983950eebb318ebba0db9b954f338553c376 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pin.c +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pin.c @@ -11,6 +11,7 @@ pin_t pin_new(PortGroup *port, uint32_t pin_number){ pin_t pin; pin.port = port; + pin.pin = pin_number; pin.bm = (uint32_t)(1 << pin_number); return pin; } @@ -23,6 +24,16 @@ void pin_output(pin_t *pin){ void pin_input(pin_t *pin){ pin->port->DIRCLR.reg = pin->bm; + pin->port->PINCFG[pin->pin].bit.INEN = 1; +} + +void pin_pullup(pin_t *pin){ + pin->port->PINCFG[pin->pin].bit.PULLEN = 1; + pin->port->OUTSET.reg |= pin->bm; +} + +void pin_pulldown(pin_t *pin){ + pin->port->PINCFG[pin->pin].bit.PULLEN = 1; } void pin_set(pin_t *pin){ diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pin.h b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pin.h index 8ea143d44285a299ca78e49da22ffc154f0b4a7f..bc6c45f7b5ba388717003bd3ffe887134a6cd624 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pin.h +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pin.h @@ -13,14 +13,20 @@ typedef struct { PortGroup *port; + uint32_t pin; uint32_t bm; // bitmask } pin_t; pin_t pin_new(PortGroup *port, uint32_t pin); void pin_output(pin_t *pin); + void pin_input(pin_t *pin); +void pin_pullup(pin_t *pin); + +void pin_pulldown(pin_t *pin); + void pin_set(pin_t *pin); void pin_clear(pin_t *pin); void pin_toggle(pin_t *pin); diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pwm_foc.c b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pwm_foc.c index 03b334718a58e644f828a677c6d49d19b74b2075..c748d902d38c4ad1fea1d5bae6ca56354841c70c 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pwm_foc.c +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pwm_foc.c @@ -5,6 +5,7 @@ * Author: Jake */ #include "pwm_foc.h" +#include "hardware.h" void pwmsetup_foc(void){ /* TCC SETUP */ @@ -49,7 +50,7 @@ void pwmsetup_foc(void){ GCLK->PCHCTRL[TCC0_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK5; - TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV8 | TCC_CTRLA_PRESCSYNC_PRESC |TCC_CTRLA_RESOLUTION(0); + TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV4 | TCC_CTRLA_PRESCSYNC_PRESC |TCC_CTRLA_RESOLUTION(0); // (2) Select Waveform Generation operation in the WAVE register WAVE.WAVEGEN // we want dual slope pwm @@ -62,14 +63,14 @@ void pwmsetup_foc(void){ TCC_WEXCTRL_DTIEN1 | TCC_WEXCTRL_DTIEN2 | TCC_WEXCTRL_DTIEN3 | TCC_WEXCTRL_DTIEN0 | TCC_WEXCTRL_OTMX(0); - TCC0->PER.reg = TCC_PER_PER(256); // 18 bit + TCC0->PER.reg = TCC_PER_PER(256); TCC0->COUNT.reg = 0; - TCC0->CC[0].reg = 0; // '3' - TCC0->CC[1].reg = 0; // '2' - TCC0->CC[2].reg = 0; // '1' - TCC0->CC[3].reg = 0; + TCC0->CCBUF[0].reg = 0; // '3' + TCC0->CCBUF[1].reg = 0; // '2' + TCC0->CCBUF[2].reg = 0; // '1' + TCC0->CCBUF[3].reg = 0; // (4) Enable with CTRLA.ENABLE @@ -77,8 +78,27 @@ void pwmsetup_foc(void){ while(TCC0->SYNCBUSY.bit.ENABLE); } +#define PWMFOC_MIN_PWM 3 +#define PWMFOC_MAX_PWM 253 + void pwmupdate_foc(uint32_t one, uint32_t two, uint32_t three){ - TCC0->CC[0].reg = three; // '3' - TCC0->CC[1].reg = two; // '2' - TCC0->CC[2].reg = one; // '1' + pwm_bounds(&three); + pwm_bounds(&two); + pwm_bounds(&one); + /* + uart_sendchar_buffered(&up1, one); + uart_sendchar_buffered(&up1, two); + uart_sendchar_buffered(&up1, three); + */ + TCC0->CCBUF[0].reg = three; // '3' + TCC0->CCBUF[1].reg = two; // '2' + TCC0->CCBUF[2].reg = one; // '1' +} + +void pwm_bounds(uint32_t *val){ + if(*val > PWMFOC_MAX_PWM){ + *val = PWMFOC_MAX_PWM; + } else if(*val < PWMFOC_MIN_PWM){ + *val = PWMFOC_MIN_PWM; + } } \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pwm_foc.h b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pwm_foc.h index 94b7909950635e1c92add467fbdf2dc953e10f84..c9a35bee01d1a656bc7d34fefbed67d4fef8379e 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pwm_foc.h +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/pwm_foc.h @@ -12,6 +12,11 @@ #include "sam.h" void pwmsetup_foc(void); -void pwmupdate_foc(uint32_t one, uint32_t two, uint32_t three); // 0 -> 255 (but count deadtime?) midpoint is 126 + +// 0 -> 255 (but count deadtime?) midpoint is 126 +void pwmupdate_foc(uint32_t one, uint32_t two, uint32_t three); + +// asserts min and max for pwm +void pwm_bounds(uint32_t *val); #endif /* PWM_FOC_H_ */ \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/sinelut.h b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/sinelut.h index 198f4b46dc015cfeb6c52245aea8c4516279835d..943c4f388dcc425b28a42a4412263f725fd8100a 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/sinelut.h +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/sinelut.h @@ -11,8 +11,8 @@ /* takes 0 - 1023 phase position and returns sin from 0 - 255 +http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml */ - uint32_t sinelut[1024] = { 128,128,129,130,131,131,132,133, 134,135,135,136,137,138,138,139, @@ -144,5 +144,4 @@ uint32_t sinelut[1024] = { 122,123,124,124,125,126,127,128 }; - #endif /* SINELUT_H_ */ \ No newline at end of file diff --git a/images/programming-currents-olcommutate-1.png b/images/programming-currents-olcommutate-1.png new file mode 100644 index 0000000000000000000000000000000000000000..70e5f1c980841ccf3880faa77974bd53acdf667c Binary files /dev/null and b/images/programming-currents-olcommutate-1.png differ diff --git a/images/programming-currents-olcommutate-2.png b/images/programming-currents-olcommutate-2.png new file mode 100644 index 0000000000000000000000000000000000000000..19cfcda57666956cbef1ca0f78a0a93169704779 Binary files /dev/null and b/images/programming-currents-olcommutate-2.png differ diff --git a/images/programming-pwm-ticking.png b/images/programming-pwm-ticking.png new file mode 100644 index 0000000000000000000000000000000000000000..a8bd6576714b180d5c05bc6f8b94917d7f1d0cad Binary files /dev/null and b/images/programming-pwm-ticking.png differ diff --git a/video/20khz-commutate.mp4 b/video/20khz-commutate.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..fb0945c781d785c08aec9296a054a155092f23aa Binary files /dev/null and b/video/20khz-commutate.mp4 differ