1
0
forked from me/IronOS

Retune PID, improve response rate slightly. (But slightly more oscillation)

This commit is contained in:
Ben V. Brown
2017-08-02 21:38:42 +10:00
parent b0264be3c5
commit 90599a8ae6
8 changed files with 90 additions and 51 deletions

View File

@@ -18,6 +18,7 @@
#include "Analog.h"
#include "MMA8652FC.h"
#include <string.h>
typedef enum {
STARTUP, //we are sitting on the prompt to push a button
SOLDERING, //Normal operating mode
@@ -31,8 +32,12 @@ typedef enum {
TEMPCAL, //Cal tip temp offset
} operatingModeEnum;
#define SETTINGSOPTIONSCOUNT 11 /*Number of settings in the settings menu*/
//#define PIDTUNING
#ifdef PIDTUNING
#define SETTINGSOPTIONSCOUNT (11+3) /*Number of settings in the settings menu*/
#else
#define SETTINGSOPTIONSCOUNT (11) /*Number of settings in the settings menu*/
#endif
typedef enum {
UVCO = 0,
SLEEP_TEMP,
@@ -46,6 +51,11 @@ typedef enum {
BOOSTMODE,
BOOSTTEMP,
POWERDISPLAY,
#ifdef PIDTUNING
PIDP,
PIDI,
PIDD,
#endif
} settingsPageEnum;
void ProcessUI();

View File

@@ -18,4 +18,5 @@ typedef struct {
int32_t computePID(uint16_t setpoint);
void setupPID(void);
extern pidSettingsType pidSettings;
#endif /* PID_H_ */

View File

@@ -23,7 +23,7 @@ uint16_t readDCVoltage(uint16_t divFactor) {
//This allows us to read it in X10 mode
//Returns temperature in C X10 mode
int16_t readTipTemp() {
static uint32_t rollingAverage[16];
static uint32_t rollingAverage[8];
static uint8_t rIndex = 0;
/*The head has a thermocouple inline with the heater
@@ -54,13 +54,10 @@ int16_t readTipTemp() {
ad_sum = ad_sum - max - min; //remove the two outliers
avg_data = ad_sum / 8; //take the average
rollingAverage[rIndex] = avg_data;
rIndex = (rIndex + 1) % 16;
rIndex = (rIndex + 1) % 8;
return (rollingAverage[0] + rollingAverage[1] + rollingAverage[2]
+ rollingAverage[3] + rollingAverage[4] + rollingAverage[5]
+ rollingAverage[6] + rollingAverage[7] + rollingAverage[8]
+ rollingAverage[9] + rollingAverage[10] + rollingAverage[11]
+ rollingAverage[12] + rollingAverage[13] + rollingAverage[14]
+ rollingAverage[15]) / 16; //get the average
+ rollingAverage[6] + rollingAverage[7]) / 8;
}

View File

@@ -81,7 +81,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
volatile int I2C_TimeOut = 0;
// /* While the bus is busy * /
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -92,7 +92,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
I2C_GenerateSTART(I2C1, ENABLE);
// / * Test on EV5 and clear it * /
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -103,7 +103,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
I2C_Send7bitAddress(I2C1, deviceAddr, I2C_Direction_Transmitter);
// / * Test on EV6 and clear it * /
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -114,7 +114,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
I2C_SendData(I2C1, readAddr);
/// * Test on EV8 and clear it * /
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -125,7 +125,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
I2C_GenerateSTART(I2C1, ENABLE);
/// * Test on EV5 and clear it * /
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -137,7 +137,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
if (numByteToRead == 1) {
/* Wait until ADDR is set */
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while ((I2C1->SR1 & 0x0002) != 0x0002) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -155,7 +155,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
/* Re-enable IRQs */
__enable_irq();
/* Wait until a data is received in DR register (RXNE = 1) EV7 */
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while ((I2C1->SR1 & 0x00040) != 0x000040) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -169,7 +169,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
/* Set POS bit */
I2C1->CR1 |= CR1_POS_Set;
/* Wait until ADDR is set: EV6 */
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while ((I2C1->SR1 & 0x0002) != 0x0002) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -186,7 +186,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
/*Re-enable IRQs */
__enable_irq();
/* Wait until BTF is set */
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while ((I2C1->SR1 & 0x00004) != 0x000004) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -210,7 +210,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
else { //numByteToRead > 2
// * Test on EV6 and clear it * /
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while (!I2C_CheckEvent(I2C1,
I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {
if (I2C_TimeOut-- <= 0) {
@@ -223,7 +223,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
if (numByteToRead != 3) {
/* Poll on BTF to receive data because in polling mode we can not guarantee the
EV7 software sequence is managed before the current byte transfer completes */
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while ((I2C1->SR1 & 0x00004) != 0x000004) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -239,7 +239,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
/* it remains to read three data: data N-2, data N-1, Data N */
if (numByteToRead == 3) {
/* Wait until BTF is set: Data N-2 in DR and data N -1 in shift register */
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while ((I2C1->SR1 & 0x00004) != 0x000004) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -263,7 +263,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
/* Increment */
pBuffer++;
/* Wait until RXNE is set (DR contains the last data) */
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while ((I2C1->SR1 & 0x00040) != 0x000040) {
if (I2C_TimeOut-- <= 0) {
return 1;
@@ -278,7 +278,7 @@ int I2C_Master_Read(uint8_t deviceAddr, uint8_t readAddr, uint8_t* pBuffer,
}
/* Make sure that the STOP bit is cleared by Hardware before CR1 write access */
I2C_TimeOut = 3000;
I2C_TimeOut = 1000;
while ((I2C1->CR1 & 0x200) == 0x200) {
if (I2C_TimeOut-- <= 0) {
return 1;

View File

@@ -24,7 +24,7 @@ uint8_t getButtons() {
//We want to check the times for the lat buttons & also the rawKeys state
//If a key has just gone down, rawKeys & KEY ==1
uint8_t out = 0;
if (millis() - AkeyChange > 30) {
if (millis() - AkeyChange > 100) {
if (LongKeys & BUT_A) {
if (rawKeys & BUT_A) {
if (millis() - AkeyChange > 800) {
@@ -41,7 +41,7 @@ uint8_t getButtons() {
} else if (LongKeys & (BUT_A << 2)) {
if (rawKeys & BUT_A) {
if (millis() - AkeyChange > 300) {
if (millis() - AkeyChange > 100) {
out |= BUT_A;
AkeyChange = millis();
}
@@ -61,7 +61,7 @@ uint8_t getButtons() {
}
}
}
if (millis() - BkeyChange > 30) {
if (millis() - BkeyChange > 100) {
if (LongKeys & BUT_B) {
if (rawKeys & BUT_B) {
if (millis() - BkeyChange > 800) {
@@ -76,7 +76,7 @@ uint8_t getButtons() {
}
} else if (LongKeys & (BUT_B << 2)) {
if (rawKeys & BUT_B) {
if (millis() - BkeyChange > 300) {
if (millis() - BkeyChange > 100) {
out |= BUT_B;
BkeyChange = millis();
}

View File

@@ -18,7 +18,7 @@ int main(void) {
Clear_Watchdog(); //reset the Watch dog timer
ProcessUI();
DrawUI();
delayMs(50); //Slow the system down a little bit
delayMs(30); //Slow the system down a little bit
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5) == Bit_RESET) {
lastMovement = millis();
//This is a workaround for the line staying low as the user is still moving. (ie sensitivity is too high for their amount of movement)
@@ -39,13 +39,13 @@ void setup() {
setupPID(); //Init the PID values
readIronTemp(systemSettings.tempCalibration, 0, 0); //load the default calibration value
if (systemSettings.OrientationMode == 2)
Init_Oled(!getOrientation()); //Init the OLED display
Init_Oled(0); //Init the OLED display in RH mode, since accel wont have started up yet
else
Init_Oled(systemSettings.OrientationMode); //Init the OLED display
Init_Oled(systemSettings.OrientationMode); //Init the OLED display
OLED_DrawString("VER 1.16", 8); //Version Number
delayMs(400); //Pause to show version number
delayMs(400); //Pause to show version number
showBootLogoIfavailable();
Start_Watchdog(5000); //start the system watch dog as 5 second timeout
Start_Watchdog(5000); //start the system watch dog as 5 second timeout
}

View File

@@ -27,7 +27,6 @@ void ProcessUI() {
uint8_t Buttons = getButtons(); //read the buttons status
static uint32_t lastModeChange = 0;
switch (operatingMode) {
case STARTUP:
@@ -175,7 +174,7 @@ void ProcessUI() {
case SLEEP_TEMP:
systemSettings.SleepTemp += 100; //Go up 10C at a time
if (systemSettings.SleepTemp > 3000)
systemSettings.SleepTemp = 1000;//cant sleep higher than 300
systemSettings.SleepTemp = 500; //cant sleep higher than 300 or less than 50
break;
case SLEEP_TIME:
++systemSettings.SleepTime; //Go up 1 minute at a time
@@ -194,7 +193,8 @@ void ProcessUI() {
break;
case SCREENROTATION:
systemSettings.OrientationMode++;
systemSettings.OrientationMode = systemSettings.OrientationMode % 3;
systemSettings.OrientationMode =
systemSettings.OrientationMode % 3;
break;
case MOTIONSENSITIVITY:
@@ -225,6 +225,20 @@ void ProcessUI() {
case POWERDISPLAY:
systemSettings.powerDisplay = !systemSettings.powerDisplay;
break;
#ifdef PIDTUNING
case PIDP:
pidSettings.kp++;
pidSettings.kp %= 20;
break;
case PIDI:
pidSettings.ki++;
pidSettings.ki %= 10;
break;
case PIDD:
pidSettings.kd++;
pidSettings.kd %= 30;
break;
#endif
default:
break;
}
@@ -474,7 +488,7 @@ void DrawUI() {
if (systemSettings.powerDisplay) {
//We want to draw in a neat little bar graph of power being pushed to the tip
//ofset 11
uint16_t count = getIronTimer() / (30000 / 28);
uint16_t count = getIronTimer() / (1000 / 28);
if (count > 28)
count = 28;
OLED_DrawWideChar((count), 6);
@@ -641,7 +655,22 @@ void DrawUI() {
break;
}
break;
#ifdef PIDTUNING
case PIDP:
OLED_DrawString("PIDP ", 5);
OLED_DrawThreeNumber(pidSettings.kp, 5);
break;
case PIDI:
OLED_DrawString("PIDI ", 5);
OLED_DrawThreeNumber(pidSettings.ki, 5);
break;
case PIDD:
OLED_DrawString("PIDD ", 5);
OLED_DrawThreeNumber(pidSettings.kd, 5);
break;
#endif
default:
break;
}
}

View File

@@ -7,38 +7,40 @@
#include "PID.h"
#define MAXPIDOUTPUT 50000
//MAXPIDOUTPUT is the maximum time duration we can support for the irons output, as anything longer than this will be cut off by the next PID iteration
pidSettingsType pidSettings;
//This function computes the new value for the ON time of the system
//This is the return value from this function
int32_t computePID(uint16_t setpoint) {
int32_t ITerm = 0;
static int16_t lastReading = 0;
uint16_t currentReading = readIronTemp(0, 1,setpoint); //get the current temp of the iron
static int32_t ITerm = 0; //Used to store the integral error
static int16_t lastError = 0;
uint16_t currentReading = readIronTemp(0, 1, setpoint); //get the current temp of the iron
int16_t error = (int16_t) setpoint - (int16_t) currentReading; //calculate the error term
ITerm += (pidSettings.ki * error);
if (ITerm > MAXPIDOUTPUT/2)
ITerm = MAXPIDOUTPUT/2;
else if (ITerm < 0)
ITerm = 0; //cap at 0 since we cant force the iron to cool itself :)
int16_t DInput = (error - lastError) / 10; //compute the input to the D term
int16_t DInput = (currentReading - lastReading); //compute the input to the D term
int32_t output = (pidSettings.kp * error) + (ITerm)
ITerm += ((error) / 20);
if (ITerm > 300)
ITerm = 0; //Prevents this accumulating too much during inital heatup
else if (ITerm < 0)
ITerm = 0; //Cap at 0 as we can't force cool
if (DInput > 1000)
DInput = 0;
int32_t output = (pidSettings.kp * error) + (ITerm * pidSettings.ki)
- (pidSettings.kd * DInput);
if (output > MAXPIDOUTPUT)
output = MAXPIDOUTPUT;
else if (output < 0)
output = 0;
lastReading = currentReading; //storing values for next iteration of the loop
lastError = error;
return output;
}
/*Sets up the pid values*/
/*Sets up the pid values to defaults*/
void setupPID(void) {
pidSettings.kp = 15;
pidSettings.ki = 2;
pidSettings.kd = 3;
pidSettings.kp = 8;
pidSettings.ki = 1;
pidSettings.kd = 0; //Not using D atm
}