commit f3f397a6056c500549f07a7c5e18ebfa8a07e35f Author: klavirshik Date: Fri Jun 14 12:45:36 2024 +0000 sketch diff --git a/hot_plato.ino b/hot_plato.ino new file mode 100644 index 0000000..e5275ad --- /dev/null +++ b/hot_plato.ino @@ -0,0 +1,599 @@ +#include +#include +#include +#include +#include + + +#define CLK 25 +#define DT 33 +#define SW 14 +#define cs 5 +#define dc 27 +#define rst 26 +#define RELEY 32 +#define COUNT_selected 5 + +#define GRAY 0x2965 + +Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst); + +const float BETA = 2450; +int8_t last_temp[120]; +int8_t index_temp = 0; +int selected_opt[COUNT_selected]; +const String selected_name[COUNT_selected] = {"Diff P","Diff I","Diff D","Start temp","Preheat temp"}; +int pos = 0; +int set_temp=0; +int8_t stage = 0; +int8_t enc_turn = 0; +int timer_td = 0; +int8_t selected = 0; +volatile boolean flag, resetFlag; +volatile byte curState, prevState; +int button_t=0; +volatile unsigned long last_time; +int start_hot=0; +int last_celsius; +int hoting_on = 0; +Preferences prefs; + + +//timer varebles +bool pwm_flag, pwm_dir; +uint32_t pwm_timer; +int pwm_period = 1000; +int pwm_activePeriod; + +//action vareblios +uint32_t act_timer; +int act_period = 25; + +//read_temp vareblios +uint32_t read_timer; +int read_period = 500; + +//read_temp vareblios +uint32_t time_timer; +int time_period = 1000, timers = 0; + +void Task_temp_read(void *pvParameters); +uint32_t blink_delay; + + +void IRAM_ATTR int0(){ + encoder_tick(); +} + +//const int8_t increment[16] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0}; +void setup() { + pinMode(SW, INPUT_PULLUP); + pinMode(CLK, INPUT); + pinMode(DT, INPUT); + pinMode(RELEY, OUTPUT); + analogReadResolution(12); + Serial.begin(9600); + //attachInterrupt(DT, int0, CHANGE); + attachInterrupt(CLK, int0, CHANGE); + //selected_opt[0] = 0; + //selected_opt[1] = 0; + //selected_opt[2] = 0; + + prefs.begin("setting"); + size_t schLen = prefs.getBytesLength("setting"); + Serial.println(schLen); + if(!schLen){ + prefs.putBytes("setting", selected_opt, sizeof(selected_opt)); + }else{ + char buffer[schLen]; + + Serial.println(schLen); + Serial.println(sizeof(selected_opt)); + prefs.getBytes("setting", buffer, schLen); + if (schLen % sizeof(selected_opt)) { // simple check that data fits + Serial.println("Data is not correct size!"); + return; + } + Serial.println(buffer); + //selected_opt = (int[]) buffer; + memcpy(&selected_opt, &buffer, sizeof(buffer)); + prefs.end(); + + } + set_temp = selected_opt[3]; + + tft.initR(INITR_GREENTAB); + tft.fillScreen(ST77XX_BLACK); + + ds_main(); + // xTaskCreate(Task_temp_read, "Temp_read", 2048, (void*) &blink_delay, 2, NULL); + + + +/* tft.fillScreen(ST77XX_BLACK); + for(int i = 0 ; i < COUNT_selected; i++){ + if(selected == i)tft.drawRoundRect(2,5+(i*19),79,17,3,ST77XX_GREEN); + tft.setTextWrap(false); + tft.setCursor(7,10+(i*19)); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE); + tft.print(selected_name[i]); + + tft.drawRoundRect(83,5+(i*19),42,17,3,ST77XX_RED); + tft.setCursor(87,10+(i*19)); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE,ST77XX_BLACK); + tft.print(selected_opt[i]); + } + */ +} + + + +void encoder_tick() { + curState = digitalRead(CLK); + if (curState != prevState) { + enc_turn = (digitalRead(DT) != prevState) ? -1 : 1; + flag = true; + prevState = curState; + } +} + +int8_t encoder_read() { + int8_t ch = 0; + if (flag) { + ch = enc_turn; + flag = 0; + } + return ch; +} + +int8_t timer_read(){ + if(timer_td > 0){ + timer_td--; + if(timer_td == 0) return 40; + } + return 0; +} + +int8_t button_read(){ + if(!digitalRead(SW)){ + button_t++; + if(button_t == 30) return 20; + }else if(button_t != 0){ + if(button_t > 30){ + button_t = 0; + }else{ + button_t = 0; + return 10; + } + } + return 0; +} + +int8_t read_action(){ + return button_read() + encoder_read() + timer_read(); +} + + +//selected config +void ds_save_set_selected(int opt){ + tft.fillRoundRect(83,5+(selected*19),42,17,3,ST77XX_BLACK); + tft.drawRoundRect(83,5+(selected*19),42,17,3,ST77XX_RED); + tft.setCursor(87,10+(selected*19)); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE,ST77XX_BLACK); + tft.print(opt); +} + +void ds_set_selected(int opt){ + tft.fillRoundRect(83,5+(selected*19),42,17,3,ST77XX_RED); + tft.setCursor(87,10+(selected*19)); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE,ST77XX_RED); + tft.print(opt); +} + +//config menu +void ds_config(){ + tft.fillScreen(ST77XX_BLACK); + for(int i = 0 ; i < COUNT_selected; i++){ + if(selected == i)tft.drawRoundRect(2,5+(i*19),79,17,3,ST77XX_GREEN); + tft.setTextWrap(false); + tft.setCursor(7,10+(i*19)); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE); + tft.print(selected_name[i]); + Serial.println(selected_name[i]); + + tft.drawRoundRect(83,5+(i*19),42,17,3,ST77XX_RED); + tft.setCursor(87,10+(i*19)); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE,ST77XX_BLACK); + tft.print(selected_opt[i]); + } + +} + +void ds_change_selected(){ + for(int8_t i = 0 ; i < COUNT_selected; i++){ + if( selected != i){ + tft.drawRoundRect(2 ,(i * 19) + 5 , 79, 17, 3, ST77XX_BLACK); + }else{ + tft.drawRoundRect(2 ,(i * 19) + 5 , 79, 17, 3, ST77XX_GREEN); + } + + /* tft.setTextWrap(false); + tft.setCursor(7,10+(i*19)); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE); + tft.print(selected_name[i]);*/ + } +} + + +//main menu +void ds_main(){ + tft.fillScreen(ST77XX_BLACK); + + ds_renew_hoting(); + + ds_renew_temp(); + + ds_tick_timers(); + + tft.fillRoundRect(3,5,78,42,3,ST77XX_RED); + + tft.setTextWrap(false); + tft.setCursor(17,14); //Horiz/Vertic + tft.setTextSize(3); + tft.setTextColor(ST77XX_WHITE); + tft.print("000"); + + + //tft.drawRoundRect(83,27,42,20,3,ST77XX_RED); + char buff[3]; + sprintf(buff, "%03d", set_temp); + tft.setTextWrap(false); + tft.setCursor(87,30); //Horiz/Vertic + tft.setTextSize(2); + tft.setTextColor(ST77XX_WHITE); + tft.print(buff); + + + + + //tft.drawFastHLine(3, 70, 120, ST77XX_YELLOW); + + tft.drawFastHLine(3, 120, 120, ST77XX_WHITE); + tft.setCursor(3,122); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE); + tft.print("0"); +} + +void ds_tick_timers(){ + char buff[9]; + sprintf(buff, "%02d:%02d:%02d", timers/3600, (timers%3600)/60, timers%60); + tft.setCursor(77,122); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE,ST77XX_BLACK); + tft.print(buff); +} + +void ds_ch_set_temp(int tmp){ + char buff[4]; + sprintf(buff, "%03d", tmp); + tft.setCursor(87,30); //Horiz/Vertic + tft.setTextSize(2); + tft.setTextColor(ST77XX_WHITE,ST77XX_BLACK); + tft.print(buff); +} + +void ds_set_temp(int tmp){ + tft.drawRoundRect(83,27,42,20,3,ST77XX_RED); + ds_ch_set_temp(tmp); +} + +void ds_clear_set_temp(int tmp){ + tft.drawFastHLine(3,map(tmp,0,350,120,50), 120, ST77XX_BLACK); +} + +void ds_save_set_temp(int tmp){ + tft.drawRoundRect(83,27,42,20,3,ST77XX_BLACK); + ds_ch_set_temp(tmp); +} + +void ds_renew_temp(){ + tft.setCursor(88,8); + tft.setTextSize(2); + if(start_hot == 2){ + tft.setTextColor(ST77XX_WHITE); + tft.fillRoundRect(83,5,20,20,3,ST77XX_GREEN); + }else if(start_hot == 1){ + tft.setTextColor(ST77XX_WHITE); + tft.fillRoundRect(83,5,20,20,3,ST77XX_BLACK); + tft.drawRoundRect(83,5,20,20,3,ST77XX_GREEN); + } + else if(start_hot == 0){ + tft.setTextColor(GRAY); + tft.fillRoundRect(83,5,20,20,3,ST77XX_BLACK); + tft.drawRoundRect(83,5,20,20,3,GRAY); + } + tft.print(">"); +} + + +void ds_renew_hoting(){ + if(hoting_on){ + tft.fillRoundRect(105,5,20,20,3,ST77XX_YELLOW); + digitalWrite(RELEY, HIGH); + }else{ + tft.fillRoundRect(105,5,20,20,3,ST77XX_BLACK); + tft.drawRoundRect(105,5,20,20,3,ST77XX_YELLOW); + digitalWrite(RELEY, LOW); + } + tft.setCursor(110,8); + tft.setTextSize(2); + tft.setTextColor(ST77XX_WHITE); + tft.print("+"); +} + +void ds_ch_temp(int tmp){ + + if(stage < 2){ + char buff[3]; + sprintf(buff, "%03d", tmp); + tft.setCursor(17,14); //Horiz/Vertic + tft.setTextSize(3); + tft.setTextColor(ST77XX_WHITE,ST77XX_RED); + tft.print(buff); + ds_grafik_draw(tmp); + } + +} + +void ds_grafik_draw(int tmp){ + /*tft.drawFastVLine(3, 50, 70, ST77XX_WHITE); + tft.setCursor(5,50); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE); + tft.print("300"); + + tft.drawFastHLine(3, 70, 120, ST77XX_YELLOW); + + tft.drawFastHLine(3, 120, 120, ST77XX_WHITE); + tft.setCursor(3,122); //Horiz/Vertic + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE); + tft.print("0");*/ + + for(int8_t i = 0; i < 12; i++){ + tft.drawFastVLine(i*10+4, 50, 70, GRAY); + } + + for(int8_t i = 0; i < 8; i++){ + tft.drawFastHLine(3, 121 - i*10, 120, GRAY); + } + if(start_hot==1){ + tft.drawFastHLine(3,map(selected_opt[4],0,350,120,50), 120, ST77XX_YELLOW); + }else if(start_hot==2){ + tft.drawFastHLine(3,map(set_temp,0,350,120,50), 120, ST77XX_YELLOW); + } + + last_temp[index_temp] = map(tmp,0,350,120,50); + if(last_temp[index_temp] < 50)last_temp[index_temp] = 50; + for(int8_t i = 0; i < 120; i++){ + int offset = i + index_temp; + if(offset > 120) offset -= 120; + // Serial.println(offset); + tft.drawPixel(i+4, last_temp[offset], ST77XX_BLACK); + tft.drawPixel(i+3, last_temp[offset], ST77XX_RED); + } + + + index_temp++; + if(index_temp>120) index_temp=0; + + tft.drawFastVLine(3, 50, 70, ST77XX_WHITE); + tft.setTextSize(1); + tft.setTextColor(ST77XX_WHITE); + tft.setCursor(5,53); //Horiz/Vertic + tft.print("350"); + tft.setCursor(5,73); + tft.print("250"); + tft.setCursor(5,93); + tft.print("150"); + tft.setCursor(128,128); + +} + + +int computePID(float input, float setpoint, float kp, float ki, float kd, float dt, int minOut, int maxOut) { + float err = setpoint - input; + static float integral = 0, prevErr = 0; + integral = constrain(integral + (float)err * dt * ki, minOut, maxOut); + float D = (err - prevErr) / dt; + prevErr = err; + return constrain(err * kp + integral + D * kd, minOut, maxOut); +} + +void action(){ + int8_t act = read_action(); + if(act != 0){ + Serial.println(act); + switch(stage){ + case 0://main sreen; + if(act < 2){ + pos = set_temp; + stage = 1; + timer_td = 300; + Serial.println("stage = 1"); + }else if(act == 20){ + if(start_hot > 0){ + start_hot = 0; + ds_clear_set_temp(selected_opt[4]); + ds_clear_set_temp(set_temp); + Serial.println("stop preheat"); + ds_renew_temp(); + }else{ + stage = 2; + selected = 0; + ds_config(); + Serial.println("stage = 2"); + } + }else if(act == 10){ + if(start_hot == 0){ + start_hot = 1; + Serial.println("start preheat"); + }else if(start_hot == 1){ + timers = 0; + start_hot = 2; + ds_clear_set_temp(selected_opt[4]); + Serial.println("start hoting"); + }else if(start_hot == 2){ + start_hot = 1; + ds_clear_set_temp(set_temp); + Serial.println("stop hoting"); + } + ds_renew_temp(); + } + + break; + + case 1://main sreen; + if(act < 2){ + pos += act; + if(pos > 350) pos = 350; + if(pos < 0) pos = 0; + ds_set_temp(pos); + timer_td = 300; + }else if(act == 40){ + stage = 0; + ds_save_set_temp(set_temp); + Serial.println("stage = 0"); + }else if(act == 10){ + stage = 0; + ds_clear_set_temp(set_temp); + set_temp = pos; + timer_td = 0; + ds_save_set_temp(set_temp); + ds_grafik_draw(last_celsius); + Serial.println("stage = 0"); + }else if(act == 20){ + stage = 0; + timer_td = 0; + ds_save_set_temp(set_temp); + Serial.println("stage = 0"); + } + + Serial.println(pos); + break; + case 2://menu + if(act < 2){ + selected += act; + if(selected < 0) selected = COUNT_selected-1; + if(selected > (COUNT_selected -1)) selected = 0; + ds_change_selected(); + }else if(act == 10){ + stage = 3; + pos = selected_opt[selected]; + ds_set_selected(selected_opt[selected]); + timer_td = 300; + Serial.println("stage = 3"); + }else if(act == 20){ + stage = 0; + selected = 0; + ds_main(); + Serial.println("stage = 0"); + } + Serial.println(selected); + break; + case 3://select + if(act < 2){ + pos += act; + ds_set_selected(pos); + timer_td = 300; + }else if(act == 10){ + stage = 2; + selected_opt[selected] = pos; + ds_save_set_selected(selected_opt[selected]); + timer_td = 0; + prefs.begin("setting"); + prefs.putBytes("setting", selected_opt, sizeof(selected_opt)); + prefs.end(); + Serial.println("stage = 2 save"); + + }else if(act == 20 || act == 40){ + stage = 2; + ds_save_set_selected(selected_opt[selected]); + timer_td = 0; + Serial.println("stage = 2 nosave"); + } + Serial.println(pos); + break; + } + } +} + +void Task_temp_read(){ + int analogValue = analogRead(12); + int streng; + int celsius = 1 / (log(1 / (4095. / analogValue - 1)) / BETA + 1.0 / 298.15) - 273.15+3; + last_celsius = celsius; + if(start_hot == 1){ + streng = computePID(celsius, selected_opt[4], selected_opt[0]/10, selected_opt[1]/10, selected_opt[2]/10, 0.5, 0, 1000); + }else if(start_hot == 2){ + streng = computePID(celsius, set_temp, selected_opt[0]/10, selected_opt[1]/10, selected_opt[2]/10, 0.5, 0, 1000); + }else if(start_hot == 0){ + streng = 0; + } + pwm_activePeriod = streng; + //Serial.println(streng); + ds_ch_temp((celsius + last_celsius)/2); + +} +void Task_time(){ + if(start_hot== 2){ + timers++; + ds_tick_timers(); + } +} + +void loop() { + if (millis() - time_timer >= time_period){ + time_timer = millis(); + Task_time(); + } + + + if (millis() - read_timer >= read_period){ + read_timer = millis(); + Task_temp_read(); + } + + if (millis() - act_timer >= act_period){ + act_timer = millis(); + action(); + } + + if(pwm_activePeriod){ + if (millis() - pwm_timer >= (pwm_flag ? pwm_activePeriod : (pwm_period - pwm_activePeriod))) { + pwm_timer = millis(); + pwm_flag = !pwm_flag; + digitalWrite(RELEY, pwm_flag ^ pwm_dir); + hoting_on = pwm_flag ^ pwm_dir; + //Serial.println(hoting_on); + if(stage < 2){ + ds_renew_hoting(); + } + } + }else if(pwm_flag){ + pwm_flag = !pwm_flag; + digitalWrite(RELEY, pwm_flag ^ pwm_dir); + hoting_on = pwm_flag ^ pwm_dir; + ds_renew_hoting(); + } + + +}