Помогите пожалуйста убрать мерцание символов!
- Войдите на сайт для отправки комментариев
Нашел такой интересный проект Шкала визуализации для аналоговых датчиков
Скетч рабочий. Единственное, что мне не понравилось - выводимая на экран переменная (точнее её символы) очень часто меняется. Эффект такой словно происходит мерцание! Можно ли как-то его убрать без функции delay();
Я вижу только два способа:
1. С помощью millis();
Пробовал вот так:
#include <Wire.h> // Подключаем библиотеку для работы с шиной I2C #include <LiquidCrystal_I2C.h> // Подключаем библиотеку для работы с LCD дисплеем по шине I2C LiquidCrystal_I2C lcd(0x3F,16,2); // Объявляем объект библиотеки, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2) Если дисплей не отвечает, то измените адрес на 0x3F uint8_t symbol[8] = {31,31,31,31,31,31,31,31}; // Определяем массив который содержит полностью закрашенный символ const uint8_t pinSensor = A0; // Определяем константу для хранения номера аналогового входа с которого будут браться данные uint16_t valSensor; // Объявляем переменную для хранения данных с аналогового входа pinSensor long previousMillis = 0; long interval = 1000; // void setup(){ // lcd.init(); // Инициируем работу с LCD дисплеем lcd.backlight(); // Включаем подсветку LCD дисплея lcd.createChar(1, symbol); // Загружаем символ из массива symbol в первую ячейку ОЗУ дисплея } // Так как символ был загружен в 1 ячейку, то для его отображения на дисплее нужно вывести символ с кодом 1 // Если бы мы загрузили символ во 2 ячейку, то для его отображения на дисплее нужно было бы вывести символ с кодом 2 void loop(){ unsigned long currentMillis = millis(); //проверяем не прошел ли нужный интервал, если прошел то if(currentMillis - previousMillis > interval) { // сохраняем время previousMillis = currentMillis; valSensor = analogRead(pinSensor); // Читаем данные с аналогового входа pinSensor в переменную valSensor lcd.setCursor(6, 1); lcd.print(" "); // Устанавливаем курсор дисплея на 6 символ 1 строки и выводим 4 пробела начиная с той позиции, куда ранее был установлен курсор. lcd.setCursor(6, 1); lcd.print(valSensor); } // Устанавливаем курсор дисплея на 6 символ 1 строки и выводим значение переменной valSensor на дисплей (начиная с той позиции, куда ранее был установлен курсор) lcd.setCursor(0, 0); // Устанавливаем курсор дисплея на 0 символ 0 строки для вывода шкалы, дальнейший вывод символов начнётся именно с этой позиции uint8_t j=map(valSensor,0,1023,0,17); // Определяем переменную j которой присваиваем значение valSensor преобразованное от диапазона 0...1023 к диапазону 0...17 for(uint8_t i=0; i<16; i++){ // Выполняем цикл 16 раз для вывода шкалы из 16 символов начиная с позиции в которую ранее был установлен курсор lcd.write(j>i? 1:32); // Выводим на дисплей символ по его коду, либо 1 (символ из 1 ячейки ОЗУ дисплея), либо 32 (символ пробела) } // После вывода каждого символа, курсор дисплея сдвигается автоматически }
По моему это не самый лучший вариант!
Второй вариант обновлять значение переменной на экране, только тогда, когда её значение существенно изменилось, например на +5 или - 5 (или больше).
Только я не знаю, какой функцией можно проверить выход переменной за определенные границы?
Или готовых функций нету?
Например текущее значение, считанное с датчика равно 95, как сделать так, чтобы на дисплей вывелось только 90 или 100. То есть изменение меньше, чем на 5, просто игнорировались? То есть цифры 94,93,92,91... и 96,97,98,99 не выводились!
Нужно писать так:
if (valSensor >= (analogRead(pinSensor)+5) || valSensor <= (analogRead(pinSensor)-5) { lcd.setCursor(6, 1); lcd.print(" "); lcd.setCursor(6, 1); lcd.print(valSensor); }
Или можно проще? Подскажите пожалуйста, кто в этом разбирается!
А можно ли написать так:
Или это неправильно?
Спасибо!
И ещё вопрос к знатокам: как сделать такую же шкалу визуализации на две строки? То есть в зависимости от уровня с датчика сначала символами заполняется первая строка, а потом ещё вторая!
То есть розрядность уже не 16, а 32!
Возможно мой вопрос покажется глупым, но я не знаю, как реализовать переход к другой строке?
Понимаю только, что в функции map нужно будет изменить значение на большее! То есть:
Как сделать перенос, во вторую строку, если значение з датчика будет больше половины? Нужно создать ещё одну переменную для строки?
То есть написать
а потом добавить проверку
Пробовал писать и так:
И так:
Однако все равно работает неправильно! Подскажите пожалуйста, что здесь неправильно?
Что то типа такого
Попробовал таким способом:
Вот код :
Впечатление такое, что в функцию вывода не передается значение переменной! Или передается что-то не то! Посмотрите пожалуйста, кому не сложно! Заранее спасибо!
В выводе через Serial обнаружил очень странный глюк! Откуда берется это число? И как оно может быть больше, чем переменная j ?
Наконец-то исправил код! Теперь он выглядит так:
Попробовал. Вроде бы работает, но я не уверен, что написан он правильно! Подскажите пожалуйста, может его можно как-то улучшить?
Можно улучшить. Производите вывод на экран только если отображаемое значение изменилось (увеличилось или уменьшилось).
Или, например, используйте четыре собственных изображения: закрашено 1/4, 2/4, 3/4 и 4/4 знакоместа. Немного придется с математикой посидеть, но шкала будет иметь больше градаций и влезет в одну строку LCD.
Опять таки, как вариант оптимизации можно рассмотреть вот такое:
lcd.clear(), к сожалению, не поможет оптимизации, а тормознет процесс.
Или, например, используйте четыре собственных изображения: закрашено 1/4, 2/4, 3/4 и 4/4 знакоместа.
К сожалению знакогенератор 5x8, так что делить надо на 5, а не на 4. но и в этом случае будет не очень выглядеть из за промежутка между символами. Тут надо топикстартеру решать что ему нужно.
Это не готовое решение, а пример того, как можно сделать. Я бы на месте топикстартера закрашивал слева на право, а гасил кубики в обратном направлении. и только те, которые надо.
К сожалению знакогенератор 5x8, так что делить надо на 5, а не на 4. но и в этом случае будет не очень выглядеть из за промежутка между символами. Тут надо топикстартеру решать что ему нужно.
Согласен, выглядеть будет так себе. Однако логичней, чем на две строчки растягивать. Кстати, средний столбец знакоместа можно не красить, будет дырок побольше, повеселей.