// разобратся с заданием скорости мотора в различных режимах, сменой направлении вращения
// обратить внимание на !!! в коментариях
//
//#include <arduino.h> // onli on esp
//OLED
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // Adafruit Feather ESP8266/32u4 Boards + FeatherWing OLED
String StrRezult; //for test
int Rejim, Old_Rejim; //выбранный режим работы стир. машины
float Temp_Water_Initial, Temp_Water, Temp_Water_Ust;
int Timer_Water_Osn, Timer_Water_Dop, Timer_TEN, Soaking_Cycle, Cnt_Soaking_Cycle, Cnt_Rinsing_Cycle,Rinsing_Cycle, Mot_Speed_Soaking, Timer_Mot_Soaking;
int Timer_Mot_Washing, Timer_Washing,Mot_Speed_Washing,Cnt_Washing_Cycle,Timer_Pumping,Timer_Mot_Rinsing, Timer_Rinsing, Mot_Speed_Rinsing, Cnt_Rinsing_Pump2_Cycle,Rinsing_Pump2_Cycle;
int Mot_Speed_Spin,Mot_Speed_Spin2,Mot_Speed_Spin3,Timer_Spin,Timer_Spin2,Timer_Spin3;
bool Btn_Start=false, Status_Wash_Start=false, Status_Pump_Start=false, Status_Rinsing_Start=false, Status_Pump2_Start=false,Status_Spin_Start=false;
byte Water_Level; //уровень до которого необходимо наливать воду в текущем режиме
byte N_screen; // номер экрана LCD для фукнкции LCD_Print (используется для тригера)
byte ChekEncoder;//состояние энкодера 0 - нет действий, 1 - вращ по часовой, 2 - вращ против часовой , 3 - нажата кнопка , 13- нажата кнопка и вращ по часовой, 23 - нажата кнопка и вращ против часовой
int EncoderValue;
// переменные состояния выходов
bool Mot_Out_Value, Mot_Dir_Value, Klap_Water_Osn_Value, Klap_Water_Dop_Value, TEN_Value, UBL_OUT_Value, Pump_Value;
// переменные состояния входов
bool Mot_Faza_Detect_Value, Mot_Dir_Detect1_Value, Mot_Dir_Detect2_Value, Mot_Speed_Value, Level_1_Value, Level_2_Value, Level_3_Value, UBL_Control_Value, BTN_Forward_Value, BTN_Back_Value, BTN_Enter_Value, BTN_Start_Stop_Value;
int lastClk = HIGH; //encoder
#include <Ticker.h> //Ticker Library
Ticker Tic_Water_Osn;
Ticker Tic_TEN;
Ticker Tic_Mot_Soaking;
Ticker Tic_Washing;
Ticker Tic_Mot_Washing;
Ticker Tic_Pumping;
Ticker Tic_Water_Dop;
Ticker Tic_Mot_Rinsing;
Ticker Tic_Rinsing;
Ticker Tic_Spin;
Ticker Tic_Spin1;
Ticker Tic_Spin2;
Ticker Tic_Spin3;
Ticker OledPrint; //test
int Err_code_Word; //слово ошибок
#define ENCODER_CLK 12
#define ENCODER_DT 13
//#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
//LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
int Status;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#define PinOn 0x1 // В зависимости от типа устройства определяет по какому состоянию (HIGH или LOW) будет включатся устройство
#define PinOff 0x0 // В зависимости от типа устройства определяет по какому состоянию (HIGH или LOW) будет выключатся устройство
#define Mot_Out 19 //Управление мотором Выход Дискр. 17 !!! не забыть что этот выход будет импульсным, поэтому не исползовать в булевой логике (сделать отдельную переменную типа bool Mot_Out )
#define Mot_Dir 18//Направление вращения Выход Дискр. 16
#define Mot_Faza_Detect //Детектор перехода синуса сетевого напряжения через 0 Вход Дискр. 32
#define Mot_Dir_Detect1 //Наличие напряжения на направлении вращения реле 1 Вход Дискр. 39
#define Mot_Dir_Detect2 //Наличие напряжения на направлении вращения реле 2 Вход Дискр. 34
#define Mot_Speed Датчик //скорости вращения мотора Вход Дискр. 33
#define Klap_Water_Osn 5//Клапан воды Основной (стирка) Выход Дискр. 19
#define Klap_Water_Dop 17//Клапан воды Дополнительный (полоскание ) Выход Дискр. 18
#define TEN 16//Нагрев воды (ТЭН) Выход Дискр. 2
#define Temp_Water_Raw //Датчик Температуры воды Аналоговый Вход 36
#define Level_1 39//Реле уровня 1 (пустой бак) Вход Дискр. 25
#define Level_2 35//Реле уровня 2 (наполненный бак) Вход Дискр. 26
#define Level_3 32//Реле уровня 3 (переполненный бак) Вход Дискр. 27
#define UBL_OUT 4//Устройство блокировки люка (блокировка) Выход Дискр. 23
#define UBL_Control //Устройство блокировки люка (Заблокировано) Вход Дискр. 14
#define Pump 2//Помпа откачки воды Выход Дискр. 4
#define Displ_SCL 22//Экран 1 SCL Протокол I2C 22
#define Displ_SDA 21//Экран 1 SDA Протокол I2C 21
#define BTN_Forward //Кнопка вперед Вход Дискр. 5
#define BTN_Back //Кнопка назад Вход Дискр. 15
#define BTN_Enter //Кнопка Выбор Вход Дискр. 12
#define BTN_Start_Stop //Кнопка Пуск/Стоп Вход Дискр. 13
#define MP3_RX //Динамик (RX) Протокол RX/TX 16
#define MP3_TX //Динамик (TX) Протокол RX/TX 17
#define BTN_Encoder 14 // кнопка энкодера
#define PIN36 digitalRead(36)
#define PIN39 digitalRead(39)
#define PIN34 digitalRead(34)
#define PIN35 digitalRead(35)
#define PIN32 digitalRead(32)
#define PIN33 digitalRead(33)
#define PIN25 digitalRead(25)
#define PIN26 digitalRead(26)
#define RD_Mot_Faza_Detect digitalRead(Mot_Faza_Detect)
#define RD_Mot_Dir_Detect1 digitalRead(Mot_Dir_Detect1)
#define RD_Mot_Dir_Detect2 digitalRead(Mot_Dir_Detect2)
#define RD_Mot_Speed digitalRead(Mot_Speed)
#define RD_Level_1 digitalRead(Level_1)
#define RD_Level_2 digitalRead(Level_2)
#define RD_Level_3 digitalRead(Level_3)
#define RD_UBL_Control digitalRead(UBL_Control)
#define RD_BTN_Forward digitalRead(BTN_Forward)
#define RD_BTN_Back digitalRead(BTN_Back)
#define RD_BTN_Enter digitalRead(BTN_Enter)
#define RD_BTN_Start_Stop digitalRead(BTN_Start_Stop)
// чтение выходов
#define RD_TEN digitalRead(TEN)
#define RD_Mot_Out digitalRead(Mot_Out)
#define RD_Mot_Dir digitalRead(Mot_Dir)
#define RD_Klap_Water_Osn digitalRead(Klap_Water_Osn)
// LED
#define LED_PIN 27
#define LED_NUM 11
#include "FastLED.h"
CRGB leds[LED_NUM];
byte counter;
//Led
//OLED
void RejimToOled() /// Быстрая шерсть хлопок синтетика отжим полоскание обувь чистка Джинсы свободный Отложенный старт деликтная
{
Serial.print("RejimToOled Rejim=");
Serial.println(Rejim);
u8g2.firstPage();
do {
switch (Rejim)
{
case 0:
u8g2.setCursor(1, 10);
u8g2.print(" Выбор"); //
u8g2.setCursor(1, 25);
u8g2.print(" Режима"); //
break;
case 1:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" БЫСТРАЯ"); //
break;
case 2:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" ШЕРСТЬ"); //
break;
case 3:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" ХЛОПОК"); //
break;
case 4:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" СИНТЕТИКА"); //
break;
case 5:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" ОТЖИМ"); //
break;
case 6:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print("ПОЛОСКАНИЕ"); //
break;
case 7:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" ОБУВЬ"); //
break;
case 8:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" ЧИСТКА"); //
break;
case 9:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" ДЖИНСЫ"); //
break;
case 10:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" СВОБОДНЫЙ"); //
break;
case 11:
u8g2.setCursor(1, 10);
u8g2.print(" Режим"); //
u8g2.setCursor(1, 25);
u8g2.print(" ОТЛОЖЕННЫЙ"); //
break;
}
}while ( u8g2.nextPage() );
}
void RejimToOled_old()
{
Serial.print("RejimToOled Rejim=");
Serial.println(Rejim);
// Быстрая шерсть хлопок синтетика отжим полоскание обувь чистка Джинсы свободный Отложенный старт деликтная
////oled.autoPrintln(true);
// //oled.setScale(2);
// //oled.clear();
// //oled.home();
switch (Rejim)
{
case 0:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Vibor, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " Programmi"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 1:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Rejim"); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " Bistriy"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 2:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Rejim, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " Hlopok"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 3:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Rejim, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " Sintetika"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 4:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Rejim"); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " Otjim"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 5:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Rejim"); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " Poloskanie"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 6:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Hello, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " World6"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 7:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Hello, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " World7"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 8:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Hello, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " World8"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 9:
u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Hello, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " World9"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
case 10:
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Hello, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " World10"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
break;
}
/*
case 0:
oled.clear();
oled.home();
oled.print("");
oled.setCursor(0, 2);
oled.print("Выбор");
oled.setCursor(0, 4);
oled.print("Программы");
break;
case 1:
oled.clear();
oled.home();
oled.print("Режим");
oled.setCursor(0, 2);
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("Быстрый");
break;
case 2:
oled.clear();
oled.home();;
oled.setCursor(0, 2
oled.print("Режим"));
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("хлопок");
break;
case 3:
oled.clear();
oled.home();
oled.print("Режим");
oled.setCursor(0, 2);
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("синтетика");
break;
case 4:
oled.clear();
oled.home();
oled.print("Режим");
oled.setCursor(0, 2);
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("отжим");
break;
case 5:
oled.clear();
oled.home();
oled.print("Режим");
oled.setCursor(0, 2);
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("полоскание");
break;
case 6:
oled.clear();
oled.home();
oled.print("Режим");
oled.setCursor(0, 2);
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("обувь");
break;
case 7:
oled.clear();
oled.home();
oled.print("Режим");
oled.setCursor(0, 2);
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("чистка");
break;
case 8:
oled.clear();
oled.home();
oled.print("Режим");
oled.setCursor(0, 2);
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("Джинсы");
break;
case 9:
oled.clear();
oled.home();
oled.print("Режим");
oled.setCursor(0, 2);
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("свободный");
break;
case 10:
oled.clear();
oled.home();
oled.print("Режим");
oled.setCursor(0, 2);
oled.print("Стирки");
oled.setCursor(0, 4);
oled.print("Отложенный");
break;
*/
}
void OledPrint_Sub()
{
Serial.println("OledPrint_Sub");
RejimToOled();
Rejim++;
if (Rejim>10)
{
Rejim=0;
}
}
void LCD_Print(byte N_scr,bool Overwrite, String Str_Dop) // byte N_scr № экрана, bool Overwrite разрешение на вывод экрана если номер не изменился
{
//String Str_tmp;
//String Str_tmp2;
char buff[16];
//Str_tmp.reserve(16);
if (N_scr!=N_screen || Overwrite ) // выводим экран только при изменении
{
N_screen=N_scr; //запоминаем какой экран был выведен
Serial.print("RejimToOled Print Rejim=");
Serial.println(Rejim);
u8g2.firstPage();
do {
switch(N_scr)
{
case 0: // начальный экран
u8g2.setCursor(1, 10);
u8g2.print(" Ожидание "); //
u8g2.setCursor(1, 25);
u8g2.print(" Выбора"); //
//oled.print("Ожидание");
// //oled.setCursor(0, 2);
////oled.print("Выбора");
////oled.setCursor(0, 4);
////oled.print("Режима");
//oled.update();
break;
case 1: // Набор воды экран
Serial.println("Nabor Vodi OLED");
//u8g2.setCursor(1, 10);
//u8g2.print(" Ожидание "); //
u8g2.setCursor(1, 25);
u8g2.print(" НАБОР ВОДЫ"); //
//oled.autoPrintln(true);
//oled.setScale(2);
//oled.clear();
//oled.home();
//oled.print("Статус");
// //oled.setCursor(0, 2);
// //oled.print("Набор Воды");
//oled.update();
break;
case 2: // статус Замачивание + счетчик
u8g2.setCursor(1, 35);
//u8g2.print(" "); //
sprintf(buff, "Цикл=%d ", Cnt_Soaking_Cycle); //
u8g2.print(buff);
u8g2.setCursor(1, 10);
u8g2.print(" ЗАМАЧИВАНИЕ"); //
//oled.autoPrintln(true);S
//oled.setScale(2);
//oled.clear();
//oled.home();
//if (!Overwrite)
// {
//oled.print("Статус");
// //oled.setCursor(0, 2);
// //oled.print("Замачивание");
// //oled.setCursor(0, 5);
// //oled.print(buff);
// u8g2.setFont(u8g_font_unifont);
// u8g2.setCursor(1, 10);
// u8g2.print(buff);
// }
// else
{
// //oled.setCursor(60, 5);
// sprintf(buff, "%d ", Cnt_Soaking_Cycle); //
////oled.print(buff);
}
//oled.update();
//strcpy(str1, str2) Копирует str2 в str1, включая NULL. Так как мы передаём указатель, цель и место назначения можно “подвинуть”:
//strcat(str1, str2) Прибавляет str2 к str1, при этом str1 должна иметь достаточный для этого размер. NULL первой строки заменяется на первый символ из str2
//strncpy(str1, str2, num) Копирует num символов из начала str2 в начало str1
//strncat(str1, str2, num) Добавляет num символов из начала str2 к концу str1
break;
case 3: // статус Стирка + счетчик
/*
Overwrite?(void)0:lcd.clear();
lcd.setCursor(0, 0);
//itoa(Cnt_Washing_Cycle, buff, DEC);
//Str_tmp=buff;
//Str_tmp="Status CNT="+Str_tmp;
sprintf(buff, "Status CNT=%d ", Cnt_Washing_Cycle); //
lcd.print(buff);
lcd.setCursor(0, 1);
sprintf(buff,"Stirka ");
lcd.print(buff);
*/
//oled.autoPrintln(true);
//oled.setScale(2);
//oled.clear();
//oled.home();
u8g2.setCursor(1, 35);
sprintf(buff, "Цикл=%d ", Cnt_Washing_Cycle); //
u8g2.print(buff);
u8g2.setCursor(1, 10);
u8g2.print(" СТИРКА"); //
if (!Overwrite)
{
//oled.print("Статус");
////oled.setCursor(0, 2);
////oled.print("Стирка");
////oled.setCursor(0, 5);
//sprintf(buff, "Цикл=%d ", Cnt_Washing_Cycle); //
////oled.print(buff);
}
else
{
// //oled.setCursor(60, 5);
// sprintf(buff, "%d ", Cnt_Washing_Cycle); //
////oled.print(buff);
}
//oled.update();
break;
case 4:
/*
Overwrite?(void)0:lcd.clear();
lcd.setCursor(0, 0);
//Str_tmp="Status ";
sprintf(buff, "Status "); //
lcd.print(buff);
lcd.setCursor(0, 1);
lcd.print(" Sliv vodi ");
*/
//oled.autoPrintln(true);
//oled.setScale(2);
//oled.clear();
//oled.home();
// if (!Overwrite)
//{
//oled.print("Статус");
////oled.setCursor(0, 2);
////oled.print("Слив");
//}
//oled.update();
//u8g2.setCursor(1, 35);
//sprintf(buff, "Цикл=%d ", Cnt_Washing_Cycle); //
//u8g2.print(buff);
u8g2.setCursor(1, 10);
u8g2.print(" СЛИВ"); //
break;
case 5:
/*
Overwrite?(void)0:lcd.clear(); // статус Полоскание + счетчик
lcd.setCursor(0, 0);
//Str_tmp="Status CNT="+Cnt_Rinsing_Cycle;
//itoa(Cnt_Rinsing_Cycle, buff, DEC);
//Str_tmp=buff;
//Str_tmp="Status CNT="+Str_tmp;
sprintf(buff, "Status CNT=%d ", Cnt_Rinsing_Cycle); //
lcd.print(buff);
lcd.setCursor(0, 1);
lcd.print(" Poloskanie ");
*/
//oled.autoPrintln(true);
//oled.setScale(2);
//oled.clear();
//oled.home();
u8g2.setCursor(1, 35);
sprintf(buff, "Цикл=%d ", Cnt_Rinsing_Cycle); //
u8g2.print(buff);
u8g2.setCursor(1, 10);
u8g2.print(" ПОЛОСКАНИЕ"); //
if (!Overwrite)
{
//oled.print("Статус");
////oled.setCursor(0, 2);
////oled.print("Полоскание");
////oled.setCursor(0, 5);
//sprintf(buff, "Цикл=%d ", Cnt_Rinsing_Cycle); //
//oled.print(buff);
}
else
{
////oled.setCursor(60, 5);
//sprintf(buff, "%d ", Cnt_Rinsing_Cycle); //
////oled.print(buff);
}
//oled.update();
break;
case 6:
/*
Overwrite?(void)0:lcd.clear(); // статус Отжим + уровень скорости
lcd.setCursor(0, 0);
//Str_tmp="Status Speed="+Str_Dop;
sprintf(buff, "Status Speed=%s ", Str_Dop); //
lcd.print(buff);
lcd.setCursor(0, 1);
lcd.print(" Otjim ");
*/
//oled.autoPrintln(true);
//oled.setScale(2);
//oled.clear();
//oled.home();
u8g2.setCursor(1, 35);
//sprintf(buff, "Цикл=%d ", Cnt_Rinsing_Cycle); //
u8g2.print(Str_Dop);
u8g2.setCursor(1, 10);
u8g2.print(" ОТЖИМ"); //
if (!Overwrite)
{
////oled.print("Статус");
////oled.setCursor(0, 2);
//oled.print("Отжим");
////oled.setCursor(0, 5);
//sprintf(buff, "Скор=%s ", ); //
////oled.print(Str_Dop);
}
else
{
////oled.setCursor(60, 5);
//sprintf(buff, "%s ", ); //
//oled.print(Str_Dop);
}
//oled.update();
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
}
}while ( u8g2.nextPage() );
}
}
byte ChekEncoder_Sub() //при изменении менять режим(Rejim и зажигать светодиоды)
{ byte state;
state=0;// если не было изменений вернуть 0
int newClk = digitalRead(ENCODER_CLK);
if (newClk != lastClk)
{
// There was a change on the CLK pin
lastClk = newClk;
int dtValue = digitalRead(ENCODER_DT);
if (newClk == PinOff && dtValue == PinOn) {
Serial.println("Rotated clockwise ?");
Rejim =Rejim+1;
//Serial.print("EncoderValue=");
//Serial.println(EncoderValue);
state= 1; // если вращение по часовой то вернуть 1
}
if (newClk == PinOff && dtValue == LOW) {
Serial.println("Rotated counterclockwise ?");
Rejim =Rejim-1;
state= 2; // если вращение против часовой то вернуть 2
}
if (Rejim<0)
{
Rejim=10;
}
if (Rejim>10)
{
Rejim=0;
}
Serial.print("EncoderValue=");
Serial.println(EncoderValue);
Serial.print("Rejim=");
Serial.println(Rejim);
RejimToOled();
}
return state;
}
void Check_Rejim()
{ byte state;
state=ChekEncoder_Sub();
int SWValue = digitalRead(BTN_Encoder);
if (SWValue ) // !!!! кнопка старт ()она же пауза
{
//Serial.print("EncoderValue=");
//Serial.println(EncoderValue);
//Serial.print("Rejim=");
//Serial.println(Rejim);
}
}
void Timer_Water_Osn_Sub() // &&& /////////////////////////////////// Защиты
{
Err_code_Word = Err_code_Word | 32; //Сраб.таймера не набора воды1
}
void Timer_Spin_Sub()
{
Err_code_Word = Err_code_Word | 512; //Сраб.таймера не набора воды2
}
void Timer_TEN_Sub()
{
Err_code_Word = Err_code_Word | 128; //Сраб.таймера не нагрева воды
}
//////////////////////////////////////////////////////////////////////Защиты
void Timer_Mot_Soaking_Sub()
{
//digitalWrite(Mot_Dir, !RD_Mot_Dir ? HIGH : LOW); // ---digitalWr //смена направления вращения
Mot_Dir_Value=!RD_Mot_Dir ? PinOn : PinOff; //смена направления вращения
// изменение количества циклов
Cnt_Soaking_Cycle = Cnt_Soaking_Cycle + 1; // считаем сколко раз сменилось направление вращения
if (Cnt_Soaking_Cycle < Soaking_Cycle)
{
Tic_Mot_Soaking.once(Timer_Mot_Soaking, Timer_Mot_Soaking_Sub); // запускаем таймер вращения при замачивании
}
Serial.print("void Timer_Mot_Soaking_Sub =");
Serial.println(Cnt_Soaking_Cycle);
LCD_Print(2,true,"");
}
void Timer_Washing_Sub()
{
//digitalWrite(Mot_Out, LOW);// ---digitalWr
Mot_Out_Value = PinOff;
// digitalWrite(TEN, LOW); // ---digitalWr
TEN_Value = PinOff;
Status=4;
Tic_Mot_Washing.detach();
Tic_Washing.detach();
Serial.println("Timer_Mot_Washing_Sub =");
Serial.println("step to next status");
Serial.println("status =4");
LCD_Print(3,false,"");
}
void Timer_Mot_Washing_Sub()
{
//digitalWrite(Mot_Dir, !RD_Mot_Dir ? HIGH : LOW); // ---digitalWr //смена направления вращения
Mot_Dir_Value=!RD_Mot_Dir ? PinOn : PinOff; //смена направления вращения
Cnt_Washing_Cycle = Cnt_Washing_Cycle + 1;
Serial.print("Timer_Mot_Washing_Sub =");
Serial.println(Cnt_Washing_Cycle);
LCD_Print(3,true,"");
}
void Timer_Pumping_Sub()
{
Err_code_Word = Err_code_Word | 256; //Сраб.таймера не откачки воды
}
void Timer_Water_Dop_Sub()
{
Err_code_Word = Err_code_Word | 64; //Сраб.таймера не набора воды при открытом втором клапане
}
void Timer_Mot_Rinsing_Sub()
{
//digitalWrite(Mot_Dir, !RD_Mot_Dir ? HIGH : LOW); // ---digitalWr //смена направления вращения
Mot_Dir_Value=!RD_Mot_Dir ? PinOn : PinOff; //смена направления вращения
Cnt_Rinsing_Cycle = Cnt_Rinsing_Cycle + 1;
Serial.print("void Timer_Mot_Rinsing_Sub =");
Serial.println(Cnt_Rinsing_Cycle);
//lcd.clear();
//lcd.setCursor(0, 0);
//lcd.print("CS_Cycle");
//lcd.setCursor(0, 1);
//lcd.print(Cnt_Rinsing_Cycle);
LCD_Print(5,true,"");
}
void Timer_Rinsing_Sub()
{
//digitalWrite(Mot_Out, LOW); //!!! // ---digitalWr
Mot_Out_Value= PinOff; // //!!!
Status=6;
Tic_Mot_Rinsing.detach();
Tic_Rinsing.detach();
Serial.print("Timer_Rinsing_Sub ");
Serial.println("step to next status");
//lcd.clear();
//lcd.setCursor(0, 0);
//lcd.print("status=6");
}
void Timer_Spin3_Sub()
{
Pump_Value=PinOff;// отключить насос откачки
Status=0;
Tic_Spin3.detach();
UBL_OUT_Value=PinOff;
}
void Timer_Spin2_Sub()
{
Mot_Speed_Spin=Mot_Speed_Spin3; //смена скорости вращения
Tic_Spin3.once(Timer_Spin3, Timer_Spin3_Sub); // запускаем таймер вращения при замачивании
Tic_Spin2.detach();
Serial.print("Mot_Speed_Spin=Mot_Speed_Spin3; ");
//lcd.clear();
//lcd.setCursor(0, 0);
//lcd.print("Spin3");
//lcd.setCursor(0, 1);
//lcd.print("Spin_Cycle3");
LCD_Print(6,true,"3");
}
void Timer_Spin1_Sub()
{
Mot_Speed_Spin=Mot_Speed_Spin2; //смена скорости вращения
Tic_Spin2.once(Timer_Spin2, Timer_Spin2_Sub); // запускаем таймер вращения при замачивании
Tic_Spin.detach();
Serial.print("Mot_Speed_Spin=Mot_Speed_Spin2; ");
//lcd.clear();
//lcd.setCursor(0, 0);
//lcd.print("Spin2");
//lcd.setCursor(0, 1);
//lcd.print("Spin_Cycle2");
LCD_Print(6,true,"2");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//Create a Motor class. IT must have the following functions: On; Off; Direction of rotation; Detector...
class Motor { // %%%%%%%%%%% class Motor %%%%%%%%%%%
private:
bool isOn;
bool isClockwise;
bool isVoltageTransition;
bool isVoltagePresent;
bool isSpeedSensorWorking;
bool Ten_output;
public:
// Constructor
Motor() {
isOn = false;
isClockwise = true;
isVoltageTransition = false;
isVoltagePresent = false;
isSpeedSensorWorking = false;
Ten_output = false;
}
// Turn TEN on/off
void Ten(bool Ten_output) {
//digitalWrite(TEN, Ten_output ? HIGH : LOW); // ---digitalWr
TEN_Value= RD_TEN ? HIGH : LOW;
StrRezult = RD_TEN ? "On" : "Off";
Serial.println( "Ten " + StrRezult);
}
// Turn on the motor
void On() {
//digitalWrite(Mot_Out, HIGH); // ---digitalWr
Mot_Out_Value =PinOn; //!!!
isOn = true;
Serial.println ( "Motor is turned on.");
}
// Turn off the motor
void Off() {
//digitalWrite(Mot_Out, LOW); // ---digitalWr
Mot_Out_Value =PinOff; //!!!
isOn = false;
Serial.println("Motor is turned off." );
}
// Set the direction of rotation
void SetDirection(bool clockwise) {
isClockwise = clockwise;
//digitalWrite(Mot_Dir, isClockwise ? HIGH : LOW); // ---digitalWr
Mot_Dir_Value= isClockwise ? PinOn : PinOff;
StrRezult = isClockwise ? "clockwise" : "counterclockwise";
Serial.println("Direction of rotation is set to " + StrRezult );
}
// Check if ther noe is a transition of the sine of the mains voltage through 0
bool IsVoltageTransition() {
return isVoltageTransition;
}
// Check if there is voltage in the direction of rotation of the relay
bool IsVoltagePresent() {
return isVoltagePresent;
}
// Check if the motor speed sensor is working
bool IsSpeedSensorWorking() {
return isSpeedSensorWorking;
}
};
Motor Washmotor;
void EEPROM_Init() // Читаем из EEPROM уставки
{
}
void Pin_init() // Инициализация режимов работы входов / выходов.
{
pinMode(Mot_Out, OUTPUT);
pinMode(Mot_Dir, OUTPUT);
pinMode(Klap_Water_Osn, OUTPUT);
pinMode(Klap_Water_Dop, OUTPUT);
pinMode(TEN, OUTPUT);
pinMode(UBL_OUT, OUTPUT);
pinMode(Pump, OUTPUT);
pinMode(36, INPUT_PULLUP);
pinMode(39, INPUT_PULLUP);
pinMode(34, INPUT_PULLUP);
pinMode(35, INPUT_PULLUP);
pinMode(32, INPUT_PULLUP);
pinMode(33, INPUT_PULLUP);
pinMode(25, INPUT_PULLUP);
pinMode(26, INPUT_PULLUP);
pinMode(ENCODER_CLK, INPUT); //encoder
pinMode(ENCODER_DT, INPUT);
}
bool CheckWaterLevel(byte Level) //проверка уровня воды в баке по запросу (1 , 2, 3 )
{
bool Ret_Level;
switch (Level)
{
case 1:
!RD_Level_1? Ret_Level =true: Ret_Level=false; //!!! проверить инверсию на реальном устройстве
break;
case 2:
!RD_Level_2? Ret_Level =true: Ret_Level=false;//!!! проверить инверсию на реальном устройстве
break;
case 3:
!RD_Level_3? Ret_Level =true: Ret_Level=false;//!!! проверить инверсию на реальном устройстве
break;
}
return Ret_Level;
}
void setup() { //%%%%%%%%%%%%%%%%%% void setup() %%%%%%%%%%%%%%%%%%%
// put your setup code here, to run once:
//Led
Pin_init();
//OLED
u8g2.begin();
u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
//u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
//u8g2.setFontDirection(0);
u8g2.setFont(u8g2_font_unifont_t_cyrillic); //
//u8g2.setFont(u8g2_font_ncenB14_tr); // Задаем шрифт текста
//u8g2.setFont(u8g2_font_10x20_tn); // Задаем шрифт текста
//u8g2.setFont(u8g2_font_unifont_t_chinese2); // использовать китайский2 для всех глифов "Hello World"
/*
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " Hello, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, " World!"); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
char b[2];
String str;
str=String(Rejim);
str.toCharArray(b,2);
u8g2.clearBuffer(); // Очищаем буфер экрана
u8g2.drawStr(0, 15, " HOHO, "); // Выводим текст на дисплей
u8g2.drawStr(0, 30, b); // Выводим текст на дисплей
u8g2.sendBuffer(); // Отправляем буфер на дисплей
*/
/*u8g2.setFont(u8g2_font_unifont_t_cyrillic); //
u8g2.setFontDirection(0);
u8g2.firstPage();
do {
u8g2.setCursor(10, 10);
u8g2.print("Привет decoder");
} while ( u8g2.nextPage() );
*/
//OLED @
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, LED_NUM);
FastLED.setBrightness(255);
Btn_Start = false;
EncoderValue=0;
Status = 0;
Temp_Water = 10; // Ustavki !!!
Timer_Water_Osn = 10;
Timer_Water_Dop = 10;
Timer_TEN = 10;
Temp_Water_Ust = 20;
Timer_Pumping=10;
Timer_Spin=5;
Timer_Spin2=5;
Timer_Spin3=5;
Soaking_Cycle = 6; //Сколько раз сменится направление вращения барабана при замачивании после которого произойдет переход в режим стирка
//Rinsing_Cycle=
Mot_Speed_Soaking = 15 ; // скорость барабана при замачивании об/мин
Timer_Mot_Soaking = 3 ; // время работы при вращении в одну сторону (при работе происходит смена направления вращения)
Mot_Speed_Washing = 15 ; // скорость барабана при замачивании об/мин
Timer_Mot_Washing = 5 ; // время работы при вращении в одну сторону (при работе происходит смена направления вращения)
Timer_Washing=25;
Timer_Rinsing=25;
Timer_Mot_Rinsing =5;
Rinsing_Pump2_Cycle=2;
//Mot_Dir ; // направление вращения
//Temp_Water ; // температура воды
//&&&&&&&
//Tic_Water_Osn.once(5, Timer_Water_Osn_Sub); //Use attach_ms if you need time in ms
//Tic_TEN.once(5, Timer_TEN_Sub); //Use attach_ms if you need time in ms
//Tic_Mot_Soaking.once(5, Timer_Mot_Soaking_Sub); //Use attach_ms if you need time in ms
//Tic_Washing.once(5, Timer_Washing_Sub); //Use attach_ms if you need time in ms
//Tic_Mot_Washing.once(5,Timer_Mot_Washing);
//Tic_Pumping.once(5, Timer_Pumping_Sub); //Use attach_ms if you need time in ms
//Tic_Water_Dop.once(5, Timer_Water_Dop_Sub); //Use attach_ms if you need time in ms
//Tic_Spin.once(5, Timer_Spin_Sub); //Use attach_ms if you need time in ms
//Tic_Spin1.once(5, Timer_Spin1_Sub); //Use attach_ms if you need time in ms
//Tic_Spin2.once(5, Timer_Spin2_Sub); //Use attach_ms if you need time in ms
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Запись выходов через переопределение
//#define DW_Mot_Out DigitalWrite(Mot_Out,Wr_Value)
//#define DW_Mot_Dir DigitalWrite(Mot_Dir,Wr_Value)
//#define DW_Klap_Water_Osn DigitalWrite(Klap_Water_Osn,Wr_Value)
//#define DW_Klap_Water_Dop DigitalWrite(Klap_Water_Dop,Wr_Value)
//#define DW_TEN DigitalWrite(TEN,Wr_Value)
//#define DW_UBL_OUT DigitalWrite(UBL_OUT,Wr_Value)
//#define DW_Pump DigitalWrite(Pump,Wr_Value)
Err_code_Word = 0; //Обнуляем слово ошибок при включении питания
EEPROM_Init();
Serial.begin(115200);
Serial.println("Hello, ESP32!");
//OledPrint.attach(3,OledPrint_Sub); //test
}
void Temperature_Reg() // тестовая функция регулировки температуры воды в баке
{
}
void SetLedRejim()
{
}
void loop() {
//SetLedRejim();
Check_Rejim();
///Led!!!
if ((Rejim!=Old_Rejim) || (Rejim==0))
{
Old_Rejim=Rejim;
FastLED.clear();
leds[Rejim] = CRGB(9, 251, 53);
FastLED.show();
}
//delay(30);
//Led
//EncoderValue=ChekEncoder_Sub();
if (!PIN36 ) // !!!! кнопка старт
{
if (!Btn_Start)
{ Btn_Start = true;
Status = 1;
}
}
else {
Status = 0;
Cnt_Washing_Cycle=0;//!!! предусмотреть кпри кнопке пауза не сбрасывать
Cnt_Rinsing_Cycle=0;//!!! предусмотреть кпри кнопке пауза не сбрасывать
Cnt_Soaking_Cycle=0;
Cnt_Rinsing_Pump2_Cycle=0;//!!! предусмотреть кпри кнопке пауза не сбрасывать Pump2
Btn_Start = false;
Status_Wash_Start=false;
Status_Pump_Start=false;
Status_Rinsing_Start=false;
Status_Pump2_Start=false;
Status_Spin_Start=false;
//digitalWrite(UBL_OUT, LOW); // ---digitalWr
UBL_OUT_Value=PinOff;
//digitalWrite(TEN, LOW); // ---digitalWr
TEN_Value=PinOff;
//digitalWrite(Klap_Water_Osn, LOW); // ---digitalWr
Klap_Water_Osn_Value=PinOff;
}
//PIN36 ? Washmotor.Off() : Washmotor.On();
//PIN39 ? digitalWrite(Klap_Water_Osn, HIGH): digitalWrite(Klap_Water_Osn, LOW); // ---digitalWr
PIN34 ? Temp_Water = 10 : Temp_Water = 20;
switch ( Status )
{
case 0:
LCD_Print(0,false,"");
break;
case 1: //Статус - Набор воды и Нагрев
// Блокировка люка (Контроль люка?)
// Открытие клапана Воды1 (если не был открыт и зауск таймера Воды1)
// Контроль Температуры (Поддержание заданного значения если включен ТЭН )
// При Достижеии минимального уровня Включение ТЕН (если не был включен ) и запуск таймера нагрева и запоминание текущей температуры
// Контроль максимального уровня (отключение клапанов Воды при достижении)
// При изменении температуры воды на 5 Гр.С от текущей переход в Статус Замачивание
//Timer_Water_Osn , Klap_Water_Osn , UBL_OUT , Temp_Water , TEN , Timer_TEN , Temp_Water_Initial , Level_1
//lcd.clear(); //Тест
//lcd.setCursor(0, 0); //Тест
//lcd.print("Status=1"); //Тест
//digitalWrite(UBL_OUT, HIGH); // ---digitalWr // включить блокировку люка
UBL_OUT_Value=PinOn; // включить блокировку люка
Water_Level=1; // !!! указать значение (считать) из массива уставок
if (!RD_Klap_Water_Osn) // если клапан основной забора воды не открыт то пускаем воду в бак и запускаем таймер защиты заполнения бака !!! (проверить инверсию на реальном устройстве)
{
//lcd.clear(); //Тест
//lcd.setCursor(0, 0); //Тест
//lcd.print("Status=1"); //Тест
LCD_Print(1,false,"");
Serial.println("Klap_Water_Osn 1");
//digitalWrite(Klap_Water_Osn, HIGH); // ---digitalWr //Открыть клапан воды основной
Klap_Water_Osn_Value=PinOn;
Tic_Water_Osn.once(Timer_Water_Osn, Timer_Water_Osn_Sub); //Защита по заполнению бака за заданное время (таймер)
Serial.println("Step 1");
//delay(1000); //********Test
}
if (CheckWaterLevel(Water_Level) ) //********Level_1 если вода налита до уровня 1 !!! (проверить инверсию на реальном устройстве количесво воды в зависимости от режима (ткани))
{
Klap_Water_Osn_Value=PinOff ; //!!! отключить подачу воды (проверить инверсию на реальном устройстве количесво воды в зависимости от режима (ткани))
if (!RD_TEN ) // !!! если тэн не включен то запускаем таймер защиты по нагреву и запоминаем текущую температуру для дальнейшего перехода в статус замачивание
{ Serial.println("TEN 1");
Tic_TEN.once(Timer_TEN, Timer_TEN_Sub); //Защита по нагреву бака за заданное время (таймер)
//digitalWrite(TEN, HIGH); // ---digitalWr //Включить нагрев воды !!!
TEN_Value=PinOn;
Temp_Water_Initial = Temp_Water; //Запомнить температуру воды при включении тэна
Serial.print(" TEN Temp_Water_Initial=");
Serial.println( Temp_Water_Initial);
Serial.print(" TEN Temp_Water 0=");
Serial.println( Temp_Water);
Serial.println("Step 2");
delay(1000); //********Test !!!
}
if ((Temp_Water >= Temp_Water_Initial + 5) || (Temp_Water >= Temp_Water_Ust) ) //Если температура воды изменилась на 5 градусов от момента включения и есть вода в баке то перейти в статус замачивание
{
StrRezult = Temp_Water > Temp_Water_Initial + 5 ? "true" : "false";
Serial.print("Temp_Water_Initial+5>Temp_Water ");
Serial.println(StrRezult);
Serial.println("Step 3");
Serial.print("Temp_%%%%%%%%%%%%%%%%%=");
Serial.println(Temp_Water_Initial + 5);
Serial.print("Temp_Water=");
Serial.println(Temp_Water);
Serial.print("Temp_Water_Initial=");
Serial.println( Temp_Water_Initial);
Status = 2; //перейти в статус замачивание
Serial.println("Замачивание");
//lcd.clear();
//lcd.setCursor(0, 0);
//lcd.print("Status=2");
//digitalWrite(Klap_Water_Osn, LOW); // ---digitalWr //!!! отключить подачу воды (проверить инверсию на реальном устройстве количесво воды в зависимости от режима (ткани))
}
//Temperature_Reg();//регулятора температуры
}
break;
case 2: //Замачивание
// Mot_Out , Mot_Speed_Soaking , Timer_Mot_Soaking , Mot_Dir , Temp_Water , Soaking_Cycle , TEN
// Вращение барабана на минимальной скорости Заданное время
// Смена направления вращения
// Вращение барабана на минимальной скорости Заданное время
// Долив воды ???
// Контроль Температуры (Поддержание заданного значения)
// При выполнении заданного количества циклов смены вращения переход в Стирка
//Temperature_Reg();//регулятор температуры
if ( !RD_Mot_Out) // если мотор не включен то:
{
LCD_Print(2,false,"");
//digitalWrite(Mot_Out, HIGH); // ---digitalWr //включаем мотор
Mot_Out_Value=PinOn;// ---digitalWr //включаем мотор !!!
Tic_Mot_Soaking.once(Timer_Mot_Soaking, Timer_Mot_Soaking_Sub); // запускаем таймер вращения при замачивании
//lcd.clear();
//lcd.setCursor(0, 0);
//lcd.print("TimerS");
//lcd.setCursor(0, 1);
//lcd.print(Timer_Mot_Soaking);
}
if (Cnt_Soaking_Cycle >= Soaking_Cycle)
{
Tic_Mot_Soaking.detach();
Cnt_Soaking_Cycle = 0;
Status = 3;
//lcd.clear();
//lcd.setCursor(0, 0);
//lcd.print("Status=3");
}
break;
case 3: //Стирка
//Mot_Speed_Washing , Timer_Mot_Washing , Mot_Dir , Temp_Water , Timer_Washing , TEN
if (!Status_Wash_Start)
{
LCD_Print(3,false,"");
Status_Wash_Start=true; // выполняе только один раз при входе в статус стирка
Mot_Speed_Washing=Mot_Speed_Washing; //!!! назначить значение скорости вращения из массива
Tic_Washing.once(Timer_Washing, Timer_Washing_Sub); // запускаем таймера стирка
Tic_Mot_Washing.attach(Timer_Mot_Washing, Timer_Mot_Washing_Sub); // запускаем таймер вращения при замачивании
}
//Temperature_Reg();//регулятор температуры
break;
case 4: //Слив 1
//4 Pumping1
//Включение насоса откачки. Запуск таймера Откачки
//Придостжении минимального уровня отключение насоса откачки переход в Полоскание
if (!Status_Pump_Start)
{
LCD_Print(4,false,"");
Status_Pump_Start=true;
//digitalWrite(Pump, HIGH); // ---digitalWr
Pump_Value=PinOn; // включить насос
Tic_Pumping.once(Timer_Pumping, Timer_Pumping_Sub); // запускаем защитный таймера отжим за заданное время
Serial.println( "case 4 Status=4");
//lcd.clear();
//lcd.backlight();
//lcd.setCursor(0, 0);
//lcd.print("Status=4");
}
if (RD_Level_1)
{
//digitalWrite(Pump, LOW); // ---digitalWr
Pump_Value=PinOff; // отключить насос
Tic_Pumping.detach();
Status=5;
//Serial.print("Temp_Water_Initial=");
Serial.println( "Status=5");
}
break;
case 5: //Полоскание Timer_Water_Dop, Mot_Speed_Rinsing, Count_Rinsing
//Rinsing
// Открытие клапана Воды2 (если не был открыт и зауск таймера Воды2)
//Вращение барабана на Заданной скорости Заданное время
//Смена направления вращения
//Вращение барабана на Заданной скорости Заданное время
// При достижении заданного времени Уменьшение счетчика количества полосканий и переход в Слив 2
if (!Status_Rinsing_Start)
{
LCD_Print(5,false,"");
Status_Rinsing_Start=true;
//digitalWrite(Klap_Water_Dop, HIGH); // ---digitalWr // открыть дополнительный (полоскание) клапан воды
Klap_Water_Dop_Value=PinOn; // открыть дополнительный (полоскание) клапан воды //#1
Tic_Water_Dop.once(Timer_Water_Dop, Timer_Water_Dop_Sub); // запускаем защитный таймера наполнения бака водой за заданное время !!! сделать если заполнение до 3 уровня то проверять 2 пердшедствующих
Water_Level=3; //контролировать 3 (последний) уровень воды в баке
}
if (CheckWaterLevel(Water_Level)) // если требуемый уровень достигнут
{
// !!! вместо digitalWrite(Mot_out, HIGH) должен быть вызов функции с ПИД регулятором (класс Мотор)
if ( !RD_Mot_Out) // если мотор не включен то:
{
Klap_Water_Dop_Value=PinOff; // закрыть дополнительный (полоскание) клапан воды //#1
Tic_Water_Dop.detach();
//digitalWrite(Mot_Out, HIGH); // ---digitalWr //включаем мотор
Mot_Out_Value=PinOn; //включаем мотор !!!
Mot_Speed_Rinsing=Mot_Speed_Rinsing; //!!! назначить значение скорости вращения из массива
Tic_Rinsing.once(Timer_Rinsing, Timer_Rinsing_Sub); // запускаем таймера Полоскание
Tic_Mot_Rinsing.attach(Timer_Mot_Rinsing, Timer_Mot_Rinsing_Sub); // запускаем таймер вращения при замачивании
//lcd.clear();
//lcd.setCursor(0, 0);
//lcd.print("TimerS Rinsing");
//lcd.setCursor(0, 1);
//lcd.print(Timer_Mot_Rinsing);
}
}
break;
case 6: //Слив 2
//4 Pumping1
//Включение насоса откачки. Запуск таймера Откачки
//Придостжении минимального уровня отключение насоса откачки переход в
if (!Status_Pump2_Start)
{
Status_Pump2_Start=true;
//digitalWrite(Pump, HIGH); // ---digitalWr
Pump_Value=PinOn;
Tic_Pumping.once(Timer_Pumping, Timer_Pumping_Sub); // запускаем защитный таймера отжим за заданное время
//lcd.clear();
//lcd.backlight();
//lcd.setCursor(0, 0);
//lcd.print("Status=5");
Water_Level=1; //контролировать 31 (послпервый ) уровень воды в баке
Serial.println( "!Status_Pump2_Start ");
LCD_Print(4,false,"");
}
if (!CheckWaterLevel(Water_Level)) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% !!! уровень 1 пропал
{
Tic_Pumping.detach();
//digitalWrite(Pump, LOW); // ---digitalWr
Pump_Value=PinOff;
if (Cnt_Rinsing_Pump2_Cycle>=Rinsing_Pump2_Cycle)
{
//Tic_Pumping.detach();
Status=7;//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//Serial.print("Temp_Water_Initial=");
Serial.println( "Status=7");
}
else
{
Cnt_Rinsing_Pump2_Cycle=Cnt_Rinsing_Pump2_Cycle+1;
Status_Rinsing_Start=false;
Status=5;//увеличить счетчик сбросить тригер (Полоскание) и вернутся на статус полоскание
Status_Pump2_Start=false; // сбросить тригер (Слив 2)
Cnt_Rinsing_Cycle=0; // обнулить счетчики полосканий
Serial.print( "Cnt_Rinsing_Pump2_Cycle=Cnt_Rinsing_Pump2_Cycle+1=");
Serial.println(Cnt_Rinsing_Pump2_Cycle);
}
}
break;
case 7: //Отжим Spin
//Отжим
//Вращение барабана на Заданной скорости Заданное время
//Плавное Увеличение оборотов до заданных в режиме отжим
//Включение насоса откачки
//Вращение барабана на Заданной скорости Заданное время
//Включение насоса откачки
//Плавное Увеличение оборотов до заданных при отжиме
//При достижении заданного времени отключени двигателя переход в режим Конец стирки
if (!Status_Spin_Start)
{
LCD_Print(6,false,"1");
Status_Spin_Start=true;
Pump_Value=PinOn;
Mot_Speed_Spin=Mot_Speed_Spin; //!!! назначить значение скорости вращения из массива
Tic_Spin.attach(Timer_Spin, Timer_Spin1_Sub); // запускаем таймер вращения при замачивании
}
break;
default:
(void)0; // ничего не делать
}
//контроль устройств
if (Status == 1 || Status == 2 || Status==3)
{
Temperature_Reg();//регулятор температуры //для тена сделать опрос если режимы замачивание и стирка то вызов регулятора температуры иначе отключить тен.
}
else
{ TEN_Value=false; } // отключ. ТЕН
// Запись значений Выходов
digitalWrite(TEN,TEN_Value ? PinOn:PinOff); // PinOff PinOn
digitalWrite(Mot_Out,Mot_Out_Value? PinOn:PinOff);
digitalWrite(Mot_Dir,Mot_Dir_Value? PinOn:PinOff);
digitalWrite(Klap_Water_Osn,Klap_Water_Osn_Value? PinOn:PinOff);
digitalWrite(Klap_Water_Dop,Klap_Water_Dop_Value? PinOn:PinOff); //#2
digitalWrite(TEN,TEN_Value? PinOn:PinOff);
digitalWrite(UBL_OUT,UBL_OUT_Value? PinOn:PinOff);
digitalWrite(Pump,Pump_Value? PinOn:PinOff);
// Запись значений Выходов
//@@@@@@@@@@@ Защиты должны выполнять запись независимо от алгоритмов @@@@@@@
if (Err_code_Word > 0)
{
digitalWrite(TEN, PinOff); // ---digitalWr
digitalWrite(Klap_Water_Osn, PinOff); // ---digitalWr
digitalWrite(Klap_Water_Dop, PinOff); // ---digitalWr //#3
digitalWrite(Mot_Out, PinOff); // ---digitalWr
digitalWrite(TEN, PinOff); // ---digitalWr
digitalWrite(Pump, PinOff); // ---digitalWr
Serial.print("Ошибка ") ;
Serial.println(Err_code_Word) ;
}
// проверить на реальном устройстве по какому уровню будет срабатывание 1 или 0 !!!
!RD_Level_1 ? Tic_Water_Osn.detach() : digitalWrite(TEN, PinOff) ; // ---digitalWr // Защита 1 Наличие воды и ТЭН (нет воды ТЭН отключить.) + сброс таймера защиты не налива воды
CheckWaterLevel(Water_Level) ? digitalWrite(Klap_Water_Osn, PinOff):(void)0 ; // ---digitalWr //если достигнут заданный уровень отключение воды
CheckWaterLevel(Water_Level) ? digitalWrite(Klap_Water_Dop, PinOff):(void)0 ; //#4 // ---digitalWr//если достигнут заданный уровень отключение воды
CheckWaterLevel(3) ? digitalWrite(Klap_Water_Osn, PinOff):(void)0 ; // ---digitalWr //если достигнут 3 уровень отключение воды
CheckWaterLevel(3) ? digitalWrite(Klap_Water_Dop, PinOff):(void)0 ; //#5 // ---digitalWr//если достигнут 3 уровень отключение воды
!RD_TEN || Temp_Water >= Temp_Water_Ust ? Tic_TEN.detach() : (void)0 ; // ---digitalWr // Сброс таймера защиты не нагрева воды если тен выключен или уста
// вода нагрелась до заданной температуры
// Сброс защит
!RD_Level_1 ? digitalWrite(UBL_OUT, PinOn) : (void)0 ; // ---digitalWr // Защита 1 Наличие воды и блокировка люка !!!(добавить уровень 2 и уровень 3)
//@@@@@@@@@@@ Защиты
//StrRezult=Washmotor.IsVoltageTransition() ? "Yes" : "No";
//Serial.println("Voltage transition: " + StrRezult );
//StrRezult=Washmotor.IsVoltagePresent() ? "Yes" : "No";
//Serial.println("Voltage present: " +StrRezult );
//StrRezult=Washmotor.IsSpeedSensorWorking() ? "Yes" : "No";
//Serial.println("Speed sensor working: "+ StrRezult);
//delay(1000); // this speeds up the simulation
//ChekEncoder();
//pinMode(4, OUTPUT);
// digitalWrite(UBL_OUT, UBL_OUT_Value);
}
//№ Бита Коды Слова неисправностей Слово неисправностей Описание Биты Слова неисправностей Слово неисправностей INT
//1 Err_Temperature Неисправность датчика температуры 0000000000000001 1
//2 Err_Dir неисправность реле направления вращения 0000000000000010 2
//3 0000000000000100 4
//4 0000000000001000 8
//5 0000000000010000 16
//6 Err_Timer_Water_Osn Сраб.таймера не набора воды1 0000000000100000 32
//7 Err_Timer_Water_Dop Сраб.таймера не набора воды2 0000000001000000 64
//8 Err_Timer_TEN Сраб.таймера не нагрева воды 0000000010000000 128
//9 Err_Timer_Pump Сраб.таймера не откачки воды 0000000100000000 256
//Err_Timer_Spin 0000001000000000 512
/*
выключено
Быстрая
шерсть
хлопок
синтетика
отжим
полоскание
обувь
чистка
Джинсы
свободный
Отложенный старт
*/36
39
MotOn
MotDir
WatOsn
TEN
UBL
1- Старт
2- Ур.1
3-Изм.темп.
4-Lvl.2
WatDop
PUMP
5-Lvl.3