├── .gitattributes ├── Firmware ├── 01_DEFINES.h ├── 02_VARIABLES.h ├── 03_BUTTON.ino ├── 04_MENU.ino ├── 05_VOLTMETER.ino ├── 06_AMPERMETER.ino ├── 07_RESISTANCE.ino ├── 08_CAPACITANCE.ino ├── 09_INDUCTANCE.ino ├── 10_OSCILLOGRAPH.ino ├── 11_UART.ino ├── 12_UART_PLOT.ino ├── 13_SETTINGS.ino ├── 14_BATTERY.ino ├── 15_GRAPH.ino ├── 16_BLUETOOTH.ino ├── Data │ ├── BL_ico.bmp │ ├── CenturyGothic-10.vlw │ ├── CenturyGothic-12.vlw │ ├── CenturyGothic-14.vlw │ ├── CenturyGothic-16.vlw │ ├── CenturyGothic-18.vlw │ ├── CenturyGothic-24.vlw │ ├── CenturyGothic-32.vlw │ ├── CenturyGothic-48.vlw │ ├── CenturyGothic-64.vlw │ ├── CenturyGothic-8.vlw │ └── logo.jpg └── FW_QUARK │ └── FW_QUARK.ino └── Schematic ├── ESP32_3.2_PCB_BOTTOM.pdf ├── ESP32_3.2_PCB_TOP.pdf └── ESP32_3.2_SCHEMATIC.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Firmware/01_DEFINES.h: -------------------------------------------------------------------------------- 1 | #define WIDTH 240 // Ширина дисплея 2 | #define HEIGHT 135 // Высота дисплея 3 | #define USB_POW // Уровни при подключении USB 4 | #define ADDRES_AD5254_RC 0x2C // Адрес потенциометра RC 5 | #define ADDRES_AD5254_OSC 0x2D // Адрес потенциометра OSC 6 | 7 | #define RXD2 16 // RX2 пин 8 | #define TXD2 -1 // TX2 пин 9 | #define SDA1 21 // Переназначение SDA 10 | #define SCL1 22 // Переназначение SCL 11 | #define IND_VAL 35 // Индуктивность ВХОД 12 | #define SPEAK 17 // Динамик 13 | #define REL_02 25 // Реле 1 14 | #define REL_01 26 // Реле 2 15 | #define POWER 14 // Включение 16 | #define PCB_LIGHT 12 // Подсветка платы 17 | #define BUTTON 27 // Кнопки 18 | #define CHRG 36 // Статус зарядки 19 | #define ADC_CR 39 // Вход измерения резисторов и конденсаторов 20 | #define ADC_BAT 34 // Вход заряда батареи 21 | #define RC_EN 13 // Включение измерения резисторов и конденасторов 22 | #define IND_EN 15 // Включение измерения индуктивности 23 | #define L_GEN 2 // Генератор индуктора 24 | 25 | #define RC_ON digitalWrite(RC_EN, 1) // Включение коммутатора RC 26 | #define RC_OFF digitalWrite(RC_EN, 0) // Выключение коммутатора RC 27 | #define IND_ON digitalWrite(IND_EN, 1) // Включение коммутатора индуктора 28 | #define IND_OFF digitalWrite(IND_EN, 0) // Выключение коммутатора индуктора 29 | #define PWR_ON digitalWrite(POWER, 0) // Питание включено 30 | #define PWR_OFF digitalWrite(POWER, 1) // Питание выключено 31 | #define LIGHT_ON digitalWrite(PCB_LIGHT, 1) // Подсветка платы включено 32 | #define LIGHT_OFF digitalWrite(PCB_LIGHT, 0) // Подсветка платы выключено 33 | #define BATT_LEVEL analogRead(ADC_BAT) // Уровень заряда 34 | #define CHRG_ON digitalRead(CHRG)==0 // Заряд идет 35 | #define CHRG_OFF digitalRead(CHRG)==1 // Заряд не идет 36 | 37 | #define AMPERS relay(true) // Измерение амперов и напряжения 38 | #define MEAS relay(false) // Измерение сопротивления, индуктивности, емкости 39 | 40 | //ОСЦИЛЛОГРАФ 41 | #define ADC_CHANNEL ADC1_CHANNEL_3 // Номер канала осциллографа GPIO39 42 | #define NUM_SAMPLES 1000 // Количество семплов 43 | #define BUFF_SIZE 5000 // Размер буфера 44 | #define DISP_WIDTH 200 // Ширина дисплея осциллографа 45 | #define DISP_HEIGHT 200 // Ширина дисплея осциллографа 46 | 47 | //АМПЕРМЕТР 48 | #define R_SHUNT 0.5 // Значение шунта Ом. 0.00375 49 | #define V_SHUNT_MAX 0.075 // Максимальное значение напряжения на шунте. 50 | #define V_BUS_MAX 26 // Максимальное напряжение шины. 51 | #define I_MAX 3.2 // Максимальный ток, потребляемый шиной + шунтом. 52 | 53 | //ОМЕТР 54 | //Цвета резисторов 55 | #define RES_BACK 0xCD71 56 | #define RES_GOLD_T 0xEC06 57 | #define RES_GOLD_B 0x6226 58 | #define RES_SILVER_T 0x9D35 59 | #define RES_SILVER_B 0x3A8B 60 | #define RES_GRAY_2 0x8C71 61 | 62 | #define RES_BLACK 0x0020 63 | #define RES_BROWN 0xB280 64 | #define RES_RED 0xD800 65 | #define RES_ORANGE 0xFC40 66 | #define RES_YELOW 0xE6A0 67 | #define RES_GREEN 0x0583 68 | #define RES_BLUE 0x04FD 69 | #define RES_VIOLET 0x801D 70 | #define RES_GRAY 0x8410 71 | #define RES_WHITE 0xEF7D 72 | 73 | //ЕМКОСТЬ 74 | #define CAP_BACK 0xED6B 75 | 76 | //UART 77 | #define BUF_SIZE (1024 * 2) // Размер буфера UART 78 | #define PORT_NUM UART_NUM_2 // Номер порта UART 79 | 80 | //ШРИФТЫ 81 | #define Font_8 "CenturyGothic-8" 82 | #define Font_10 "CenturyGothic-10" 83 | #define Font_12 "CenturyGothic-12" 84 | #define Font_14 "CenturyGothic-14" 85 | #define Font_16 "CenturyGothic-16" 86 | #define Font_18 "CenturyGothic-18" 87 | #define Font_24 "CenturyGothic-24" 88 | #define Font_32 "CenturyGothic-32" 89 | #define Font_48 "CenturyGothic-48" 90 | #define Font_64 "CenturyGothic-64" 91 | 92 | // ЦВЕТА 93 | // http://www.barth-dev.de/online/rgb565-color-picker/ 94 | // Конвертер 95 | // https://www.rapidtables.com/convert/color/hex-to-rgb.html 96 | //СЕРЫЕ 97 | #define TFT_GRAY 0x2945 98 | #define TFT_GRAY_1 0x94B2 99 | #define TFT_GRAY_2 0x0821 100 | #define TFT_GRAY_3 0xAD75 101 | //КРАСНЫЕ 102 | #define TFT_RED_5 0x5000 103 | //ЗЕЛЕНЫЕ 104 | #define TFT_GREEN_1 0x0602 105 | //СИНИЕ 106 | #define TFT_BLUE_1 0x2A0B 107 | #define TFT_BLUE_5 0x008C 108 | #define HEADER 0x0883 109 | #define TEXT_01 0x7C76 110 | #define TEXT_02 0x9E93 111 | #define OSC_LEFT 0x0001 112 | #define OSC_PINK 0xf818 113 | #define OSC_LEVEL 0xc000 114 | #define DIGIT 0x08C8 115 | //ФИОЛЕТОВЫЕ 116 | #define TFT_VIOL_1 0xD81F 117 | -------------------------------------------------------------------------------- /Firmware/02_VARIABLES.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // ВРЕМЕННЫЕ /////////////////////////////////////////////////////////////////////////// 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | float increment = 3.14 / 20; 6 | float angle = 0; 7 | int amplitude = 1000; 8 | int y; 9 | 10 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // ОБЩИЕ НАСТРОЙКИ /////////////////////////////////////////////////////////////////////////// 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | uint8_t mode = 0; // Выбранный режим работы 14 | uint8_t mode_last = 0; // Последний выбранный режим работы 15 | bool mode_change = true; // Разрешение изменения режимов работы 16 | bool meas_voltage = true; // Измерение напряжения 17 | bool meas_amper = false; // Измерение тока 18 | bool meas_resistance = false; // Измерение сопротивления 19 | bool meas_capacitance = false; // Измерение емкости 20 | bool meas_inductance = false; // Измерение индуктивности 21 | bool meas_oscillograph = false; // Осциллограф 22 | bool read_UART = false; // Чтение UART 23 | bool plotter = false; // Плоттер 24 | bool settings = false; // Настройки 25 | bool light_pcb = false; // Подсветка платы 26 | uint16_t delay_mode = 500; // Задержка для подписи режима 27 | bool amper = false; // Положение реле по умолчанию 28 | bool meny_draw = false; // Отображение названия пункта меню 29 | uint64_t reg_b; // Отображение названия пункта меню 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | // БЛЮТУЗ /////////////////////////////////////////////////////////////////////////// 32 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | char *pin = "1234"; // Пин код 34 | String DEV_NAME = "QUARK"; // Имя блютуз устройства 35 | bool connectBL = false; // Состояние соединения 36 | // ПРЕФФИКСЫ 37 | String PREF_FIN = "FIN"; // Префикс конца строки 38 | // ВОЛЬТМЕТР 39 | String PREF_VLT = "VLT"; // Префикс вольтажа 40 | // АМПЕРМЕТР 41 | String PREF_AMP = "AMP"; // Префикс ампер 42 | String PREF_AAP = "AAP"; // Префикс массива 43 | // ОСЦИЛЛОГРАФ 44 | String PREF_ARR = "ARR"; // Префикс массива 45 | String PREF_FRQ = "FRQ"; // Префикс частоты 46 | String PREF_SCL = "SCL"; // Префикс масштаба 47 | String PREF_OMX = "OMX"; // Префикс максимума волны 48 | String PREF_OMN = "OMN"; // Префикс минимума волны 49 | 50 | 51 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | // БАТАРЕЯ /////////////////////////////////////////////////////////////////////////// 53 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 54 | volatile uint8_t bat_counter = 0; // Счетчик для проверки батареи 55 | volatile bool bat_redraw = true; // Перерисовка батареи 56 | bool bat_redraw_chrg = true; // Перерисовка зарядки батареи 57 | bool bat_red = true; // Красная батарея 58 | uint8_t bat_counter_check = 600; // Через сколько секунд проверить батарею /10 59 | volatile uint8_t counter_seconds = 0; // Секундный счетчик 60 | 61 | bool check_bat = true; // Первый старт 62 | uint16_t batt_level = 0; // Уровень заряда сырой 63 | uint16_t batt_level_0 = 1700; // Уровень заряда 1 64 | uint16_t batt_level_1 = 1800; // Уровень заряда 1 65 | uint16_t batt_level_2 = 1900; // Уровень заряда 1 66 | uint16_t batt_level_3 = 2000; // Уровень заряда 1 67 | uint16_t batt_level_4 = 2100; // Уровень заряда 1 68 | uint16_t batt_level_5 = 2200; // Уровень заряда 1 69 | 70 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 71 | // КНОПКИ /////////////////////////////////////////////////////////////////////////// 72 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | bool btn_en = false; // Активация кнопок 74 | bool btn_up = false; // Вверх 75 | bool btn_dwn = false; // Вниз 76 | bool btn_01_en = false; // 77 | bool btn_02_en = false; // 78 | bool btn_03_en = false; // 79 | bool btn_04_en = false; // 80 | bool btn_05_en = false; // 81 | 82 | uint32_t count_mult = 100000; // Частота таймера в микросекундах 83 | uint8_t btn_press_delay = 5; // Задержка для определения нажатия 84 | volatile uint8_t btn_counter = 0; // Таймер кнопки 85 | uint8_t btn_press_counter = 0; // Количество нажатий 86 | uint8_t btn_press_arr[6]; // Массив для хранения последовательности нажатий 87 | 88 | //НАСТРОЙКИ ЧУВСТВИТЕЛЬНОСТИ КНОПОК 89 | #ifdef USB_POW 90 | uint16_t btn_01_min = 20; 91 | uint16_t btn_01_max = 60; 92 | uint16_t btn_02_min = 300; 93 | uint16_t btn_02_max = 400; 94 | uint16_t btn_03_min = 150; 95 | uint16_t btn_03_max = 250; 96 | uint16_t btn_04_min = 3500; 97 | uint16_t btn_04_max = 3600; 98 | uint16_t btn_05_min = 3000; 99 | uint16_t btn_05_max = 3100; 100 | #else 101 | #endif 102 | 103 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 104 | // ВОЛЬТМЕТР /////////////////////////////////////////////////////////////////////////// 105 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 106 | float voltage_prew; // Уровень напряжения на входе 107 | float voltage_last; // Последнее значение напряжения на входе 108 | uint16_t voltage_alarm = 24; // Уровень напряжения до опасного 109 | 110 | float volt_level; // Минимальное значение вольт 111 | float CMOS_5V_1 = 3.5; // Уровень логической единицы 5V 112 | float CMOS_5V_0 = 1.5; // Уровень логического нуля 5V 113 | float TTL_1 = 2.2; // Уровень логической единицы TTL 114 | float TTL_0 = 0.6; // Уровень логического нуля TTL 115 | float CMOS_18_1 = 1.35; // Уровень логической единицы 1.8V 116 | float CMOS_18_0 = 0.63; // Уровень логического нуля 1.8V 117 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 118 | // АМПЕРМЕТР /////////////////////////////////////////////////////////////////////////// 119 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 120 | bool amper_count = true; // Разрешение перерисовки амперметра 121 | float amper_prew; // Уровень тока на входе 122 | float amper_last; // Последнее значение тока на входе 123 | uint16_t amper_alarm = 3.0; // Уровень тока до опасного 124 | float power; // Значение мощности 125 | 126 | uint16_t graph_width = 239; // Ширина графика 127 | uint16_t amper_array_1[239]; // Массив гравика 128 | uint16_t amper_array_2[239]; // Массив гравика сдвига 129 | uint16_t amper_pos_time_1 = 40; // Позиция первого числа 130 | uint16_t amper_pos_time_2 = 140; // Позиция второго числа 131 | uint16_t amper_pos_time_3 = 240; // Позиция третьего числа 132 | 133 | uint8_t amper_pos_grid = 0; // Позиция сетки 134 | 135 | uint16_t amper_time_1 = 0; // Время 1 136 | uint16_t amper_time_2 = 0; // Время 2 137 | uint16_t amper_time_3 = 0; // Время 3 138 | 139 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 140 | // СОПРОТВИЛЕНИЕ /////////////////////////////////////////////////////////////////////////// 141 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 142 | float res_prew; // Уровень тока на входе 143 | float res_last; // Последнее значение тока на входе 144 | 145 | float res_array[24] 146 | { 1.0, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, // Массив сопротивлений 147 | 2.0, 2.2, 2.4, 2.7, 148 | 3.0, 3.3, 3.6, 3.9, 149 | 4.3, 4.7, 150 | 5.1, 5.6, 151 | 6.2, 6.8, 152 | 7.5, 153 | 8.2, 154 | 9.1 155 | }; 156 | 157 | uint8_t mult = 0; // Множитель 158 | uint8_t num_01 = 0; // Первый знак 159 | uint8_t num_02 = 0; // Второй знак 160 | uint8_t num_03 = 0; // Третий знак 161 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 162 | // ОСЦИЛЛОГРАФ /////////////////////////////////////////////////////////////////////////// 163 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 164 | uint16_t shift = 12288; // Сдвиг. ADC_3(IO39) - 12288 / ADC_5(IO33) - 20480 165 | bool i2s_enable = false; // Запуск I2S 166 | uint16_t osc_buffer_raw[BUFF_SIZE]; // Буффер сырых данных 167 | uint16_t osc_buffer[BUFF_SIZE]; // Буффер данных 168 | uint8_t num_rate = 2; // Номер диапазона по умолчанию 169 | uint32_t mass_rate[] = {10000, // Массив диапазонов 170 | 20000, 171 | 50000, 172 | 100000, 173 | 200000, 174 | 400000 175 | }; 176 | bool auto_rate = true; // Автодиапазон 177 | bool auto_scale = true; // Автомасштаб 178 | float volt_level_min; // Минимальное значение вольт 179 | float volt_level_max; // Максимальное значение вольт 180 | float volt_level_min_last; // Последнее минимальное значение вольт 181 | float volt_level_max_last; // Последнее максимальное значение вольт 182 | uint8_t check_volt_num = 2; // Количество итераций для определения напряжения 183 | uint8_t check_volt_cur = 0; // Текущая итерация 184 | float check_v_min_mass[2]; // Массив для хранения итераций минимального напряжения 185 | float check_v_max_mass[2]; // Массив для хранения итераций максимального напряжения 186 | 187 | uint16_t triger_01 = 0; // Положение первого тригера в бфере 188 | uint16_t triger_02 = 0; // Положение второго тригера в бфере 189 | uint16_t triger_level = 0; // Значение для тригера 190 | uint16_t triger_level_min; // Минимальное значение тригера 191 | uint16_t triger_level_max; // Максимальное значение тригера 192 | 193 | uint16_t duty = 0; // Период сырой 194 | uint16_t duty_last = 0; // Период сырой последний 195 | uint8_t duty_min = 50; // Период минимальная ширина на экране в пикселях 196 | uint8_t duty_max = 80; // Период максимальная ширина на экране в пикселях 197 | uint16_t period = 0; // Период вычисленный 198 | uint32_t freq; // Частота вычисленная 199 | 200 | uint8_t check_freq_num = 3; // Количество итераций для определения частоты 201 | uint8_t check_freq_cur = 0; // Текущая итерация 202 | uint32_t check_freq_mass[3]; // Массив для хранения итераций 203 | 204 | uint8_t osc_width = 210; // Ширина экрана 205 | uint8_t osc_height = 95; // Высота экрана 206 | 207 | uint8_t pos_y_max; // Высота маскимального уровня 208 | uint8_t pos_y_min; // Высота минимального уровня 209 | float curr_max; // Значение маскимального уровня 210 | float curr_min; // Значение минимального уровня 211 | bool BL_type; // Тип отправляемых данных 212 | 213 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 214 | // UART /////////////////////////////////////////////////////////////////////////// 215 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 216 | uint32_t BAUD_RATE; // Скорость UART 217 | bool baud_true = false; // Определена ли скорость 218 | bool baud_exit = false; // выход из режима 219 | String incomming; // Входящее сообщение 220 | bool end_mess; // Окончание передачи 221 | String incoming_array[7]; // Массив строк 222 | uint8_t uart_arr = 0; // Текуущая итерация байта 223 | uint16_t uart_buff = 1024; // Размер буфера 224 | uart_event_t event; // Переменная события для UART 225 | uint16_t baud_count; // Текущая попытка определить скорость 226 | uint16_t baud_count_max = 500; // Количество попыток определиь скорость 227 | -------------------------------------------------------------------------------- /Firmware/03_BUTTON.ino: -------------------------------------------------------------------------------- 1 | void button_2() 2 | { 3 | switch (mode) 4 | { 5 | case 0: 6 | 7 | break; 8 | case 1: 9 | 10 | break; 11 | case 2: 12 | 13 | break; 14 | case 3: 15 | 16 | break; 17 | case 4: 18 | 19 | break; 20 | case 5: 21 | auto_rate = !auto_rate; 22 | mode_change = auto_rate; 23 | redraw_footer(); 24 | break; 25 | case 6: 26 | 27 | break; 28 | case 7: 29 | 30 | break; 31 | case 8: 32 | 33 | break; 34 | } 35 | } 36 | 37 | void button() 38 | { 39 | restore_ADC_Reg(); 40 | if (analogRead(BUTTON) > btn_01_min && analogRead(BUTTON) < btn_01_max) 41 | { 42 | if (!btn_01_en) 43 | { 44 | btn_press_arr[btn_press_counter] = 1; 45 | btn_press_counter++; 46 | btn_counter = 0; 47 | } 48 | btn_en = true; 49 | btn_01_en = true; 50 | btn_02_en = false; 51 | btn_03_en = false; 52 | btn_04_en = false; 53 | btn_05_en = false; 54 | } 55 | if (analogRead(BUTTON) > btn_02_min && analogRead(BUTTON) < btn_02_max) 56 | { 57 | if (!btn_02_en) 58 | { 59 | btn_press_arr[btn_press_counter] = 2; 60 | btn_press_counter++; 61 | btn_counter = 0; 62 | } 63 | btn_en = true; 64 | btn_01_en = false; 65 | btn_02_en = true; 66 | btn_03_en = false; 67 | btn_04_en = false; 68 | btn_05_en = false; 69 | } 70 | if (analogRead(BUTTON) > btn_03_min && analogRead(BUTTON) < btn_03_max) 71 | { 72 | if (!btn_03_en) 73 | { 74 | btn_press_arr[btn_press_counter] = 3; 75 | btn_press_counter++; 76 | btn_counter = 0; 77 | } 78 | btn_en = true; 79 | btn_01_en = false; 80 | btn_02_en = false; 81 | btn_03_en = true; 82 | btn_04_en = false; 83 | btn_05_en = false; 84 | } 85 | if (analogRead(BUTTON) > btn_04_min && analogRead(BUTTON) < btn_04_max) 86 | { 87 | if (!btn_04_en) 88 | { 89 | btn_press_arr[btn_press_counter] = 4; 90 | btn_press_counter++; 91 | btn_counter = 0; 92 | } 93 | btn_en = true; 94 | btn_01_en = false; 95 | btn_02_en = false; 96 | btn_03_en = false; 97 | btn_04_en = true; 98 | btn_05_en = false; 99 | } 100 | if (analogRead(BUTTON) > btn_05_min && analogRead(BUTTON) < btn_05_max) 101 | { 102 | if (!btn_05_en) 103 | { 104 | btn_press_arr[btn_press_counter] = 5; 105 | btn_press_counter++; 106 | btn_counter = 0; 107 | } 108 | btn_en = true; 109 | btn_01_en = false; 110 | btn_02_en = false; 111 | btn_03_en = false; 112 | btn_04_en = false; 113 | btn_05_en = true; 114 | } 115 | 116 | if (btn_counter == 10 && btn_05_en) 117 | { 118 | btn_05_en = false; 119 | btn_counter = 0; 120 | light_pcb = !light_pcb; 121 | if (light_pcb) 122 | { 123 | Serial.println("PCB LIGHT ON"); 124 | LIGHT_ON; 125 | } 126 | else 127 | { 128 | Serial.println("PCB LIGHT OFF"); 129 | LIGHT_OFF; 130 | } 131 | } 132 | 133 | if (analogRead(BUTTON) == 0 && btn_en) 134 | { 135 | btn_en = false; 136 | if (btn_counter >= btn_press_delay) 137 | { 138 | btn_up = false; 139 | btn_dwn = false; 140 | btn_01_en = false; 141 | btn_02_en = false; 142 | btn_03_en = false; 143 | btn_04_en = false; 144 | btn_05_en = false; 145 | } 146 | 147 | if (btn_press_arr[0] < btn_press_arr[1] && 148 | btn_press_arr[1] < btn_press_arr[2] && 149 | btn_press_arr[2] < btn_press_arr[3]) 150 | { 151 | btn_up = true; 152 | btn_dwn = false; 153 | btn_01_en = false; 154 | btn_02_en = false; 155 | btn_03_en = false; 156 | btn_04_en = false; 157 | btn_05_en = false; 158 | } 159 | if (btn_press_arr[0] > btn_press_arr[1] && 160 | btn_press_arr[1] > btn_press_arr[2] && 161 | btn_press_arr[2] > btn_press_arr[3]) 162 | { 163 | btn_up = false; 164 | btn_dwn = true; 165 | btn_01_en = false; 166 | btn_02_en = false; 167 | btn_03_en = false; 168 | btn_04_en = false; 169 | btn_05_en = false; 170 | } 171 | btn_counter = 0; 172 | btn_press_counter = 0; 173 | for (uint8_t i = 0; i < 6; i++) btn_press_arr[i] = 0; 174 | if (btn_counter < btn_press_delay) button_funct(); 175 | } 176 | if (btn_counter >= 100)btn_counter = 0; 177 | } 178 | 179 | void button_funct() 180 | { 181 | if (btn_up) 182 | { 183 | Serial.println("BTN UP"); 184 | if (mode == 6 && baud_true) 185 | { 186 | Serial.println("STOP UART"); 187 | baud_exit = false; 188 | baud_true = false; 189 | uart_flush(PORT_NUM); 190 | uart_driver_delete(PORT_NUM); 191 | } 192 | } 193 | if (btn_dwn) 194 | { 195 | Serial.println("BTN DWN"); 196 | if (mode == 6 && baud_true) 197 | { 198 | Serial.println("STOP UART"); 199 | baud_exit = false; 200 | baud_true = false; 201 | uart_flush(PORT_NUM); 202 | uart_driver_delete(PORT_NUM); 203 | } 204 | } 205 | if (btn_01_en) 206 | { 207 | Serial.println("BTN 01"); 208 | } 209 | if (btn_02_en) 210 | { 211 | Serial.println("BTN 02"); 212 | } 213 | if (btn_03_en) 214 | { 215 | Serial.println("BTN 03"); 216 | } 217 | if (btn_04_en) 218 | { 219 | Serial.println("BTN 05"); 220 | } 221 | if (btn_05_en) 222 | { 223 | Serial.println("BTN 05"); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /Firmware/04_MENU.ino: -------------------------------------------------------------------------------- 1 | void mode_handler() 2 | { 3 | switch (mode) 4 | { 5 | case 0: 6 | voltage_last = voltage_prew; 7 | voltage_prew = INA_219.busVoltage();// - 0,87; 8 | if (voltage_last != voltage_prew) voltmeter_draw(voltage_prew); 9 | //delay(50); 10 | break; 11 | case 1: 12 | y = 1500 * sin(angle); 13 | angle = angle + increment; 14 | y = map(y, -1500, 1500, 0, 3000); 15 | y = y; 16 | 17 | amper_last = amper_prew; 18 | amper_prew = INA_219.shuntCurrent(); 19 | //amper_prew = y; 20 | amper_prew = amper_prew / 1000; 21 | 22 | if (amper_count) 23 | { 24 | amper_count = false; 25 | amper_pos_grid++; 26 | amper_pos_time_1++; 27 | amper_pos_time_2++; 28 | amper_pos_time_3++; 29 | if (amper_pos_grid >= 10) amper_pos_grid = 0; 30 | if (amper_pos_time_1 >= 300) 31 | { 32 | amper_time_1 += 3; 33 | amper_pos_time_1 = 0; 34 | } 35 | if (amper_pos_time_2 >= 300) 36 | { 37 | if (amper_time_2 == 0) amper_time_2 = -1; 38 | amper_time_2 += 3; 39 | amper_pos_time_2 = 0; 40 | } 41 | if (amper_pos_time_3 >= 300) 42 | { 43 | if (amper_time_3 == 0) amper_time_3 = -2; 44 | amper_time_3 += 3; 45 | amper_pos_time_3 = 0; 46 | } 47 | ampermeter_graph_draw(amper_prew); 48 | } 49 | if (amper_last != amper_prew) ampermeter_draw(amper_prew); 50 | delay(50); 51 | break; 52 | case 2: 53 | res_last = res_prew; 54 | res_prew = adc1_get_raw(ADC_CHANNEL); 55 | if (res_last != res_prew) resistance_draw(res_prew, mult); 56 | break; 57 | case 3: 58 | 59 | break; 60 | case 4: 61 | 62 | break; 63 | case 5: 64 | ADC_Sampling(osc_buffer); 65 | if (freq == 0)find_triger(); 66 | triger(); 67 | draw_graph(); 68 | break; 69 | case 6: 70 | if (baud_true) uartHandler(); 71 | break; 72 | case 7: 73 | 74 | break; 75 | case 8: 76 | 77 | break; 78 | } 79 | } 80 | 81 | void menu_change() 82 | { 83 | if (connectBL) 84 | { 85 | String mess = "M"; 86 | mess.concat(mode); 87 | Bluetooth.print(mess); 88 | Bluetooth.write('>'); 89 | } 90 | mode_last = mode; 91 | //counter_seconds = 0; 92 | bat_counter = 0; 93 | check_bat = true; 94 | 95 | meas_voltage = false; 96 | meas_amper = false; 97 | meas_resistance = false; 98 | meas_capacitance = false; 99 | meas_inductance = false; 100 | meas_oscillograph = false; 101 | read_UART = false; 102 | plotter = false; 103 | settings = false; 104 | 105 | tft.fillRect(0, 20, 240, 115, TFT_BLACK); 106 | 107 | switch (mode) 108 | { 109 | case 0: 110 | Serial.println("VOLTAGE"); 111 | Wire.beginTransmission(ADDRES_AD5254_RC); 112 | Wire.write(0x00); 113 | Wire.write(byte(0)); 114 | Wire.endTransmission(); 115 | RC_OFF; 116 | IND_OFF; 117 | voltage_last = 0; 118 | voltage_prew = 0; 119 | 120 | meas_voltage = true; 121 | voltmeter_init(); 122 | break; 123 | case 1: 124 | Serial.println("AMPER"); 125 | IND_OFF; 126 | amper_last = 0; 127 | amper_prew = 0; 128 | 129 | meas_amper = true; 130 | ampermeter_init(); 131 | break; 132 | case 2: 133 | Serial.println("RESISTANCE"); 134 | meas_resistance = true; 135 | resistance_init(); 136 | break; 137 | case 3: 138 | Serial.println("CAPACITANCE"); 139 | meas_capacitance = true; 140 | capacitance_init(); 141 | break; 142 | case 4: 143 | Serial.println("INDUCTANCE"); 144 | meas_inductance = true; 145 | inductance_init(); 146 | break; 147 | case 5: 148 | Serial.println("OSCILOGRAPH"); 149 | meas_oscillograph = true; 150 | 151 | triger_01 = 0; 152 | triger_02 = 0; 153 | triger_level; 154 | triger_level_min = 0; 155 | triger_level_max = 0; 156 | 157 | duty = 0; 158 | duty_last = 0; 159 | period = 0; 160 | freq = 0; 161 | 162 | oscillograph_init(); 163 | break; 164 | case 6: 165 | Serial.println("READ UART"); 166 | read_UART = true; 167 | UART_init(); 168 | break; 169 | case 7: 170 | Serial.println("PLOTTER"); 171 | plotter = true; 172 | plotter_init(); 173 | break; 174 | case 8: 175 | Serial.println("SETTINGS"); 176 | settings = true; 177 | settings_init(); 178 | break; 179 | } 180 | if (!meas_oscillograph && i2s_enable) 181 | { 182 | i2s_enable = false; 183 | i2s_adc_disable(I2S_NUM_0); 184 | i2s_driver_uninstall(I2S_NUM_0); 185 | Serial.println("I2S DISABLE"); 186 | adc1_config_width(ADC_WIDTH_12Bit); //настройка ширины канала ацп 0-4095 187 | adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN_DB_11); //настройка уровня приёма, тут от 150 до 1750 мВ 188 | } 189 | if (mode != 6) 190 | { 191 | baud_exit = false; 192 | baud_true = false; 193 | uart_event_t event; 194 | } 195 | if (meas_amper) AMPERS; 196 | else MEAS; 197 | } 198 | -------------------------------------------------------------------------------- /Firmware/05_VOLTMETER.ino: -------------------------------------------------------------------------------- 1 | void voltmeter_init() 2 | { 3 | menyDraw("VOLTMETER", true); 4 | valueDraw(0, 2, TFT_WHITE); 5 | simbolDraw("V", TFT_BLUE); 6 | 7 | voltLevelMenyDraw(); 8 | voltLevelDraw(1, "N"); 9 | voltLevelDraw(2, "N"); 10 | voltLevelDraw(3, "N"); 11 | } 12 | 13 | void voltmeter_draw(float value) 14 | { 15 | if (value >= CMOS_18_1) voltLevelDraw(1, "1"); 16 | else if (value <= CMOS_18_0) voltLevelDraw(1, "0"); 17 | else voltLevelDraw(1, "N"); 18 | 19 | if (value >= TTL_1) voltLevelDraw(2, "1"); 20 | else if (value <= TTL_0) voltLevelDraw(2, "0"); 21 | else voltLevelDraw(2, "N"); 22 | 23 | if (value >= CMOS_5V_1) voltLevelDraw(3, "1"); 24 | else if (value <= CMOS_5V_0) voltLevelDraw(3, "0"); 25 | else voltLevelDraw(3, "N"); 26 | 27 | if (value < voltage_alarm) valueDraw(value, 2, TFT_WHITE); 28 | else valueDraw(value, 2, TFT_RED); 29 | 30 | if (connectBL) 31 | { 32 | String data_volt; 33 | data_volt = PREF_VLT; 34 | data_volt.concat(String(value, 2)); 35 | data_volt.concat(PREF_FIN); 36 | Bluetooth.print(data_volt); 37 | Bluetooth.write('>'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Firmware/06_AMPERMETER.ino: -------------------------------------------------------------------------------- 1 | void ampermeter_init() 2 | { 3 | menyDraw("AMPERMETER", true); 4 | valueDraw(0, 2, TFT_WHITE); 5 | simbolDraw("A", TFT_RED); 6 | 7 | for (uint8_t i = 0; i < graph_width; i++) 8 | { 9 | amper_array_1[i] = 0; 10 | amper_array_2[i] = 0; 11 | } 12 | 13 | amper_pos_grid = 0; 14 | amper_pos_time_1 = 40; 15 | amper_pos_time_2 = 140; 16 | amper_pos_time_3 = 240; 17 | 18 | amper_time_1 = 0; 19 | amper_time_2 = 0; 20 | amper_time_3 = 0; 21 | 22 | amper_count = 0; 23 | } 24 | 25 | void ampermeter_draw(float value) 26 | { 27 | if (value < amper_alarm) valueDraw(value, 3, TFT_WHITE); 28 | else valueDraw(value, 2, TFT_RED); 29 | 30 | String mess; 31 | mess = PREF_AAP; 32 | for (uint8_t i = 36; i < 239; i++) 33 | { 34 | mess.concat(amper_array_1[i]); 35 | mess.concat("|"); 36 | } 37 | mess.concat(PREF_FIN); 38 | if (connectBL) 39 | { 40 | Bluetooth.print(mess); 41 | Bluetooth.write('>'); 42 | } 43 | } 44 | 45 | void ampermeter_graph_draw(float value) 46 | { 47 | if (value > 3) value = 3; 48 | tft.fillRect(0, 95, 240, 40, HEADER); 49 | for (uint8_t i = 0; i < 26; i++) tft.drawLine(((i * 10) - amper_pos_grid), 104, ((i * 10) - amper_pos_grid), 134, TFT_GRAY); 50 | tft.drawLine(0, 104, 239, 104, TFT_GRAY); 51 | tft.drawLine(0, 114, 239, 114, TFT_GRAY); 52 | tft.drawLine(0, 124, 239, 124, TFT_GRAY); 53 | 54 | tft.unloadFont(); 55 | tft.setTextSize(1); 56 | tft.setTextColor(TEXT_01, HEADER); 57 | 58 | if (amper_time_1 == 0) tft.drawString("00", (275 - amper_pos_time_1), 96, 1); 59 | else tft.drawNumber(amper_time_1 * 10, (275 - amper_pos_time_1), 96, 1); 60 | if (amper_time_2 != 0) tft.drawNumber(amper_time_2 * 10, (275 - amper_pos_time_2), 96, 1); 61 | if (amper_time_3 != 0) tft.drawNumber(amper_time_3 * 10, (275 - amper_pos_time_3), 96, 1); 62 | 63 | for (uint8_t i = 0; i < graph_width; i++) tft.drawLine(i, 134 - amper_array_1[i] / 100, i, 134 - amper_array_2[i] / 100, TFT_VIOL_1); 64 | for (uint8_t i = 0; i < graph_width; i++) amper_array_2[i] = amper_array_1[i]; 65 | for (uint8_t i = 1; i < graph_width + 1; i++) 66 | { 67 | amper_array_1[i - 1] = amper_array_1[i]; 68 | amper_array_1[graph_width] = value * 1000; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Firmware/07_RESISTANCE.ino: -------------------------------------------------------------------------------- 1 | void resistance_init() 2 | { 3 | menyDraw("RESISTANCE", true); 4 | valueDraw(0, 0, TFT_WHITE); 5 | simbolDraw("ОМ", TFT_GRAY_1); 6 | 7 | tft.setTextColor(TFT_GRAY_1, HEADER); 8 | tft.drawString("КОМ", 195, 114); 9 | 10 | // SMD РЕЗИСТОР 11 | tft.fillRect(25, 105, 39, 20, TFT_GRAY_3); 12 | tft.fillRect(30, 106, 29, 18, TFT_BLACK); 13 | tft.setTextColor(TFT_GRAY_1, TFT_BLACK); 14 | tft.drawNumber(num_01, 33, 110); 15 | tft.drawNumber(num_02, 41, 110); 16 | tft.drawNumber(num_03 + 1, 49, 110); 17 | 18 | // ЦВЕТОВАЯ МАРКИРОВКА 19 | tft.fillRoundRect(80, 105, 55, 20, 4, RES_BACK); 20 | 21 | tft.fillRect(90, 105, 5, 20, RES_GRAY); 22 | tft.fillRect(100, 105, 5, 20, RES_GRAY); 23 | tft.fillRect(110, 105, 5, 20, RES_GRAY); 24 | //tft.fillRect(120, 105, 5, 20, RES_GRAY); 25 | 26 | //rectGradient(120, 105, 5, 20, RES_GOLD_T, RES_GOLD_B); 27 | rectGradient(120, 105, 5, 20, RES_SILVER_T, RES_SILVER_B); 28 | 29 | // КИЛЛООМЫ 30 | tft.setTextColor(TFT_WHITE, HEADER); 31 | tft.loadFont(Font_24); 32 | tft.setTextColor(TFT_GRAY_1, HEADER); 33 | tft.setTextDatum(TR_DATUM); 34 | tft.drawString("0.0", 190, 107); 35 | } 36 | 37 | void resistance_draw(float value, int multipiller) 38 | { 39 | float value_ = value; 40 | for (uint8_t i = 0; i < multipiller; i++) value_ = value_ * 10; 41 | 42 | if (value_ < 10000) valueDraw(value_, 0, TFT_WHITE); 43 | else valueDraw(value_ / 1000, 0, TFT_WHITE); 44 | 45 | draw_res_color(value, multipiller); 46 | 47 | // ЗНАЧЕНИЕ 48 | tft.setTextDatum(TR_DATUM); 49 | tft.setTextColor(TFT_WHITE, HEADER); 50 | tft.loadFont(Font_24); 51 | tft.setTextColor(TFT_GRAY_1, HEADER); 52 | tft.fillRect(140, 107, 30, 18, HEADER); 53 | if (value_ < 10000) tft.drawString(String(value_ / 1000, 1), 190, 107); 54 | else tft.drawString(String(value_ / 1000000, 1), 190, 107); 55 | tft.setTextDatum(TL_DATUM); 56 | 57 | tft.loadFont(Font_14); 58 | tft.setTextDatum(TL_DATUM); 59 | if (value_ < 10000) 60 | { 61 | simbolDraw("ОМ", TFT_GRAY_1); 62 | 63 | tft.setTextColor(TFT_GRAY_1, HEADER); 64 | tft.fillRect(195, 114, 40, 12, HEADER); 65 | tft.drawString("КОМ", 195, 114); 66 | } 67 | else 68 | { 69 | simbolDraw("КОМ", TFT_GRAY_1); 70 | 71 | tft.setTextColor(TFT_GRAY_1, HEADER); 72 | tft.fillRect(195, 114, 40, 12, HEADER); 73 | tft.drawString("МОМ", 195, 114); 74 | } 75 | } 76 | 77 | void draw_res_color(float value, uint8_t multipiller) 78 | { 79 | num_01 = (String(value).substring(0, 1)).toInt(); 80 | num_02 = (String(value).substring(1, 2)).toInt(); 81 | num_03 = multipiller; 82 | 83 | tft.setTextDatum(TL_DATUM); 84 | tft.loadFont(Font_14); 85 | tft.fillRect(30, 106, 29, 18, TFT_BLACK); 86 | tft.setTextColor(TFT_GRAY_1, TFT_BLACK); 87 | tft.drawNumber(num_01, 33, 110); 88 | if (multipiller == 0 && value < 10) tft.drawString("R", 41, 110); 89 | else tft.drawNumber(num_02, 41, 110); 90 | tft.drawNumber(num_03, 49, 110); 91 | 92 | switch (num_01) 93 | { 94 | case 0: 95 | tft.fillRect(90, 105, 5, 20, RES_BLACK); 96 | break; 97 | case 1: 98 | tft.fillRect(90, 105, 5, 20, RES_BROWN); 99 | break; 100 | case 2: 101 | tft.fillRect(90, 105, 5, 20, RES_RED); 102 | break; 103 | case 3: 104 | tft.fillRect(90, 105, 5, 20, RES_ORANGE); 105 | break; 106 | case 4: 107 | tft.fillRect(90, 105, 5, 20, RES_YELOW); 108 | break; 109 | case 5: 110 | tft.fillRect(90, 105, 5, 20, RES_GREEN); 111 | break; 112 | case 6: 113 | tft.fillRect(90, 105, 5, 20, RES_BLUE); 114 | break; 115 | case 7: 116 | tft.fillRect(90, 105, 5, 20, RES_VIOLET); 117 | break; 118 | case 8: 119 | tft.fillRect(90, 105, 5, 20, RES_GRAY); 120 | break; 121 | case 9: 122 | tft.fillRect(90, 105, 5, 20, RES_WHITE); 123 | break; 124 | } 125 | 126 | switch (num_02) 127 | { 128 | case 0: 129 | tft.fillRect(100, 105, 5, 20, RES_BLACK); 130 | break; 131 | case 1: 132 | tft.fillRect(100, 105, 5, 20, RES_BROWN); 133 | break; 134 | case 2: 135 | tft.fillRect(100, 105, 5, 20, RES_RED); 136 | break; 137 | case 3: 138 | tft.fillRect(100, 105, 5, 20, RES_ORANGE); 139 | break; 140 | case 4: 141 | tft.fillRect(100, 105, 5, 20, RES_YELOW); 142 | break; 143 | case 5: 144 | tft.fillRect(100, 105, 5, 20, RES_GREEN); 145 | break; 146 | case 6: 147 | tft.fillRect(100, 105, 5, 20, RES_BLUE); 148 | break; 149 | case 7: 150 | tft.fillRect(100, 105, 5, 20, RES_VIOLET); 151 | break; 152 | case 8: 153 | tft.fillRect(100, 105, 5, 20, RES_GRAY); 154 | break; 155 | case 9: 156 | tft.fillRect(100, 105, 5, 20, RES_WHITE); 157 | break; 158 | } 159 | 160 | switch (multipiller) 161 | { 162 | case 0: 163 | tft.fillRect(110, 105, 5, 20, RES_BLACK); 164 | break; 165 | case 1: 166 | tft.fillRect(110, 105, 5, 20, RES_BROWN); 167 | break; 168 | case 2: 169 | tft.fillRect(110, 105, 5, 20, RES_RED); 170 | break; 171 | case 3: 172 | tft.fillRect(110, 105, 5, 20, RES_ORANGE); 173 | break; 174 | case 4: 175 | tft.fillRect(110, 105, 5, 20, RES_YELOW); 176 | break; 177 | case 5: 178 | tft.fillRect(110, 105, 5, 20, RES_GREEN); 179 | break; 180 | case 6: 181 | tft.fillRect(110, 105, 5, 20, RES_BLUE); 182 | break; 183 | case 7: 184 | tft.fillRect(110, 105, 5, 20, RES_VIOLET); 185 | break; 186 | } 187 | } 188 | 189 | void rectGradient(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t TC, uint16_t BC) 190 | { 191 | for (uint16_t i = 0; i < h; ++i) tft.drawFastHLine(x, y + i, w, (tft.alphaBlend((map(i, 0, h, 0, 255)), BC, TC))); 192 | } 193 | -------------------------------------------------------------------------------- /Firmware/08_CAPACITANCE.ino: -------------------------------------------------------------------------------- 1 | void capacitance_init() 2 | { 3 | menyDraw("CAPACITANCE", true); 4 | valueDraw(10, 0, TFT_WHITE); 5 | simbolDraw("UF", TFT_GRAY_1); 6 | 7 | // КОНДЕНСАТОР 8 | capLevelDraw(102); 9 | } 10 | -------------------------------------------------------------------------------- /Firmware/09_INDUCTANCE.ino: -------------------------------------------------------------------------------- 1 | void inductance_init() 2 | { 3 | menyDraw("INDUCTANCE", true); 4 | valueDraw(22, 0, TFT_WHITE); 5 | simbolDraw("UH", TFT_GRAY_1); 6 | 7 | // ИНДУКТИВНОСТЬ 8 | indLevelDraw(102); 9 | } 10 | -------------------------------------------------------------------------------- /Firmware/10_OSCILLOGRAPH.ino: -------------------------------------------------------------------------------- 1 | void oscillograph_init() 2 | { 3 | tft.fillRect(30, 0, 178, 20, HEADER); 4 | tft.fillRect(30, 115, 210, 20, HEADER); 5 | tft.fillRect(0, 0, 30, 135, OSC_LEFT); 6 | if (connectBL) drawBmp("/BL_ico.bmp", 192, 2); 7 | tft.setTextColor(TEXT_01, HEADER); 8 | tft.loadFont(Font_14); 9 | tft.setTextDatum(TL_DATUM); 10 | tft.drawString("F", 40, 5); 11 | tft.drawString("P", 130, 5); 12 | tft.drawString("RANGE", 40, 120); 13 | tft.drawString("SCALE", 150, 120); 14 | if (auto_scale) 15 | { 16 | tft.setTextColor(TFT_RED, HEADER); 17 | tft.drawString("А", 225, 120); 18 | } 19 | else 20 | { 21 | tft.setTextColor(TFT_GREEN, HEADER); 22 | tft.drawString("Р", 225, 120); 23 | } 24 | tft.setTextColor(TEXT_02, HEADER); 25 | tft.drawString("0", 55, 5); 26 | tft.drawString("0", 145, 5); 27 | tft.drawString(String(mass_rate[num_rate]), 90, 120); 28 | 29 | configure_i2s(mass_rate[num_rate]); 30 | } 31 | 32 | void redraw_footer() 33 | { 34 | tft.loadFont(Font_14); 35 | tft.fillRect(30, 115, 210, 20, HEADER); 36 | if (auto_rate) tft.setTextColor(TEXT_01, HEADER); 37 | else tft.setTextColor(TFT_GREEN, HEADER); 38 | tft.drawString("RANGE", 40, 120); 39 | tft.setTextColor(TEXT_01, HEADER); 40 | tft.drawString("SCALE", 150, 120); 41 | if (auto_scale) 42 | { 43 | tft.setTextColor(TFT_RED, HEADER); 44 | tft.drawString("А", 225, 120); 45 | } 46 | else 47 | { 48 | tft.setTextColor(TFT_GREEN, HEADER); 49 | tft.drawString("Р", 225, 120); 50 | } 51 | tft.setTextColor(TEXT_02, HEADER); 52 | tft.drawString(String(mass_rate[num_rate]), 90, 120); 53 | drawLevelOscill(); 54 | } 55 | 56 | void find_triger() 57 | { 58 | for (uint16_t i = 1; i < NUM_SAMPLES; i++) 59 | { 60 | if (osc_buffer[i] < osc_buffer[i - 1])triger_level_min = osc_buffer[i]; 61 | if (osc_buffer[i] > osc_buffer[i - 1])triger_level_max = osc_buffer[i]; 62 | } 63 | //triger_level = (triger_level_max - triger_level_min)/2 + 12288; 64 | triger_level = triger_level_min; 65 | } 66 | 67 | void triger() 68 | { 69 | uint16_t duty_temp = 0; 70 | bool triger_minimum_01 = false; 71 | bool triger_maximum_01 = false; 72 | bool triger_minimum_02 = false; 73 | bool triger_maximum_02 = false; 74 | 75 | triger_level_min = 16384; 76 | triger_level_max = 12288; 77 | 78 | if (triger_level == 0) find_triger(); 79 | 80 | for (uint16_t i = 1; i < NUM_SAMPLES; i++) 81 | { 82 | if (!triger_minimum_01) 83 | { 84 | if (osc_buffer[i] < triger_level) 85 | { 86 | triger_maximum_01 = true; 87 | } 88 | } 89 | if (!triger_minimum_01 && triger_maximum_01) 90 | { 91 | if (osc_buffer[i] > triger_level) 92 | { 93 | triger_minimum_01 = true; 94 | triger_01 = i; 95 | } 96 | } 97 | 98 | if (triger_minimum_01) 99 | { 100 | if (!triger_minimum_02) 101 | { 102 | if (osc_buffer[i] < triger_level) 103 | { 104 | triger_maximum_02 = true; 105 | } 106 | } 107 | if (!triger_minimum_02 && triger_maximum_02) 108 | { 109 | if (osc_buffer[i] > triger_level) 110 | { 111 | triger_minimum_02 = true; 112 | triger_02 = i; 113 | duty_temp = triger_02 - triger_01; 114 | } 115 | } 116 | } 117 | if (osc_buffer[i] < triger_level_min) triger_level_min = osc_buffer[i]; 118 | if (osc_buffer[i] > triger_level_max) triger_level_max = osc_buffer[i]; 119 | } 120 | if (check_freq_cur != check_freq_num) 121 | { 122 | if (duty_temp != 0) check_freq_mass[check_freq_cur] = duty_temp; 123 | check_freq_cur ++; 124 | } 125 | else 126 | { 127 | check_freq_cur = 0; 128 | if (check_freq_mass[0] == check_freq_mass[1] && check_freq_mass[0] == check_freq_mass[2]) 129 | { 130 | duty = check_freq_mass[0]; 131 | if (duty < duty_min && num_rate != 5 && auto_rate) rate_increment(); 132 | if (duty > duty_max && num_rate != 0 && auto_rate) rate_decrement(); 133 | } 134 | } 135 | } 136 | 137 | void draw_graph() 138 | { 139 | String mess; 140 | uint16_t y_trig; 141 | uint16_t x = 30; 142 | float v_max = triger_level_max; 143 | float v_min = triger_level_min; 144 | 145 | if (check_volt_cur != check_volt_num) 146 | { 147 | check_v_max_mass[check_volt_cur] = v_max; 148 | check_v_min_mass[check_volt_cur] = v_min; 149 | check_volt_cur ++; 150 | } 151 | else 152 | { 153 | check_volt_cur = 0; 154 | if (check_v_max_mass[0] == check_v_max_mass[1]) volt_level_max = check_v_max_mass[0]; 155 | if (check_v_min_mass[0] == check_v_min_mass[1]) volt_level_min = check_v_min_mass[0]; 156 | if (volt_level_min_last != volt_level_min || volt_level_max_last != volt_level_max) drawLevelOscill(); 157 | volt_level_min_last = volt_level_min; 158 | volt_level_max_last = volt_level_max; 159 | } 160 | 161 | tft.fillRect(30, 20, 210, 95, TFT_BLACK); 162 | if (duty_last != duty) 163 | { 164 | freq = (mass_rate[num_rate] / duty) * 2; 165 | period = 1000000 / freq; 166 | float period_ = period; 167 | tft.fillRect(30, 0, 178, 20, HEADER); 168 | tft.setTextColor(TEXT_01, HEADER); 169 | tft.loadFont(Font_14); 170 | tft.drawString("F", 40, 5); 171 | tft.drawString("P", 130, 5); 172 | tft.setTextColor(TEXT_02, HEADER); 173 | tft.drawString(String(freq) + " Hz", 55, 5); 174 | if (period < 1000) tft.drawString(String(period) + " uS", 145, 5); 175 | if (period > 1000) tft.drawString(String(period_ / 1000, 1) + " mS", 145, 5); 176 | if (connectBL) drawBmp("/BL_ico.bmp", 192, 2); 177 | } 178 | duty_last = duty; 179 | 180 | if (auto_scale) y_trig = map(triger_level, triger_level_min, triger_level_max, 0, 94); 181 | else y_trig = map(triger_level, 12288, 16384, 0, 94); 182 | if (y_trig > 94) y_trig = 0; 183 | 184 | mess = PREF_ARR; 185 | for (uint16_t i = triger_01; i < 210 + triger_01; i++) 186 | { 187 | x++; 188 | uint8_t y_curr; 189 | uint8_t y_next; 190 | uint8_t y_bl; 191 | if (auto_scale) 192 | { 193 | y_curr = map(osc_buffer[i], triger_level_min, triger_level_max, 0, 94); 194 | y_next = map(osc_buffer[i + 1], triger_level_min, triger_level_max, 0, 94); 195 | y_bl = map(osc_buffer[i + 1], triger_level_min, triger_level_max, 0, 188); 196 | } 197 | else 198 | { 199 | y_curr = map(osc_buffer[i], 12288, 16384, 0, 94); 200 | y_next = map(osc_buffer[i + 1], 12288, 16384, 0, 94); 201 | y_bl = map(osc_buffer[i], 12288, 16384, 0, 188); 202 | } 203 | if (y_curr > 94) y_curr = 0; 204 | if (y_next > 94) y_next = y_curr; 205 | tft.drawLine(x, 114 - y_curr, x + 1, 114 - y_next, TFT_VIOL_1); 206 | 207 | 208 | mess.concat(y_bl); 209 | mess.concat("|"); 210 | } 211 | if (BL_type && connectBL) 212 | { 213 | Bluetooth.print(mess); 214 | Bluetooth.write('>'); 215 | } 216 | if (!BL_type && connectBL) 217 | { 218 | String data_osc; 219 | data_osc = PREF_FRQ; 220 | data_osc.concat(String(freq)); 221 | data_osc.concat(PREF_SCL); 222 | if (auto_scale) data_osc.concat("A"); 223 | if (!auto_scale) data_osc.concat("M"); 224 | data_osc.concat(PREF_OMX); 225 | data_osc.concat(String(curr_max, 1)); 226 | data_osc.concat(PREF_OMN); 227 | data_osc.concat(String(curr_min, 1)); 228 | data_osc.concat(PREF_FIN); 229 | Bluetooth.print(data_osc); 230 | Bluetooth.write('>'); 231 | } 232 | triger_01 = 0; 233 | BL_type = !BL_type; 234 | } 235 | 236 | void drawLevelOscill() 237 | { 238 | if (!auto_scale) 239 | { 240 | pos_y_max = 109 - (map(volt_level_max, 12288, 16384, 0, 95)); 241 | pos_y_min = 109 - (map(volt_level_min, 12288, 16384, 0, 95)); 242 | } 243 | else 244 | { 245 | pos_y_max = 15; 246 | pos_y_min = 109; 247 | } 248 | 249 | curr_max = (volt_level_max - shift) / 4095.0 * 3.3; 250 | curr_min = (volt_level_min - shift) / 4095.0 * 3.3; 251 | 252 | //curr_max = volt_level_max / 4095.0 * 3.3; 253 | //curr_min = volt_level_min / 4095.0 * 3.3; 254 | 255 | tft.fillRect(0, 0, 30, 135, OSC_LEFT); 256 | tft.loadFont(Font_10); 257 | tft.setTextColor(TFT_WHITE, OSC_LEVEL); 258 | 259 | tft.fillRect(0, pos_y_min, 24, 11, OSC_LEVEL); 260 | tft.fillRect(24, pos_y_min + 1, 1, 9, OSC_LEVEL); 261 | tft.fillRect(25, pos_y_min + 2, 1, 7, OSC_LEVEL); 262 | tft.fillRect(26, pos_y_min + 3, 1, 5, OSC_LEVEL); 263 | tft.fillRect(27, pos_y_min + 4, 1, 3, OSC_LEVEL); 264 | tft.drawPixel(28, pos_y_min + 5, OSC_LEVEL); 265 | tft.drawString(String(curr_min, 1), 4, pos_y_min + 2); 266 | 267 | tft.fillRect(0, pos_y_max, 24, 11, OSC_LEVEL); 268 | tft.fillRect(24, pos_y_max + 1, 1, 9, OSC_LEVEL); 269 | tft.fillRect(25, pos_y_max + 2, 1, 7, OSC_LEVEL); 270 | tft.fillRect(26, pos_y_max + 3, 1, 5, OSC_LEVEL); 271 | tft.fillRect(27, pos_y_max + 4, 1, 3, OSC_LEVEL); 272 | tft.drawPixel(28, pos_y_max + 5, OSC_LEVEL); 273 | tft.drawString(String(curr_max, 1), 4, pos_y_max + 2); 274 | } 275 | 276 | void rate_increment() 277 | { 278 | i2s_adc_disable(I2S_NUM_0); 279 | i2s_driver_uninstall(I2S_NUM_0); 280 | if (num_rate < 5) num_rate++; 281 | configure_i2s(mass_rate[num_rate]); 282 | redraw_footer(); 283 | } 284 | void rate_decrement() 285 | { 286 | i2s_adc_disable(I2S_NUM_0); 287 | i2s_driver_uninstall(I2S_NUM_0); 288 | if (num_rate > 0) num_rate--; 289 | configure_i2s(mass_rate[num_rate]); 290 | redraw_footer(); 291 | } 292 | 293 | void configure_i2s(uint32_t rate) 294 | { 295 | //keep in mind: 296 | //dma_buf_len * dma_buf_count * bits_per_sample/8 > 4096 297 | i2s_config_t i2s_config = 298 | { 299 | .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN), // I2S receive mode with ADC 300 | .sample_rate = rate, // sample rate 301 | .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // 16 bit I2S 302 | .channel_format = I2S_CHANNEL_FMT_ALL_LEFT, // only the left channel 303 | .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), // I2S format 304 | .intr_alloc_flags = 1, // none 305 | .dma_buf_count = 2, // number of DMA buffers 306 | .dma_buf_len = NUM_SAMPLES, // number of samples 307 | .use_apll = 0, // no Audio PLL 308 | }; 309 | adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN_11db); // ADC channel 0 with 11db (divide by input 3.6) 310 | adc1_config_width(ADC_WIDTH_12Bit); // 12 bit ADC 311 | i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); // install I2S 0 driver, using event queue 312 | 313 | i2s_set_adc_mode(ADC_UNIT_1, ADC_CHANNEL); // ADC should use ADC_CHANNEL 314 | // The raw ADC data is written in DMA in inverted form. This add aninversion: 315 | SET_PERI_REG_MASK(SYSCON_SARADC_CTRL2_REG, SYSCON_SARADC_SAR1_INV); 316 | i2s_adc_enable(I2S_NUM_0); // enable I2S ADC 317 | i2s_enable = true; 318 | find_triger(); 319 | } 320 | 321 | void ADC_Sampling(uint16_t *osc_buffer) 322 | { 323 | for (int i = 0; i < BUFF_SIZE / NUM_SAMPLES; i++) 324 | { 325 | i2s_read_bytes(I2S_NUM_0, (char*)&osc_buffer[i * NUM_SAMPLES], NUM_SAMPLES * sizeof(uint16_t), portMAX_DELAY); 326 | } 327 | } 328 | 329 | void characterize_adc() 330 | { 331 | esp_adc_cal_value_t val_type = esp_adc_cal_characterize( 332 | (adc_unit_t)ADC_UNIT_1, 333 | (adc_atten_t)ADC_CHANNEL, 334 | (adc_bits_width_t)ADC_WIDTH_BIT_12, 335 | 1100, 336 | &adc_chars); 337 | } 338 | -------------------------------------------------------------------------------- /Firmware/11_UART.ino: -------------------------------------------------------------------------------- 1 | void UART_init() 2 | { 3 | menyDraw("UART", false); 4 | 5 | tft.setTextDatum(TL_DATUM); 6 | tft.loadFont(Font_12); 7 | tft.setTextColor(TEXT_01, TFT_BLACK); 8 | pinMode(RXD2, INPUT); 9 | detectionBaud(); 10 | } 11 | 12 | void UART_draw(uint8_t arr) 13 | { 14 | if (arr == 10) 15 | { 16 | tft.fillRect(0, 20, 240, 114, TFT_BLACK); 17 | if (uart_arr == 7) uart_arr = 0; 18 | incoming_array[0] = incomming; 19 | for (uint8_t i = 0; i < 7; i++) tft.drawString(incoming_array[i], 10, 30 + 15 * i); 20 | for (uint8_t i = 6; i > 0; i--) incoming_array[i] = incoming_array[i - 1]; 21 | uart_arr++; 22 | incomming = ""; 23 | } 24 | else incomming += String((char)arr); 25 | } 26 | 27 | void uartHandler() 28 | { 29 | uart_event_t event; 30 | size_t buffered_size; 31 | //if (xQueueReceive(UART_QUEUE, (void * )&event, (portTickType)portMAX_DELAY)) 32 | if (xQueueReceive(UART_QUEUE, (void * )&event, 50)) 33 | { 34 | if (event.type == UART_DATA) 35 | { 36 | uint8_t UART_data[128]; 37 | int UART_data_length = 0; 38 | 39 | ESP_ERROR_CHECK(uart_get_buffered_data_len(PORT_NUM, (size_t*)&UART_data_length)); 40 | UART_data_length = uart_read_bytes(PORT_NUM, UART_data, UART_data_length, 100); 41 | 42 | for (byte i = 0; i < UART_data_length; i++) if (baud_true) UART_draw(UART_data[i]); 43 | //Serial.print((char)UART_data[i]); 44 | } 45 | if (event.type == UART_FIFO_OVF) 46 | { 47 | Serial.println("UART_FIFO_OVF"); 48 | uart_flush(PORT_NUM); 49 | } 50 | if (event.type == UART_BUFFER_FULL) 51 | { 52 | Serial.println("UART_BUFFER_FULL"); 53 | uart_flush(PORT_NUM); 54 | } 55 | if (event.type == UART_BREAK) 56 | { 57 | Serial.println("UART_BREAK"); 58 | uart_flush(PORT_NUM); 59 | } 60 | if (event.type == UART_PARITY_ERR) 61 | { 62 | Serial.println("UART_PARITY_ERR"); 63 | uart_flush(PORT_NUM); 64 | } 65 | if (event.type == UART_FRAME_ERR) 66 | { 67 | Serial.println("UART_FRAME_ERR"); 68 | uart_driver_delete(PORT_NUM); 69 | uart_flush(PORT_NUM); 70 | UART_setup(); 71 | } 72 | if (event.type == UART_PATTERN_DET) 73 | { 74 | Serial.println("UART_PATTERN_DET"); 75 | uart_flush(PORT_NUM); 76 | } 77 | } 78 | } 79 | 80 | long detectionBaud() 81 | { 82 | UART_baudDraw("DETECTION", TFT_RED); 83 | uint32_t width_impulse; // Ширина импульса 84 | uint32_t width_impulse_last = 10000; // Ширина импульса последняя 85 | for (uint16_t i = 0; i < baud_count_max; i++) 86 | { 87 | while (digitalRead(RXD2) == 1) 88 | { 89 | if (btn_up || btn_dwn) 90 | { 91 | Serial.println("BREAK"); 92 | baud_exit = true; 93 | break; 94 | } 95 | } 96 | if (!baud_exit) 97 | { 98 | width_impulse = pulseIn(RXD2, LOW); 99 | if (width_impulse < width_impulse_last) 100 | { 101 | if (width_impulse < 12) BAUD_RATE = 115200; 102 | else if (width_impulse < 20) BAUD_RATE = 57600; 103 | else if (width_impulse < 29) BAUD_RATE = 38400; 104 | else if (width_impulse < 40) BAUD_RATE = 28800; 105 | else if (width_impulse < 60) BAUD_RATE = 19200; 106 | else if (width_impulse < 80) BAUD_RATE = 14400; 107 | else if (width_impulse < 150) BAUD_RATE = 9600; 108 | else if (width_impulse < 300) BAUD_RATE = 4800; 109 | else if (width_impulse < 600) BAUD_RATE = 2400; 110 | else if (width_impulse < 1200) BAUD_RATE = 1200; 111 | else BAUD_RATE = 0; 112 | width_impulse_last = width_impulse; 113 | } 114 | if (i == 50) UART_baudDraw("DETECTION", TEXT_02); 115 | if (i == 100) UART_baudDraw("DETECTION", TFT_RED); 116 | if (i == 150) UART_baudDraw("DETECTION", TEXT_02); 117 | if (i == 200) UART_baudDraw("DETECTION", TFT_RED); 118 | if (i == 250) UART_baudDraw("DETECTION", TEXT_02); 119 | if (i == 300) UART_baudDraw("DETECTION", TFT_RED); 120 | if (i == 350) UART_baudDraw("DETECTION", TEXT_02); 121 | if (i == 400) UART_baudDraw("COMPLITTED", RES_GREEN); 122 | } 123 | else break; 124 | } 125 | if (!baud_exit) 126 | { 127 | UART_baudDraw(String(BAUD_RATE), TEXT_02); 128 | tft.setTextDatum(TL_DATUM); 129 | tft.loadFont(Font_12); 130 | tft.setTextColor(TEXT_01, TFT_BLACK); 131 | baud_true = true; 132 | delay(10); 133 | UART_setup(); 134 | } 135 | } 136 | 137 | void UART_setup() 138 | { 139 | uart_config_t uart_config = { 140 | .baud_rate = BAUD_RATE, 141 | .data_bits = UART_DATA_8_BITS, 142 | .parity = UART_PARITY_DISABLE, 143 | .stop_bits = UART_STOP_BITS_1, 144 | .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, 145 | .rx_flow_ctrl_thresh = 122, 146 | }; 147 | uart_param_config(PORT_NUM, &uart_config); 148 | uart_set_pin(PORT_NUM, TXD2, RXD2, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); 149 | uart_driver_install(PORT_NUM, BUF_SIZE, BUF_SIZE, 10, &UART_QUEUE, 0); 150 | } 151 | -------------------------------------------------------------------------------- /Firmware/12_UART_PLOT.ino: -------------------------------------------------------------------------------- 1 | void plotter_init() 2 | { 3 | menyDraw("PLOTTER", true); 4 | } 5 | -------------------------------------------------------------------------------- /Firmware/13_SETTINGS.ino: -------------------------------------------------------------------------------- 1 | void settings_init() 2 | { 3 | menyDraw("НАСТРОЙКИ", true); 4 | } 5 | -------------------------------------------------------------------------------- /Firmware/14_BATTERY.ino: -------------------------------------------------------------------------------- 1 | void battery() 2 | { 3 | if (batt_level < batt_level_0 && bat_redraw && CHRG_OFF) 4 | { 5 | batt_level = BATT_LEVEL; 6 | bat_redraw = false; 7 | 8 | if (bat_red) 9 | { 10 | tft.drawRect(209, 4, 23, 12, TFT_RED); 11 | tft.fillRect(232, 7, 3, 7, TFT_RED); 12 | } 13 | else 14 | { 15 | tft.drawRect(209, 4, 23, 12, TEXT_01); 16 | tft.fillRect(232, 7, 3, 7, TEXT_01); 17 | } 18 | bat_red = !bat_red; 19 | } 20 | 21 | if ((bat_counter >= bat_counter_check || check_bat) && CHRG_OFF) 22 | { 23 | check_bat = false; 24 | bat_counter = 0; 25 | batt_level = BATT_LEVEL; 26 | 27 | //tft.loadFont(Font_14); 28 | //tft.setTextDatum(TL_DATUM); 29 | //tft.setTextColor(TEXT_01, HEADER); 30 | //tft.drawNumber(batt_level, 130, 5); 31 | 32 | if (batt_level > batt_level_0) 33 | { 34 | tft.drawRect(209, 4, 23, 12, TEXT_01); 35 | tft.fillRect(232, 7, 3, 7, TEXT_01); 36 | } 37 | 38 | if (batt_level > batt_level_1) tft.fillRect(211, 6, 3, 8, TEXT_01); 39 | else tft.fillRect(211, 6, 3, 8, HEADER); 40 | if (batt_level > batt_level_2) tft.fillRect(215, 6, 3, 8, TEXT_01); 41 | else tft.fillRect(215, 6, 3, 8, HEADER); 42 | if (batt_level > batt_level_3)tft.fillRect(219, 6, 3, 8, TEXT_01); 43 | else tft.fillRect(219, 6, 3, 8, HEADER); 44 | if (batt_level > batt_level_4)tft.fillRect(223, 6, 3, 8, TEXT_01); 45 | else tft.fillRect(223, 6, 3, 8, HEADER); 46 | if (batt_level > batt_level_5)tft.fillRect(227, 6, 3, 8, TEXT_01); 47 | else tft.fillRect(227, 6, 3, 8, HEADER); 48 | } 49 | 50 | if (CHRG_ON && bat_redraw) 51 | { 52 | batt_level = BATT_LEVEL; 53 | bat_redraw = false; 54 | 55 | if (bat_redraw_chrg) 56 | { 57 | bat_redraw_chrg = false; 58 | counter_seconds = 0; 59 | } 60 | 61 | if (counter_seconds > 10 && counter_seconds < 20) 62 | { 63 | tft.drawRect(209, 4, 23, 12, TFT_GREEN); 64 | tft.fillRect(232, 7, 3, 7, TFT_GREEN); 65 | tft.fillRect(211, 5, 20, 10, HEADER); 66 | } 67 | if (counter_seconds > 20 && counter_seconds < 30)tft.fillRect(211, 6, 3, 8, TFT_GREEN); 68 | if (counter_seconds > 30 && counter_seconds < 40)tft.fillRect(215, 6, 3, 8, TFT_GREEN); 69 | if (counter_seconds > 40 && counter_seconds < 50)tft.fillRect(219, 6, 3, 8, TFT_GREEN); 70 | if (counter_seconds > 50 && counter_seconds < 60)tft.fillRect(223, 6, 3, 8, TFT_GREEN); 71 | if (counter_seconds > 60) 72 | { 73 | tft.fillRect(227, 6, 3, 8, TFT_GREEN); 74 | counter_seconds = 0; 75 | } 76 | } 77 | if (CHRG_OFF && !bat_redraw_chrg) 78 | { 79 | bat_redraw_chrg = true; 80 | bat_redraw = false; 81 | batt_level = BATT_LEVEL; 82 | bat_counter = bat_counter_check; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Firmware/15_GRAPH.ino: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // БАЗОВАЯ ГРАФИКА /////////////////////////////////////////////////////////////////////////// 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | // МЕНЮ 5 | void menyDraw(String string, bool bottom) 6 | { 7 | if (meny_draw) 8 | { 9 | tft.fillScreen(TFT_BLACK); 10 | tft.setTextDatum(TC_DATUM); 11 | tft.loadFont(Font_24); 12 | tft.setTextColor(TFT_WHITE, TFT_BLACK); 13 | tft.drawString(string, 120, 60); 14 | delay(delay_mode); 15 | tft.fillScreen(TFT_BLACK); 16 | } 17 | // Рисуем графику меню 18 | tft.fillRect(0, 0, 208, 20, HEADER); 19 | if (connectBL) drawBmp("/BL_ico.bmp", 192, 2); 20 | if (bottom) tft.fillRect(0, 95, 240, 40, HEADER); 21 | 22 | tft.setTextDatum(TL_DATUM); 23 | tft.loadFont(Font_14); 24 | tft.setTextColor(TEXT_01, HEADER); 25 | tft.drawString(string, 10, 5); 26 | } 27 | // ЗНАЧЕНИЕ 28 | void valueDraw(float value, uint8_t dot, uint16_t color) 29 | { 30 | tft.setTextDatum(TR_DATUM); 31 | tft.loadFont(Font_64); 32 | tft.setTextColor(color, TFT_BLACK); 33 | tft.fillRect(20, 33, 160, 50, TFT_BLACK); 34 | if (dot > 0) tft.drawFloat(value, dot, 180, 33); 35 | else tft.drawNumber(value, 180, 33); 36 | } 37 | // СИМВОЛ 38 | void simbolDraw(String simbol, uint16_t color) 39 | { 40 | tft.setTextDatum(TL_DATUM); 41 | tft.loadFont(Font_14); 42 | tft.setTextColor(color, TFT_BLACK); 43 | tft.drawString(simbol, 190, 70); 44 | } 45 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 46 | // ВОЛЬТМЕТР /////////////////////////////////////////////////////////////////////////// 47 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | void voltLevelMenyDraw() 49 | { 50 | tft.fillRoundRect(6, 100, 72, 30, 3, TFT_BLUE_1); 51 | tft.fillRoundRect(84, 100, 72, 30, 3, TFT_BLUE_1); 52 | tft.fillRoundRect(162, 100, 72, 30, 3, TFT_BLUE_1); 53 | tft.loadFont(Font_24); 54 | tft.setTextColor(TEXT_01, TFT_BLUE_1); 55 | tft.drawString("1.8", 14, 106); 56 | tft.drawString("TTL", 92, 106); 57 | tft.drawString("5V", 170, 106); 58 | } 59 | 60 | void voltLevelDraw(uint8_t num, String level) 61 | { 62 | tft.setTextDatum(TC_DATUM); 63 | tft.loadFont(Font_24); 64 | if (num == 1) 65 | { 66 | tft.fillRect(51, 106, 20, 20, TFT_BLUE_1); 67 | if (level == "0")tft.setTextColor(TFT_BLUE, TFT_BLUE_1); 68 | if (level == "1")tft.setTextColor(TFT_GREEN, TFT_BLUE_1); 69 | if (level == "N")tft.setTextColor(TFT_GRAY, TFT_BLUE_1); 70 | tft.drawString(level, 60, 106); 71 | } 72 | if (num == 2) 73 | { 74 | tft.fillRect(129, 106, 20, 20, TFT_BLUE_1); 75 | if (level == "0")tft.setTextColor(TFT_BLUE, TFT_BLUE_1); 76 | if (level == "1")tft.setTextColor(TFT_GREEN, TFT_BLUE_1); 77 | if (level == "N")tft.setTextColor(TFT_GRAY, TFT_BLUE_1); 78 | tft.drawString(level, 138, 106); 79 | } 80 | if (num == 3) 81 | { 82 | tft.fillRect(207, 106, 20, 20, TFT_BLUE_1); 83 | if (level == "0")tft.setTextColor(TFT_BLUE, TFT_BLUE_1); 84 | if (level == "1")tft.setTextColor(TFT_GREEN, TFT_BLUE_1); 85 | if (level == "N")tft.setTextColor(TFT_GRAY, TFT_BLUE_1); 86 | tft.drawString(level, 216, 106); 87 | } 88 | } 89 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 90 | // ЕМКОСТЬ /////////////////////////////////////////////////////////////////////////// 91 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 92 | void capLevelDraw(uint16_t value) 93 | { 94 | tft.fillRoundRect(30, 105, 40, 20, 4, CAP_BACK); 95 | 96 | tft.setTextDatum(TC_DATUM); 97 | tft.loadFont(Font_18); 98 | tft.setTextColor(TFT_BLACK, CAP_BACK); 99 | tft.drawNumber(value, 50, 108); 100 | } 101 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 102 | // ИНДУКТИВНОСТЬ /////////////////////////////////////////////////////////////////////////// 103 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 104 | void indLevelDraw(uint16_t value) 105 | { 106 | tft.fillRoundRect(30, 105, 40, 20, 4, TFT_BLUE_1); 107 | 108 | tft.setTextDatum(TC_DATUM); 109 | tft.loadFont(Font_18); 110 | tft.setTextColor(TFT_BLACK, TFT_BLUE_1); 111 | tft.drawNumber(value, 50, 108); 112 | } 113 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 114 | // UART /////////////////////////////////////////////////////////////////////////// 115 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 116 | void UART_dataDraw(String mess) 117 | { 118 | tft.fillRect(0, 20, 100, 80, TFT_BLACK); 119 | 120 | tft.setTextDatum(TC_DATUM); 121 | tft.loadFont(Font_14); 122 | tft.setTextColor(TFT_WHITE, TFT_BLACK); 123 | tft.drawString(mess, 20, 30); 124 | } 125 | void UART_baudDraw(String value, uint16_t color) 126 | { 127 | tft.fillRect(100, 0, 85, 20, HEADER); 128 | 129 | tft.setTextDatum(TL_DATUM); 130 | tft.loadFont(Font_14); 131 | tft.setTextColor(color, HEADER); 132 | tft.drawString(value, 100, 5); 133 | tft.setTextColor(TEXT_01, HEADER); 134 | tft.drawString("BAUD", 55, 5); 135 | } 136 | 137 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 138 | // BMP /////////////////////////////////////////////////////////////////////////// 139 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 140 | void drawBmp(const char *filename, int16_t x, int16_t y) 141 | { 142 | if ((x >= tft.width()) || (y >= tft.height())) return; 143 | fs::File bmpFS; 144 | bmpFS = SPIFFS.open(filename, "r"); 145 | 146 | if (!bmpFS) 147 | { 148 | Serial.print("File not found"); 149 | return; 150 | } 151 | 152 | uint32_t seekOffset; 153 | uint16_t w, h, row, col; 154 | uint8_t r, g, b; 155 | uint32_t startTime = millis(); 156 | 157 | if (read16(bmpFS) == 0x4D42) 158 | { 159 | read32(bmpFS); 160 | read32(bmpFS); 161 | seekOffset = read32(bmpFS); 162 | read32(bmpFS); 163 | w = read32(bmpFS); 164 | h = read32(bmpFS); 165 | 166 | if ((read16(bmpFS) == 1) && (read16(bmpFS) == 24) && (read32(bmpFS) == 0)) 167 | { 168 | y += h - 1; 169 | 170 | bool oldSwapBytes = tft.getSwapBytes(); 171 | tft.setSwapBytes(true); 172 | bmpFS.seek(seekOffset); 173 | 174 | uint16_t padding = (4 - ((w * 3) & 3)) & 3; 175 | uint8_t lineBuffer[w * 3 + padding]; 176 | 177 | for (row = 0; row < h; row++) { 178 | 179 | bmpFS.read(lineBuffer, sizeof(lineBuffer)); 180 | uint8_t* bptr = lineBuffer; 181 | uint16_t* tptr = (uint16_t*)lineBuffer; 182 | // Convert 24 to 16 bit colours 183 | for (uint16_t col = 0; col < w; col++) 184 | { 185 | b = *bptr++; 186 | g = *bptr++; 187 | r = *bptr++; 188 | *tptr++ = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); 189 | } 190 | tft.pushImage(x, y--, w, 1, (uint16_t*)lineBuffer); 191 | } 192 | tft.setSwapBytes(oldSwapBytes); 193 | Serial.print("Loaded in "); Serial.print(millis() - startTime); 194 | Serial.println(" ms"); 195 | } 196 | else Serial.println("BMP format not recognized."); 197 | } 198 | bmpFS.close(); 199 | } 200 | 201 | uint16_t read16(fs::File &f) { 202 | uint16_t result; 203 | ((uint8_t *)&result)[0] = f.read(); // LSB 204 | ((uint8_t *)&result)[1] = f.read(); // MSB 205 | return result; 206 | } 207 | 208 | uint32_t read32(fs::File &f) { 209 | uint32_t result; 210 | ((uint8_t *)&result)[0] = f.read(); // LSB 211 | ((uint8_t *)&result)[1] = f.read(); 212 | ((uint8_t *)&result)[2] = f.read(); 213 | ((uint8_t *)&result)[3] = f.read(); // MSB 214 | return result; 215 | } 216 | -------------------------------------------------------------------------------- /Firmware/16_BLUETOOTH.ino: -------------------------------------------------------------------------------- 1 | void printDeviceAddress() 2 | { 3 | const uint8_t* point = esp_bt_dev_get_address(); 4 | String MAC_CONNECT; 5 | String MAC_CURR; 6 | for (int i = 0; i < 6; i++) 7 | { 8 | MAC_CURR = String(point[i], HEX); 9 | MAC_CURR.toUpperCase(); 10 | if (MAC_CURR.length() == 1) MAC_CONNECT += "0" + MAC_CURR; 11 | else MAC_CONNECT += MAC_CURR; 12 | if (i < 5) MAC_CONNECT += ":"; 13 | } 14 | Serial.println(MAC_CONNECT); 15 | } 16 | 17 | void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) { 18 | if (event == ESP_SPP_SRV_OPEN_EVT) 19 | { 20 | String mess = "M"; 21 | mess.concat(mode); 22 | Bluetooth.print(mess); 23 | Bluetooth.write('>'); 24 | connectBL = true; 25 | drawBmp("/BL_ico.bmp", 192, 2); 26 | Serial.println("Client CONNECTED"); 27 | delay(100); 28 | } 29 | if (event == 27) 30 | { 31 | tft.fillRect(192, 2, 12, 16, HEADER); 32 | connectBL = false; 33 | Serial.println("Client DISCONNECTED"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Firmware/Data/BL_ico.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/BL_ico.bmp -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-10.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-10.vlw -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-12.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-12.vlw -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-14.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-14.vlw -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-16.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-16.vlw -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-18.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-18.vlw -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-24.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-24.vlw -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-32.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-32.vlw -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-48.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-48.vlw -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-64.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-64.vlw -------------------------------------------------------------------------------- /Firmware/Data/CenturyGothic-8.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/CenturyGothic-8.vlw -------------------------------------------------------------------------------- /Firmware/Data/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Firmware/Data/logo.jpg -------------------------------------------------------------------------------- /Firmware/FW_QUARK/FW_QUARK.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "driver/uart.h" 9 | #include "esp_adc_cal.h" 10 | #include "01_DEFINES.h" 11 | #include "02_VARIABLES.h" 12 | #include "FS.h" 13 | #include "SPIFFS.h" 14 | #include "BluetoothSerial.h" 15 | #include "esp_bt_main.h" 16 | #include "esp_bt_device.h" 17 | 18 | #include "soc/rtc_io_reg.h" 19 | #include "soc/rtc_cntl_reg.h" 20 | #include "soc/sens_reg.h" 21 | 22 | INA219 INA_219; 23 | TFT_eSPI tft = TFT_eSPI(HEIGHT, WIDTH); 24 | BluetoothSerial Bluetooth; 25 | 26 | esp_adc_cal_characteristics_t adc_chars; 27 | 28 | TaskHandle_t TASK_BTN; 29 | TaskHandle_t TASK_MENY; 30 | TaskHandle_t TASK_BL; 31 | QueueHandle_t UART_QUEUE; 32 | 33 | // ТАЙМЕРЫ 34 | hw_timer_t * count_timer = NULL; 35 | portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; 36 | 37 | void IRAM_ATTR counter_funct() 38 | { 39 | portENTER_CRITICAL_ISR(&timerMux); 40 | if (mode == 1) amper_count = true; 41 | counter_seconds++; 42 | btn_counter ++; 43 | bat_counter ++; 44 | bat_redraw = true; 45 | portEXIT_CRITICAL_ISR(&timerMux); 46 | } 47 | 48 | void save_ADC_Reg(void) 49 | { 50 | reg_b = READ_PERI_REG(SENS_SAR_READ_CTRL2_REG); 51 | } 52 | 53 | void restore_ADC_Reg(void) 54 | { 55 | WRITE_PERI_REG(SENS_SAR_READ_CTRL2_REG, reg_b); 56 | SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV); 57 | } 58 | 59 | void setup() 60 | { 61 | save_ADC_Reg(); 62 | Bluetooth.register_callback(callback); 63 | Bluetooth.setPin(pin); 64 | Bluetooth.begin("QUARK"); 65 | Serial.begin(115200); 66 | Serial.println(); 67 | Serial.println("START"); 68 | 69 | SPIFFS.begin(); 70 | INA_219.begin(); 71 | INA_219.configure(INA219::RANGE_32V, 72 | INA219::GAIN_2_80MV, 73 | INA219::ADC_16SAMP, 74 | INA219::ADC_16SAMP, 75 | INA219::CONT_SH_BUS); 76 | INA_219.calibrate(R_SHUNT, 77 | V_SHUNT_MAX, 78 | V_BUS_MAX, 79 | I_MAX); 80 | 81 | Wire.begin(SDA1, SCL1); 82 | 83 | pinMode(IND_VAL, INPUT); 84 | pinMode(SPEAK, OUTPUT); 85 | pinMode(REL_01, OUTPUT); 86 | pinMode(REL_02, OUTPUT); 87 | pinMode(POWER, OUTPUT); 88 | pinMode(PCB_LIGHT, OUTPUT); 89 | pinMode(BUTTON, INPUT); 90 | pinMode(CHRG, INPUT); 91 | pinMode(ADC_CR, INPUT); 92 | pinMode(ADC_BAT, INPUT); 93 | pinMode(RC_EN, OUTPUT); 94 | pinMode(IND_EN, OUTPUT); 95 | pinMode(L_GEN, OUTPUT); 96 | 97 | pinMode(32, INPUT); 98 | pinMode(33, INPUT); 99 | 100 | MEAS; 101 | PWR_ON; 102 | IND_OFF; 103 | RC_OFF; 104 | 105 | tft.init(); 106 | tft.setRotation(1); 107 | tft.fillScreen(TFT_BLACK); 108 | tft.setTextDatum(TL_DATUM); 109 | tft.fillRect(0, 0, 240, 20, HEADER); 110 | 111 | //printDeviceAddress(); 112 | battery(); 113 | menu_change(); 114 | 115 | // ТАЙМЕРЫ 116 | count_timer = timerBegin(0, 80, true); // Таймер анимации, делитель 80 117 | timerAttachInterrupt(count_timer, &counter_funct, true); // Присоединяем функцию counter_funct к нашему таймеру. 118 | timerAlarmWrite(count_timer, count_mult, true); // Вызов count_timer десять раз в секунду, повтор 119 | timerAlarmEnable(count_timer); // Запсук 120 | 121 | xTaskCreatePinnedToCore( 122 | btn_handle, 123 | "btn_handle", 124 | 10000, /* Stack size in words */ 125 | NULL, /* Task input parameter */ 126 | 0, /* Priority of the task */ 127 | &TASK_BTN, /* Task handle. */ 128 | 0); /* Core where the task should run */ 129 | 130 | xTaskCreatePinnedToCore( 131 | menu_handle, 132 | "menu_handle", 133 | 10000, /* Stack size in words */ 134 | NULL, /* Task input parameter */ 135 | 3, /* Priority of the task */ 136 | &TASK_MENY, /* Task handle. */ 137 | 1); /* Core where the task should run */ 138 | } 139 | 140 | void btn_handle( void * pvParameters ) 141 | { 142 | (void) pvParameters; 143 | for (;;) 144 | { 145 | button(); 146 | vTaskDelay(pdMS_TO_TICKS(10)); 147 | } 148 | } 149 | 150 | void menu_handle( void * pvParameters ) 151 | { 152 | (void) pvParameters; 153 | for (;;) 154 | { 155 | if (Serial.available()) serialHandler(); 156 | if (Bluetooth.available()) BluetoothHandler(); 157 | if (btn_up) 158 | { 159 | btn_up = false; 160 | mode++; 161 | if (mode > 8) mode = 0; 162 | menu_change(); 163 | } 164 | if (btn_dwn) 165 | { 166 | btn_dwn = false; 167 | mode--; 168 | if (mode == 255) mode = 8; 169 | menu_change(); 170 | } 171 | battery(); 172 | mode_handler(); 173 | vTaskDelay(pdMS_TO_TICKS(20)); 174 | } 175 | } 176 | 177 | void loop() {} 178 | 179 | void BluetoothHandler() 180 | { 181 | String mess = Bluetooth.readString(); 182 | Serial.println(mess); 183 | if (mess == "RESTART") ESP.restart(); 184 | if (mess == "M0" && mode != 0) 185 | { 186 | mode = 0; 187 | menu_change(); 188 | } 189 | if (mess == "M1" && mode != 1) 190 | { 191 | mode = 1; 192 | menu_change(); 193 | } 194 | if (mess == "M2" && mode != 2) 195 | { 196 | mode = 2; 197 | menu_change(); 198 | } 199 | if (mess == "M3" && mode != 3) 200 | { 201 | mode = 3; 202 | menu_change(); 203 | } 204 | if (mess == "M4" && mode != 4) 205 | { 206 | mode = 4; 207 | menu_change(); 208 | } 209 | if (mess == "M5" && mode != 5) 210 | { 211 | mode = 5; 212 | menu_change(); 213 | } 214 | if (mess == "M6" && mode != 6) 215 | { 216 | mode = 6; 217 | menu_change(); 218 | } 219 | if (mess == "M7" && mode != 7) 220 | { 221 | mode = 7; 222 | menu_change(); 223 | } 224 | } 225 | 226 | 227 | void serialHandler() 228 | { 229 | String mess = Serial.readString(); 230 | if (mess == "r") ESP.restart(); 231 | if (mess == "1") 232 | { 233 | uart_flush(PORT_NUM); 234 | Serial.println("BTN UP"); 235 | mode++; 236 | if (mode > 8) mode = 0; 237 | menu_change(); 238 | } 239 | if (mess == "2") 240 | { 241 | Serial.println("BTN DWN"); 242 | mode--; 243 | if (mode == 255) mode = 8; 244 | menu_change(); 245 | } 246 | } 247 | 248 | void relay(bool state) 249 | { 250 | pinMode(REL_01, OUTPUT); 251 | pinMode(REL_02, OUTPUT); 252 | if (state) 253 | { 254 | digitalWrite(REL_01, 1); 255 | digitalWrite(REL_02, 0); 256 | } 257 | else 258 | { 259 | digitalWrite(REL_01, 0); 260 | digitalWrite(REL_02, 1); 261 | } 262 | delay(300); 263 | pinMode(REL_01, INPUT); 264 | pinMode(REL_02, INPUT); 265 | } 266 | -------------------------------------------------------------------------------- /Schematic/ESP32_3.2_PCB_BOTTOM.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Schematic/ESP32_3.2_PCB_BOTTOM.pdf -------------------------------------------------------------------------------- /Schematic/ESP32_3.2_PCB_TOP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Schematic/ESP32_3.2_PCB_TOP.pdf -------------------------------------------------------------------------------- /Schematic/ESP32_3.2_SCHEMATIC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MulinGROUP/QUARK/03487e847c651b00f2432cd0581bd1a817c7b3a0/Schematic/ESP32_3.2_SCHEMATIC.pdf --------------------------------------------------------------------------------