#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(); } }