//https://wokwi.com/projects/359550905810577409
// https://wokwi.com/projects/360844714334185473
/**************************************************************************
Номер контакта Наименование контакта К какому контакту Arduino необходимо подключить на NANO
1 Gnd, Ground Ground
2 Vdd, Vcc, 5V 5V
3 SCK, D0,SCL, CLK 13!!!!
4 SDA, D1, MOSI 11!!!!
5 RES, RST, RESET 6
6 DC, A0 DC 7
7 CS, Chip Select CS 8
**************************************************************************/
/////////////////////////////////// ПИНЫ //////////////////////////////////
// Подключение энкодера
#define CLK 4
#define DT 5
#define SW 2
/////////////////////////////// БИБЛИОТЕКИ ////////////////////////////////////////////////////
//#include <avr/pgmspace.h>
#include <GyverOLED.h>
#include "GyverEncoder.h"
#include <EEPROM.h>
Encoder enc1(CLK, DT, SW); // для работы c кнопкой
GyverOLED<SSD1306_128x64, OLED_NO_BUFFER> oled; // I2C
//GyverOLED<SSD1306_128x64, OLED_NO_BUFFER, OLED_SPI, 8, 7, 6> oled; // CS , DC, Res
//#include <iarduino_I2C_pH.h> // Подключаем библиотеку для работы с pH-метром I2C-flash.
//iarduino_I2C_pH sensor(0x09); // Объявляем объект sensor для работы с функциями и методами библиотеки iarduino_I2C_pH, указывая адрес модуля на шине I2C.
///////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////структура меню ///////////////////////////////////////////
/*
const PROGMEM byte nomer[18][8] = {{0, 1, 2, 3, 4, 5, 6, 7 }, //0
{8, 9, 10, 11, 12, 13, 14, 15},
{16, 17, 18, 19, 20, 21, 22, 23}, //2
{24, 25, 26, 27, 28, 29, 30, 31},
{32, 33, 34, 35, 36, 37, 38, 39}, //4
{40, 41, 42, 43, 44, 45, 46, 47},
{48, 49, 50, 51, 52, 53, 54, 55}, //6
{56, 57, 58, 59, 60, 61, 62, 63},
{64, 65, 66, 67, 68, 69, 70, 71},
{72, 73, 74, 75, 76, 77, 78, 79}, //9
{80, 81 ,82, 83, 84, 85, 86, 87},
{88, 89, 90, 91, 92, 93, 94, 95},
{96, 97, 98, 99, 100,101,102,103},
{104,105,106,107,108,109,110,111}, //14
{112,113,114,115,116,117,118,119}, //15
{120,121,122,123,124,125,126,127},
{128,129,130,131,132,133,134,135},
{136,137,138,139,140,141,142,143}, //18
}; // строка - номер меню, столбец - номер элемента меню,
//значение - номер элемента
*/
//меню 0
const char m0[] PROGMEM = "МЕНЮ";
const char m1[] PROGMEM = "ДОЗАТОР";
const char m2[] PROGMEM = "рН-МЕТР";
const char m3[] PROGMEM = "КОНДУКТОМЕТР";
const char m4[] PROGMEM = "ТИТРАТОР";
const char mback[] PROGMEM = "НАЗАД"; //101
//меню 1
const char m5[] PROGMEM = "КАЛИБРОВКА ДОЗАТОРА";
const char m6[] PROGMEM = "НЕПРЕРЫВНО";
const char m7[] PROGMEM = "ЗАДАННЫЙ V";
//меню 2
const char m8[] PROGMEM = "КАЛИБРОВКА pH";
const char m9[] PROGMEM = "ИЗМЕРЕНИЕ pH";
// меню 3
const char m10[] PROGMEM = "КАЛИБРОВКА S";
const char m11[] PROGMEM = "ИЗМЕРЕНИЕ S";
//меню 4
const char m12[] PROGMEM = "КИСЛОТОЙ";
const char m13[] PROGMEM = "ЩЕЛОЧЬЮ";
const char m14[] PROGMEM = "ОСАДИТЕЛЬНОЕ";
const char m15[] PROGMEM = "ДО рН";
const char m16[] PROGMEM = "ДО СИГМА";
// меню 5
const char m17[] PROGMEM = "КАЛИБРОВКА ДОЗАТОРА";
const char m18[] PROGMEM = "ПРОКАЧАТЬ 10с";
const char m19[] PROGMEM = "НАЧАТЬ";
//меню 6
const char m20[] PROGMEM = "КАЧАЮ БЕСКОНЕЧНО!";
const char m21[] PROGMEM = "w, мл/мин";
const char m44[] PROGMEM = "НАЧАТЬ";
//меню 7
const char m22[] PROGMEM = "ДОЗИРОВАНИЕ V";
const char m23[] PROGMEM = "V, мл";
const char m24[] PROGMEM = "w, мл/мин";
const char m45[] PROGMEM = "НАЧАТЬ";
// меню 8
const char m25[] PROGMEM = "КАЛИБРОВКА рН-МЕТРА";
const char m26[] PROGMEM = "НАЧАТЬ";
// меню 9
const char m27[] PROGMEM = "ИЗМЕРЕНИЕ рН";
const char m28[] PROGMEM = "рН = ";
const char m46[] PROGMEM = "НАЧАТЬ";
// меню 10
const char m29[] PROGMEM = "КАЛИБРОВКА S";
const char m30[] PROGMEM = "НАЧАТЬ";
// меню 11
const char m31[] PROGMEM = "ИЗМЕРЕНИЕ S";
const char m32[] PROGMEM = "НАЧАТЬ";
const char m47[] PROGMEM = "Электропроводность";
const char m33[] PROGMEM = "мкСм/см";
// меню 12
const char m34[] PROGMEM = "ТИТРОВАНИЕ H+";
const char m35[] PROGMEM = "ПРОКАЧАТЬ 10с";
const char m36[] PROGMEM = "НАЧАТЬ";
const char m37[] PROGMEM = "w, мл/мин";
const char* const name[18][8] PROGMEM = {
{m0, m1, m2, m3, m4}, // "МЕНЮ","ДОЗАТОР", "рН-МЕТР", "КОНДУКТОМЕТР", "ТИТРАТОР", "НАЗАД" //0
{m1, m5, m6, m7, mback}, //"ДОЗАТОР","КАЛИБРОВКА ДОЗАТОРА", "НЕПРЕРЫВНО", "ЗАДАННЫЙ V", "НАЗАД" //1
{m2, m8, m9, mback}, //рН-МЕТР", "КАЛИБРОВКА", "ИЗМЕРЕНИЕ рН", "НАЗАД" //2
{m3, m10, m11, mback}, //КОНДУКТОМЕТР","КАЛИБРОВКА", "ИЗМЕРЕНИЕ S", "НАЗАД" //3
{m4, m12, m13, m14, m15, m16, mback}, //"ТИТРАТОР","КИСЛОТОЙ", "ЩЕЛОЧЬЮ", "ОСАДИТЕЛЬНОЕ", "ДО рН", "ДО СИГМА", "НАЗАД" //4
{m17, m18, m19, mback}, //"КАЛИБРОВКА ДОЗАТОРА", "Какое то меню", "НАЗАД" //5
{m20, mback, m44, m21}, //"КАЧАЮ БЕСКОНЕЧНО!", "НАЗАД" ,"СТАРТ", " w, мл/мин", //6
{m22, mback, m45, m23, m24 }, //"ДОЗИРОВАНИЕ V", "НАЗАД", "СТАРТ", " V, мл", " w, мл/мин", //7
{m25, m26, mback}, //"КАЛИБРОВКА рН-МЕТРА", "Какое то меню" , "НАЗАД" //8
{m27, mback, m46,}, //"ИЗМЕРЕНИЕ рН", "НАЗАД", "НАЧАТЬ", "рН = ", //9
{m29, mback, m30}, //"КАЛИБРОВКА S","НАЗАД" "НАЧАТЬ"/10
{m31, mback, m32, m47, m33}, //"ИЗМЕРЕНИЕ S", "СТАРТ", "НАЗАД", "S, мкСм/см" //11
{m34, mback, m35, m36, m37}, //"ТИТРОВАНИЕ H+", "ПРОКАЧАТЬ","СТАРТ", "НАЗАД", " w, мл/мин" //12
};
const PROGMEM byte x0[18][8] = {{0,5,5,5,5}, //0
{0,5,5,5,5}, //1
{0,5,5,5}, //2
{0,5,5,5}, //3
{0,5,5,5,5,5,5}, //4
{0,5,5,5}, //5
{0,5,5,5,80}, //6
{0,5,5,5,5,80,80}, //7
{0,5,5}, //8
{0,5,5,35}, //9
{0,5,5}, //10
{0,5,5,10,35,40}, //11
{0,5,5,5,5,80}, //12
}; //x0 на экране (1-128)
const PROGMEM byte y[18][8] = {{0,2,3,4,5,6,7}, //0
{0,2,3,4,7}, //1
{0,2,3,7}, //2
{0,2,3,7}, //3
{0,2,3,4,5,6,7}, //4
{0,2,3,5}, //5 Калибровка дозатора
{0,2,3,5,5}, //6 Непрерывная прокачка, установка скорости
{0,2,3,5,6,5,6}, //7
{0,2,3}, //8
{0,2,3,5}, //9
{0,2,3}, //10
{0,2,3,0,5,6}, //11
{0,2,3,4,6,6}, //12
}; //номер строки на экране 0-7
const PROGMEM byte size[18][8] = {{1,1,1,1,1}, //0
{1,1,1,1,1}, //1
{1,1,1,1}, //2
{1,1,1,1}, //3
{1,1,1,1,1,1,1}, //4
{1,1,1,1}, //5
{1,1,1,1,1}, //6
{1,1,1,1,1,1,1}, //7
{1,1,1}, //8
{1,1,1,2}, //9
{1,1,1}, //10
{1,1,1,1,2,1}, //11
{1,1,1,1,1,1}, //12
}; //номер строки на экране 0-7
const PROGMEM byte nbrStr[18] = {4, 4,3,3,6,3, 3,4,2,2,2, 2,4,4,3,3}; //0 //количество пунктов в меню для папок (без заголовка)
const PROGMEM byte nm[18][8] = {
{0,1,2,3,4}, //0
{1,5,6,7,101}, //1
{2,8,9,101}, //2
{3,10,11,101}, //3
{4,12,13,14,15,16,101}, //4
{17,18,19,101}, //5
{20,101,44,21}, //6
{22,101,45,23,24}, //7
{25,26,101}, //8
{27,101,46}, //9
{29,101,30}, //10
{31,101,32,47,127,33}, //11
{34,101,35,36,37}, //12
{37,38,101,39}, //13
{41,42,101,43}, //14
}; //номер меню, на которое переходит при клике
const PROGMEM byte type[18][8] = {
{0,0,0,0,0},
{0,0,0,0,0},
{0,0,0,0},
{0,0,0,0}, //3
{0,0,0,0,0,0,0}, //4
{0,1,1,0}, //5
{0,0,1,2}, //6
{0,0,1,2,2}, //7
{0,1,0}, //8
{0,0,1}, //9
{0,0,1}, //10
{0,0,1}, //11
{0,0,1,1,2}, //12
{37,38,101,39}, //13
{41,42,101,43}, //14
// тип элемента 0 - папка, 1 - программа, 2- изменяемый элемент
};
//////////////////////////////////////////////////////////////////////////
//////////////////////// КОНФИГ ДЛЯ ПЕРЕМЕННЫХ МЕНЮ ///////////////////////////////////
struct config {
byte nomer;
byte a;
byte b;
byte lvl; // номер меню
byte lvl0; // предыдущий номер меню
byte lvl00;
boolean izm = false; // флаг редакт. знач.
byte type; //тип элемента меню
byte rh = 1; //режим изменения цифер. 1 - тысячи, 2 - сотни, 3 - десяти, 4- единицы, 5 - выход
};
config dir;
byte tick = 1; // порядковый номер в меню (без заглолвка)
/////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// класс на таймер //////////////////////////////////////
class Timer {
public:
Timer(uint32_t nprd = 0) {
setPeriod(nprd);
}
void setPeriod(uint32_t nprd) {
prd = nprd;
}
bool ready() {
return (prd && millis() - tmr >= prd) ? (tmr = millis(), 1) : 0;
}
private:
uint32_t tmr = 0, prd = 0;
};
/////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// ТАЙМЕРЫ //////////////////////////////////////
Timer tmr1 (1000);
Timer tmr2;
Timer tmr3;
Timer tmr4;
Timer tmr5 (5000);
uint16_t counter = 0; // замена i
uint32_t tmr = 0; // переменная таймера
////////////////////////////////////////////////////////////////////////////////////
///////////////////////// МЕНЮ ПРИВЕТСТВИЯ /////////////////////////////////////////
char PR[] = "Привет!";
char Pribor[] = "Это устройство работает в режиме дозатора, рН-метра, кондуктометра и титратора. Выбери режим в меню";
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// ПЕРЕМЕННЫЕ ДЛЯ МЕНЮ ///////////////////////////////
uint32_t w1; //скорость прокачки, меню 6
uint32_t w2; //скорость прокачки, меню 7
uint32_t w3; //скорость прокачки, меню 12
uint32_t v2; //объем , меню 7
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////// ПЕРЕМЕННЫЕ ДЛЯ ДАТЧИКОВ //////////////////////////////
float pH_val; //Значение рН
float sigma_val; //Значение рН
///////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// ПРЕРЫВАНИЕ НА ЭНКОДЕР ///////////////////////
volatile bool stop = false;
volatile uint32_t debounce;
void ICACHE_RAM_ATTR stopPr () {
if (millis() - debounce >= 200 && digitalRead(5)) {
debounce = millis();
stop = true;}}
/////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200); //ПОРТ
EEPROM.begin(512); // ЕЕПРОМ
oled.init(); // инициализация ОЛЕД
Wire.setClock(400000L);
oled.clear();
enc1.setType(TYPE2);
//sensor.begin(); // Инициируем работу с pH-метром I2C-flash.
start(); // Приветствие
menu(); // Экран начального меню
attachInterrupt(5, stopPr, CHANGE); //ПРЕРЫВАЕНИЕ
///////////////////// ЧТЕНИЕ ИЗ ЕЕПРОМА ////////////////
w1=EEPROM.get(0, w1); //скорость прокачки, меню 6
w2=EEPROM.get(5, w2); //скорость прокачки, меню 7
w3=EEPROM.get(15, w3); //скорость прокачки, меню 12
v2=EEPROM.get(10, v2); //объем , меню 7
// EEPROM.put(0, w1);
// EEPROM.commit();
// float w2 = EEPROM.get(0, w1);
Serial.print("w1=");Serial.print(w1); Serial.print(" w2=");Serial.print(w2); Serial.print(" w3=");Serial.print(w3); Serial.print(" v2=");Serial.print(v2);
//w1= 1000;
//w2= 1000;
//v2= 10000;
//w3 = 1000;
////////////////////////////////////////////////////////
/////////////////////// УСТАНОВКА ВРЕМЕНИ ТАЙМЕРОВ ////////////////////
tmr2.setPeriod(1000);
//////////////////////////////////////////////////////////////////
}
void loop() {
// обязательная функция отработки. Должна постоянно опрашиваться
enc1.tick();
if (enc1.isRight()) {
Serial.println("Right"); // если был поворот
cursorNiz (); }
if (enc1.isLeft()) {
Serial.println("Left");
cursorVerh ();}
if (enc1.isClick()) {
Serial.println("Click"); // одиночный клик
menuChange (); // изменение при нажатии кнопки
}
if (enc1.isHolded()) Serial.println("Holded");
// если была удержана и энк не поворачивался
}
//pH_val = sensor.getPH();
////////////////////////////////////// Вывод на экран приветствия ////////////////////////////
void start () {
oled.clear();
//oled.update();
oled.setScale(3);
oled.setCursor(5, 2);
oled.autoPrintln(false);
oled.print(PR);
delay (500);
oled.clear();
oled.autoPrintln(true);
oled.setScale(1);
oled.setCursor(0, 2);
oled.print(Pribor);
oled.autoPrintln(false);
//oled.update();
delay (500);
oled.clear();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// ВЫПОЛЕНИЕ ПРОГРАММ ПО ТАЙМЕРАМ ///////////////////////////////
void motor_10s (long T_PERIOD, uint16_t cntr) {
if (millis() - tmr >= T_PERIOD) { // таймер на millis()
tmr = millis(); // сброс
Serial.println(counter);
counter++; // прибавляем счётчик
if (counter > cntr) counter = 0; // закольцовываем изменение
}
}
void izm_pH (long T_PERIOD, uint16_t cntr) {
if (millis() - tmr >= T_PERIOD) { // таймер на millis()
tmr = millis(); // сброс
Serial.println(counter);
counter++; // прибавляем счётчик
if (counter > cntr) counter = 0; // закольцовываем изменение
}
}
void izm_sigma (long T_PERIOD, uint16_t cntr) {
if (millis() - tmr >= T_PERIOD) { // таймер на millis()
tmr = millis(); // сброс
Serial.println(counter);
counter++; // прибавляем счётчик
if (counter > cntr) counter = 0; // закольцовываем изменение
}
}
void titr_H (long T_PERIOD, uint16_t cntr) {
if (millis() - tmr >= T_PERIOD) { // таймер на millis()
tmr = millis(); // сброс
Serial.println(counter);
counter++; // прибавляем счётчик
if (counter > cntr) counter = 0; // закольцовываем изменение
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// фунция отрисовки строки /////////////////////////////////////
void menuList(byte x0, byte y, byte Size, String Name, byte clear, byte buf, byte invert) {
if (clear == 1) oled.clear();
if (buf == 1) oled.textMode(BUF_ADD);
if (invert ==1) oled.invertText(true);
if (invert ==0) oled.invertText(false);
oled.setScale(Size);
oled.setCursor(x0, y);
oled.autoPrintln(false);
oled.print(Name);}
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////функция изменения значений в пункте меню. указать переменную, смещение, и знак 0- минус, 1 - плюс /////////////
void znach (uint32_t &chislo, byte dob, byte znak){
if (znak == 1) {
if (dir.rh == 1) {chislo = chislo + 10000;}
if (dir.rh == 2) {chislo = chislo + 1000;}
if (dir.rh == 3) {chislo = chislo + 100;}
if (dir.rh == 4) {chislo = chislo + 10;}
//if (dir.rh == 5) {chislo = chislo + 1;}
}
if (znak == 0) {
if (dir.rh == 1) {chislo = chislo - 10000;}
if (dir.rh == 2) {chislo = chislo - 1000;}
if (dir.rh == 3) {chislo = chislo - 100;}
if (dir.rh == 4) {chislo = chislo - 10;}
//if (dir.rh == 5) {chislo = chislo - 1;}
}
menuList(pgm_read_byte(&x0[dir.a][dir.b+dob]),pgm_read_byte(&y[dir.a][dir.b+dob]),pgm_read_byte(&size[dir.a][dir.b+dob]),String(" "),0,1,0);
menuList(pgm_read_byte(&x0[dir.a][dir.b+dob]),pgm_read_byte(&y[dir.a][dir.b+dob]),pgm_read_byte(&size[dir.a][dir.b+dob]),String(chislo/1000.00),0,1,1);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////функция рисования, указать переменную, смещение от строки, инверсию //////////////////////////////////
void ris (uint32_t chislo, byte dob, byte inv, float delenie) {
menuList(pgm_read_byte(&x0[dir.a][dir.b+dob]),pgm_read_byte(&y[dir.a][dir.b+dob]),pgm_read_byte(&size[dir.a][dir.b+dob]),String(chislo/delenie) + " ",0,1,inv);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////// Значение при измерении на весь экран //////////////////////////////////////
//////////////////////////////////////////////// Построение меню ////////////////////////////////////////////////////
void menu () {
switch (dir.lvl) {
case 6: { oled.clear();
byte i = 0;
do{
PGM_P pstr = (char*)pgm_read_dword(name[dir.a] + i);
char buf_g[strlen_P(pstr) + 1];
strcpy_P(buf_g, pstr);
if (i == 1) {menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,1);}
else {
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,0);}
i++;
} while (i<pgm_read_byte(&nbrStr[dir.a])+1);
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),String(w1/1000.00),0,1,0);
}
break;
case 7: { oled.clear();
byte i = 0;
do{
PGM_P pstr = (char*)pgm_read_dword(name[dir.a] + i);
char buf_g[strlen_P(pstr) + 1];
strcpy_P(buf_g, pstr);
if (i == 1) {menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,1);}
else {
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,0);}
i++;
} while (i<pgm_read_byte(&nbrStr[dir.a])+1);
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),String(v2/1000.00),0,1,0);
menuList(pgm_read_byte(&x0[dir.a][i+1]),pgm_read_byte(&y[dir.a][i+1]),pgm_read_byte(&size[dir.a][i+1]),String(w2/1000.00),0,1,0);
}
break;
case 12: { oled.clear();
byte i = 0;
do{
PGM_P pstr = (char*)pgm_read_dword(name[dir.a] + i);
char buf_g[strlen_P(pstr) + 1];
strcpy_P(buf_g, pstr);
if (i == 1) {menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,1);}
else {
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,0);}
i++;
} while (i<pgm_read_byte(&nbrStr[dir.a])+1);
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),String(w3/1000.00),0,1,0);
}
break;
/* case 36: menuList(0, 0, 2, "ЖОПА", 1, 1, 0);
menuList(5, 2, 1, " 23.45 ", 0, 1, 1);
menuList(5, 5, 1, " bvff ", 0, 1, 1);
break; */
default:
oled.clear();
byte i = 0;
do{
PGM_P pstr = (char*)pgm_read_dword(name[dir.a] + i);
char buf_g[strlen_P(pstr) + 1];
strcpy_P(buf_g, pstr);
if (i == 1) {menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,1);}
else {
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,0);}
i++;
} while (i<pgm_read_byte(&nbrStr[dir.a])+1);
break;
}}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////перемещение курсора /////////////////////////////////////////////////////////
void cursorNiz (){
switch (dir.lvl){
case 6: if (dir.izm==true){
znach (w1,1,1);
}
case 7: if (dir.izm==true){
if (dir.lvl==7 && dir.b==4){znach (w2,2,1);}
if (dir.lvl==7 && dir.b==3){znach (v2,2,1);}
}
case 12: if (dir.izm==true){
if (dir.lvl==12 && dir.b==4){znach (w3,1,1);}
}
default:
if (dir.izm==false){
byte i = tick;
PGM_P pstr = (char*)pgm_read_dword(name[dir.a] + i);
char buf_g[strlen_P(pstr) + 1];
strcpy_P(buf_g, pstr);
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,0);
i++;
if (i >pgm_read_byte(&nbrStr[dir.a])) {
PGM_P pstr = (char*)pgm_read_dword(name[dir.a] + i-1);
char buf_g[strlen_P(pstr) + 1];
strcpy_P(buf_g, pstr);
menuList(pgm_read_byte(&x0[dir.a][i-1]),pgm_read_byte(&y[dir.a][i-1]),pgm_read_byte(&size[dir.a][i-1]),buf_g,0,1,0);
i = 1;}
PGM_P pstr2 = (char*)pgm_read_dword(name[dir.a] + i);
char buf_g2[strlen_P(pstr2) + 1];
strcpy_P(buf_g2, pstr2);
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g2,0,1,1);
tick = i;
dir.b = i;
dir.type = pgm_read_byte(&type[dir.a][i]);
Serial.println(String("меню = ") + dir.a + " пункт = " + dir.b + " тип = " + dir.type + " nm = " + pgm_read_byte(&nm[dir.a][dir.b]));
break;
}}}
void cursorVerh (){
switch (dir.lvl){
case 6: if (dir.izm==true){
znach (w1,1,0);
}
case 7: if (dir.izm==true){
if (dir.lvl==7 && dir.b==4){znach (w2,2,0);}
if (dir.lvl==7 && dir.b==3){znach (v2,2,0);}
}
case 12: if (dir.izm==true){
if (dir.lvl==12 && dir.b==4){znach (w3,1,0);}
}
default: if (dir.izm==false){
byte i = tick;
PGM_P pstr = (char*)pgm_read_dword(name[dir.a] + i);
char buf_g[strlen_P(pstr) + 1];
strcpy_P(buf_g, pstr);
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g,0,1,0);
i--;
if (i <1) {
PGM_P pstr = (char*)pgm_read_dword(name[dir.a] + i+1);
char buf_g[strlen_P(pstr) + 1];
strcpy_P(buf_g, pstr);
menuList(pgm_read_byte(&x0[dir.a][i+1]),pgm_read_byte(&y[dir.a][i+1]),pgm_read_byte(&size[dir.a][i+1]),buf_g,0,1,0);
i = pgm_read_byte(&nbrStr[dir.a]);}
PGM_P pstr2 = (char*)pgm_read_dword(name[dir.a] + i);
char buf_g2[strlen_P(pstr2) + 1];
strcpy_P(buf_g2, pstr2);
menuList(pgm_read_byte(&x0[dir.a][i]),pgm_read_byte(&y[dir.a][i]),pgm_read_byte(&size[dir.a][i]),buf_g2,0,1,1);
tick = i;
dir.b = i;
dir.type = pgm_read_byte(&type[dir.a][i]);
Serial.println(String("меню = ") + dir.a + " пункт = " + dir.b+ " тип = " + dir.type+ " nm = " + pgm_read_byte(&nm[dir.a][dir.b]));
break;
}}}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////// ИЗМЕНЕНИЯ ПРИ НАЖАТИИ ////////////////////////////////////////////////////////////
void menuChange (){
switch (dir.type){
case 1: if (dir.lvl==5 && dir.b==1){Serial.println("КАЧАЮ!!!"); menu_5_1 ();}
if (dir.lvl==5 && dir.b==2){Serial.println("НАЧАЛО");}
if (dir.lvl==6 && dir.b==2){Serial.println("КАЧАЮ!!!"); menu_5_1 ();}
if (dir.lvl==7 && dir.b==2){Serial.println("КАЧАЮ!!!"); menu_5_1 ();}
if (dir.lvl==8 && dir.b==1){Serial.println("КАЛИБРОВКА рН-метра");}
if (dir.lvl==9 && dir.b==2){Serial.println("pH!!!!"); menu_9_2();}
if (dir.lvl==10 && dir.b==2){Serial.println("КАЛИБРОВКА КОНДУКТОМЕТРА");}
if (dir.lvl==11 && dir.b==2){Serial.println("Электропроводность"); menu_11_2();}
if (dir.lvl==12 && dir.b==2){Serial.println("КАЧАЮ!!!"); menu_5_1 ();}
if (dir.lvl==12 && dir.b==3){menu_12_3 ();}
break;
case 2: if (dir.lvl==6 && dir.b==3){
dir.izm = true;
ris (w1,1,1,1000.00);
dir.type = 3;
}
if (dir.lvl==7 && dir.b==4){
dir.izm = true;
ris (w2,2,1,1000.00);
dir.type = 3;
}
if (dir.lvl==7 && dir.b==3){
dir.izm = true;
ris (v2,2,1,1000.00);
dir.type = 3;
}
if (dir.lvl==12 && dir.b==4){
dir.izm = true;
ris (w3,1,1,1000.00);
dir.type = 3;
}
break;
case 3: dir.rh++;
if (dir.rh == 5 or 0) {dir.rh = 1; dir.type = 2; dir.izm = false;
if (dir.lvl == 6){EEPROM.put(0, w1);}
if (dir.lvl == 7){EEPROM.put(5, w2); EEPROM.put(10, v2);}
if (dir.lvl == 12){EEPROM.put(15, w3);}
EEPROM.commit();
if(dir.lvl==6 && dir.b==3){ris (w1,1,0,1000.00);}
if(dir.lvl==7 && dir.b==4){ris (w2,2,0,1000.00);}
if(dir.lvl==7 && dir.b==3){ris (v2,2,0,1000.00);}
if(dir.lvl==12 && dir.b==4){ris (w3,1,0,1000.00);}
}
Serial.println(dir.rh);
break;
default:
dir.lvl0 = dir.lvl;
dir.lvl = pgm_read_byte(&nm[dir.a][dir.b]);
if (dir.lvl ==101){dir.lvl = 0; dir.lvl0 = 0;}
dir.a = dir.lvl;
dir.b = 1;
dir.type = pgm_read_byte(&type[dir.a][1]);
Serial.println(String("меню = ") + dir.lvl + " прошлое меню = " + dir.lvl0 +" пункт = " + dir.b+" тип = " + dir.type+ " nm = " + pgm_read_byte(&nm[dir.a][dir.b]));
tick = 1;
menu();
break;
}}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// ПРОГРАММЫ ВЫПОЛНЕНИЯ РАЗНЫХ ПУНКТОВ МЕНЮ ///////////////////////////
void menu_5_1 (){
Serial.println("Кручу, верчу, работаю...");
counter = 0;
stop = false;
//if (millis() - debounce >= 1000 && digitalRead(4)) {
// debounce = millis();
do {
if (stop) {
stop = false; // сбрасываем
Serial.println("Interrupt!");
counter = 65534;
// delay (1000);
}
motor_10s (1000,100); //
} while (counter <65530); //}
}
/*
void menu_11_2 (){
Serial.println("Кручу, верчу, работаю...");
counter = 0;
stop = false;
//if (millis() - debounce >= 1000 && digitalRead(4)) {
// debounce = millis();
do {
if (stop) {
stop = false; // сбрасываем
Serial.println("Interrupt!");
counter = 65534;
// delay (1000);
}
izm_sigma(1000,100);
} while (counter <65530); //}
}
*/
void menu_12_3 (){
counter = 0;
stop = false;
Serial.println("Титрую кислотой");
menuList(15,0,1,"V",1,0,0); menuList(42,0,1,"pH",0,0,0); menuList(77,0,1,"V",0,0,0); menuList(105,0,1,"pH",0,0,0);
oled.fastLineH(8, 1, 127); oled.fastLineV(63, 0, 63); oled.fastLineV(31, 8, 63); oled.fastLineV(95, 8, 63);
do {
titr_H(1000,65000); // !!! нужно сделать дозирование объема раз в 5-10 сек. первые 5 точек объем по 0,01 мл, затем V = dpH/(dpH/dV). закончить при рН = 1.
if (stop) {
stop = false; // сбрасываем
Serial.println("Interrupt!");
counter = 65534;
tick = 1; dir.a = 12; dir.b = 1; dir.type = 0; menu ();}
} while (counter <65530); //
}
void menu_9_2 (){
counter = 0;
do {
if (stop) {
stop = false; // сбрасываем
Serial.println("Interrupt!");
counter = 65534;}
timer_pH(100,65000);
} while (counter <65530); //}
}
void timer_pH (long T_PERIOD, uint16_t cntr) {
if (millis() - tmr >= T_PERIOD) { // таймер на millis()
tmr = millis(); // сброс
if(dir.lvl==9 && dir.b==2){ris (pH_val,1,0,100.0);}
Serial.print("Кислотность = " ); //
Serial.print(pH_val,2); // Выводим значение с 2 знаками после запятой.
Serial.print(" pH.\r\n" );
Serial.println("");
counter++; // прибавляем счётчик
pH_val = counter;
if (counter > cntr) counter = 0; // закольцовываем изменение
}
}
void menu_11_2 (){
counter = 0;
do {
if (stop) {
stop = false; // сбрасываем
Serial.println("Interrupt!");
counter = 65534;}
timer_sigma(100,65000);
} while (counter <65530); //}
}
void timer_sigma (long T_PERIOD, uint16_t cntr) {
String u2;
float kd;
if (millis() - tmr >= T_PERIOD) { // таймер на millis()
tmr = millis(); // сброс
if(dir.lvl==11 && dir.b==2){
if (sigma_val < 1000) {u2 = "мкСм/см"; kd = 1;} if (sigma_val >= 1000) {u2 = " мСм/см "; kd = 1000;} if (sigma_val >= 1000000) {u2 = " См/см "; kd = 1000000;}
ris (sigma_val,2,0,kd);
menuList(40, 7, 1, u2, 0, 1, 0);}
Serial.println(String(sigma_val/kd,2)+ " "+ u2);
counter++; // прибавляем счётчик
sigma_val = counter;
if (counter > cntr) counter = 0; // закольцовываем изменение
}
}