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+=
./%.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: $<
......
......@@ -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>
......
......@@ -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);
*/
}
......
......@@ -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
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