Files
IronOS/workspace/ts100/src/CTRL.c
Ben V. Brown 624fbe8e3f Commenting through most of the remaining files.
Fixing logic errors throughout as well
2016-09-13 23:50:51 +10:00

451 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/********************* (C) COPYRIGHT 2015 e-Design Co.,Ltd. **********************
File Name : CTRL.c
Version : S100 APP Ver 2.11
Description:
Author : Celery
Data: 2015/08/03
History:
2015/07/07 ͳһ<CDB3><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2015/08/03 <20>Ż<EFBFBD><C5BB>ƶ<EFBFBD><C6B6>ж<EFBFBD>
*******************************************************************************/
#include <stdio.h>
#include <string.h>
#include "CTRL.h"
#include "Bios.h"
#include "UI.h"
#include "Hardware.h"
#include "S100V0_1.h"
#include "Disk.h"
#include "MMA8652FC.h"
#define HEATINGCYCLE 30
/******************************************************************************/
DEVICE_INFO_SYS device_info;
/******************************************************************************/
u8 gCtrl_status = 1;
//^ System current status / operating mode.
u16 gHt_flag = 0;
vs16 gTemp_data = 250; //
s16 gPrev_temp = 250; //
u8 gIs_restartkey = 0; //
u8 gPre_status = 1; //
const DEVICE_INFO_SYS info_def = { "2.13", //Ver
2000, //T_Standby; // 200C=1800 2520
3000, // T_Work; // 350C=3362,
100, //T_Step;
3 * 60 * 100, //Wait_Time; //3*60*100 3 minutes
6 * 60 * 100 // Idle_Time; //6*60*100 6 minutes
};
struct _pid {
s16 settemp; //Current ideal setpoint for the temp
s16 actualtemp; //Actual current temp of the tip
s16 err; //Error term
s16 err_last; //last error term
s32 ht_time; //
u16 kp, ki, kd; //Constants for the PID Controller
s32 integral; //
} pid;
/*******************************************************************************
Function: Get_Ctrl_Status
Description: Returns the current operating Mode
Input:Void
Output:Current System Status
*******************************************************************************/
u8 Get_CtrlStatus(void) {
return gCtrl_status;
}
/*******************************************************************************
Function: Set_CtrlStatus
Description: Set the current operating Mode
Input:status uint8_t
Output:Void
*******************************************************************************/
void Set_CtrlStatus(u8 status) {
gCtrl_status = status;
}
/*******************************************************************************
Function: Set_PrevTemp
Description:Set the previous temp record for the PID
Input:Previous Temp (int16_t)
Output:Void
*******************************************************************************/
void Set_PrevTemp(s16 temp) {
gPrev_temp = temp;
}
/*******************************************************************************
Function: Get_HtFlag
Description:
Input:Void
Output:Void
*******************************************************************************/
u16 Get_HtFlag(void) {
return gHt_flag;
}
/*******************************************************************************
Function:Get_TempVal
Description:
Input:Void
Output:Void
*******************************************************************************/
s16 Get_TempVal(void) {
return gTemp_data;
}
/*******************************************************************************
Function:System_Init
Description:Init the device info to be a known start value (as defined at top of CTRL.c)
Input:Void
Output:Void
*******************************************************************************/
void System_Init(void) {
memcpy((void*) &device_info, (void*) &info_def, sizeof(device_info));
}
/*******************************************************************************
Function:Pid_Init
Description:Inits the PID values to defaults (0 usually)
Input:Void
Output:Void
*******************************************************************************/
void Pid_Init(void) {
pid.settemp = 0;
pid.actualtemp = 0;
pid.err = 0;
pid.err_last = 0;
pid.integral = 0;
pid.ht_time = 0;
pid.kp = 15;
pid.ki = 2;
pid.kd = 1;
}
/*******************************************************************************
Function:Pid_Realize
Description: Calculates the next heating value using the PID algorithum
Input:Current temp from the tip
Output:
*******************************************************************************/
u16 Pid_Realize(s16 temp) {
u8 index = 0, index1 = 1;
s16 d_err = 0;
pid.actualtemp = temp;
pid.err = pid.settemp - pid.actualtemp; //
if (pid.err >= 500)
index = 0;
else {
index = 1;
pid.integral += pid.err; //
}
////////////////////////////////////////////////////////////////////////////////
//
if (pid.settemp < pid.actualtemp) {
d_err = pid.actualtemp - pid.settemp;
if (d_err > 20) {
pid.integral = 0; //
index1 = 0;
index = 0;
}
}
////////////////////////////////////////////////////////////////////////////////
if (pid.err <= 30)
index1 = 0;
else
index1 = 1;
pid.ht_time = pid.kp * pid.err + pid.ki * index * pid.integral
+ pid.kd * (pid.err - pid.err_last) * index1;
pid.err_last = pid.err;
if (pid.ht_time <= 0)
pid.ht_time = 0;
else if (pid.ht_time > 30 * 200)
pid.ht_time = 30 * 200;
return pid.ht_time;
}
/*******************************************************************************
Function:Heating_Time
Description:Calcuates the on time for the heating element
Input: (temp) current Tip Temp, (wk_temp) current ideal setpoint temp
Output: The ON time for the heater element
*******************************************************************************/
u32 Heating_Time(s16 temp, s16 wk_temp) {
u32 heat_timecnt;
pid.settemp = wk_temp;
if (wk_temp > temp) {
if (wk_temp - temp >= 18)
gHt_flag = 0; //<2F><><EFBFBD><EFBFBD>
else
gHt_flag = 2; //<2F><><EFBFBD><EFBFBD>
} else {
if (temp - wk_temp <= 18)
gHt_flag = 2; //<2F><><EFBFBD><EFBFBD>
else
gHt_flag = 1; //<2F><><EFBFBD><EFBFBD>
}
heat_timecnt = Pid_Realize(temp); //Sub_data * 1000;
return heat_timecnt;
}
/*******************************************************************************
Function:Status_Tran
Description: Handles the current status of the unit, and task selection
Basically this is called in main() repeatedly
Input:Void
Output:Void
*******************************************************************************/
void Status_Tran(void) //
{
static u16 init_waitingtime = 0; //<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>־λ: 0=> δ<><CEB4>ʼ<EFBFBD><CABC>,1=><3E>ѳ<EFBFBD>ʼ<EFBFBD><CABC>
static u8 back_prestatus = 0;
s16 heat_timecnt = 0, wk_temp;
u16 mma_active;
switch (Get_CtrlStatus()) {
case IDLE:
switch (Get_gKey()) { //Read current switch positions
case KEY_V1: //If V1 key is pressed
if (gIs_restartkey != 1) { //check we are not in a soft restart situation
if (Read_Vb(1) < 4) { //Read that the input voltage is acceptable??
Set_CtrlStatus(TEMP_CTR); //Set to temperature controlled mode (Aka soldering mode)
init_waitingtime = 0; //Initialize the wait count to 0
TEMPSHOW_TIMER= 0; //Initialize the timer to 0
UI_TIMER= 0;
G6_TIMER= 0;
}
}
break;
case KEY_V2: //check if V2 key is pressed
if(gIs_restartkey != 1) { //check this is not a soft restart situation
Set_CtrlStatus(THERMOMETER);//Change system to Thermometer mode instead (ie reading temp only, no drive)
UI_TIMER = 0;
Set_LongKeyFlag(1);//Set the long key pressed flag??
}
break;
case KEY_CN|KEY_V3: //If A&B pressed at the same time, no action
break;
}
if(gIs_restartkey && (KD_TIMER == 0)) { //This is a soft restart situation instead
gIs_restartkey = 0;//reset the flag for soft restart
Set_gKey(NO_KEY);//reset keys pressed
}
if(Read_Vb(1) == 0) { //Invalid voltage, I think this means no input power detected
if(Get_UpdataFlag() == 1) Set_UpdataFlag(0);
Set_CtrlStatus(ALARM);
}
if(gPre_status != WAIT && gPre_status != IDLE) { //System has been left alone, turn off screen to stop burn in
G6_TIMER = device_info.idle_time;
Set_gKey(NO_KEY);
gPre_status = IDLE;
}
break;
case TEMP_CTR: //We are in soldering mode
switch(Get_gKey()) { //switch on the pressed key
case KEY_CN|KEY_V1:
case KEY_CN|KEY_V2://if either key long pressed
Set_HeatingTime(0);//turn off heater
Set_CtrlStatus(TEMP_SET);//Goto temperature set mode
HEATING_TIMER = 0;//reset heating timer
EFFECTIVE_KEY_TIMER = 500;
break;
case KEY_CN|KEY_V3://Both keys pressed
Set_HeatingTime(0);//Stop the heater
Set_LongKeyFlag(0);//Reset the long key press flag
Set_CtrlStatus(IDLE);//Change the system back to IDLE state (stop soldering)
gPre_status = TEMP_CTR;//Set previous status
gIs_restartkey = 1;
KD_TIMER = 50;//
break;
}
if(Read_Vb(1) >= 4) { //Check input voltage is in the acceptable range
Set_HeatingTime(0);//Turn of heater as we are out of range
Set_LongKeyFlag(0);//reset key flag
Set_CtrlStatus(IDLE);//reset to IDLE state
gPre_status = TEMP_CTR;//set previous state
gIs_restartkey = 1;
KD_TIMER = 50;//
}
wk_temp = device_info.t_work; //update setpoint temp from the struct
if(HEATING_TIMER == 0) {
gTemp_data = Get_Temp(wk_temp);
heat_timecnt = Heating_Time(gTemp_data,wk_temp); //Calculate the on time for the heating cycle
Set_HeatingTime(heat_timecnt);//set the on time for the heating cycle
HEATING_TIMER = HEATINGCYCLE;
}
if(Get_HeatingTime() == 0) { //If calcuated heater time is 0 stop the timer ?
HEATING_TIMER = 0;
}
/*
* The logic here is :
* If the device is moving then disarm the timer and mark it as needed a re-init
* else check if the timer needs init, if it does set it up and exit
* if the timer does not need init, then check if the timer has expired (its a count down)
* If the timer has expired goto wait state instead and shutdown iron
*/
mma_active = Get_MmaShift(); //check the accelerometer for movement
if(mma_active == 0) { //MMA_active = 0 ==> static ,MMA_active = 1 ==>move
if(init_waitingtime == 0) { //If the waiting countdown timer is not initialized
init_waitingtime = 1;//we initialize it and set this <- flag.
ENTER_WAIT_TIMER = device_info.wait_time;
}
if((init_waitingtime != 0) && (ENTER_WAIT_TIMER == 0)) { //if timeout has been initalized and enter_wait_timer has reached 0
gHt_flag = 0;//reset heating flags
UI_TIMER = 0;//reset ui timers
Set_HeatingTime(0);//turn off the soldering iron
Set_gKey(0);//clear keys
G6_TIMER = device_info.idle_time;//set the device to idle timer move
Set_CtrlStatus(WAIT);//Set system mode to waiting for movement
}
} else { //The iron is moving
init_waitingtime = 0;//mark the waiting timer for needing reset if movement stops again
}
if(Get_AlarmType() > NORMAL_TEMP) { //
if(Get_UpdataFlag() == 1) Set_UpdataFlag(0);
Set_CtrlStatus(ALARM);//Change to alarm state
}
break;
case WAIT:
//This mode (WAIT) occures when the iron has been idling on a desk for too long (ie someone forgot it was left on)
//In this state we drop to a lower, safer temp and wait for movement or button push to wake up to operating temp again
wk_temp = device_info.t_standby;
if(device_info.t_standby > device_info.t_work) {
//Check if the set temp was greater than the idle temp, if it was we set the idle temp to the set temp
//This is done to avoid standby going to a higher temp
wk_temp = device_info.t_work;
}
//if the heating timer has expired, update the readings
if(HEATING_TIMER == 0) {
gTemp_data = Get_Temp(wk_temp); //read the tip temp
heat_timecnt = Heating_Time(gTemp_data,wk_temp);//calculate the new heating timer value from temps
Set_HeatingTime(heat_timecnt);//apply the new heating timer
HEATING_TIMER = 30;//set update rate for heating_timer
}
if(Read_Vb(1) >= 4) { //If the input voltage is not valid
Set_HeatingTime(0);//turn off heater
Set_LongKeyFlag(0);//reset key press flag
Set_CtrlStatus(IDLE);//goto IDLE state
G6_TIMER = device_info.idle_time;
gPre_status = WAIT;//set previous state
gIs_restartkey = 1;
KD_TIMER = 50;//
}
if(G6_TIMER == 0) { //
Set_HeatingTime(0);
Set_LongKeyFlag(0);
gIs_restartkey = 1;
KD_TIMER = 200;//
gPre_status = WAIT;
Set_CtrlStatus(IDLE);
}
//If movement has occurred OR a key has been pressed -> Wakeup back to soldering
mma_active = Get_MmaShift();//read accelerometer
if(mma_active == 1 || Get_gKey() != 0) {
UI_TIMER = 0; //reset the un-needed timers
G6_TIMER = 0;
init_waitingtime = 0;
Set_CtrlStatus(TEMP_CTR);//Go back to soldering iron mode
}
if(Get_AlarmType() > NORMAL_TEMP) { //If an alarm has occurred??
if(Get_UpdataFlag() == 1) Set_UpdataFlag(0);
Set_CtrlStatus(ALARM);//goto alarm error state
}
break;
case TEMP_SET: //We are in the setting soldering iron temp mode
if(EFFECTIVE_KEY_TIMER == 0) {
gCalib_flag = 1;
Disk_BuffInit();
Config_Analysis(); //
gCalib_flag = 0;
Set_CtrlStatus(TEMP_CTR);//return to soldering mode
TEMPSHOW_TIMER = 0;//turn off the timer
}
break;
case THERMOMETER: //we are measuring the tip temp without applying any power
if(KD_TIMER > 0) {
Set_gKey(NO_KEY);
break;
}
switch(Get_gKey()) {
case KEY_CN|KEY_V1:
case KEY_CN|KEY_V2:
back_prestatus = 1;
break;
case KEY_CN|KEY_V3:
Zero_Calibration(); //Calibrate the temperature (i think??)
if(Get_CalFlag() == 1) {
Disk_BuffInit();
Config_Analysis(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>U<EFBFBD><55>
}
KD_TIMER = 200; //20150717 <20>޸<EFBFBD>
break;
default:
break;
}
if(back_prestatus == 1) { //we are exiting
back_prestatus = 0;//clear flag
Set_HeatingTime(0);//turn off heater? (not sure why this is done again)
Set_CtrlStatus(IDLE);//Goto IDLE state
gPre_status = THERMOMETER;//set previous state
gIs_restartkey = 1;//signal soft restart required as we may have done a calibration
Set_LongKeyFlag(0);//reset long key hold flag
KD_TIMER = 50;//
}
break;
case ALARM: //An error has occured so we are in alarm state
switch(Get_AlarmType()) {
case HIGH_TEMP: //over temp condition
case SEN_ERR://sensor reading error
wk_temp = device_info.t_work;
gTemp_data = Get_Temp(wk_temp);
if(Get_AlarmType() == NORMAL_TEMP) {
Set_CtrlStatus(TEMP_CTR);
Set_UpdataFlag(0);
}
break;
case HIGH_VOLTAGE: //over voltage
case LOW_VOLTAGE://under voltage
if(Read_Vb(1) >= 1 && Read_Vb(1) <= 3) {
Set_HeatingTime(0); //turn off heater
Set_LongKeyFlag(0);//reset key flag
gIs_restartkey = 1;
UI_TIMER = 2;// 2<><32>
gPre_status = THERMOMETER;
Set_CtrlStatus(IDLE);
}
break;
}
//V-- No idea what this does yet.. At all.. since it will always be skipped..
if(Get_HeatingTime != 0) {
Set_HeatingTime(0); //<2F><><EFBFBD><EFBFBD>ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD>
HEAT_OFF();
}
break;
default:
break;
}
}
/******************************** END OF FILE *********************************/