Add support for dual speed PWM
This commit is contained in:
@@ -10,6 +10,12 @@
|
||||
#include "systick.h"
|
||||
#include <IRQ.h>
|
||||
|
||||
const uint16_t powerPWM = 255;
|
||||
const uint8_t holdoffTicks = 13; // delay of 7 ms
|
||||
const uint8_t tempMeasureTicks = 17;
|
||||
|
||||
uint16_t totalPWM; //htim2.Init.Period, the full PWM cycle
|
||||
|
||||
//2 second filter (ADC is PID_TIM_HZ Hz)
|
||||
history<uint16_t, PID_TIM_HZ> rawTempFilter = { { 0 }, 0, 0 };
|
||||
void resetWatchdog() {
|
||||
@@ -58,7 +64,6 @@ uint16_t getHandleTemperature() {
|
||||
}
|
||||
uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
|
||||
|
||||
|
||||
static uint8_t preFillneeded = 10;
|
||||
static uint32_t samples[BATTFILTERDEPTH];
|
||||
static uint8_t index = 0;
|
||||
@@ -84,24 +89,24 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
|
||||
}
|
||||
|
||||
void unstick_I2C() {
|
||||
/* configure SDA/SCL for GPIO */
|
||||
GPIO_BC(GPIOB) |= SDA_Pin|SCL_Pin;
|
||||
gpio_init(SDA_GPIO_Port,GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin);
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
GPIO_BOP(GPIOB) |= SCL_Pin;
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
GPIO_BOP(GPIOB) |= SDA_Pin;
|
||||
/* connect PB6 to I2C0_SCL */
|
||||
/* connect PB7 to I2C0_SDA */
|
||||
gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin);
|
||||
/* configure SDA/SCL for GPIO */
|
||||
GPIO_BC(GPIOB) |= SDA_Pin | SCL_Pin;
|
||||
gpio_init(SDA_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin);
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
GPIO_BOP(GPIOB) |= SCL_Pin;
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
GPIO_BOP(GPIOB) |= SDA_Pin;
|
||||
/* connect PB6 to I2C0_SCL */
|
||||
/* connect PB7 to I2C0_SDA */
|
||||
gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin);
|
||||
}
|
||||
|
||||
uint8_t getButtonA() {
|
||||
@@ -120,3 +125,5 @@ void reboot() {
|
||||
void delay_ms(uint16_t count) {
|
||||
delay_1ms(count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -55,13 +55,54 @@ void TIMER1_IRQHandler(void) {
|
||||
}
|
||||
|
||||
void setTipPWM(uint8_t pulse) {
|
||||
PWMSafetyTimer = 10;
|
||||
// This is decremented in the handler for PWM so that the tip pwm is
|
||||
// disabled if the PID task is not scheduled often enough.
|
||||
|
||||
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
|
||||
// disabled if the PID task is not scheduled often enough.
|
||||
pendingPWM = pulse;
|
||||
}
|
||||
|
||||
static bool fastPWM;
|
||||
static void switchToFastPWM(void) {
|
||||
fastPWM = true;
|
||||
totalPWM = powerPWM + tempMeasureTicks * 2;
|
||||
TIMER_CAR(TIMER1) = (uint32_t)totalPWM;
|
||||
|
||||
// ~3.5 Hz rate
|
||||
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks * 2;
|
||||
//1 kHz tick rate
|
||||
TIMER_PSC(TIMER1) = 12000;
|
||||
/* generate an update event */
|
||||
TIMER_SWEVG(TIMER1) |= (uint32_t) TIMER_SWEVG_UPG;
|
||||
|
||||
}
|
||||
|
||||
static void switchToSlowPWM(void) {
|
||||
fastPWM = false;
|
||||
totalPWM = powerPWM + tempMeasureTicks;
|
||||
TIMER_CAR(TIMER1) = (uint32_t)totalPWM;
|
||||
// ~1.84 Hz rate
|
||||
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks;
|
||||
// 500 Hz tick rate
|
||||
TIMER_PSC(TIMER1) = 24000;
|
||||
/* generate an update event */
|
||||
TIMER_SWEVG(TIMER1) |= (uint32_t) TIMER_SWEVG_UPG;
|
||||
|
||||
}
|
||||
|
||||
bool tryBetterPWM(uint8_t pwm) {
|
||||
if (fastPWM && pwm == powerPWM) {
|
||||
// maximum power for fast PWM reached, need to go slower to get more
|
||||
switchToSlowPWM();
|
||||
return true;
|
||||
} else if (!fastPWM && pwm < 230) {
|
||||
// 254 in fast PWM mode gives the same power as 239 in slow
|
||||
// allow for some reasonable hysteresis by switching only when it goes
|
||||
// below 230 (equivalent to 245 in fast mode)
|
||||
switchToFastPWM();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EXTI5_9_IRQHandler(void) {
|
||||
#ifdef POW_PD
|
||||
if (RESET != exti_interrupt_flag_get(EXTI_5)) {
|
||||
|
||||
@@ -211,7 +211,7 @@ void setup_timers() {
|
||||
timer_initpara.prescaler = 24000;
|
||||
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
|
||||
timer_initpara.counterdirection = TIMER_COUNTER_UP;
|
||||
timer_initpara.period = 255 + 17;
|
||||
timer_initpara.period = powerPWM + tempMeasureTicks;
|
||||
timer_initpara.clockdivision = TIMER_CKDIV_DIV4;
|
||||
timer_initpara.repetitioncounter = 0;
|
||||
timer_init(TIMER1, &timer_initpara);
|
||||
@@ -222,7 +222,7 @@ void setup_timers() {
|
||||
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
|
||||
timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara);
|
||||
|
||||
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, 255 + 13);
|
||||
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, powerPWM + holdoffTicks);
|
||||
timer_channel_output_mode_config(TIMER1, TIMER_CH_0,
|
||||
TIMER_OC_MODE_PWM1);
|
||||
timer_channel_output_shadow_config(TIMER1, TIMER_CH_0,
|
||||
|
||||
@@ -19,5 +19,6 @@ void setupFUSBIRQ();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern const uint8_t holdoffTicks;
|
||||
extern const uint8_t tempMeasureTicks;
|
||||
#endif /* SETUP_H_ */
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "OLED.hpp"
|
||||
// Second last page of flash set aside for logo image.
|
||||
#define FLASH_LOGOADDR (0x8000000 | 0xF800)
|
||||
//TODO
|
||||
// Logo header signature.
|
||||
#define LOGO_HEADER_VALUE 0xF00DAA55
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ static uint32_t availableW10(uint8_t sample) {
|
||||
//P = V^2 / R, v*v = v^2 * 100
|
||||
// R = R*10
|
||||
// P therefore is in V^2*100/R*10 = W*10.
|
||||
uint32_t v = getInputVoltageX10(systemSettings.voltageDiv, sample); // 100 = 10v
|
||||
uint32_t v = getInputVoltageX10(systemSettings.voltageDiv, sample); // 100 = 10v
|
||||
uint32_t availableWattsX10 = (v * v) / tipResistance;
|
||||
//However, 100% duty cycle is not possible as there is a dead time while the ADC takes a reading
|
||||
//Therefore need to scale available milliwats by this
|
||||
@@ -53,8 +53,6 @@ uint8_t X10WattsToPWM(int32_t milliWatts, uint8_t sample) {
|
||||
getInputVoltageX10(systemSettings.voltageDiv, sample);
|
||||
return 0;
|
||||
}
|
||||
// if (milliWatts > (int(systemSettings.pidPowerLimit) * 10))
|
||||
// milliWatts = (int(systemSettings.pidPowerLimit) * 10);
|
||||
|
||||
//Calculate desired milliwatts as a percentage of availableW10
|
||||
uint32_t pwm;
|
||||
@@ -74,5 +72,4 @@ static int32_t PWMToX10Watts(uint8_t pwm, uint8_t sample) {
|
||||
uint32_t maxMW = availableW10(sample); //Get the milliwatts for the max pwm period
|
||||
//Then convert pwm into percentage of powerPWM to get the percentage of the max mw
|
||||
return (((uint32_t) pwm) * maxMW) / powerPWM;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user