1
0
forked from me/IronOS

Compare commits

..

1 Commits

Author SHA1 Message Date
Ben V. Brown
586267f586 PID retune, ADC Blocks PID properly 2018-04-13 16:19:05 +10:00
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.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" 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 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.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/> <language-scope id="org.eclipse.cdt.core.g++"/>
</provider> </provider>
@@ -18,7 +18,7 @@
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" 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 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.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/> <language-scope id="org.eclipse.cdt.core.g++"/>
</provider> </provider>

View File

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

View File

@@ -134,11 +134,12 @@ static void MX_ADC1_Init(void) {
sConfigInjected.InjectedChannel = ADC_CHANNEL_8; sConfigInjected.InjectedChannel = ADC_CHANNEL_8;
sConfigInjected.InjectedRank = 1; sConfigInjected.InjectedRank = 1;
sConfigInjected.InjectedNbrOfConversion = 4; sConfigInjected.InjectedNbrOfConversion = 4;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_13CYCLES_5; sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_7CYCLES_5;
sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T2_CC1; sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T2_CC1;
sConfigInjected.AutoInjectedConv = DISABLE; sConfigInjected.AutoInjectedConv = DISABLE;
sConfigInjected.InjectedDiscontinuousConvMode = DISABLE; sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
sConfigInjected.InjectedOffset = 0; sConfigInjected.InjectedOffset = 0;
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected); HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
sConfigInjected.InjectedRank = 2; sConfigInjected.InjectedRank = 2;
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected); HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
@@ -146,14 +147,14 @@ static void MX_ADC1_Init(void) {
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected); HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
sConfigInjected.InjectedRank = 4; sConfigInjected.InjectedRank = 4;
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected); 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 */ /* I2C1 init function */
static void MX_I2C1_Init(void) { static void MX_I2C1_Init(void) {
hi2c1.Instance = I2C1; hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 300000; //200Khz hi2c1.Init.ClockSpeed = 300000; //300Khz
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; 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. * It takes 4 milliseconds for output to be stable after PWM turns off.
* Assume ADC samples in 0.5ms * 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.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;

View File

@@ -60,35 +60,17 @@ uint16_t getTipInstantTemperature() {
} }
uint16_t getTipRawTemp(uint8_t instant) { uint16_t getTipRawTemp(uint8_t instant) {
#define filterDepth1 1 static int64_t filterFP = 0;
/*Pre filter used before PID*/ const uint8_t filterBeta = 5; //higher values smooth out more, but reduce responsiveness
#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;
if (instant) { if (instant) {
uint16_t itemp = getTipInstantTemperature(); uint16_t itemp = getTipInstantTemperature();
filterLayer1[index] = itemp; filterFP = (filterFP << filterBeta) - filterFP;
index = (index + 1) % filterDepth1; filterFP += (itemp << 9);
uint32_t total = 0; filterFP = filterFP >> filterBeta;
for (uint8_t i = 0; i < filterDepth1; i++) return itemp;
total += filterLayer1[i];
return total / filterDepth1;
} else { } else {
uint32_t total = 0; return filterFP >> 9;
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;
} }
} }
uint16_t getInputVoltageX10(uint8_t divisor) { uint16_t getInputVoltageX10(uint8_t divisor) {
@@ -120,15 +102,10 @@ uint8_t getTipPWM() {
return htim2.Instance->CCR4; return htim2.Instance->CCR4;
} }
void setTipPWM(uint8_t pulse) { 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) if (pulse > 100)
pulse = 100; pulse = 100;
if (pulse) { htim2.Instance->CCR4 = pulse;
htim2.Instance->CCR4 = pulse;
} else {
htim2.Instance->CCR4 = 0;
}
} }
//Thse are called by the HAL after the corresponding events from the system timers. //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) { if (htim->Instance == TIM2) {
//we want to turn on the output again //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. 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) { if (htim2.Instance->CCR4 && PWMSafetyTimer) {
htim3.Instance->CCR1 = 50; htim3.Instance->CCR1 = 50;
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
@@ -159,12 +136,9 @@ void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
htim3.Instance->CCR1 = 0; htim3.Instance->CCR1 = 0;
} /*else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { } /*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_13, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_14, 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 PIDTaskHandle;
osThreadId ROTTaskHandle; osThreadId ROTTaskHandle;
osThreadId MOVTaskHandle; osThreadId MOVTaskHandle;
SemaphoreHandle_t rotationChangedSemaphore = NULL;
SemaphoreHandle_t accelDataAvailableSemaphore = NULL; static TaskHandle_t pidTaskNotification = NULL;
void startGUITask(void const *argument); void startGUITask(void const *argument);
void startPIDTask(void const *argument); void startPIDTask(void const *argument);
@@ -62,7 +62,7 @@ int main(void) {
PCBVersion = 3; PCBVersion = 3;
systemSettings.SleepTime = 0; systemSettings.SleepTime = 0;
systemSettings.ShutdownTime = 0; //No accel -> disable sleep systemSettings.ShutdownTime = 0; //No accel -> disable sleep
systemSettings.sensitivity=0; systemSettings.sensitivity = 0;
} }
HAL_IWDG_Refresh(&hiwdg); HAL_IWDG_Refresh(&hiwdg);
restoreSettings(); // load the settings from flash restoreSettings(); // load the settings from flash
@@ -85,11 +85,7 @@ int main(void) {
osThreadDef(MOVTask, startMOVTask, osPriorityNormal, 0, 512); //2k osThreadDef(MOVTask, startMOVTask, osPriorityNormal, 0, 512); //2k
MOVTaskHandle = osThreadCreate(osThread(MOVTask), NULL); 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 */ /* Start scheduler */
osKernelStart(); osKernelStart();
@@ -98,7 +94,7 @@ int main(void) {
} }
} }
void GUIDelay() { void GUIDelay() {
osDelay(50); // 20Hz osDelay(66); // 15Hz
} }
void gui_drawTipTemp() { void gui_drawTipTemp() {
// Draw tip temp handling unit conversion & tolerance near setpoint // Draw tip temp handling unit conversion & tolerance near setpoint
@@ -762,7 +758,7 @@ void startGUITask(void const *argument) {
currentlyActiveTemperatureTarget = 0; // ensure tip is off 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) { if (tipTemp < 50) {
@@ -854,17 +850,20 @@ void startPIDTask(void const *argument) {
int32_t kp, ki, kd; int32_t kp, ki, kd;
kp = 40; kp = 40;
ki = 60; ki = 60;
kd = 20; kd = 15;
// REMEBER ^^^^ These constants are backwards // REMEBER ^^^^ These constants are backwards
// They act as dividers, so to 'increase' a P term, you make the number // They act as dividers, so to 'increase' a P term, you make the number
// smaller. // smaller.
if(getInputVoltageX10(systemSettings.voltageDiv) < 150) if (getInputVoltageX10(systemSettings.voltageDiv) < 150) {
{
//Boot P term if < 15 Volts //Boot P term if < 15 Volts
kp=30; kp = 30;
} }
const int32_t itermMax = 100; const int32_t itermMax = 100;
pidTaskNotification = xTaskGetCurrentTaskHandle();
uint32_t ulNotificationValue;
for (;;) { 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 uint16_t rawTemp = getTipRawTemp(1); // get instantaneous reading
if (currentlyActiveTemperatureTarget) { if (currentlyActiveTemperatureTarget) {
// Compute the PID loop in here // Compute the PID loop in here
@@ -900,9 +899,9 @@ void startPIDTask(void const *argument) {
output = 0; output = 0;
} }
if (currentlyActiveTemperatureTarget < rawTemp) { /*if (currentlyActiveTemperatureTarget < rawTemp) {
output = 0; output = 0;
} }*/
setTipPWM(output); setTipPWM(output);
derivativeLastValue = rawTemp; // store for next loop derivativeLastValue = rawTemp; // store for next loop
@@ -914,12 +913,11 @@ void startPIDTask(void const *argument) {
} }
HAL_IWDG_Refresh(&hiwdg); HAL_IWDG_Refresh(&hiwdg);
osDelay(10); // 100 Hz temp loop
} }
} }
#define MOVFilter 8 #define MOVFilter 8
void startMOVTask(void const *argument) { void startMOVTask(void const *argument) {
osDelay(4000); // wait for accel to stabilize osDelay(250); // wait for accelerometer to stabilize
lastMovementTime = 0; lastMovementTime = 0;
int16_t datax[MOVFilter]; int16_t datax[MOVFilter];
int16_t datay[MOVFilter]; int16_t datay[MOVFilter];
@@ -936,10 +934,6 @@ void startMOVTask(void const *argument) {
uint32_t max = 0; uint32_t max = 0;
#endif #endif
if (PCBVersion == 3) {
for (;;)
osDelay(5000);
}
for (;;) { for (;;) {
int32_t threshold = 1500 + (9 * 200); int32_t threshold = 1500 + (9 * 200);
threshold -= systemSettings.sensitivity * 200; // 200 is the step size 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 * This task is used to manage rotation of the LCD screen & button re-mapping
* *
*/ */
if (PCBVersion == 3) {
for (;;)
osDelay(5000);
}
switch (systemSettings.OrientationMode) { switch (systemSettings.OrientationMode) {
case 0: case 0:
lcd.setRotation(false); lcd.setRotation(false);
@@ -1026,7 +1016,7 @@ void startRotationTask(void const *argument) {
default: default:
break; break;
} }
osDelay(500); // wait for accel to stabilize osDelay(250); // wait for accel to stabilize
for (;;) { for (;;) {
@@ -1077,3 +1067,18 @@ bool showBootLogoIfavailable() {
lcd.refresh(); lcd.refresh();
return true; 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);
}
}