Commit 8539995e authored by Jake Read's avatar Jake Read

six step with fullly individual waveforms

parent c58120a5
...@@ -141,7 +141,7 @@ LINKER_SCRIPT_DEP+= ...@@ -141,7 +141,7 @@ LINKER_SCRIPT_DEP+=
./%.o: .././%.c ./%.o: .././%.c
@echo Building file: $< @echo Building file: $<
@echo Invoking: AVR/GNU C Compiler : 5.4.0 @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: $< @echo Finished building: $<
......
...@@ -109,41 +109,41 @@ ...@@ -109,41 +109,41 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings> <ToolchainSettings>
<AvrGcc> <AvrGcc>
<avrgcc.common.Device>-mmcu=atxmega256a3u -B "%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\gcc\dev\atxmega256a3u"</avrgcc.common.Device> <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.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec> <avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures> <avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols> <avrgcc.compiler.symbols.DefSymbols>
<ListValues> <ListValues>
<Value>DEBUG</Value> <Value>DEBUG</Value>
</ListValues> </ListValues>
</avrgcc.compiler.symbols.DefSymbols> </avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths> <avrgcc.compiler.directories.IncludePaths>
<ListValues> <ListValues>
<Value>%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\include</Value> <Value>%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\include</Value>
</ListValues> </ListValues>
</avrgcc.compiler.directories.IncludePaths> </avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level> <avrgcc.compiler.optimization.level>Optimize more (-O2)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers> <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel> <avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings> <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.linker.libraries.Libraries> <avrgcc.linker.libraries.Libraries>
<ListValues> <ListValues>
<Value>libm</Value> <Value>libm</Value>
</ListValues> </ListValues>
</avrgcc.linker.libraries.Libraries> </avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths> <avrgcc.assembler.general.IncludePaths>
<ListValues> <ListValues>
<Value>%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\include</Value> <Value>%24(PackRepoDir)\atmel\XMEGAA_DFP\1.1.68\include</Value>
</ListValues> </ListValues>
</avrgcc.assembler.general.IncludePaths> </avrgcc.assembler.general.IncludePaths>
<avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel> <avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>
</AvrGcc> </AvrGcc>
</ToolchainSettings> </ToolchainSettings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "sinelut.h" #include "sinelut.h"
// first setup all the pins // 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){ void clock_init(void){
OSC.XOSCCTRL = OSC_XOSCSEL_XTAL_256CLK_gc | OSC_FRQRANGE_12TO16_gc; // select external source OSC.XOSCCTRL = OSC_XOSCSEL_XTAL_256CLK_gc | OSC_FRQRANGE_12TO16_gc; // select external source
...@@ -48,7 +48,7 @@ void encoder_init(void){ ...@@ -48,7 +48,7 @@ void encoder_init(void){
pin_init(&spiEncCsPin, &PORTD, PIN4_bm, 4, 1); pin_init(&spiEncCsPin, &PORTD, PIN4_bm, 4, 1);
spi_init(&spiEncoder, &USARTD1, &PORTD, PIN6_bm, PIN7_bm, PIN5_bm, &spiEncCsPin); spi_init(&spiEncoder, &USARTD1, &PORTD, PIN6_bm, PIN7_bm, PIN5_bm, &spiEncCsPin);
spi_start(&spiEncoder, 1); spi_start(&spiEncoder, 1);
// startup object // startup object
ams5047_init(&ams5047, &spiEncoder); ams5047_init(&ams5047, &spiEncoder);
} }
...@@ -66,7 +66,7 @@ static uint16_t enc_reading = 0; ...@@ -66,7 +66,7 @@ static uint16_t enc_reading = 0;
static uint16_t phase_target = 0; static uint16_t phase_target = 0;
// 2^14 = 16,384 // 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 // check overrun
(peru > 1024) ? peru = 1024 : (0); (peru > 1024) ? peru = 1024 : (0);
(perv > 1024) ? perv = 1024 : (0); (perv > 1024) ? perv = 1024 : (0);
...@@ -84,16 +84,16 @@ void pwm_periods(uint16_t peru, uint16_t perv, uint16_t perw){ ...@@ -84,16 +84,16 @@ void pwm_periods(uint16_t peru, uint16_t perv, uint16_t perw){
TCC0.CCCBUFH = (uint8_t) (peru >> 8); 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 // +ve offset to spend more time with hi-side off, signals are complimentary
uint16_t peru = 512 + ofu; uint16_t peru = 512 + ofu;
uint16_t perv = 512 + ofv; uint16_t perv = 512 + ofv;
uint16_t perw = 512 + ofw; uint16_t perw = 512 + ofw;
// now through business // 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 // phases respective of home
int16_t pu = phase; int16_t pu = phase;
(pu >= twoPi_enc) ? (pu -= twoPi_enc) : (0); (pu >= twoPi_enc) ? (pu -= twoPi_enc) : (0);
...@@ -107,35 +107,37 @@ void pwm_by_sin_duty(uint16_t phase, float duty){ ...@@ -107,35 +107,37 @@ void pwm_by_sin_duty(uint16_t phase, float duty){
int16_t perv = ((sinelut[pv] - 512) * duty) + 512; int16_t perv = ((sinelut[pv] - 512) * duty) + 512;
int16_t perw = ((sinelut[pw] - 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]; void pwm_sixstep(uint16_t lo1, uint16_t hi1, uint16_t lo2, uint16_t hi2, uint16_t lo3, uint16_t hi3){
uint8_t readIndex = 0; TCC1.CCABUFL = (uint8_t) lo1;
TCC1.CCABUFH = (uint8_t) (lo1 >> 8);
void putReading(uint16_t reading){ TCC1.CCBBUFL = (uint8_t) hi1;
readings[readIndex] = reading; TCC1.CCBBUFH = (uint8_t) (hi1 >> 8);
readIndex ++;
} TCC0.CCCBUFL = (uint8_t) lo2;
TCC0.CCCBUFH = (uint8_t) (lo2 >> 8);
void getReadAverage(uint16_t *avg){ TCC0.CCDBUFL = (uint8_t) hi2;
uint8_t numReads = readIndex; // sloppy, but makes this interrupt safe TCC0.CCDBUFH = (uint8_t) (hi2 >> 8);
uint32_t readSum = 0;
for(uint8_t i = 0; i < numReads; i ++){ TCC0.CCABUFL = (uint8_t) lo3;
readSum += readings[i]; TCC0.CCABUFH = (uint8_t) (lo3 >> 8);
} TCC0.CCBBUFL = (uint8_t) hi3;
*avg = readSum / numReads; TCC0.CCBBUFH = (uint8_t) (hi3 >> 8);
} }
void pwm_init(void){ void pwm_init(void){
// setup awex etc // setup awex etc
pin_init(&lo1, &PORTC, PIN4_bm, 4, 1); pin_init(&lo1, &PORTC, PIN4_bm, 4, 1); // TCC1 OC1A
pin_init(&hi1, &PORTC, PIN5_bm, 5, 1); pin_init(&hi1, &PORTC, PIN5_bm, 5, 1); // TCC1 OC1B
pin_init(&lo2, &PORTC, PIN2_bm, 2, 1);
pin_init(&hi2, &PORTC, PIN3_bm, 3, 1); pin_init(&lo2, &PORTC, PIN2_bm, 2, 1); // TCC0 OC0C
pin_init(&lo3, &PORTC, PIN0_bm, 0, 1); pin_init(&hi2, &PORTC, PIN3_bm, 3, 1); // TCC0 OC0D
pin_init(&hi3, &PORTC, PIN1_bm, 1, 1);
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 // compare and capture at value
uint16_t per = 1024; // at DIV1, 1024 period is 23.5kHz uint16_t per = 1024; // at DIV1, 1024 period is 23.5kHz
...@@ -143,10 +145,22 @@ void pwm_init(void){ ...@@ -143,10 +145,22 @@ void pwm_init(void){
uint8_t perl = (uint8_t) per; uint8_t perl = (uint8_t) per;
uint8_t perh = (uint8_t) (per >> 8); uint8_t perh = (uint8_t) (per >> 8);
// PWM for 6-step commutation
TCC0.CTRLA = TC_CLKSEL_DIV1_gc; TCC0.CTRLA = TC_CLKSEL_DIV1_gc;
TCC1.CTRLA = TC_CLKSEL_DIV1_gc;
TCC0.PERBUFL = perl; TCC0.PERBUFL = perl;
TCC0.PERBUFH = perh; 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 // 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 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){ ...@@ -156,6 +170,7 @@ void pwm_init(void){
AWEXC.OUTOVEN = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5); AWEXC.OUTOVEN = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
pwm_periods(0, 0, 0); pwm_periods(0, 0, 0);
*/
} }
void drv_init(void){ void drv_init(void){
...@@ -172,7 +187,7 @@ 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_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_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(&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){ void drv_enable(void){
...@@ -187,7 +202,7 @@ void tickers_init(void){ ...@@ -187,7 +202,7 @@ void tickers_init(void){
// sets up two timers // sets up two timers
// compare and capture at value // 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 // write low first, bc bussing / xmega 8-bit oddities cc datasheet @ 3.11
uint8_t perSl = (uint8_t) perStartSpeed; uint8_t perSl = (uint8_t) perStartSpeed;
uint8_t perSh = (uint8_t) (perStartSpeed >> 8); uint8_t perSh = (uint8_t) (perStartSpeed >> 8);
...@@ -236,48 +251,69 @@ int main(void) ...@@ -236,48 +251,69 @@ int main(void)
// initialize the bldc state structure // initialize the bldc state structure
bldc_init(&bldc); bldc_init(&bldc);
bldc_setTargetSpeed(&bldc, 1000); bldc_setTargetSpeed(&bldc, 800);
bldc_setDuty(&bldc, 45); // MAX 512, dangerous above ~ 120
// start the timers that do work
tickers_init();
bldc_setSpeed(&bldc, 100); bldc_setSpeed(&bldc, 100);
bldc.currentSpeed = 100;
bldc_setDuty(&bldc, 52); // MAX 512, dangerous above ~ 120
// startup the driver // startup the driver
drv_init(); drv_init();
// and enable the gate // and enable the gate
drv_enable(); drv_enable();
// start the timers that do work
tickers_init();
// runtime globals // runtime globals
uint32_t tck = 0; uint32_t tck = 0;
while (1) while (1)
{ {
atkport_scan(&atkp0, 2); atkport_scan(&atkp0, 2);
// just... as fast as we can // just... as fast as we can
tck++; tck++;
// this modulo op is slow AF if(!(fastModulo(tck, 4096))){
// that means streamlining atkport_scan without modulos is probably a rad thing pin_toggle(&stlclk);
if(!(fastModulo(tck, 4096))){ }
pin_toggle(&stlclk);
}
} }
} }
// commutation timer // commutation timer
ISR(TCD0_OVF_vect){ ISR(TCD0_OVF_vect){
// open-loop commutation // open-loop commutation
(bldc.comDir) ? (bldc.comState ++) : (bldc.comState --); (bldc.comDir) ? (bldc.comState ++) : (bldc.comState --);
if(bldc.comState > 5){ if(bldc.comState > 5){
bldc.comState = 0; 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][1] * bldc.comDuty,
comTable[bldc.comState][2] * bldc.comDuty comTable[bldc.comState][2] * bldc.comDuty
); );
*/
/* /*
// CL 6-step Commutate // CL 6-step Commutate
...@@ -288,7 +324,7 @@ ISR(TCD0_OVF_vect){ ...@@ -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 // 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 // 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; 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); pwm_by_sin_duty(phase_target, 0.75);
*/ */
} }
......
...@@ -160,13 +160,13 @@ const static int16_t sinelut[2340] = { ...@@ -160,13 +160,13 @@ const static int16_t sinelut[2340] = {
}; };
const static int8_t comTable[6][3] = { const static int8_t ct[6][6] = {
{1,-1,0}, {0,1,1,0,0,0}, // hi1, lo2
{1,0,-1}, {0,1,0,0,1,0}, // hi1, lo3
{0,1,-1}, {0,0,0,1,1,0}, // hi2, lo3
{-1,1,0}, {1,0,0,1,0,0}, // hi2, lo1
{-1,0,1}, {1,0,0,0,0,1}, // hi3, lo1
{0,-1,1} {0,0,1,0,0,1}, // hi3, lo2
}; };
#endif /* SINELUT_H_ */ #endif /* SINELUT_H_ */
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment