Преамбула. Я врач-травматолог из Донецка. Спасибо сыну, 4 года назад он попросил меня найти ему кружок робототехники, ничего толкового я не нашел и пришлось вникать самому, благодаря чему я открыл дивный мир Arduino и ресурс AlexGyver и достал давно забытый паяльник. С тех пор я сделал довольно много бесполезных, но и реально полезных вещей, в частности, в своей специальности. Это я к чему, в последние 2 года свободное время стремится к -273, паять научился вместо перекуров (с электронной сигаретой) и возможности самому вникать глубоко просто нет, потому прошу помощи и не клевать за колхоз.
В общем, уже сделал вот такую штуковину, программируемый блок клапанов для промывания ран:
После практического применения прибор оказался на 100% работоспособным, но выяснились недоработки, просралась финальная прошивка, появилась необходимость в нескольких приборах. В общем решил я доработать это все дело c основания в направлении: изменить немного работу блока клапанов, перейти на LCD128*64 на ST7920 (большой) для вывода информации в более удововоримом виде и....._ перейти на esp32, т.к. в перспективе хочется контролировать состояние аппарата через IoT. Прилепил интерфейс, припаял энкодер и...
...уже начал замечать легкие тормоза в виде нечеткой отработки энкодера. Когда добавил основную логику с 1 серво - просто адовые тормоза... .
При переключении в программе switch (run_butt) в case1 энкодер вообще практически не срабатывает... Хотя там ничего кроме таймеров и элементарной логики нет...
Собственно вопрос: в чем причина тормозов, ошибка в выборе сочетания контроллера (мегу взять...) и дисплея, выбора библиотек энкодера или в самом коде? Еще раз, код (да все) -адовый колхоз, у самого через год на него глядя слезы текут, пол дня потратил, чтоб вспомнить что и зачем. Но это как-то работает здесь и сейчас.
Хоть вникать в какую сторону....???
Спасибо откликнувшимся!
В общем, уже сделал вот такую штуковину, программируемый блок клапанов для промывания ран:
После практического применения прибор оказался на 100% работоспособным, но выяснились недоработки, просралась финальная прошивка, появилась необходимость в нескольких приборах. В общем решил я доработать это все дело c основания в направлении: изменить немного работу блока клапанов, перейти на LCD128*64 на ST7920 (большой) для вывода информации в более удововоримом виде и....._ перейти на esp32, т.к. в перспективе хочется контролировать состояние аппарата через IoT. Прилепил интерфейс, припаял энкодер и...
...уже начал замечать легкие тормоза в виде нечеткой отработки энкодера. Когда добавил основную логику с 1 серво - просто адовые тормоза... .
При переключении в программе switch (run_butt) в case1 энкодер вообще практически не срабатывает... Хотя там ничего кроме таймеров и элементарной логики нет...
Собственно вопрос: в чем причина тормозов, ошибка в выборе сочетания контроллера (мегу взять...) и дисплея, выбора библиотек энкодера или в самом коде? Еще раз, код (да все) -адовый колхоз, у самого через год на него глядя слезы текут, пол дня потратил, чтоб вспомнить что и зачем. Но это как-то работает здесь и сейчас.
Хоть вникать в какую сторону....???
Спасибо откликнувшимся!
C++:
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/18, /* data=*/23, /* CS=*/5, /* reset=*/22); // ESP32
#include <EncButton.h>
EncButton eb(15, 16, 4);
//#define EB_CLICK_TIME 700 // таймаут ожидания кликов (кнопка)
#include <ServoSmooth.h>
ServoSmooth servo1(90);
bool eepflag = 1;
uint16_t expo = 0;
static uint16_t timing = 0;
bool cclick = 0;
//const uint8_t rook_bitmap[] U8X8_PROGMEM = { }; // ВСТАВИТЬ МАССИВ С ЛОГО
//ПЕРЕМЕННЫЕ ИЗ В1
static uint32_t tmr_p1;
static uint32_t tmr_w1;
static uint32_t w11 = 0;
static uint32_t w_period1;
static uint8_t period = 0;
//bool i1 = false; //
bool is_off = 1;
bool is_off_LCD = 1;
//uint8_t i = 0; //clear LCD counter
bool run_butt = 0;
uint16_t stime = 0;
static int16_t w_period = 0;
uint16_t tmr_p = 0;
uint16_t tmr_w = 0;
uint16_t serv2 = 0;
uint32_t cycleft;
bool led_blink = 1;
bool vblock = 1;
bool timer_p_flag = 0;
bool vBlockFlag = 0;
bool encHoldFlag = 0;
const uint8_t PWMPin = 25; //*******************PINS
const uint8_t Servo1Pin = 26;
void setup() {
Serial.begin(115200);
u8g2.begin();
pinMode(PWMPin, OUTPUT);
servo1.attach(Servo1Pin); // подключить
servo1.setSpeed(230); // ограничить скорость
servo1.setAccel(0.1); // установить ускорение (разгон и торможение)
// u8g2.firstPage(); //ВЫВОД ЛОГОТИПА
// do {
// u8g2.drawXBMP(0, 0, 128, 64, rook_bitmap);
// } while (u8g2.nextPage());
// delay(300);
// clearLCD();
eb.setBtnLevel(LOW);
eb.setClickTimeout(700);
eb.setDebTimeout(50);
eb.setHoldTimeout(600);
eb.setStepTimeout(200);
eb.setEncReverse(0);
eb.setEncType(EB_STEP4_LOW);
eb.setFastTimeout(30);
eb.counter = 0;
while (!eb.hasClicks()) {
eb.tick();
servo1.tick();
if (uint16_t start_timer; millis() - start_timer > 500) {
start_timer = millis();
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.setFontPosTop();
u8g2.firstPage();
u8g2.drawStr(10, 1, "CHECK OLL TUBES AND");
u8g2.drawStr(9, 12, "VALVES, PRESS BUTTON");
//u8g2.drawStr(45, 23, "TWICE");
u8g2.drawStr(50, 31, "*RUN*");
u8g2.setDrawColor(2); // XOR
u8g2.drawBox(48, 26, 33, 20);
u8g2.nextPage();
}
servo1.setTargetDeg(5);
}
}
void loop() {
eb.tick();
servo1.tick();
//***************СЕКЦИЯ ОБРАБОТКИ ЭНКОДЕРА
if (eb.hasClicks(1)) {
run_butt = !run_butt;
}
if (eb.hasClicks(2)) {
cclick = !cclick;
}
if (!cclick && eb.left() && period > 0) {
period -= 1;
eepflag = 1; //ЕСЛИ НАДУМАЮ ХРАНИТЬ В ЕЕПРОМ
}
if (!cclick && eb.right() && period < 90) {
period += 1;
eepflag = 1; //ЕСЛИ НАДУМАЮ ХРАНИТЬ В ЕЕПРОМ
}
if (cclick && eb.left() && expo > 0) {
expo -= 1;
}
if (cclick && eb.right() && expo < 9) {
expo += 1;
}
//}
if (eb.holding()) { //если кн энкодера ЗАЖАТА
if (is_off) {
w_period = 0; //однократное обнуление счетчика по зажатию энк
vblock = 0;
vBlockFlag = !vBlockFlag;
// enc_butt = !enc_butt;
}
is_off = 0;
//Serial.println("IS HOLD");
//счетчик секунд для ++ в_периода
if (millis() - w_period1 >= 1000) {
w_period1 = millis();
w_period += 1;
//Serial.println(w_period);
vblock = 0; //******************ПЕРЕКЛЮЧЕНИЕ ВБЛОКА В НАГРЕВ
}
}
if (!eb.holding()) { //если кн энкодера НЕ зажата
//encHoldFlag = !encHoldFlag;
is_off = 1; //возвращаем флаг обнуления в_период
if (vBlockFlag) { //********************чтобы однократно вызвать греть
vblock = 1;
vBlockFlag = 0;
}
}
//**************************
//**************************ЛОГИКА
switch (run_butt) { //еще не нажимали ран
case 0:
{
//обнуляем все внутренние таймеры
tmr_p = 0;
tmr_w = 0;
uint8_t w1 = 0; //однократно вызываем функцию блока сосать
if (!eb.holding()) {
while (w1 < 1) {
vblock = 1;
w1++;
}
}
}
break;
case 1:
{
//************************************ВНУТРЕННИЕ ТАЙМЕРЫ, ЗАПУСКАЕМЫе ПО РУН
//запускаем таймер отсчета периода вклучения цикла подогрева с 0 по клику кнопки RUN
if (millis() - tmr_p1 >= 1000) {
tmr_p1 = millis();
tmr_p += 1;
//Serial.println(tmr_p);
//*******************************************************ЛОГИКА
if (tmr_p / 60 >= period) { // если таймер периода В МИН досчитывает до выставленного энкодером!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// запускаем таймер длительности цикла подогрева
if (millis() - tmr_w1 >= 1000) {
tmr_w1 = millis();
tmr_w += 1;
}
}
if (tmr_w + (expo) <= w_period && tmr_p / 60 >= period) { //****************************ГЛАВНОЕ УСЛОВИЕ + ВРЕМЯ ЭКСПОЗИЦИИ НЕ ЗАБЫТЬ *60!!!!!!!!!!!!!!!
if (!eb.holding()) {
while (w11 < 1) {
vblock = 0;
w11++;
}
//счетчик цикла подогрева < установленного таймера цикла подогрева И счетчик таймера больше выставленного таймера
//меняем флаг блока клапанов на подогрев!!!
}
}
if (tmr_w + (expo) >= w_period && tmr_p / 60 >= period) {
// если счетчик цикла подогрева досчитывает до w_period обнуляем счетчики и переключаем
//блок клапанов на отсос
tmr_p = 0;
tmr_w = 0;
if (!eb.holding()) vblock = 1; //**********БЛОК В ОТСОС
}
}
}
break;
}
if (vblock) vBlockSuck();
else vBlockHeat();
//*****************ВРЕМЯ
//время
static uint32_t time1;
if (millis() - time1 >= 1000) {
time1 = millis();
stime += 1;
}
//**************************ТАЙМЕР ОТРАБОТКИ ЭКРАНА
if (millis() - timing > 500) { // Вместо 10000 подставьте нужное вам значение паузы
timing = millis();
MainScreen();
cycleft = period - (tmr_p / 60); //*****************************CycleLEFT счетчик
}
}
void clearLCD() {
u8g2.firstPage();
do {
} while (u8g2.nextPage());
}
void MainScreen() {
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.setFontPosTop();
u8g2.firstPage();
u8g2.drawLine(60, 0, 60, 64);
u8g2.drawStr(5, 0, "Infusion");
u8g2.drawStr(40, 16, "Sec");
//u8g2.drawStr(9, 10, "time (s)");
u8g2.drawStr(0, 35, "Cycle time");
u8g2.drawStr(40, 50, "Min");
//u8g2.drawStr(9, 40, "time (s)");
u8g2.drawStr(62, 0, "System:");
u8g2.drawLine(61, 11, 128, 11);
u8g2.drawStr(65, 12, "Exposition");
u8g2.setFontPosTop();
u8g2.setCursor(74, 22);
u8g2.print(expo);
//u8g2.drawStr(74, 22, "99");
u8g2.drawStr(95, 22, "Min"); //EXP TIME
u8g2.drawLine(61, 31, 128, 31);
u8g2.drawStr(65, 32, "Cycle LEFT");
u8g2.setCursor(75, 42);
u8g2.print(cycleft);
u8g2.drawStr(95, 42, "Min"); //CYCLE TIMER
u8g2.drawLine(61, 51, 128, 51);
u8g2.drawStr(65, 52, "SysON");
u8g2.setCursor(100, 52);
u8g2.print(stime);
switch (run_butt) {
case 0:
u8g2.drawStr(105, 0, "WAIT"); //SYSTEM STATE
u8g2.setDrawColor(2); // XOR
u8g2.drawBox(103, 0, 25, 10);
break;
case 1:
u8g2.drawStr(105, 0, "RUN!"); //SYSTEM STATE
u8g2.setDrawColor(2); // XOR
u8g2.drawBox(103, 0, 25, 10);
break;
}
if (cclick) {
u8g2.setDrawColor(2); // XOR
u8g2.drawBox(72, 21, 10, 10);
}
u8g2.setFont(u8g2_font_fub17_tr);
u8g2.setFontPosTop();
u8g2.setCursor(10, 11);
u8g2.print(w_period);
u8g2.setCursor(10, 45);
u8g2.print(period);
//u8g2.drawStr(20, 12, vac_val);
//u8g2.drawStr(20, 42, vac_set);
//u8g2.drawStr(50, 41, "*RUN*");
//u8g2.setDrawColor(2); // XOR
//u8g2.drawBox(48, 36, 33, 20);
u8g2.nextPage();
}
//************************************************НЕ ЗАБУДЬ, НА ЭКСПОЗИЦИЮ НУЖНО ОТКЛЮЧИТЬ НАСОС!!!!!!!!!
void vBlockHeat() {
servo1.setTargetDeg(5);
digitalWrite(PWMPin, HIGH);
static uint32_t tmrh;
if (millis() - tmrh >= 500) {
tmrh = millis();
//led_blink = !led_blink;
Serial.println("HEAT");
}
//if (led_blink) analogWrite(PWMPin, 0);
//else analogWrite(PWMPin, 50);
}
void vBlockSuck() {
servo1.setTargetDeg(45);
digitalWrite(PWMPin, LOW);
//analogWrite(PWMPin, 50);
static uint32_t tmrs;
if (millis() - tmrs >= 500) {
tmrs = millis();
Serial.println("SUCK");
}
}
Изменено: