1
0
forked from me/IronOS

PID retune, ADC Blocks PID properly

This commit is contained in:
Ben V. Brown
2018-04-13 16:19:05 +10:00
parent f2f20111b6
commit 586267f586
5 changed files with 59 additions and 73 deletions

View File

@@ -6,7 +6,7 @@
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="fr.ac6.mcu.ide.build.CrossBuiltinSpecsDetector" console="false" env-hash="1750838549288477430" id="fr.ac6.mcu.ide.build.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="Ac6 SW4 STM32 MCU Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="fr.ac6.mcu.ide.build.CrossBuiltinSpecsDetector" console="false" env-hash="1349131645423570210" id="fr.ac6.mcu.ide.build.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="Ac6 SW4 STM32 MCU Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -18,7 +18,7 @@
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="fr.ac6.mcu.ide.build.CrossBuiltinSpecsDetector" console="false" env-hash="1750838549288477430" id="fr.ac6.mcu.ide.build.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="Ac6 SW4 STM32 MCU Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="fr.ac6.mcu.ide.build.CrossBuiltinSpecsDetector" console="false" env-hash="1349131645423570210" id="fr.ac6.mcu.ide.build.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="Ac6 SW4 STM32 MCU Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

View File

@@ -25,5 +25,11 @@ enum ButtonState {
ButtonState getButtonState();
void waitForButtonPressOrTimeout(uint32_t timeout);
#ifdef __cplusplus
extern "C" {
#endif
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc);
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */

View File

@@ -134,11 +134,12 @@ static void MX_ADC1_Init(void) {
sConfigInjected.InjectedChannel = ADC_CHANNEL_8;
sConfigInjected.InjectedRank = 1;
sConfigInjected.InjectedNbrOfConversion = 4;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_13CYCLES_5;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_7CYCLES_5;
sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T2_CC1;
sConfigInjected.AutoInjectedConv = DISABLE;
sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
sConfigInjected.InjectedOffset = 0;
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
sConfigInjected.InjectedRank = 2;
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
@@ -146,14 +147,14 @@ static void MX_ADC1_Init(void) {
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
sConfigInjected.InjectedRank = 4;
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
//SET_BIT(hadc1.Instance->CR1, ( ADC_CR1_JEOCIE ));//Enable end of injected conv irq
SET_BIT(hadc1.Instance->CR1, ( ADC_CR1_JEOCIE ));//Enable end of injected conv irq
}
/* I2C1 init function */
static void MX_I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 300000; //200Khz
hi2c1.Init.ClockSpeed = 300000; //300Khz
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
@@ -256,7 +257,7 @@ static void MX_TIM2_Init(void) {
/*
* It takes 4 milliseconds for output to be stable after PWM turns off.
* Assume ADC samples in 0.5ms
* We need to set this to 100% + 4.5ms
* We need to set this to 100% + 5.5ms
* */
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;

View File

@@ -60,35 +60,17 @@ uint16_t getTipInstantTemperature() {
}
uint16_t getTipRawTemp(uint8_t instant) {
#define filterDepth1 1
/*Pre filter used before PID*/
#define filterDepth2 48
/*Post filter used for UI display*/
static uint16_t filterLayer1[filterDepth1];
static uint16_t filterLayer2[filterDepth2];
static uint8_t index = 0;
static uint8_t indexFilter = 0;
static int64_t filterFP = 0;
const uint8_t filterBeta = 5; //higher values smooth out more, but reduce responsiveness
if (instant) {
uint16_t itemp = getTipInstantTemperature();
filterLayer1[index] = itemp;
index = (index + 1) % filterDepth1;
uint32_t total = 0;
for (uint8_t i = 0; i < filterDepth1; i++)
total += filterLayer1[i];
return total / filterDepth1;
filterFP = (filterFP << filterBeta) - filterFP;
filterFP += (itemp << 9);
filterFP = filterFP >> filterBeta;
return itemp;
} else {
uint32_t total = 0;
for (uint8_t i = 0; i < filterDepth1; i++)
total += filterLayer1[i];
filterLayer2[indexFilter] = total / filterDepth1;
indexFilter = (indexFilter + 1) % filterDepth2;
total = 0;
for (uint8_t i = 0; i < filterDepth2; i++)
total += filterLayer2[i];
return total / filterDepth2;
return filterFP >> 9;
}
}
uint16_t getInputVoltageX10(uint8_t divisor) {
@@ -120,15 +102,10 @@ uint8_t getTipPWM() {
return htim2.Instance->CCR4;
}
void setTipPWM(uint8_t pulse) {
PWMSafetyTimer = 640; //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 = 2; //This is decremented in the handler for PWM so that the tip pwm is disabled if the PID task is not scheduled often enough.
if (pulse > 100)
pulse = 100;
if (pulse) {
htim2.Instance->CCR4 = pulse;
} else {
htim2.Instance->CCR4 = 0;
}
htim2.Instance->CCR4 = pulse;
}
//Thse are called by the HAL after the corresponding events from the system timers.
@@ -138,7 +115,7 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM2) {
//we want to turn on the output again
PWMSafetyTimer--; //We decrement this safety value so that lockups in the scheduler will not cause the PWM to become locked in an active driving state.
//While we could assume this could never happened, its a small price for increased safety
//While we could assume this could never happen, its a small price for increased safety
if (htim2.Instance->CCR4 && PWMSafetyTimer) {
htim3.Instance->CCR1 = 50;
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
@@ -159,12 +136,9 @@ void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
htim3.Instance->CCR1 = 0;
} /*else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_14, GPIO_PIN_RESET);
}*/
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_14, GPIO_PIN_RESET);
}*/
}
}
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc) {
}

View File

@@ -27,8 +27,8 @@ osThreadId GUITaskHandle;
osThreadId PIDTaskHandle;
osThreadId ROTTaskHandle;
osThreadId MOVTaskHandle;
SemaphoreHandle_t rotationChangedSemaphore = NULL;
SemaphoreHandle_t accelDataAvailableSemaphore = NULL;
static TaskHandle_t pidTaskNotification = NULL;
void startGUITask(void const *argument);
void startPIDTask(void const *argument);
@@ -62,7 +62,7 @@ int main(void) {
PCBVersion = 3;
systemSettings.SleepTime = 0;
systemSettings.ShutdownTime = 0; //No accel -> disable sleep
systemSettings.sensitivity=0;
systemSettings.sensitivity = 0;
}
HAL_IWDG_Refresh(&hiwdg);
restoreSettings(); // load the settings from flash
@@ -85,11 +85,7 @@ int main(void) {
osThreadDef(MOVTask, startMOVTask, osPriorityNormal, 0, 512); //2k
MOVTaskHandle = osThreadCreate(osThread(MOVTask), NULL);
}
/* Create the objects*/
rotationChangedSemaphore = xSemaphoreCreateBinary();
// Used to unlock rotation thread
accelDataAvailableSemaphore = xSemaphoreCreateBinary();
// Used to unlock the movement thread
/* Start scheduler */
osKernelStart();
@@ -98,7 +94,7 @@ int main(void) {
}
}
void GUIDelay() {
osDelay(50); // 20Hz
osDelay(66); // 15Hz
}
void gui_drawTipTemp() {
// Draw tip temp handling unit conversion & tolerance near setpoint
@@ -762,7 +758,7 @@ void startGUITask(void const *argument) {
currentlyActiveTemperatureTarget = 0; // ensure tip is off
uint16_t tipTemp = tipMeasurementToC(getTipRawTemp(1));//This forces a faster update rate on the filtering
uint16_t tipTemp = tipMeasurementToC(getTipRawTemp(1)); //This forces a faster update rate on the filtering
if (tipTemp < 50) {
@@ -854,17 +850,20 @@ void startPIDTask(void const *argument) {
int32_t kp, ki, kd;
kp = 40;
ki = 60;
kd = 20;
kd = 15;
// REMEBER ^^^^ These constants are backwards
// They act as dividers, so to 'increase' a P term, you make the number
// smaller.
if(getInputVoltageX10(systemSettings.voltageDiv) < 150)
{
if (getInputVoltageX10(systemSettings.voltageDiv) < 150) {
//Boot P term if < 15 Volts
kp=30;
kp = 30;
}
const int32_t itermMax = 100;
pidTaskNotification = xTaskGetCurrentTaskHandle();
uint32_t ulNotificationValue;
for (;;) {
ulNotificationValue = ulTaskNotifyTake( pdTRUE, 100);//Wait a max of 100ms
//This is a call to block this thread until the ADC does its samples
uint16_t rawTemp = getTipRawTemp(1); // get instantaneous reading
if (currentlyActiveTemperatureTarget) {
// Compute the PID loop in here
@@ -900,9 +899,9 @@ void startPIDTask(void const *argument) {
output = 0;
}
if (currentlyActiveTemperatureTarget < rawTemp) {
/*if (currentlyActiveTemperatureTarget < rawTemp) {
output = 0;
}
}*/
setTipPWM(output);
derivativeLastValue = rawTemp; // store for next loop
@@ -914,12 +913,11 @@ void startPIDTask(void const *argument) {
}
HAL_IWDG_Refresh(&hiwdg);
osDelay(10); // 100 Hz temp loop
}
}
#define MOVFilter 8
void startMOVTask(void const *argument) {
osDelay(4000); // wait for accel to stabilize
osDelay(250); // wait for accelerometer to stabilize
lastMovementTime = 0;
int16_t datax[MOVFilter];
int16_t datay[MOVFilter];
@@ -936,10 +934,6 @@ void startMOVTask(void const *argument) {
uint32_t max = 0;
#endif
if (PCBVersion == 3) {
for (;;)
osDelay(5000);
}
for (;;) {
int32_t threshold = 1500 + (9 * 200);
threshold -= systemSettings.sensitivity * 200; // 200 is the step size
@@ -1009,10 +1003,6 @@ void startRotationTask(void const *argument) {
* This task is used to manage rotation of the LCD screen & button re-mapping
*
*/
if (PCBVersion == 3) {
for (;;)
osDelay(5000);
}
switch (systemSettings.OrientationMode) {
case 0:
lcd.setRotation(false);
@@ -1026,7 +1016,7 @@ void startRotationTask(void const *argument) {
default:
break;
}
osDelay(500); // wait for accel to stabilize
osDelay(250); // wait for accel to stabilize
for (;;) {
@@ -1077,3 +1067,18 @@ bool showBootLogoIfavailable() {
lcd.refresh();
return true;
}
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (pidTaskNotification) {
/* Notify the task that the transmission is complete. */
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
/* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
should be performed to ensure the interrupt returns directly to the highest
priority task. The macro used for this purpose is dependent on the port in
use and may be called portEND_SWITCHING_ISR(). */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}