Решил по играть с пользовательским блоком "энкодер" и с EEPROM stm32. Раз девятая версия позволяет такие радости, почему бы и не попробовать?
По быстрому наколхозил картинку, типо менюшки с тремя переменными памяти, для предзагруки настроек энкодера. Проверка результата показала, что память грузит правильно, а два других микса по очерёдности уехали в конец коридора, из-за чего настройки первого меню убежали на второе, второго на третье и так по кругу.
Лёгким движением Ctrl+C, Ctrl+V, в тексте ардуины, поменял очерёдность и всё заработало как и задумывалось.
Прикреплённый первый файл с этой ошибкой.
Текст под спойлером, с выделенными фрагментами, это то что я поменял местами очерёдность из проекта.
.
Энкодер_EEPROM.jpg
.
Энкодер_EEPROM.flp
[spoiler]
Код: Выделить всё
#include "flprogUtilites.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "STM32encoder.h"
#include "flprogInternalEEPROM.h"
FLProgInternalEEPROM InternalEEPROM_41185707(7, 247);
LiquidCrystal_I2C _lcd1(0x27, 16, 2);
int _dispTempLength1=0;
boolean _isNeedClearDisp1;
bool en_enc;
int16_t Set;
uint8_t Set_dir;
int16_t Set_min;
int16_t Set_max;
bool en_Set;
int16_t pos_enc;
int16_t my_var;
bool Short_press;
bool Long_press;
STM32encoder enc(TIM2);
int16_t myVar= 0;
int16_t _gtv2;
int16_t _gtv3;
bool _gtv4;
int16_t _gtv6;
bool _gtv7;
int16_t _gtv8;
int16_t _gtv9;
bool _gtv10;
bool _gtv11;
bool _gtv13;
bool _dms1Q0 = 0;
bool _dms1Q1 = 0;
bool _dms1Q2 = 0;
int16_t _disp5oldLength = 0;
int16_t _disp1oldLength = 0;
bool _dms2Q0 = 0;
bool _dms2Q1 = 0;
bool _dms2Q2 = 0;
int16_t _disp4oldLength = 0;
int16_t _mux3;
int16_t _mux1;
int16_t _disp2oldLength = 0;
int16_t _mux2;
int16_t _disp3oldLength = 0;
bool _count1I = 0;
int16_t _count1_Value = 0;
void setup()
{
Wire.begin();
delay(10);
InternalEEPROM_41185707.setIntegerStartValue(1, 0);
InternalEEPROM_41185707.setIntegerStartValue(3, 2);
InternalEEPROM_41185707.setIntegerStartValue(5, 23);
InternalEEPROM_41185707.setSkippingEvents(0);
InternalEEPROM_41185707.begin();
_lcd1.init();
_lcd1.backlight();
enc.bind(&myVar, 1, 0, 100);
enc.setButton(PA2);
}
void loop()
{
InternalEEPROM_41185707.pool();
if (_isNeedClearDisp1)
{
_lcd1.clear();
_isNeedClearDisp1= 0;
}
//Плата:1
if (!(0))
{
_dispTempLength1 = ((((String("M ")) + ((String(_gtv6, DEC)))))).length();
if (_disp1oldLength > _dispTempLength1)
{
_isNeedClearDisp1 = 1;
}
_disp1oldLength = _dispTempLength1;
_lcd1.setCursor(0, 0);
_lcd1.print((((String("M ")) + ((String(_gtv6, DEC))))));
}
else
{
if (_disp1oldLength > 0)
{
_isNeedClearDisp1 = 1;
_disp1oldLength = 0;
}
}
if((_gtv6) == 0)
{
_mux1 = ((InternalEEPROM_41185707.readInteger(1)));
}
if((_gtv6) == 1)
{
_mux1 = ((InternalEEPROM_41185707.readInteger(3)));
}
if((_gtv6) == 2)
{
_mux1 = ((InternalEEPROM_41185707.readInteger(5)));
}
_gtv9 = _mux1;
// =================================================================
if((_gtv6) == 0)
{
_mux2 = 0;
}
if((_gtv6) == 1)
{
_mux2 = -10;
}
if((_gtv6) == 2)
{
_mux2 = 5;
}
_gtv3 = _mux2;
//===================================================================
if((_gtv6) == 0)
{
_mux3 = 100;
}
if((_gtv6) == 1)
{
_mux3 = 10;
}
if((_gtv6) == 2)
{
_mux3 = 50;
}
_gtv2 = _mux3;
// =================================================================
en_enc = !(0);
Set = _gtv9;
Set_dir = 1;
Set_min = _gtv3;
Set_max = _gtv2;
en_Set = _gtv7;
if(en_enc)
{
Short_press = 0;
Long_press = 0;
switch(enc.button())
{
case BTN_EVT_CLICK:
Short_press = 1;
break;
case BTN_EVT_LONG:
Long_press = 1;
break;
}
if (en_Set)
{
myVar = Set;
my_var = myVar;
enc.bind(&myVar, Set_dir, Set_min, Set_max);
}
if (enc.isUpdated())
{
pos_enc = enc.pos();
my_var = myVar;
}
}
_gtv4 = Long_press;
_gtv7 = Short_press;
_gtv8 = my_var;
if (!(0))
{
_dispTempLength1 = ((((String("S ")) + ((String(_gtv8, DEC)))))).length();
if (_disp2oldLength > _dispTempLength1)
{
_isNeedClearDisp1 = 1;
}
_disp2oldLength = _dispTempLength1;
_lcd1.setCursor(7, 0);
_lcd1.print((((String("S ")) + ((String(_gtv8, DEC))))));
}
else
{
if (_disp2oldLength > 0)
{
_isNeedClearDisp1 = 1;
_disp2oldLength = 0;
}
}
//=======================================================================================
// if((_gtv6) == 0)
// {
// _mux2 = 0;
// }
// if((_gtv6) == 1)
// {
// _mux2 = -10;
// }
// if((_gtv6) == 2)
// {
// _mux2 = 5;
// }
// _gtv3 = _mux2;
//=======================================================================================
if (_gtv10)
{
InternalEEPROM_41185707.saveInteger(1, ((_gtv8)));
}
if (_gtv11)
{
InternalEEPROM_41185707.saveInteger(3, ((_gtv8)));
}
if (_gtv13)
{
InternalEEPROM_41185707.saveInteger(5, ((_gtv8)));
}
//=======================================================================================
if((_gtv6 == 0))
{
_dms2Q0 = 1;
}
else
{
_dms2Q0 = 0;
}
if((_gtv6 == 1))
{
_dms2Q1 = 1;
}
else
{
_dms2Q1 = 0;
}
if((_gtv6 == 2))
{
_dms2Q2 = 1;
}
else
{
_dms2Q2 = 0;
}
if (_dms2Q2)
{
_dispTempLength1 = ((((String("E2 ")) + ((String(((InternalEEPROM_41185707.readInteger(5))), DEC)))))).length();
if (_disp5oldLength > _dispTempLength1)
{
_isNeedClearDisp1 = 1;
}
_disp5oldLength = _dispTempLength1;
_lcd1.setCursor(0, 1);
_lcd1.print((((String("E2 ")) + ((String(((InternalEEPROM_41185707.readInteger(5))), DEC))))));
}
else
{
if (_disp5oldLength > 0)
{
_isNeedClearDisp1 = 1;
_disp5oldLength = 0;
}
}
if (_dms2Q1)
{
_dispTempLength1 = ((((String("E1 ")) + ((String(((InternalEEPROM_41185707.readInteger(3))), DEC)))))).length();
if (_disp4oldLength > _dispTempLength1)
{
_isNeedClearDisp1 = 1;
}
_disp4oldLength = _dispTempLength1;
_lcd1.setCursor(0, 1);
_lcd1.print((((String("E1 ")) + ((String(((InternalEEPROM_41185707.readInteger(3))), DEC))))));
}
else
{
if (_disp4oldLength > 0)
{
_isNeedClearDisp1 = 1;
_disp4oldLength = 0;
}
}
if (_dms2Q0)
{
_dispTempLength1 = ((((String("E0 ")) + ((String(((InternalEEPROM_41185707.readInteger(1))), DEC)))))).length();
if (_disp3oldLength > _dispTempLength1)
{
_isNeedClearDisp1 = 1;
}
_disp3oldLength = _dispTempLength1;
_lcd1.setCursor(0, 1);
_lcd1.print((((String("E0 ")) + ((String(((InternalEEPROM_41185707.readInteger(1))), DEC))))));
}
else
{
if (_disp3oldLength > 0)
{
_isNeedClearDisp1 = 1;
_disp3oldLength = 0;
}
}
//=============================================================
// if (_gtv13)
// {
// InternalEEPROM_41185707.saveInteger(5, ((_gtv8)));
// }
//===================================================================
// if((_gtv6) == 0)
// {
// _mux3 = 100;
// }
// if((_gtv6) == 1)
// {
// _mux3 = 10;
// }
// if((_gtv6) == 2)
// {
// _mux3 = 50;
// }
// _gtv2 = _mux3;
//======================================================================
if((_gtv6 == 0))
{
_dms1Q0 = _gtv4;
}
else
{
_dms1Q0 = 0;
}
if((_gtv6 == 1))
{
_dms1Q1 = _gtv4;
}
else
{
_dms1Q1 = 0;
}
if((_gtv6 == 2))
{
_dms1Q2 = _gtv4;
}
else
{
_dms1Q2 = 0;
}
_gtv13 = _dms1Q2;
_gtv11 = _dms1Q1;
_gtv10 = _dms1Q0;
if (_gtv7)
{
if (! _count1I)
{
_count1I = 1;
_count1_Value = _count1_Value + 1;
}
}
else
{
_count1I = 0;
}
if(_count1_Value >= 3)
{
_count1_Value = 0;
}
_gtv6 = _count1_Value;
}
[/spoiler]
.
Далее я решил, в проекте с ошибкой, перед выводом
en_Set поставить кастыль в виде стандартного блока
FTrig, удивительно, но опять же всё заработало как и должно было.
.
.
Энкодер_EEPROM_2.jpg
.
.
IMG_20240504_024722.jpg
.
Энкодер_EEPROM_2.flp
.
Короткое описание тестового проекта:
При старте, в энкодере настройки по умолчанию, когда собирается проект. Шаг 1, мин 0, мах 100, позиция 0.
При коротком нажатии кнопки энкодера переходим в первое меню, с настройками мин -10, мах 10, позиция настроена в памяти EEPROM Set_E1, если правильно помню, то вроде 5 записывал.
Следующее короткое нажатие переход во второе меню, мин 5, мах 50, значение установки позиции Set_E2.
Третье нажатие возвращает в нулевое меню, а т.к. настройки начальные стёрли, то прописываются с помощью блоков Мих заново. Блок Set_E0 не обязателен, ставил просто для проверки, можно "0" прописать или использовать как третье меню, но уже без стартового.
Запись в память производится длинным нажатием кнопки энкодера.
Значения взяты произвольные, для примера, к реальным устройствам отношения не имеет.
====================================================================================
.
Прикреплю исходный энкодер, вместе с ссылкой на автора блока.
.
Энкодер_0.jpg
.
viewtopic.php?f=74&t=8461#p129506
.
Энкодер STM32.flp
.
Решил немного расширить возможности.
Вполне себе полезная в хозяйстве деталька получилась. Добавил предварительную загрузку значений.
На выходе есть выводы "+" и "-", как дополнительная опция. Если крутить умеренно, работает нормально, при быстром вращении есть пропуски импульсов "+" и "-", относительно значений счётчика таймера. А может и счётчики в проекте не успевают зафиксировать быстрое вращение, глубоко не копал. В момент запуска МК, есть один ложный импульс вверх. Импульсы "+" и "-" не зависят от значения установок, при
en_enc = 1, работают постоянно вместе с физическим энкодером.
.
Энкодер_plus_minus_3.jpg
.
На картинке 50 щелчков было вверх, 30 вниз, на счётчике остаток 20. Всё сходится.
.
IMG_20240509_235312.jpg
.
Энкодер_P_M_2.flp
[spoiler]
Код: Выделить всё
#include "flprogUtilites.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "STM32encoder.h"
LiquidCrystal_I2C _lcd1(0x27, 16, 2);
int _dispTempLength1=0;
boolean _isNeedClearDisp1;
bool en_enc;
int16_t Set;
uint8_t Set_dir;
int16_t Set_min;
int16_t Set_max;
bool en_Set;
int16_t pos_enc;
int16_t my_var;
bool Short_press;
bool Long_press;
bool Plus;
bool Minus;
STM32encoder enc(TIM2);
int16_t myVar= 0;
bool reg_dir= 0;
bool reg_Plus= 0;
bool reg_Minus= 0;
bool _gtv1;
int16_t _disp3oldLength = 0;
int16_t _disp2oldLength = 0;
int16_t _disp1oldLength = 0;
bool _count2I = 0;
int16_t _count2_Value = 0;
bool _count1I = 0;
int16_t _count1_Value = 0;
void setup()
{
Wire.begin();
delay(10);
_lcd1.init();
_lcd1.backlight();
enc.bind(&myVar, 1, 0, 100);
enc.setButton(PA2);
}
void loop()
{
if (_isNeedClearDisp1)
{
_lcd1.clear();
_isNeedClearDisp1= 0;
}
//Плата:1
en_enc = (!(0));
Set = 12;
Set_dir = 1;
Set_min = 0;
Set_max = 100;
en_Set = _gtv1;
if(en_enc)
{
Short_press = 0;
Long_press = 0;
switch(enc.button())
{
case BTN_EVT_CLICK:
Short_press = 1;
break;
case BTN_EVT_LONG:
Long_press = 1;
break;
}
if (en_Set)
{
myVar = Set;
my_var = myVar;
enc.bind(&myVar, Set_dir, Set_min, Set_max);
}
reg_Plus = 0;
reg_Minus = 0;
if (enc.isUpdated())
{
pos_enc = enc.pos();
my_var = myVar;
reg_dir = enc.dir();
if (!(en_Set))
{
if (reg_dir)
{
reg_Plus = 1;
}
if (!(reg_dir))
{
reg_Minus = 1;
}
}
}
Plus = reg_Plus;
Minus = reg_Minus;
}
if (Minus)
{
if (! _count2I)
{
_count2I = 1;
_count2_Value = _count2_Value + 1;
}
}
else
{
_count2I = 0;
}
if (!(0))
{
_dispTempLength1 = (((String(_count2_Value, DEC)))).length();
if (_disp3oldLength > _dispTempLength1)
{
_isNeedClearDisp1 = 1;
}
_disp3oldLength = _dispTempLength1;
_lcd1.setCursor(4, 1);
_lcd1.print(((String(_count2_Value, DEC))));
}
else
{
if (_disp3oldLength > 0)
{
_isNeedClearDisp1 = 1;
_disp3oldLength = 0;
}
}
if (Plus)
{
if (! _count1I)
{
_count1I = 1;
_count1_Value = _count1_Value + 1;
}
}
else
{
_count1I = 0;
}
if (!(0))
{
_dispTempLength1 = (((String(_count1_Value, DEC)))).length();
if (_disp2oldLength > _dispTempLength1)
{
_isNeedClearDisp1 = 1;
}
_disp2oldLength = _dispTempLength1;
_lcd1.setCursor(4, 0);
_lcd1.print(((String(_count1_Value, DEC))));
}
else
{
if (_disp2oldLength > 0)
{
_isNeedClearDisp1 = 1;
_disp2oldLength = 0;
}
}
_gtv1 = Short_press;
if (!(0))
{
_dispTempLength1 = (((String(my_var, DEC)))).length();
if (_disp1oldLength > _dispTempLength1)
{
_isNeedClearDisp1 = 1;
}
_disp1oldLength = _dispTempLength1;
_lcd1.setCursor(0, 0);
_lcd1.print(((String(my_var, DEC))));
}
else
{
if (_disp1oldLength > 0)
{
_isNeedClearDisp1 = 1;
_disp1oldLength = 0;
}
}
}
[/spoiler]
У вас нет необходимых прав для просмотра вложений в этом сообщении.