hot_plato/hot_plato.ino

600 lines
15 KiB
C++

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <String.h>
#include <Preferences.h>
#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();
}
}