Предполагаю, что в некоторые моменты строка содержит более 20 символов.
Попробуйте поменять местами экраны. Поставте глючный экран первым в коде.
Доберусь до компа, покажу код… Он там до того простой. Выводятся литералы… именно на них глючит. А вот динамические данные норм. Но это ни о чем не говорит пока…
мысль понял. Могу для выявления этого момента сделать отдельную переменную, в которой хранить максимальный strlen(str) из функции LCDPrint()
и выводить ее куда-нибудь например на созданный для этого еще один экран. Наверное это и
и это тоже могу попробовать без проблем… Осталось только найти время, добраться до компа сделать ответвленную версию программы и дождаться глюка) Но я это обязательно попробую. Спасибо Вам за наводку
если это на ардуине, проще в Serial наверно.
На ардуине. Я имел ввиду экран отображения а не физический экран.
Про сериал говорил выше - это не удобно сделать на рабочем устройстве. Оставлять соединение по сериал на непонятно какое время… Все же проще на экран вывести.
Спойлер
#pragma once
uint16_t tmr1, PERIOD;
void UpdLCD() {
uint16_t ms = millis();
if ((uint16_t)(ms - tmr1) >= PERIOD) {
FlashParam = !FlashParam;
if (FlashParam && editParam) PERIOD = 200;
else PERIOD = 500;
UpdateScreenData();
tmr1 = ms;
}
}
char *CorrectLengthStr(char *_str, const uint8_t _ln) {
if (_ln) {
for (byte n = strlen(_str); n < _ln; n++) _str[n] = ' ';
_str[_ln] = 0;
}
return _str;
}
char *GetTimeStr(char *_str) {
sprintf(_str, "%02d%s%02d", GetHour(), (isFlash ? ":" : " "), GetMinute());
return _str;
}
char *GetLowBarStr(const uint8_t _np, char *_str) {
if (Pump[_np].isCritLowPress) strcpy(_str, "*");
else if (Pump[_np].isLowPress) (FlashParam ? strcpy(_str, "*") : strcpy(_str, " "));
else strcpy(_str, " ");
return _str;
}
char *WorkTimeToStr(const uint32_t i, char *_str) {
if (i == 0) return strcpy(_str, "-NoData-");
int d = (i / 3600ul) / 24ul;
int h = (i / 3600ul) % 24ul;
int m = (i % 3600ul) / 60ul;
int s = (i % 3600ul) % 60ul;
if (!d) sprintf(_str, "%d:%02d:%02ds", h, m, s);
else {
if (i > 63072000) sprintf(_str, ">2y.%0d:%02d:%02ds", h, m, s);
else sprintf(_str, "%d.%0d:%02d:%02ds", d, h, m, s);
}
return _str;
}
char *IntToStr(const long _N, char *_str, const uint8_t _ln = 0, const char *_fmt = "%d") {
sprintf(_str, _fmt, _N);
return CorrectLengthStr(_str, _ln);
}
char *GetBarFromRawStr(const uint16_t _raw, char *_str, const uint8_t _ln = 0, const char *_pfx = "") {
if (!_raw) strcpy(_str, "Err");
else {
uint8_t bar = RawToBar10(_raw);
sprintf(_str, "%d.%d%s", bar / 10, bar % 10, _pfx);
}
CorrectLengthStr(_str, _ln);
return _str;
}
char *GetBarStr(const uint8_t _bar, char *_str, const uint8_t _ln = 0, const char *_pfx = "") {
sprintf(_str, "%d.%d%s", _bar / 10, _bar % 10, _pfx);
return CorrectLengthStr(_str, _ln);
}
char *GetCurrentStr(const uint16_t _curr, char *_str, const uint8_t _ln = 0, const char *_pfx = "") {
sprintf(_str, "%d.%03d", _curr / 1000, _curr % 1000);
CorrectLengthStr(_str, _ln - strlen(_pfx));
return strcat(_str, _pfx);
}
char *GetTempStr(const int _temp, char *_str, const uint8_t _ln = 0, const char *_pfx = "") {
if (_temp > 9000) strcpy(_str, "Err");
else sprintf(_str, "%2d.%d%s", _temp / 10, _temp % 10, _pfx);
return CorrectLengthStr(_str, _ln);
}
char *BoolToStr(const bool _f, char *_str, const uint8_t _ln = 0) {
if (_f) return CorrectLengthStr(strcpy(_str, "On"), _ln);
else return CorrectLengthStr(strcpy(_str, "Off"), _ln);
}
void LCDPrint(const byte x, const byte y, const char *_str) {
test = max(test, strlen(_str)); //временно для проверки максимальной длинны строки
lcd.setCursor(x, y);
lcd.print(_str);
}
void UpdateScreen() {
switch (modeScreen) {
case ViewMode:
switch (ViewScreenIndex) {
case vScr0:
lcd.clear();
Pump[0].Enable ? LCDPrint(8, 0, "Pump1") : LCDPrint(8, 0, "-Dis-");
Pump[1].Enable ? LCDPrint(14, 0, "Pump2") : LCDPrint(14, 0, "-Dis-");
LCDPrint(0, 1, "Pres(B):");
LCDPrint(0, 2, "Curr(A):");
LCDPrint(0, 3, "Counter:");
break;
case vScr1:
lcd.clear();
Pump[0].Enable ? LCDPrint(0, 0, "P1:") : LCDPrint(0, 0, "--:");
Pump[1].Enable ? LCDPrint(0, 1, "P2:") : LCDPrint(0, 1, "--:");
LCDPrint(0, 2, "Ht:");
break;
case vScr2:
lcd.clear();
if (SubScreen == 0)
LCDPrint(3, 0, "TIMES WORK DAY");
else LCDPrint(0, 0, "TIMES WORK ALL ( )");
LCDPrint(0, 1, "Pump1:");
LCDPrint(0, 2, "Pump2:");
LCDPrint(0, 3, "Heatr:");
break;
case vScr3:
lcd.clear();
if (SubScreen == 0) {
LCDPrint(2, 0, "CODE ERROR PUMP");
LCDPrint(0, 1, "PUMP1:");
LCDPrint(0, 2, "PUMP2:");
} else {
LCDPrint(5, 0, "ERROR COUNT");
LCDPrint(0, 1, "P1:");
LCDPrint(10, 1, "P2:");
LCDPrint(0, 2, "C1:");
LCDPrint(10, 2, "C2:");
LCDPrint(0, 3, "Ts:");
LCDPrint(10, 3, "CT:");
}
break;
case vScr4:
lcd.clear();
switch (SubScreen) {
case 0:
lcd.print("Tm:");
LCDPrint(10, 0, "Vcc:");
Pump[0].Enable ? LCDPrint(6, 1, "Pump1") : LCDPrint(6, 1, "-Dis-");
Pump[1].Enable ? LCDPrint(13, 1, "Pump2") : LCDPrint(13, 1, "-Dis-");
LCDPrint(1, 2, "Raw:");
LCDPrint(0, 3, "Curr:");
break;
case 1:
LCDPrint(0, 0, "Cur");
LCDPrint(4, 0, "RL1");
LCDPrint(10, 0, "RL2");
LCDPrint(16, 0, "RL3");
LCDPrint(0, 1, "S:");
LCDPrint(0, 2, "C:");
LCDPrint(0, 3, "E:");
}
break;
case vScr5: //Этот экран добавлен для выводы максимальной длинны строки в LCDPrint'e
lcd.clear();
lcd.print(test);
break;
}
break;
case SysMode:
switch (SysScreenIndex) {
case sScr0:
lcd.clear();
LCDPrint(0, 0, "SETTINGS");
LCDPrint(8, 1, "P1");
LCDPrint(15, 1, "P2");
LCDPrint(1, 2, "ON:");
LCDPrint(0, 3, "OFF:");
break;
case sScr1:
lcd.clear();
LCDPrint(0, 0, "SETLOWBAR P1 P2");
LCDPrint(1, 1, "LOW BAR:");
LCDPrint(0, 2, "CRIT BAR:");
LCDPrint(0, 3, "TRY TIME:");
break;
case sScr2:
lcd.clear();
LCDPrint(3, 0, "SETTINGS HEAT");
LCDPrint(2, 1, "ENABLE:");
LCDPrint(1, 2, "TEMP ON:");
LCDPrint(0, 3, "TEMP OFF:");
break;
case sScr3:
lcd.clear();
LCDPrint(4, 0, "START SYSTEM");
LCDPrint(1, 1, "PUMP1:");
LCDPrint(1, 2, "PUMP2:");
break;
}
}
}
void UpdScrDt0(char *str) {
LCDPrint(1, 0, GetTimeStr(str));
LCDPrint(8, 1, GetLowBarStr(0, str));
LCDPrint(9, 1, GetBarFromRawStr(Pump[0].Sens.Raw, str, 4));
LCDPrint(14, 1, GetLowBarStr(1, str));
LCDPrint(15, 1, GetBarFromRawStr(Pump[1].Sens.Raw, str, 4));
if (Pump[0].Error.Code) LCDPrint(9, 2, CorrectLengthStr(strcpy(str, "Err"), 5));
else LCDPrint(9, 2, Pump[0].Relay.State ? GetCurrentStr(Pump[0].Relay.Curr, str, 5, "A") : CorrectLengthStr(strcpy(str, "Off"), 5));
if (Pump[1].Error.Code) LCDPrint(15, 2, CorrectLengthStr(strcpy(str, "Err"), 5));
else LCDPrint(15, 2, Pump[1].Relay.State ? GetCurrentStr(Pump[1].Relay.Curr, str, 5, "A") : CorrectLengthStr(strcpy(str, "Off"), 5));
LCDPrint(9, 3, IntToStr(Pump[0].Relay.Cnt, str, 4));
LCDPrint(15, 3, IntToStr(Pump[1].Relay.Cnt, str, 4));
switch (editParam) {
case 0:
LCDPrint(8, 2, " ");
LCDPrint(14, 2, " ");
break;
case 1:
LCDPrint(8, 2, ">");
LCDPrint(14, 2, " ");
break;
case 2:
LCDPrint(8, 2, " ");
LCDPrint(14, 2, ">");
break;
}
}
void UpdScrDt1(char *str) {
LCDPrint(3, 0, GetLowBarStr(0, str));
LCDPrint(4, 0, GetBarFromRawStr(Pump[0].Sens.Raw, str, 4));
LCDPrint(3, 1, GetLowBarStr(1, str));
LCDPrint(4, 1, GetBarFromRawStr(Pump[1].Sens.Raw, str, 4));
if (Pump[0].Error.Code) LCDPrint(10, 0, CorrectLengthStr(strcpy(str, "Err"), 5));
else LCDPrint(10, 0, Pump[0].Relay.State ? GetCurrentStr(Pump[0].Relay.Curr, str, 5, "A") : CorrectLengthStr(strcpy(str, "Off"), 5));
if (Pump[1].Error.Code) LCDPrint(10, 1, CorrectLengthStr(strcpy(str, "Err"), 5));
else LCDPrint(10, 1, Pump[1].Relay.State ? GetCurrentStr(Pump[1].Relay.Curr, str, 5, "A") : CorrectLengthStr(strcpy(str, "Off"), 5));
LCDPrint(16, 0, IntToStr(Pump[0].Relay.Cnt, str, 4, "%4d"));
LCDPrint(16, 1, IntToStr(Pump[1].Relay.Cnt, str, 4, "%4d"));
LCDPrint(3, 2, GetTempStr(Heat.T, str, 6, "\1C"));
LCDPrint(10, 2, Heat.Enable ? (Heat.Relay.State ? GetCurrentStr(Heat.Relay.Curr, str, 5, "A") : CorrectLengthStr(strcpy(str, "Off"), 5)) : "Dis");
LCDPrint(16, 2, IntToStr(Heat.Relay.Cnt, str, 4, "%4d"));
LCDPrint(1, 3, GetTempStr(Heat.t1, str, 4));
LCDPrint(6, 3, GetTempStr(Heat.t2, str, 4));
LCDPrint(11, 3, GetTempStr(Heat.t3, str, 4));
LCDPrint(16, 3, GetTempStr(Heat.t4, str, 4));
switch (editParam) {
case 0:
LCDPrint(9, 0, " ");
LCDPrint(9, 1, " ");
break;
case 1:
LCDPrint(9, 0, ">");
LCDPrint(9, 1, " ");
break;
case 2:
LCDPrint(9, 0, " ");
LCDPrint(9, 1, ">");
break;
}
}
void UpdScrDt2(char *str) {
if (SubScreen == 0) {
LCDPrint(7, 1, WorkTimeToStr(Pump[0].Relay.workTimes + Pump[0].Relay.workTime, str));
LCDPrint(7, 2, WorkTimeToStr(Pump[1].Relay.workTimes + Pump[1].Relay.workTime, str));
LCDPrint(7, 3, WorkTimeToStr(Heat.Relay.workTimes + Heat.Relay.workTime, str));
} else {
LCDPrint(16, 0, IntToStr(ResetDayCount, str, 3, "%3d"));
LCDPrint(7, 1, WorkTimeToStr(Pump[0].Relay.workTimesAll + Pump[0].Relay.workTimes + Pump[0].Relay.workTime, str));
LCDPrint(7, 2, WorkTimeToStr(Pump[1].Relay.workTimesAll + Pump[1].Relay.workTimes + Pump[1].Relay.workTime, str));
LCDPrint(7, 3, WorkTimeToStr(Heat.Relay.workTimesAll + Heat.Relay.workTimes + Heat.Relay.workTime, str));
}
}
void UpdScrDt3(char *str) {
if (SubScreen == 0) {
LCDPrint(7, 1, IntToStr(Pump[0].Error.Code, str, 4));
LCDPrint(9, 1, CorrectLengthStr(strcpy(str, codeErrStr[Pump[0].Error.Code]), 11));
LCDPrint(7, 2, IntToStr(Pump[1].Error.Code, str, 4));
LCDPrint(9, 2, CorrectLengthStr(strcpy(str, codeErrStr[Pump[1].Error.Code]), 11));
if (Pump[0].Error.Code > 0 || Pump[1].Error.Code > 0)
LCDPrint(0, 3, "Press Long But Reset");
else LCDPrint(0, 3, CorrectLengthStr(strcpy(str, " "), 20));
} else {
Pump[0].Sens.Err ? LCDPrint(3, 1, "*") : LCDPrint(3, 1, " ");
LCDPrint(4, 1, IntToStr(Pump[0].Sens.ErrCnt, str, 4));
Pump[1].Sens.Err ? LCDPrint(13, 1, "*") : LCDPrint(13, 1, " ");
LCDPrint(14, 1, IntToStr(Pump[1].Sens.ErrCnt, str, 4));
Pump[0].Relay.Err ? LCDPrint(3, 2, "*") : LCDPrint(3, 2, " ");
LCDPrint(4, 2, IntToStr(Pump[0].Relay.ErrCnt, str, 4));
Pump[1].Relay.Err ? LCDPrint(13, 2, "*") : LCDPrint(13, 2, " ");
LCDPrint(14, 2, IntToStr(Pump[1].Relay.ErrCnt, str, 4));
Heat.Err ? LCDPrint(3, 3, "*") : LCDPrint(3, 3, " ");
LCDPrint(4, 3, IntToStr(Heat.ErrCnt, str, 4));
Heat.Relay.Err ? LCDPrint(13, 3, "*") : LCDPrint(13, 3, " ");
LCDPrint(14, 3, IntToStr(Heat.Relay.ErrCnt, str, 4));
}
}
void UpdScrDt4(char *str) {
switch (SubScreen) {
case 0:
LCDPrint(4, 0, GetTimeStr(str));
lcd.setCursor(15, 0);
lcd.print(analogRead_VCC());
lcd.print("v");
LCDPrint(7, 2, IntToStr(Pump[0].Sens.Raw, str, 3));
LCDPrint(14, 2, IntToStr(Pump[1].Sens.Raw, str, 3));
LCDPrint(6, 3, GetCurrentStr(Pump[0].Relay.Curr, str, 5));
LCDPrint(13, 3, GetCurrentStr(Pump[1].Relay.Curr, str, 5));
break;
case 1:
LCDPrint(3, 1, GetCurrentStr(Pump[0].Relay.StartCurr, str, 5));
LCDPrint(9, 1, GetCurrentStr(Pump[1].Relay.StartCurr, str, 5));
LCDPrint(15, 1, GetCurrentStr(Heat.Relay.StartCurr, str, 5));
LCDPrint(3, 2, GetCurrentStr(Pump[0].Relay.Curr, str, 5));
LCDPrint(9, 2, GetCurrentStr(Pump[1].Relay.Curr, str, 5));
LCDPrint(15, 2, GetCurrentStr(Heat.Relay.Curr, str, 5));
LCDPrint(3, 3, Pump[0].Relay.ErrCnt ? GetCurrentStr(Pump[0].Relay.ErrorCurr, str, 5) : CorrectLengthStr(strcpy(str, "noErr"), 5));
LCDPrint(9, 3, Pump[1].Relay.ErrCnt ? GetCurrentStr(Pump[1].Relay.ErrorCurr, str, 5) : CorrectLengthStr(strcpy(str, "noErr"), 5));
LCDPrint(15, 3, Heat.Relay.ErrCnt ? GetCurrentStr(Heat.Relay.ErrorCurr, str, 5) : CorrectLengthStr(strcpy(str, "noErr"), 5));
break;
}
}
void UpdateScreenData() {
switch (modeScreen) {
char str[20];
case ViewMode:
switch (ViewScreenIndex) {
case vScr0:
UpdScrDt0(str);
break;
case vScr1:
UpdScrDt1(str);
break;
case vScr2:
UpdScrDt2(str);
break;
case vScr3:
UpdScrDt3(str);
break;
case vScr4:
UpdScrDt4(str);
break;
}
break;
case SysMode:
switch (SysScreenIndex) {
case sScr0:
LCDPrint(7, 2, editParam == 1 && FlashParam ? " " : editParam > 0 ? GetBarStr(Pump[0].PBarOnEd, str, 3)
: GetBarFromRawStr(Pump[0].PRawOn, str, 3));
LCDPrint(7, 3, editParam == 2 && FlashParam ? " " : editParam > 0 ? GetBarStr(Pump[0].PBarOffEd, str, 3)
: GetBarFromRawStr(Pump[0].PRawOff, str, 3));
LCDPrint(15, 2, editParam == 3 && FlashParam ? " " : editParam > 0 ? GetBarStr(Pump[1].PBarOnEd, str, 3)
: GetBarFromRawStr(Pump[1].PRawOn, str, 3));
LCDPrint(15, 3, editParam == 4 && FlashParam ? " " : editParam > 0 ? GetBarStr(Pump[1].PBarOffEd, str, 3)
: GetBarFromRawStr(Pump[1].PRawOff, str, 3));
LCDPrint(17, 0, editParam == 5 && FlashParam ? " " : editParam > 0 ? IntToStr(SecCorMsEd, str, 3, "%+2d")
: IntToStr(SecondCorMs, str, 3, "%+2d"));
lcd.setCursor(10, 0);
if (editParam < 6) {
LCDPrint(10, 0, GetTimeStr(str));
} else {
if (editParam == 6) {
if (FlashParam) lcd.print(" ");
else {
sprintf(str, "%02d", HourEd);
lcd.print(str);
}
sprintf(str, ":%02d", MinuteEd);
lcd.print(str);
}
if (editParam == 7) {
sprintf(str, "%02d:", HourEd);
lcd.print(str);
if (FlashParam) lcd.print(" ");
else {
sprintf(str, "%02d", MinuteEd);
lcd.print(str);
}
}
}
break;
case sScr1:
LCDPrint(11, 1, editParam == 1 && FlashParam ? " " : editParam > 0 ? GetBarStr(Pump[0].PLowBarEd, str, 3)
: GetBarFromRawStr(Pump[0].PLowRaw, str, 3));
LCDPrint(11, 2, editParam == 2 && FlashParam ? " " : editParam > 0 ? GetBarStr(Pump[0].PCritLowBarEd, str, 3)
: GetBarFromRawStr(Pump[0].PCritLowRaw, str, 3));
LCDPrint(11, 3, editParam == 3 && FlashParam ? " " : editParam > 0 ? IntToStr(Pump[0].TryTimeEd, str, 3)
: IntToStr(Pump[0].TryTime, str, 3));
LCDPrint(16, 1, editParam == 4 && FlashParam ? " " : editParam > 0 ? GetBarStr(Pump[1].PLowBarEd, str, 3)
: GetBarFromRawStr(Pump[1].PLowRaw, str, 3));
LCDPrint(16, 2, editParam == 5 && FlashParam ? " " : editParam > 0 ? GetBarStr(Pump[1].PCritLowBarEd, str, 3)
: GetBarFromRawStr(Pump[1].PCritLowRaw, str, 3));
LCDPrint(16, 3, editParam == 6 && FlashParam ? " " : editParam > 0 ? IntToStr(Pump[1].TryTimeEd, str, 3)
: IntToStr(Pump[1].TryTime, str, 3));
break;
case sScr2:
LCDPrint(11, 1, editParam == 1 && FlashParam ? " " : editParam > 0 ? BoolToStr(Heat.EnableEd, str, 3)
: BoolToStr(Heat.Enable, str, 3));
if (!editParam) LCDPrint(10, 2, !Heat.Enable ? " " : GetTempStr(Heat.TOn, str, 6, "\1C"));
else LCDPrint(10, 2, (editParam == 2 && FlashParam) ? " " : !Heat.EnableEd ? " --- "
: GetTempStr(Heat.TOnEd, str, 6, "\1C"));
if (!editParam) LCDPrint(10, 3, !Heat.Enable ? " " : GetTempStr(Heat.TOff, str, 6, "\1C"));
else LCDPrint(10, 3, (editParam == 3 && FlashParam) ? " " : !Heat.EnableEd ? " --- "
: GetTempStr(Heat.TOffEd, str, 6, "\1C"));
break;
case sScr3:
if (!Pump[0].Error.Code || Pump[0].Error.Code == errCritLowPress) {
if (!Pump[0].Enable) LCDPrint(8, 1, CorrectLengthStr(strcpy(str, "Disable"), 12));
else if (Pump[0].isStartLowBar) {
LCDPrint(8, 1, CorrectLengthStr(strcpy(str, "Starting"), 12));
sprintf(str, "%2lds", Pump[0].TryTime - Pump[0].Relay.workTime);
LCDPrint(17, 1, str);
} else if (Pump[0].isCritLowPress) LCDPrint(8, 1, CorrectLengthStr(strcpy(str, "Start"), 12));
else if (Pump[0].isLowPress) LCDPrint(8, 1, CorrectLengthStr(strcpy(str, "Low"), 12));
else LCDPrint(8, 1, CorrectLengthStr(strcpy(str, "Ok"), 12));
} else LCDPrint(8, 1, CorrectLengthStr(strcpy(str, "(ERROR)"), 12));
if (!Pump[1].Error.Code || Pump[1].Error.Code == errCritLowPress) {
if (!Pump[1].Enable) LCDPrint(8, 2, CorrectLengthStr(strcpy(str, "Disable"), 12));
else if (Pump[1].isStartLowBar) {
LCDPrint(8, 2, CorrectLengthStr(strcpy(str, "Starting"), 12));
sprintf(str, "%2lds", Pump[1].TryTime - Pump[1].Relay.workTime);
LCDPrint(17, 2, str);
} else if (Pump[1].isCritLowPress) LCDPrint(8, 2, CorrectLengthStr(strcpy(str, "Start"), 12));
else if (Pump[1].isLowPress) LCDPrint(8, 2, CorrectLengthStr(strcpy(str, "Low"), 12));
else LCDPrint(8, 2, CorrectLengthStr(strcpy(str, "Ok"), 12));
} else LCDPrint(8, 2, CorrectLengthStr(strcpy(str, "(ERROR)"), 12));
if (editParam == 1) {
LCDPrint(0, 1, ">");
LCDPrint(0, 2, " ");
if (Pump[0].isCritLowPress || Pump[0].Error.Code) LCDPrint(1, 3, "Press Long Button");
} else if (editParam == 2) {
LCDPrint(0, 1, " ");
LCDPrint(0, 2, ">");
if (Pump[1].isCritLowPress || Pump[1].Error.Code) LCDPrint(1, 3, "Press Long Button");
} else {
LCDPrint(0, 1, " ");
LCDPrint(0, 2, " ");
LCDPrint(1, 3, " ");
}
break;
}
break;
}
}
Вот собс-но файл, где происходит практически весь вывод на экран. В том числе и этот глючный экран. Вывод, как я и говорил, происходит практически весь функцией LCDPrint которая находится в строках 96-90
В нее сейчас добавил запоминание в переменную максимальную длину строки. Вывод значения этой переменной в специально созданном дополнительном экране в строках 156-159
Пока там на этом экране показывает 20
Но это сейчас в прототипе на столе… Если успею, сегодня залью в устройство и “буду ждать этого глюка”. Потом посмотрю что там будет на этом экране.
Глюк происходит на строках 126-132. Тут выводится статичная часть экрана и именно с ней проблемы отображения. Динамичные данные этого экрана в строках 282-293
ЗЫЖ Залил в устройство, экраны местами тоже поменял. Теперь осталось дождаться этого глюка
А на рабочем устройстве это и не нужно делать. Нужно делать на макете.
Дык там целая система (датчики, реле…) на рабочем… на макетке я этого не смогу повторить. Да и макетка - это получается другой экран 2004. А если это в нем дело? Сомневаюсь я конечно, больше на свой код грешу. Вот сегодня проверил устройство - пока нет глюка (больше суток работает, последний раз глюк через две недели появился). Если в файле, который я приложил выше, опытным вашим взглядом нет грубых ошибок при работе с указателями, то буду смотреть еще раз остальной свой код, но он вроде как не связан с выводом на экран, но может такое быть, что где-то в коде у меня так портится память что вывод на экран литерала LCDPrint(5, 0, “ERROR COUNT”); - выводится только ERROR а COUNT куда-то теряется?
Проработало 3-е суток. Глюк не проявился, макс длинна строки 20.
За это время пересмотрел остальной код и нашел одно место где потенциально мог выйти за границы массива:
} else {
if (Pump[editParam - 1].Relay.State) {
PumpOff(editParam - 1);
editParam = 0;
UpdateScreenData();
} else PumpOn(editParam - 1);
}
где editParam по идеи в этом месте всегда либо 1 либо 2, а массив Pump состоит из двух элементов. Но обратил внимание, что в “особых” случаях все-таки в editParam мог быть - 0. Это нужно извернуться, но это возможно оказалось. Скорее всего это и есть причина глюка (но это не точно ) Вернул код в первоначальный вид, изменив данный участок на:
} else {
if (editParam) {
if (Pump[editParam - 1].Relay.State) {
PumpOff(editParam - 1);
editParam = 0;
UpdateScreenData();
} else PumpOn(editParam - 1);
}
}
В общем работает опять три дня уже, …без глюка. Буду надеяться, что косяк исправил. (Ведь и предыдущий код мог работать долгое время нормально)
0х27
Возможно именно так и есть, очень на это надеюсь)))
Значит без буквы А в конце.
ну вы блин даете, а я заказал по ссылке выше,пришел уже, ща принесут))
и че теперь?
Распаковывать датчик какой новый, или заказывать ))
Я не утверждал что дело в LCD2004, но все может быть… Еще пока не понятно, но скорее всего все таки в коде дело…
Пока работает без глюка. Уже больше 10 дней непрерывно…
Я тут решил оптимизировать(модернизировать) функцию LCDPrint
Потом переделаю под нее остальной код файла работы с экраном
Вот она (точнее скетч ее теста с ссылкой на вокви):
Скетч немного отличается от того, что по ссылке (там старый)
Спойлер
//https://wokwi.com/projects/394794352265771009
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
enum TAlign {alL, alC, alR};
void LCDPrint(const byte &x, const byte &y, const char * txt,
byte ln = 0, const TAlign &alg = alL, const char &ch = ' ') {
if (x > 19 || y > 3) return;
byte tln = strlen(txt);
if (!ln) ln = tln;
if (x + ln > 20) ln = 20 - x;
char str[ln + 1];
if (ln == tln) strcpy(str, txt);
else {
if (alg == alL) {
if (tln > ln) {
strncpy(str, txt, ln);
}
if (ln > tln) {
strcpy(str, txt);
for (byte n = tln; n < ln; n++) str[n] = ch;
}
}
if (alg == alC) {
if (tln > ln) {
strncpy(str, txt + (tln / 2 - ln / 2), ln);
}
if (ln > tln) {
for (byte n = 0; n < ln; n++) str[n] = ch;
strncpy(str + (ln / 2 - tln / 2), txt, tln);
}
}
if (alg == alR) {
if (tln > ln) {
strncpy(str, txt + tln - ln, ln);
}
if (ln > tln) {
for (byte n = 0; n < ln - tln; n++) str[n] = ch;
strcpy(str + ln - tln, txt);
}
}
}
lcd.setCursor(x, y);
str[ln] = 0;
lcd.print(str);
}
void setup() {
lcd.init();
lcd.backlight();
LCDPrint(7, 0, "12345678901234567890111");
LCDPrint(10, 1, "77", 7, alR, '0');
LCDPrint(3, 2, "HRtyX12345TestLongStringUp20", 6, alC);
LCDPrint(0, 3, "11", 20, alC, '=');
}
void loop() {
}
Вопрос, на сколько я ее сделал не/оптимально? Важна скорость ее работы.
Может кто грамотно подправит эту функцию.
Что она делает: Печатает текст в указанных координатах на LCD2004 с указанием длинны блока и с выравниванием текста в этом блоке
В ИДЕ не запускал, вот только на сайте, поэтому варнигов пока не видел(
Если важна скорость, переписывать нужно LiquidCrystal_I2C в соответствии с рекомендациями, изложенными здесь:
“Из коробки” вывод каждого символа занимает более миллисекунды (несколько десятков тысяч тактов), так что что-то оптимизировать в коде, когда все тормоза происходят из-за библиотеки, вряд ли целесообразно.
Давеча делал студенту метеостанцию. Символы в псевдографике. При выводе, сначала стираем всё, затем выводим. Это из коробки. Нормально ли? “Ну, вопрос, конечно, интересный!”)
Это на несколько литров обсуждения тянет ))
Нет, это Гайвер. Тяп-ляп, куча всего, готово.) Главное побольше, дабы не разобраться.)