Строим графики на LCD дисплеях 1602 и 2004 - Error

HellRaider

✩✩✩✩✩✩✩
12 Ноя 2018
19
1
Где я сделал коде ошибку.
Я хотел добавить процент числом, рядом с графикой.
Все работает, но на экране появляются знаки процента дополнительно! Почему?
Коде указываю начало места знака "%" но он появляется и дальше.
Знак "?" исполосовал, чтобы понят что именно меняется.

IMG_20190719_223509.jpg IMG_20190719_223522.jpg IMG_20190719_223531.jpg

/*
Скетч примера полосы загрузки на символьном LCD дисплее 1602/2004 итд.
*/

// библиотеки дисплея
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// создаём дисплей
// дисплей 1602. Если не работает, используйте другой адрес
//LiquidCrystal_I2C lcd(0x3f, 16, 2);
LiquidCrystal_I2C lcd(0x27, 16, 2);

// дисплей 2004. Если не работает, используйте другой адрес!
//LiquidCrystal_I2C lcd(0x3f, 20, 4);
//LiquidCrystal_I2C lcd(0x27, 20, 4);

boolean change_flag = true; // флаг для 3 типа полосы

void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.clear();

// инициализация символов для отрисовки. При использовании каких то своих символов,
// нужно вызывать эту функцию перед отрисовкой графика/полосы!
initBar3();
}

void loop() {
// для примера потенциометр подключен к A0

int perc = map(analogRead(2), 0, 1022, 0, 100);
lcd.setCursor(5,1);
lcd.print(perc);






//fillBar3 принимает аргументы (столбец, строка, длина полосы, значение в % (0 - 100) )
fillBar3(0, 0, 16, perc);
// fillBar3(0, 1, 8, perc);
delay(50);
if(perc<=9)
lcd.setCursor(6,1);
lcd.print("% ");
if(perc>=10&&perc<=99)
lcd.setCursor(7,1);
lcd.print("% ");
if(perc==100)
lcd.setCursor(8,1);
lcd.print("?");

}

void initBar3() {
// необходимые символы для работы
// создано в http://maxpromer.github.io/LCD-Character-Creator/
byte right_empty[8] = {0b11111, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b11111};
byte left_empty[8] = {0b11111, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111};
byte center_empty[8] = {0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111};
byte bar2[] = {0b11111, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11111};
byte bar3[] = { B11111, B11100, B11100, B11100, B11100, B11100, B11100, B11111};
byte bar4[] = { B11111, B11110, B11110, B11110, B11110, B11110, B11110, B11111};
lcd.createChar(0, left_empty);
lcd.createChar(1, center_empty);
lcd.createChar(2, right_empty);
lcd.createChar(3, bar2);
lcd.createChar(4, bar3);
lcd.createChar(5, bar4);
}

void fillBar3(byte start_pos, byte row, byte bar_length, byte fill_percent) {
byte infill = bar_length * fill_percent / 10;
byte fract = infill % 10;
infill = infill / 10;
// change_flag - true слева, false справа
if (infill < bar_length - 1) {
if (!change_flag) {
change_flag = true;
byte bar2[] = {0b11111, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11111};
byte bar3[] = { B11111, B11100, B11100, B11100, B11100, B11100, B11100, B11111};
byte bar4[] = { B11111, B11110, B11110, B11110, B11110, B11110, B11110, B11111};
lcd.createChar(3, bar2);
lcd.createChar(4, bar3);
lcd.createChar(5, bar4);
}
} else {
if (change_flag) {
change_flag = false;
byte leftbar1[] = { B11111, B10001, B10001, B10001, B10001, B10001, B10001, B11111};
byte leftbar2[] = { B11111, B11001, B11001, B11001, B11001, B11001, B11001, B11111};
byte leftbar3[] = { B11111, B11101, B11101, B11101, B11101, B11101, B11101, B11111};
lcd.createChar(3, leftbar1);
lcd.createChar(4, leftbar2);
lcd.createChar(5, leftbar3);
}
}
lcd.setCursor(start_pos, row);
if (infill == 0) {
if (fract >= 0 && fract < 2) lcd.write(0);
else if (fract >= 2 && fract < 4) lcd.write(0);
else if (fract >= 4 && fract < 6) lcd.write(3);
else if (fract >= 6 && fract < 8) lcd.write(4);
else if (fract >= 8) lcd.write(5);
}
else lcd.write(255);
for (int n = 1; n < bar_length - 1; n++) {
if (n < infill) lcd.write(255);
if (n == infill) {
if (fract >= 0 && fract < 2) lcd.write(1);
else if (fract >= 2 && fract < 4) lcd.write(0);
else if (fract >= 4 && fract < 6) lcd.write(3);
else if (fract >= 6 && fract < 8) lcd.write(4);
else if (fract >= 8) lcd.write(5);
}
if (n > infill) lcd.write(1);
}
if (infill == bar_length - 1) {
if (fract >= 0 && fract < 2) lcd.write(2);
else if (fract >= 2 && fract < 4) lcd.write(3);
else if (fract >= 4 && fract < 6) lcd.write(4);
else if (fract >= 6 && fract < 8) lcd.write(5);
else if (fract >= 8) lcd.write(255);
}
else if (infill == bar_length) lcd.write(255);
else lcd.write(2);
}

/*
Скетч примера полосы загрузки на символьном LCD дисплее 1602/2004 итд.
*/

// библиотеки дисплея
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// создаём дисплей
// дисплей 1602. Если не работает, используйте другой адрес
LiquidCrystal_I2C lcd(0x3f, 16, 2);
//LiquidCrystal_I2C lcd(0x27, 16, 2);

// дисплей 2004. Если не работает, используйте другой адрес!
//LiquidCrystal_I2C lcd(0x3f, 20, 4);
//LiquidCrystal_I2C lcd(0x27, 20, 4);

boolean change_flag = true; // флаг для 3 типа полосы

void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.clear();

// инициализация символов для отрисовки. При использовании каких то своих символов,
// нужно вызывать эту функцию перед отрисовкой графика/полосы!
initBar3();
}

void loop() {
// для примера потенциометр подключен к A0
int perc = map(analogRead(0), 0, 1023, 0, 100);

//fillBar3 принимает аргументы (столбец, строка, длина полосы, значение в % (0 - 100) )
fillBar3(0, 0, 10, perc);
fillBar3(0, 1, 16, perc);
delay(50);
}

void initBar3() {
// необходимые символы для работы
// создано в http://maxpromer.github.io/LCD-Character-Creator/
byte right_empty[8] = {0b11111, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b11111};
byte left_empty[8] = {0b11111, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111};
byte center_empty[8] = {0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111};
byte bar2[] = {0b11111, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11111};
byte bar3[] = { B11111, B11100, B11100, B11100, B11100, B11100, B11100, B11111};
byte bar4[] = { B11111, B11110, B11110, B11110, B11110, B11110, B11110, B11111};
lcd.createChar(0, left_empty);
lcd.createChar(1, center_empty);
lcd.createChar(2, right_empty);
lcd.createChar(3, bar2);
lcd.createChar(4, bar3);
lcd.createChar(5, bar4);
}

void fillBar3(byte start_pos, byte row, byte bar_length, byte fill_percent) {
byte infill = bar_length * fill_percent / 10;
byte fract = infill % 10;
infill = infill / 10;
// change_flag - true слева, false справа
if (infill < bar_length - 1) {
if (!change_flag) {
change_flag = true;
byte bar2[] = {0b11111, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11111};
byte bar3[] = { B11111, B11100, B11100, B11100, B11100, B11100, B11100, B11111};
byte bar4[] = { B11111, B11110, B11110, B11110, B11110, B11110, B11110, B11111};
lcd.createChar(3, bar2);
lcd.createChar(4, bar3);
lcd.createChar(5, bar4);
}
} else {
if (change_flag) {
change_flag = false;
byte leftbar1[] = { B11111, B10001, B10001, B10001, B10001, B10001, B10001, B11111};
byte leftbar2[] = { B11111, B11001, B11001, B11001, B11001, B11001, B11001, B11111};
byte leftbar3[] = { B11111, B11101, B11101, B11101, B11101, B11101, B11101, B11111};
lcd.createChar(3, leftbar1);
lcd.createChar(4, leftbar2);
lcd.createChar(5, leftbar3);
}
}
lcd.setCursor(start_pos, row);
if (infill == 0) {
if (fract >= 0 && fract < 2) lcd.write(0);
else if (fract >= 2 && fract < 4) lcd.write(0);
else if (fract >= 4 && fract < 6) lcd.write(3);
else if (fract >= 6 && fract < 8) lcd.write(4);
else if (fract >= 8) lcd.write(5);
}
else lcd.write(255);
for (int n = 1; n < bar_length - 1; n++) {
if (n < infill) lcd.write(255);
if (n == infill) {
if (fract >= 0 && fract < 2) lcd.write(1);
else if (fract >= 2 && fract < 4) lcd.write(0);
else if (fract >= 4 && fract < 6) lcd.write(3);
else if (fract >= 6 && fract < 8) lcd.write(4);
else if (fract >= 8) lcd.write(5);
}
if (n > infill) lcd.write(1);
}
if (infill == bar_length - 1) {
if (fract >= 0 && fract < 2) lcd.write(2);
else if (fract >= 2 && fract < 4) lcd.write(3);
else if (fract >= 4 && fract < 6) lcd.write(4);
else if (fract >= 6 && fract < 8) lcd.write(5);
else if (fract >= 8) lcd.write(255);
}
else if (infill == bar_length) lcd.write(255);
else lcd.write(2);
}
 

HellRaider

✩✩✩✩✩✩✩
12 Ноя 2018
19
1
if(perc<=9)
lcd.setCursor(6,1);

lcd.print("% "); // 0-9 выявляет % и два пробела

if(perc>=10&&perc<=99)
lcd.setCursor(7,1);
lcd.print("% "); //10-99 выявляет % и один пробел

if(perc==100)
lcd.setCursor(8,1);
lcd.print("?"); // 100 выявляет ? без пробела
}
 

HellRaider

✩✩✩✩✩✩✩
12 Ноя 2018
19
1
Понял. Спасибо

if(perc<=9){
lcd.setCursor(6,1);
lcd.print("% ");
}

принципе так работал(Foto1), но не понятно, почему появиться % и ? на местах (9,1) и (11,1)? но это уже не важно

IMG_20190719_223509.jpg
 

Александр Симонов

★★★★✩✩✩
2 Авг 2018
727
207
принципе так работал(Foto1), но не понятно, почему появиться % и ? на местах (9,1) и (11,1)? но это уже не важно

У тебя в коде стоят выводы "% " потом "% " и "?".
Ровно это ты и видишь на дисплее. Вывод строки сдвигает курсор.
 

Nick_SPb

★✩✩✩✩✩✩
1 Ноя 2018
55
12
Привет автор, я делал счётчик на таких экранчиках , только для ATMEGA... но это не важно.
В твоём случае ты просто не стираешь старые символы, я тоже с этим сталкивался, пробовал полностью очищать экран...
но тогда появляется неприятное моргание (эффект при перерисовке экрана), проще заполнять остаток строки пробелами. Желаю удачи)
 

Nick_SPb

★✩✩✩✩✩✩
1 Ноя 2018
55
12
Понял. Спасибо

if(perc<=9){
lcd.setCursor(6,1);
lcd.print("% ");
}

принципе так работал(Foto1), но не понятно, почему появиться % и ? на местах (9,1) и (11,1)? но это уже не важно

тут сделал правильно, естественно в остальных условиях тело кода тоже надо заключить в фигурные скобки)
 

Arhat109

★★★★✩✩✩
9 Июн 2019
473
203
Не обязательно очищать весь экран. Можно поступать проще: заполнять нужный буфер символами фикс. длины, а потом выводить его с одной и той же позиции. Само перезатрется (если буфер пересобирается целиком каждый раз). Это быстрее, посокльку сборка в буфере = работа в ОЗУ, а не отрисовка с перемещениями курсора "туда-сюда".
Самое медленно тут - реакция самого дисплея, и отсюда - каждая отправка чего-либо на дисплей, в т.ч. и смена позиции - есть время для моргания дисплеем.
Сам по себе I2C дисплея способен работать вплоть до 880кГц (проверено), но вот его реакция занимает куда как больше времени - около 200мксек на "байт" (команду или данные), а то и больше.