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