/* * calibration_screen.c * * Created on: Jan 12, 2021 * Author: David Original work by Jose (PTDreamer), 2017 */ #include "calibration_screen.h" #include "settings_screen.h" #include "oled.h" #include "gui.h" typedef enum {cal_250, cal_350, cal_450, cal_suceed, cal_failed, cal_needsAdjust}state_t; static uint32_t temp; static bool error; static uint32_t errorTimer; static uint32_t screenTimer; static uint16_t adjustSetPoint; static uint32_t lastUpdateTick; static int16_t lastTipTemp; static uint16_t backupTemp; static bool backupTempUnit; static uint16_t backupCal250; static uint16_t backupCal350; static uint16_t backupCal450; const static uint16_t state_temps[3] = {250, 350, 450}; static char* state_tempstr[3] = {"250C", "350C", "450C"}; static uint16_t measured_temps[3]; static uint16_t adcAtTemp[3]; static state_t current_state = cal_250; static uint8_t tempReady; static int32_t measuredTemp; static uint16_t adcCal[3]; static uint8_t processCalibration(); static tipData * Currtip; screen_t Screen_edit_calibration; screen_t Screen_edit_calibration_start; screen_t Screen_edit_calibration_adjust; screen_t Screen_edit_calibration_input; static widget_t comboWidget_Cal; static comboBox_widget_t comboBox_Cal; static comboBox_item_t Cal_Combo_Start; static comboBox_item_t Cal_Combo_Adjust; static comboBox_item_t Cal_Combo_Exit; static widget_t Widget_Cal_Start_Cancel; static button_widget_t button_Cal_Start_Cancel; static widget_t comboWidget_Cal_Adjust; static comboBox_widget_t comboBox_Cal_Adjust; static comboBox_item_t Cal_Combo_Adjust_Target; static comboBox_item_t Cal_Combo_Adjust_Setpoint; static comboBox_item_t Cal_Combo_Adjust_Save; static comboBox_item_t Cal_Combo_Adjust_Cancel; static widget_t Widget_Cal_Adjust_Select; static editable_widget_t editable_Cal_Adjust_Select; static widget_t Widget_Cal_Adjust_Setpoint; static editable_widget_t editable_Cal_Adjust_Setpoint; static widget_t Widget_Cal_Input_Measured; static editable_widget_t editable_Cal_Input_Measured; static widget_t Widget_Cal_Input_Cancel; static button_widget_t button_Cal_Input_Cancel; static widget_t Widget_Cal_Input_OK; static button_widget_t button_Cal_Input_OK; static void tempReached(uint16_t temp) { if(temp == state_temps[(int)current_state]) tempReady = 1; } static setTemperatureReachedCallback tempReachedCallback = &tempReached; static void *getMeasuredTemp() { return &measuredTemp; } static void setMeasuredTemp(int32_t *val) { measuredTemp = *val; } //****************************************************** static void *getCalStep() { temp = current_state; return &temp; } static void setCalStep(int32_t *val) { current_state = *val; adjustSetPoint = adcAtTemp[current_state]; setDebugTemp(adjustSetPoint); } static void *getAdjustSetpoint() { temp = adjustSetPoint; return &temp; } static void setAdjustSetpoint(int32_t *val) { adjustSetPoint = *val; adcAtTemp[current_state] = *val; setDebugTemp(*val); } static int cal_adjust_SaveAction(widget_t* w) { systemSettings.Profile.Cal250_default = adcAtTemp[cal_250]; systemSettings.Profile.Cal350_default = adcAtTemp[cal_350]; systemSettings.Profile.Cal450_default = adcAtTemp[cal_450]; systemSettings.Profile.CalNTC = readColdJunctionSensorTemp_x10(mode_Celsius) / 10; return screen_edit_calibration; } static int cal_adjust_CancelAction(widget_t* w) { return screen_edit_calibration; } //*************************************************** static void setCalState(state_t s) { current_state = s; if(current_state < cal_suceed) { setCurrentMode(mode_run); setUserTemperature(state_temps[(int)s]); measuredTemp = state_temps[(int)s]; } else if(current_state == cal_suceed) { if(processCalibration()){ backupCal250 = adcCal[cal_250]; backupCal350 = adcCal[cal_350]; backupCal450 = adcCal[cal_450]; } else{ current_state = cal_failed; } } } static int cancelAction(widget_t* w) { return screen_edit_calibration; } static int okAction(widget_t *w) { tempReady = 0; // Abort if the measured temp is >50ÂșC than requested if( measuredTemp > (state_temps[current_state]+50)){ setCalState(cal_needsAdjust); } else{ measured_temps[current_state] = measuredTemp - (readColdJunctionSensorTemp_x10(mode_Celsius) / 10); adcAtTemp[(int)current_state] = TIP.last_avg; setCalState(++current_state); } return screen_edit_calibration_start; } //------------------------------------------------------------------------------------------------------------------------------- // Calibration screen functions //------------------------------------------------------------------------------------------------------------------------------- static void Cal_onEnter(screen_t *scr) { screenTimer = HAL_GetTick(); errorTimer=0; error=0; if(scr == &Screen_settingsmenu) { comboResetIndex(&comboWidget_Cal); } } static void Cal_draw(screen_t *scr){ if(error){ if(errorTimer==0){ errorTimer=HAL_GetTick(); FillBuffer(BLACK,fill_dma); scr->refresh=screenRefresh_alreadyErased; putStrAligned("ERROR DETECTED!", 10, align_center); putStrAligned("Aborting...", 25, align_center); } } else{ default_screenDraw(scr); } } static int Cal_ProcessInput(struct screen_t *scr, RE_Rotation_t input, RE_State_t *s) { if(GetIronError()){ error=1; } if(error){ if((errorTimer==0) || ((HAL_GetTick()-errorTimer)<2000) ){ return -1; } else{ return screen_settingsmenu; } } else{ if(input!=Rotate_Nothing){ screenTimer=HAL_GetTick(); } if(input==LongClick || (HAL_GetTick()-screenTimer)>15000){ return screen_main; } } return default_screenProcessInput(scr, input, s); } //------------------------------------------------------------------------------------------------------------------------------- // Calibration start screen functions //------------------------------------------------------------------------------------------------------------------------------- static void Cal_Start_onEnter(screen_t *scr) { if(scr != &Screen_edit_calibration_input) { Currtip = getCurrentTip(); Iron.calibrating=1; tempReady = 0; setCurrentMode(mode_run); backupTemp = getUserTemperature(); backupTempUnit=systemSettings.settings.tempUnit; setSystemTempUnit(mode_Celsius); backupCal250 = Currtip->calADC_At_250; backupCal350 = Currtip->calADC_At_350; backupCal450 = Currtip->calADC_At_450; Currtip->calADC_At_250 = systemSettings.Profile.Cal250_default; Currtip->calADC_At_350 = systemSettings.Profile.Cal350_default; Currtip->calADC_At_450 = systemSettings.Profile.Cal450_default; setCalState(cal_250); } } static int Cal_Start_ProcessInput(struct screen_t *scr, RE_Rotation_t input, RE_State_t *s) { if(GetIronError()){ return screen_edit_calibration; } if(tempReady){ return screen_edit_calibration_input; } return default_screenProcessInput(scr, input, s); } static void Cal_Start_OnExit(screen_t *scr) { if((scr != &Screen_edit_calibration_start) && (scr != &Screen_edit_calibration_input)) { setSystemTempUnit(backupTempUnit); tempReady = 0; current_state = cal_250; setUserTemperature(backupTemp); setCurrentMode(mode_run); Iron.calibrating=0; Currtip->calADC_At_250 = backupCal250; Currtip->calADC_At_350 = backupCal350; Currtip->calADC_At_450 = backupCal450; } } static void Cal_Start_draw(screen_t *scr){ if((HAL_GetTick()-lastUpdateTick)>200){ // Refresh every 200mS lastUpdateTick=HAL_GetTick(); scr->refresh=screenRefresh_eraseNow; default_screenDraw(scr); u8g2_SetDrawColor(&u8g2, WHITE); char waitstr[6]; lastTipTemp = readTipTemperatureCompensated(stored_reading,read_Avg); switch((int)current_state){ case cal_250: case cal_350: case cal_450: u8g2_DrawStr(&u8g2, 10, 15, "CAL STEP:"); // Draw current cal state u8g2_DrawStr(&u8g2, 90, 15, state_tempstr[(int)current_state]); u8g2_DrawStr(&u8g2, 10, 30, "WAIT..."); // Draw current temp sprintf(waitstr, "%3u\260C",lastTipTemp); u8g2_DrawStr(&u8g2, 90, 30, waitstr); break; case cal_suceed: { char str[20]; for(uint8_t x=0;x<3;x++){ sprintf(str, "ADC %s: %u", state_tempstr[x], adcCal[x]); u8g2_DrawStr(&u8g2, 6, (x*14), str); } u8g2_DrawStr(&u8g2, 0, 50, "SUCCEED!"); break; } case cal_failed: putStrAligned("FAILED!", 15, align_center); break; case cal_needsAdjust: putStrAligned("DELTA TOO HIGH!", 0, align_center); putStrAligned("Adjust manually", 15, align_center); putStrAligned("and try again", 30, align_center); break; } } } //------------------------------------------------------------------------------------------------------------------------------- // Calibration input screen functions //------------------------------------------------------------------------------------------------------------------------------- static void Cal_Input_init(screen_t *scr) { default_init(scr); u8g2_SetFont(&u8g2,default_font ); u8g2_SetDrawColor(&u8g2, WHITE); u8g2_DrawStr(&u8g2,0,19,"MEASURED:");//12 } static void Cal_Input_OnExit(screen_t *scr) { button_Cal_Input_OK.selectable.previous_state=widget_idle;; button_Cal_Input_OK.selectable.state=widget_idle; button_Cal_Input_Cancel.selectable.previous_state=widget_idle; button_Cal_Input_Cancel.selectable.state=widget_idle; editable_Cal_Input_Measured.selectable.previous_state=widget_selected; editable_Cal_Input_Measured.selectable.state=widget_edit; Screen_edit_calibration_input.current_widget=&Widget_Cal_Input_Measured; } static int Cal_Input_ProcessInput(struct screen_t *scr, RE_Rotation_t input, RE_State_t *s) { if(GetIronError()){ return screen_edit_calibration; } return default_screenProcessInput(scr, input, s); } //------------------------------------------------------------------------------------------------------------------------------- // Calibration adjust screen functions //------------------------------------------------------------------------------------------------------------------------------- static void Cal_Adjust_init(screen_t *scr) { comboResetIndex(&comboWidget_Cal_Adjust); adcAtTemp[cal_250] = systemSettings.Profile.Cal250_default; adcAtTemp[cal_350] = systemSettings.Profile.Cal350_default; adcAtTemp[cal_450] = systemSettings.Profile.Cal450_default; Cal_Combo_Adjust_Save.enabled=0; current_state = cal_250; adjustSetPoint = adcAtTemp[cal_250]; setDebugTemp(adjustSetPoint); setDebugMode(debug_On); setCurrentMode(mode_run); } static void Cal_Adjust_OnExit(screen_t *scr) { setDebugMode(debug_Off); setCurrentMode(mode_run); } static int Cal_Adjust_ProcessInput(struct screen_t *scr, RE_Rotation_t input, RE_State_t *s) { if(GetIronError()){ return screen_edit_calibration; } // Only enable save option is valid and different data is entered if( (adcAtTemp[cal_250] && adcAtTemp[cal_350] && adcAtTemp[cal_450]) && ((adcAtTemp[cal_250] != systemSettings.Profile.Cal250_default)|| (adcAtTemp[cal_350] != systemSettings.Profile.Cal350_default)|| (adcAtTemp[cal_450] != systemSettings.Profile.Cal450_default)) && ((adcAtTemp[cal_250] < adcAtTemp[cal_350]) && (adcAtTemp[cal_350] < adcAtTemp[cal_450]))){ Cal_Combo_Adjust_Save.enabled=1; } else{ Cal_Combo_Adjust_Save.enabled=0; } return default_screenProcessInput(scr, input, s); } //------------------------------------------------------------------------------------------------------------------------------- // Calibration screens setup //------------------------------------------------------------------------------------------------------------------------------- void calibration_screen_setup(screen_t *scr) { widget_t* w; displayOnly_widget_t *dis; editable_widget_t* edit; screen_t* sc; //########################################## CALIBRATION SCREEN ########################################## // screen_setDefaults(scr); scr->onEnter = &Cal_onEnter; scr->processInput = &Cal_ProcessInput; scr->draw = &Cal_draw; addSetTemperatureReachedCallback(tempReachedCallback); w = &comboWidget_Cal; w->content = &comboBox_Cal; screen_addWidget(w, scr); widgetDefaultsInit(w, widget_combo, &comboBox_Cal); comboAddScreen(&Cal_Combo_Start, w, "START", screen_edit_calibration_start); comboAddScreen(&Cal_Combo_Adjust, w, "ADJUST", screen_edit_calibration_adjust); comboAddScreen(&Cal_Combo_Exit, w, "BACK", screen_settingsmenu); w->posY=10; //########################################## CALIBRATION START SCREEN ########################################## // sc = &Screen_edit_calibration_start; oled_addScreen(sc, screen_edit_calibration_start); screen_setDefaults(sc); sc->processInput = &Cal_Start_ProcessInput; sc->draw = &Cal_Start_draw; sc->onExit = &Cal_Start_OnExit; sc->onEnter = &Cal_Start_onEnter; w = &Widget_Cal_Start_Cancel; screen_addWidget(w,sc); widgetDefaultsInit(w, widget_button, &button_Cal_Start_Cancel); button_Cal_Start_Cancel.displayString="BACK"; w->posX = 86; w->posY = 48; w->width = 42; ((button_widget_t*)w->content)->selectable.tab = 0; ((button_widget_t*)w->content)->action = &cancelAction; //########################################## CALIBRATION ADJUST SCREEN ########################################## // sc = &Screen_edit_calibration_adjust; oled_addScreen(sc, screen_edit_calibration_adjust); screen_setDefaults(sc); sc->init = &Cal_Adjust_init; sc->processInput = &Cal_Adjust_ProcessInput; sc->onExit = &Cal_Adjust_OnExit; w = &Widget_Cal_Adjust_Select; widgetDefaultsInit(w, widget_multi_option, &editable_Cal_Adjust_Select); dis=extractDisplayPartFromWidget(w); edit=extractEditablePartFromWidget(w); dis->getData = &getCalStep; edit->big_step = 1; edit->step = 1; edit->setData = (void (*)(void *))&setCalStep; edit->max_value = cal_450; edit->min_value = cal_250 ; edit->options = state_tempstr; edit->numberOfOptions = 3; w->posX = 20; w->posY = 20; w->width = 40; w = &Widget_Cal_Adjust_Setpoint; widgetDefaultsInit(w, widget_editable, &editable_Cal_Adjust_Setpoint); dis=extractDisplayPartFromWidget(w); edit=extractEditablePartFromWidget(w); dis->reservedChars=4; dis->getData = &getAdjustSetpoint; edit->big_step = 100; edit->step = 50; edit->setData = (void (*)(void *))&setAdjustSetpoint; edit->max_value = 4000; edit->min_value = 0; w->posX = 80; w->posY = 20; w->width = 40; w = &comboWidget_Cal_Adjust; screen_addWidget(w, sc); widgetDefaultsInit(w, widget_combo, &comboBox_Cal_Adjust); comboAddMultiOption(&Cal_Combo_Adjust_Target, w, "Cal. Step", &editable_Cal_Adjust_Select); comboAddEditable(&Cal_Combo_Adjust_Setpoint, w, "ADC Value", &editable_Cal_Adjust_Setpoint); comboAddAction(&Cal_Combo_Adjust_Save, w, "SAVE", &cal_adjust_SaveAction); comboAddAction(&Cal_Combo_Adjust_Cancel, w, "CANCEL", &cal_adjust_CancelAction); //########################################## CALIBRATION INPUT SCREEN ########################################## // sc = &Screen_edit_calibration_input; oled_addScreen(sc, screen_edit_calibration_input); screen_setDefaults(sc); sc->init = &Cal_Input_init; sc->onExit = &Cal_Input_OnExit;; sc->processInput = &Cal_Input_ProcessInput; w=&Widget_Cal_Input_Measured; widgetDefaultsInit(w, widget_editable, &editable_Cal_Input_Measured); screen_addWidget(w,sc); dis=extractDisplayPartFromWidget(w); edit=extractEditablePartFromWidget(w); dis->reservedChars = 5; dis->endString = "\260C"; w->posX = 86; w->posY = 17; w->width = 42; dis->getData = &getMeasuredTemp; edit->setData = (void (*)(void *)) &setMeasuredTemp; edit->selectable.tab = 0; w=&Widget_Cal_Input_OK; screen_addWidget(w,sc); widgetDefaultsInit(w, widget_button, &button_Cal_Input_OK); button_Cal_Input_OK.displayString="SAVE"; ((button_widget_t*)w->content)->selectable.tab = 1; ((button_widget_t*)w->content)->action = &okAction; w->posX = 86; w->posY = 48; w->width = 42; w=&Widget_Cal_Input_Cancel; screen_addWidget(w,sc); widgetDefaultsInit(w, widget_button, &button_Cal_Input_Cancel); button_Cal_Input_Cancel.displayString="CANCEL"; ((button_widget_t*)w->content)->selectable.tab = 2; ((button_widget_t*)w->content)->action = &cancelAction; w->posX = 0; w->posY = 48; w->width = 56; } static uint8_t processCalibration() { uint16_t delta = (state_temps[cal_350] - state_temps[cal_250])/2; uint16_t ambient = readColdJunctionSensorTemp_x10(mode_Celsius) / 10; // Ensure measured temps are valid (250<350<450) if ( (measured_temps[cal_250] >= measured_temps[cal_350]) || (measured_temps[cal_350] >= measured_temps[cal_450]) ){ return 0; } // Ensure adc values are valid (250<350<450) if ( (adcAtTemp[cal_250] >=adcAtTemp[cal_350]) || (adcAtTemp[cal_350] >= adcAtTemp[cal_450]) ){ return 0; } if ((measured_temps[cal_250] + delta) < measured_temps[cal_350]){ adcCal[cal_350] = map(state_temps[cal_350], measured_temps[cal_250], measured_temps[cal_350], adcAtTemp[cal_250], adcAtTemp[cal_350]); } else{ adcCal[cal_350] = map(state_temps[cal_350], ambient, measured_temps[cal_350], 0, adcAtTemp[cal_350]); } adcCal[cal_350] += map(state_temps[cal_350], measured_temps[cal_250], measured_temps[cal_450], adcAtTemp[cal_250], adcAtTemp[cal_450]) + 1; adcCal[cal_350] >>= 1; if((measured_temps[cal_250] + delta) < measured_temps[cal_350]){ adcCal[cal_250] = map(state_temps[cal_250], measured_temps[cal_250], state_temps[cal_350], adcAtTemp[cal_250], adcCal[cal_350]); } else{ adcCal[cal_250] = map(state_temps[cal_250], ambient, state_temps[cal_350], 0, adcCal[cal_350]); } if ((measured_temps[cal_350] + delta) < measured_temps[cal_450]){ adcCal[cal_450] = map(state_temps[cal_450], state_temps[cal_350], measured_temps[cal_450], adcCal[cal_350], adcAtTemp[cal_450]); } else{ adcCal[cal_450] = map(state_temps[cal_450], state_temps[cal_250], measured_temps[cal_450], adcCal[cal_350], adcAtTemp[cal_450]); } if (((adcCal[cal_250] + delta) > adcCal[cal_350]) || ((adcCal[cal_350] + delta) > adcCal[cal_450])) { adcCal[cal_250] = map(state_temps[cal_250], measured_temps[cal_250], measured_temps[cal_450], adcAtTemp[cal_250], adcAtTemp[cal_450]); adcCal[cal_350] = map(state_temps[cal_350], measured_temps[cal_250], measured_temps[cal_450], adcAtTemp[cal_250], adcAtTemp[cal_450]); adcCal[cal_450] = map(state_temps[cal_450], measured_temps[cal_250], measured_temps[cal_450], adcAtTemp[cal_250], adcAtTemp[cal_450]); } if(adcCal[cal_250]>4090 || adcCal[cal_350]>4090 || adcCal[cal_450]>4090){ // Check that values don't exceed ADC range return 0; } return 1; }