diff --git a/embedded/atkbldcdriver/atkbldcdriver/Debug/Makefile b/embedded/atkbldcdriver/atkbldcdriver/Debug/Makefile index a701f1dc9378c8c7fdc56d2afac212dc85366e6c..deff472947c802237064607424be685d920bde94 100644 --- a/embedded/atkbldcdriver/atkbldcdriver/Debug/Makefile +++ b/embedded/atkbldcdriver/atkbldcdriver/Debug/Makefile @@ -141,7 +141,7 @@ LINKER_SCRIPT_DEP+= ./%.o: .././%.c @echo Building file: $< @echo Invoking: AVR/GNU C Compiler : 5.4.0 - $(QUOTE)C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE) -x c -funsigned-char -funsigned-bitfields -DDEBUG -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\XMEGAA_DFP\1.1.68\include" -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atxmega256a3u -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\XMEGAA_DFP\1.1.68\gcc\dev\atxmega256a3u" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<" + $(QUOTE)C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE) -x c -funsigned-char -funsigned-bitfields -DDEBUG -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\XMEGAA_DFP\1.1.68\include" -O2 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atxmega256a3u -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\XMEGAA_DFP\1.1.68\gcc\dev\atxmega256a3u" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<" @echo Finished building: $< diff --git a/embedded/atkbldcdriver/atkbldcdriver/atkbldcdriver.cproj b/embedded/atkbldcdriver/atkbldcdriver/atkbldcdriver.cproj index 8614af8803da81dd29054f50f7d00ef82be149a3..c027293a2b898f49550fa0d5ab914931102bce7f 100644 --- a/embedded/atkbldcdriver/atkbldcdriver/atkbldcdriver.cproj +++ b/embedded/atkbldcdriver/atkbldcdriver/atkbldcdriver.cproj @@ -109,41 +109,41 @@ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <ToolchainSettings> <AvrGcc> - <avrgcc.common.Device>-mmcu=atxmega256a3u -B "%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\gcc\dev\atxmega256a3u"</avrgcc.common.Device> - <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex> - <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> - <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> - <avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec> - <avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures> - <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> - <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> - <avrgcc.compiler.symbols.DefSymbols> - <ListValues> - <Value>DEBUG</Value> - </ListValues> - </avrgcc.compiler.symbols.DefSymbols> - <avrgcc.compiler.directories.IncludePaths> - <ListValues> - <Value>%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\include</Value> - </ListValues> - </avrgcc.compiler.directories.IncludePaths> - <avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level> - <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers> - <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> - <avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel> - <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings> - <avrgcc.linker.libraries.Libraries> - <ListValues> - <Value>libm</Value> - </ListValues> - </avrgcc.linker.libraries.Libraries> - <avrgcc.assembler.general.IncludePaths> - <ListValues> - <Value>%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\include</Value> - </ListValues> - </avrgcc.assembler.general.IncludePaths> - <avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel> - </AvrGcc> + <avrgcc.common.Device>-mmcu=atxmega256a3u -B "%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\gcc\dev\atxmega256a3u"</avrgcc.common.Device> + <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex> + <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> + <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> + <avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec> + <avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures> + <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> + <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> + <avrgcc.compiler.symbols.DefSymbols> + <ListValues> + <Value>DEBUG</Value> + </ListValues> + </avrgcc.compiler.symbols.DefSymbols> + <avrgcc.compiler.directories.IncludePaths> + <ListValues> + <Value>%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\include</Value> + </ListValues> + </avrgcc.compiler.directories.IncludePaths> + <avrgcc.compiler.optimization.level>Optimize more (-O2)</avrgcc.compiler.optimization.level> + <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers> + <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> + <avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel> + <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings> + <avrgcc.linker.libraries.Libraries> + <ListValues> + <Value>libm</Value> + </ListValues> + </avrgcc.linker.libraries.Libraries> + <avrgcc.assembler.general.IncludePaths> + <ListValues> + <Value>%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\include</Value> + </ListValues> + </avrgcc.assembler.general.IncludePaths> + <avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel> +</AvrGcc> </ToolchainSettings> </PropertyGroup> <ItemGroup> diff --git a/embedded/atkbldcdriver/atkbldcdriver/main.c b/embedded/atkbldcdriver/atkbldcdriver/main.c index a1ca888ff8f325fdf119cdf9ce46042763397811..f66334532bcf6ec2d4d8a37ba039ad6363b1dd04 100644 --- a/embedded/atkbldcdriver/atkbldcdriver/main.c +++ b/embedded/atkbldcdriver/atkbldcdriver/main.c @@ -12,7 +12,7 @@ #include "sinelut.h" // first setup all the pins -// want six step commutation, or sinpwm on encoder reading? +// want six step commutation, or sinpwm on encoder reading? void clock_init(void){ OSC.XOSCCTRL = OSC_XOSCSEL_XTAL_256CLK_gc | OSC_FRQRANGE_12TO16_gc; // select external source @@ -48,7 +48,7 @@ void encoder_init(void){ pin_init(&spiEncCsPin, &PORTD, PIN4_bm, 4, 1); spi_init(&spiEncoder, &USARTD1, &PORTD, PIN6_bm, PIN7_bm, PIN5_bm, &spiEncCsPin); spi_start(&spiEncoder, 1); - // startup object + // startup object ams5047_init(&ams5047, &spiEncoder); } @@ -66,7 +66,7 @@ static uint16_t enc_reading = 0; static uint16_t phase_target = 0; // 2^14 = 16,384 -void pwm_periods(uint16_t peru, uint16_t perv, uint16_t perw){ +void pwm_sintype_periods(uint16_t peru, uint16_t perv, uint16_t perw){ // check overrun (peru > 1024) ? peru = 1024 : (0); (perv > 1024) ? perv = 1024 : (0); @@ -84,16 +84,16 @@ void pwm_periods(uint16_t peru, uint16_t perv, uint16_t perw){ TCC0.CCCBUFH = (uint8_t) (peru >> 8); } -void pwm_by_offset(int16_t ofu, int16_t ofv, int16_t ofw){ +void pwm_sintype_by_offset(int16_t ofu, int16_t ofv, int16_t ofw){ // +ve offset to spend more time with hi-side off, signals are complimentary uint16_t peru = 512 + ofu; uint16_t perv = 512 + ofv; uint16_t perw = 512 + ofw; // now through business - pwm_periods(peru, perv, perw); + pwm_sintype_periods(peru, perv, perw); } -void pwm_by_sin_duty(uint16_t phase, float duty){ +void pwm_sintype_by_sin_duty(uint16_t phase, float duty){ // phases respective of home int16_t pu = phase; (pu >= twoPi_enc) ? (pu -= twoPi_enc) : (0); @@ -107,35 +107,37 @@ void pwm_by_sin_duty(uint16_t phase, float duty){ int16_t perv = ((sinelut[pv] - 512) * duty) + 512; int16_t perw = ((sinelut[pw] - 512) * duty) + 512; - pwm_periods(peru, perv, perw); + pwm_sintype_periods(peru, perv, perw); } -uint16_t readings[20]; -uint8_t readIndex = 0; - -void putReading(uint16_t reading){ - readings[readIndex] = reading; - readIndex ++; -} - -void getReadAverage(uint16_t *avg){ - uint8_t numReads = readIndex; // sloppy, but makes this interrupt safe - uint32_t readSum = 0; - for(uint8_t i = 0; i < numReads; i ++){ - readSum += readings[i]; - } - *avg = readSum / numReads; +void pwm_sixstep(uint16_t lo1, uint16_t hi1, uint16_t lo2, uint16_t hi2, uint16_t lo3, uint16_t hi3){ + TCC1.CCABUFL = (uint8_t) lo1; + TCC1.CCABUFH = (uint8_t) (lo1 >> 8); + TCC1.CCBBUFL = (uint8_t) hi1; + TCC1.CCBBUFH = (uint8_t) (hi1 >> 8); + + TCC0.CCCBUFL = (uint8_t) lo2; + TCC0.CCCBUFH = (uint8_t) (lo2 >> 8); + TCC0.CCDBUFL = (uint8_t) hi2; + TCC0.CCDBUFH = (uint8_t) (hi2 >> 8); + + TCC0.CCABUFL = (uint8_t) lo3; + TCC0.CCABUFH = (uint8_t) (lo3 >> 8); + TCC0.CCBBUFL = (uint8_t) hi3; + TCC0.CCBBUFH = (uint8_t) (hi3 >> 8); } void pwm_init(void){ // setup awex etc - pin_init(&lo1, &PORTC, PIN4_bm, 4, 1); - pin_init(&hi1, &PORTC, PIN5_bm, 5, 1); - pin_init(&lo2, &PORTC, PIN2_bm, 2, 1); - pin_init(&hi2, &PORTC, PIN3_bm, 3, 1); - pin_init(&lo3, &PORTC, PIN0_bm, 0, 1); - pin_init(&hi3, &PORTC, PIN1_bm, 1, 1); + pin_init(&lo1, &PORTC, PIN4_bm, 4, 1); // TCC1 OC1A + pin_init(&hi1, &PORTC, PIN5_bm, 5, 1); // TCC1 OC1B + + pin_init(&lo2, &PORTC, PIN2_bm, 2, 1); // TCC0 OC0C + pin_init(&hi2, &PORTC, PIN3_bm, 3, 1); // TCC0 OC0D + + pin_init(&lo3, &PORTC, PIN0_bm, 0, 1); // TCC0 OC0A + pin_init(&hi3, &PORTC, PIN1_bm, 1, 1); // TCC0 OC0B // compare and capture at value uint16_t per = 1024; // at DIV1, 1024 period is 23.5kHz @@ -143,10 +145,22 @@ void pwm_init(void){ uint8_t perl = (uint8_t) per; uint8_t perh = (uint8_t) (per >> 8); + // PWM for 6-step commutation + TCC0.CTRLA = TC_CLKSEL_DIV1_gc; + TCC1.CTRLA = TC_CLKSEL_DIV1_gc; + TCC0.PERBUFL = perl; TCC0.PERBUFH = perh; + TCC1.PERBUFL = perl; + TCC1.PERBUFH = perh; + + TCC0.CTRLB = TC_WGMODE_DS_T_gc | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4); + TCC1.CTRLB = TC_WGMODE_DS_T_gc | (1 << 5) | (1 << 4); + + /* + // PWM for three complimentary pairs: // turnt to dual-slope pwm to have center aligned, and eventually sampling on top event TCC0.CTRLB = TC_WGMODE_DS_T_gc;// | (1 << 7) | (1 << 6) | (1 << 5); // dual slope, and enable channels a, b, c for capture @@ -156,6 +170,7 @@ void pwm_init(void){ AWEXC.OUTOVEN = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5); pwm_periods(0, 0, 0); + */ } void drv_init(void){ @@ -172,7 +187,7 @@ void drv_init(void){ pin_clear(&drvModePwm); // low for 6-channel pwm, hi and lo sides from uc pin_set(&drvModeGain); // low for 10v/v, hi for 40v/v current sense gains pin_clear(&drvDcCal); // turn DC cal off, we turn this high to set midpoint on amps - pin_clear(&drvEnPin); // disable the gate driver, to start. also broken by no/go hardware switch + pin_clear(&drvEnPin); // disable the gate driver, to start. also broken by no/go hardware switch } void drv_enable(void){ @@ -187,7 +202,7 @@ void tickers_init(void){ // sets up two timers // compare and capture at value - uint16_t perStartSpeed = 1024; + uint16_t perStartSpeed = 1024; // 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); @@ -236,48 +251,69 @@ int main(void) // initialize the bldc state structure bldc_init(&bldc); - bldc_setTargetSpeed(&bldc, 1000); - bldc_setDuty(&bldc, 45); // MAX 512, dangerous above ~ 120 - - // start the timers that do work - tickers_init(); + bldc_setTargetSpeed(&bldc, 800); bldc_setSpeed(&bldc, 100); + bldc.currentSpeed = 100; + bldc_setDuty(&bldc, 52); // MAX 512, dangerous above ~ 120 + // startup the driver drv_init(); // and enable the gate drv_enable(); + // start the timers that do work + tickers_init(); + // runtime globals uint32_t tck = 0; while (1) { atkport_scan(&atkp0, 2); - // just... as fast as we can - tck++; - // this modulo op is slow AF - // that means streamlining atkport_scan without modulos is probably a rad thing - if(!(fastModulo(tck, 4096))){ - pin_toggle(&stlclk); - } + // just... as fast as we can + tck++; + if(!(fastModulo(tck, 4096))){ + pin_toggle(&stlclk); + } } } // commutation timer ISR(TCD0_OVF_vect){ - // open-loop commutation + // open-loop commutation (bldc.comDir) ? (bldc.comState ++) : (bldc.comState --); if(bldc.comState > 5){ bldc.comState = 0; } - pwm_by_offset( comTable[bldc.comState][0] * bldc.comDuty, + uint8_t cs = bldc.comState; + uint16_t dt = bldc.comDuty; + + uint16_t clo1 = ct[cs][0]; + clo1 *= dt; + uint16_t chi1 = ct[cs][1]; + chi1 *= dt; + uint16_t clo2 = ct[cs][2]; + clo2 *= dt; + uint16_t chi2 = ct[cs][3]; + chi2 *= dt; + uint16_t clo3 = ct[cs][4]; + clo3 *= dt; + uint16_t chi3 = ct[cs][5]; + chi3 *= dt; + + // ct is comtable + pwm_sixstep(clo1, chi1, clo2, chi2, clo3, chi3); + + /* + // here is PWM for sinusoid-type pwm setup + pwm_by_offset(comTable[bldc.comState][0] * bldc.comDuty, comTable[bldc.comState][1] * bldc.comDuty, comTable[bldc.comState][2] * bldc.comDuty ); - + */ /* // CL 6-step Commutate @@ -288,7 +324,7 @@ ISR(TCD0_OVF_vect){ // target phase expressed in 0 - 2PI, where 2PI in terms of an encoder counts' worth of ticks // we add the encoder's resolution here so that we can safely have negative encoder offsets phase_target = (enc_resolution + enc_reading + enc_offset + pi_enc) % twoPi_enc; - // we need to compute the respective pwm positions given the phase target + // we need to compute the respective pwm positions given the phase target pwm_by_sin_duty(phase_target, 0.75); */ } diff --git a/embedded/atkbldcdriver/atkbldcdriver/sinelut.h b/embedded/atkbldcdriver/atkbldcdriver/sinelut.h index cb5f273c98a3d8f867fb368f1a6addb131e9d928..98f8a3786a59a39eec10606c52fef804bd9271c7 100644 --- a/embedded/atkbldcdriver/atkbldcdriver/sinelut.h +++ b/embedded/atkbldcdriver/atkbldcdriver/sinelut.h @@ -160,13 +160,13 @@ const static int16_t sinelut[2340] = { }; -const static int8_t comTable[6][3] = { - {1,-1,0}, - {1,0,-1}, - {0,1,-1}, - {-1,1,0}, - {-1,0,1}, - {0,-1,1} +const static int8_t ct[6][6] = { + {0,1,1,0,0,0}, // hi1, lo2 + {0,1,0,0,1,0}, // hi1, lo3 + {0,0,0,1,1,0}, // hi2, lo3 + {1,0,0,1,0,0}, // hi2, lo1 + {1,0,0,0,0,1}, // hi3, lo1 + {0,0,1,0,0,1}, // hi3, lo2 }; #endif /* SINELUT_H_ */ \ No newline at end of file