Мерцает дисплей 128х64
- Войдите на сайт для отправки комментариев
Вс, 17/01/2016 - 15:43
Помогите разобраться. Первые две строки работают нормально, а вот последняя и текст по нажатию кнопки мерцают. В чем может быть проблема?
Вот пример видео на ютубе https://www.youtube.com/watch?v=2JINHAXRKQ8
И код
#include <SPI.h> #include <Wire.h> #include <Adafruit_SSD1306.h> #define potPin A6 //Вывод резистора скорости #define uPin A5 //Вывод напряжения батареи #define fwdPin 5 //Вывод кнопки "Вперед" #define bwdPin 6 //Вывод кнопки "Назад" #define OLED_MOSI 3 //Выводы дисплея #define OLED_CLK 10 #define OLED_DC 11 #define OLED_CS 12 #define OLED_RESET 13 Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); bool con = false; //Статус соединения int u_value = 0; //Значение напряжения int spd = 0; //Скорость float ubat = 0.00; //Напряжение батареи int spd_d = 0; //Скорость для отображения на дисплее void setup() { display.begin(); //Инициализация дисплея pinMode(fwdPin, INPUT); //Режимы пинов pinMode(bwdPin, INPUT); pinMode(uPin, INPUT); pinMode(potPin, INPUT); digitalWrite(bwdPin,LOW); digitalWrite(fwdPin,LOW); display.clearDisplay(); display.setTextColor(WHITE); } //end setup void loop() { //start loop display.clearDisplay(); //Очистка дисплея u_value=analogRead(uPin); //Замер напряжения батареи ubat =(u_value*5.0)/1024.0; //Рассчет напряжения spd =analogRead(potPin); //Обработка данных резистора скорости spd =map(spd,0,1023,0,255); //Маппинг 10 бит в 8 бит spd_d =map(spd,0,255,0,100); //Маппинг скорости для дисплея из 255 в 100 //Строка напряжения батареи display.setTextSize(1); display.setCursor(0,0); display.println("Battery voltage "); display.setCursor(94,0); display.print(ubat); display.print("V"); //Строка скорости display.setCursor(9,12); display.println("Current speed "); display.setCursor(92,12); display.print(spd_d); display.print("%"); display.display(); //Строка соединения if(con==true){ display.setCursor(23,55); display.print("Connection OK"); display.display(); }//endif else{ display.setCursor(23,55); display.print("Not connected!"); display.display(); }//end else //если кнопка "Вперед" нажата ... if(digitalRead(fwdPin)==HIGH&&!digitalRead(bwdPin)==HIGH) { display.setTextSize(2); display.setCursor(15,25); display.println("Move FWD"); display.display(); }//endif //если кнопка "Назад" нажата ... if(digitalRead(bwdPin)==HIGH&&!digitalRead(fwdPin)==HIGH) { display.setTextSize(2); display.setCursor(10,25); display.println("Move BACK"); display.display(); }//endif //если обе кнопки нажаты ... if(digitalRead(fwdPin)==HIGH&&digitalRead(bwdPin)==HIGH) { display.setTextSize(2); display.setCursor(5,25); display.println("BTN ERROR!"); display.display(); } //endif } //end loop
Еще маленький вопрос. Библиотека подразумевает вывод RST, но у дисплея его нет. Как освободить занятый библиотекой вывод?
В правом верхнем углу есть кнопка "Поиск". Забиваем туда "мерцание дисплея" без кавычек и убеждаемся, что проблема не нова и решалась здесь уже раз 100500 - не меньше.
Не особо разобрался. Я так понял, мешает функция очистки дисплея, но как же без нее?
Молча. Зачем чистить целиком? Выводите букву, вот только её знакоместо и чистим, а веь экран зачем трогать?
Подскажите как. Это мой первый проект на ардуино кроме мигания светодиодом.
В тех темах, что поиск выдаёт были готовые примеры, поищите.
Не нашел. Честно
Можно использовать фунцию "fillrect" или текст заменят пробелами. Все зависит от библиотеки
А что это за функция? Библиотека от Adafruit
это прямоугольник, число/текст замещаем черным прямоугольником
зачем тебе нужно обновлять экран 3000 раз в секунду ???
сделай обновление 1 раз в секунду, даже с полной очисткой будет значительно лучше...
Это уже интересно. А как? Делей использовать нельзя
Это уже интересно. А как? Делей использовать нельзя
Спасибо.Приеду на работу, попробую
Okmor, ну не так же! LTime01 используется до инициализации! Сравнение написано так, что боится переполнения! Человек же начинающий, ему аккуратно надо давать информацию, он пока не в состоянии такие вещи сам отследить.
Сравнение написано так, что боится переполнения!
Тут уточние, а то я не понял.
Я не большой спец по Ардуино. LTime01 фиксированого типа и функция millis() того же типа.
Вот если использовать unsigned int LTime01; Да тогда возможно переполнение.
Тут уточние, а то я не понял.
Я не большой спец по Ардуино. LTime01 фиксированого типа и функция millis() того же типа.
Вот если использовать unsigned int LTime01; Да тогда возможно переполнение.
значение millis через приблизительно месяц работы переполняется и после самого большого для unsigned long значения (4 294 967 295) снова становится нулём.
При таком подходе, как у Вас, в этом момент произойдёт сбой. Смотрите:
1. допустим, что в момент очередного срабатывания LTime01 стала 4 294 966 296
2. через одну миллисекунду CTime01 будет 4 294 966 297, а LTime01 +1000 будет нулём.
3. Тогда Ваше условие благополучно сработает, хотя прошло не 1000 мс, а всего одна.
Чтобы такого не было, надо писать через вычитание и сравнивать с интервалом (см. пример "Миллис без делэй"). Там всё в порядке и никакого переполнения тот пример не боится.
CTime01 будет 4 294 966 297, а LTime01 +1000 будет нулём.
Нет не будет
4 294 966 297 +1 = -2 147 483 648
-2 147 483 648+1 = -2 147 483 647
и так по кругу.
Я всегда пользуюсь переполнением переменных когда нужно создать очень быстры перебор значений.
Напимер
Работает на 10% быстрее чем IF ... THEN ...
CTime01 будет 4 294 966 297, а LTime01 +1000 будет нулём.
Нет не будет
4 294 966 297 +1 = -2 147 483 648
-2 147 483 648+1 = -2 147 483 647
и так по кругу.
Я всегда пользуюсь
Переменная, описанная, как unsigned long станет равной -2 147 483 648 ???? У меня больше нет вопросjв, пользуйтесь дальше :)))))
А слабо написать скетч из трех строк, в котором к переменной unsigned long, равной 4 294 967 295 прибавить единицу и напечатать, что получилось? :)))
Спасибо за информацию, но в моем случае включение пульта больше, чем на час не планируется, поэтому такой вариант вполне устроит
Уже давно сделано уважаемым лешаком.
http://arduino.ru/forum/programmirovanie/eshche-raz-migaem-svetodiodom-bez-delay#comment-39994
Ну и подробные пояснения тут:
http://alxarduino.blogspot.com/2013/09/ComfortablyBlinkWithoutDelay.html
Уже давно сделано уважаемым лешаком.
Это Вы мне или Окмору? Если мне, так у меня и нет возражений против того, как сделано у Лешака. А вот так как у Окмора - сломается при переполнении. Только он не хочет этого понять. Какие-то отрицательные числа для беззнакового типа приводит.
Дело Ваше, только Вы сказали, что Вы человек начинающий. Так вот, не учитесь писать неправильно - это плохая привычка. Трудно что ли плюс на минус поменять и сделать правильно, как у Лешака?
Извините.
Я ошибся. После 4294967295 будет не -2147483648, а 0,1,2,3,,,
Видимо в этом контроллере учитывается обработа бита отрицательного значения.
Переполнения не будет, да и не может быть. Для переполнения надо использовать указатель адреса и записать туда тип большей битности. Особенно нужно быть внимательным при присвоении типа = ( &value,sizeof(value) ).
Код приведенный в примере Лешака не правильный. Потому, что к каждой задержке будет прибалятся время исполнения { action; } Измерять время можно только один раз.
Поверьте мне, инженеру-механику.
После 4294967295 будет не -2147483648, а 0,1,2,3,,,
Переполнения не будет, да и не может быть.
Именно это (сброс в 0) и называется переполнением, так что оно ещё как будет и именно из-за него не будет работать Ваш код (будет сбоить при переходе через 0).
Код приведенный в примере Лешака не правильный.
Время исполнения - проблема любой задержки и если важна точность, то его надо компенсировать. В примере лешака точность не настолько важна (время исполнения заведомо меньше миллисекунды - единицы в которой измеряется задержка).
А вот что важно в том коде - он не сбоит при переполнении (переходе через 0, если Вам угодно). А то, что Вы написали - сбоит.
Видимо в этом контроллере учитывается обработа бита отрицательного значения.
Не знаю, что Вы имеете в виду, но в этом контроллере всё абсолютно также, как и в любом другом - это общие правила арифметики в дополнительном коде.
Поверьте мне, как инженеру-программисту.
Вы не понимаете суть переполнения. Переполнение бывает опасно когда оно не контролируемое и на запись по адресу приходит значение больше чем ячейка памяти или выделенное пространство. Я имею ввиду "запись по адресу", а не запись в ячейку. Переполнение широко используется в счетчиках, когда изменение последнего бита идет на счетчик следующего регистра. В нашем варианте бит переполенеия никуда не ведет и не увеличивает значение в регистре. Также хочу заметить, что подобные переполнения широко используются повсеместно например в апаратных счетчиках, где никто не проверяет его переполнение, а он всегда работает по кругу.
Вы просили залить код в Ардуину, и я это сделал. На скриншоте видно момент так называемого переполнения. Только хочу заметить, что на скриншоте показал переполнение регистра, а переход на отрицательное значение смотрите здесь. Икак видно, что чудес не бывает и в контроллере как и всех других не учитывается переполнение бита знака числа. Да и вообще в контроллерах нету поняти знака числа - это все довольно условно.
Относительно компенсации времени исполнения тела функции.
- Нокогда не знаеш какое время отработает функция и ее нельзя заведомо компенсировать. Все нужно учитывать.
И еще. дайте пример переполнения переменной типа long, без использования указателей памяти, которое ведет к сбою программы.
Вы не понимаете суть переполнения. Переполнение бывает опасно когда оно не контролируемое и на запись по адресу приходит значение больше чем ячейка памяти или выделенное пространство.
Переполнение широко используется в счетчиках, ... он всегда работает по кругу.
Я никогда не говорю, о чём-то "вообще". Гармония вселенной - не моя тема. В данном топике мы говорим о Вашм коде, из поста №12. Там используется не long, а unsigned long.
Вам нужен пример переполнения unsigned long, которое приводит к сбою программы? Пожалуйста! Ваш код из поста №12 - и есть такой пример. Сбой проявляется в том, что при переходе через 0 задержка будет не 1с, а меньше.
Эмм...Так как лучше поступить то?
Эмм...Так как лучше поступить то?
Через 70 минут дам ответ. Запустил micros() на переполнение.
Хотя наверное на так поставил вопрос. Примерно понятно что делать...
Стирать дисплей не миллион раз в минуту, а раз в секунду, но не будут ли накладываться цифры друг на друга при изменении параметров переменным резистором? Ведь значения изменяются быстрее частоты стрирания
Хотя наверное на так поставил вопрос. Примерно понятно что делать...
Стирать дисплей не миллион раз в минуту, а раз в секунду, но не будут ли накладываться цифры друг на друга при изменении параметров переменным резистором? Ведь значения изменяются быстрее частоты стрирания
А зачем Вам вообще его стирать с какой-то периодичностью?
Поменялось что-то - стёрли это место и перерисовали. А если ничего не меняется, так и стирать нечего - пусть торчит на экране без изменений хоть секунду, хоть минуту, хоть час.
Эксперимент переполнения.
Проскочили long. Полет нормальный.
Ждем переполнения unsigned long.
Эксперимент переполнения.
Проскочили long. Полет нормальный.
Ждем переполнения unsigned long.
О, Господи, а что, написать MyMillis, которая стартует с близкого к переполнению числа и каждый раз его инкрементирует и выдаёт, и провести эксперимент за несколько секунд не судьба?
Да и зачем там эксперимент, когда и так всё ясно, в правой части получится 0, а в левой число заведомо большее? Впрочем, если Вам больше нечем заняться ....
Мы говорим о конкретном коде. А Вы что-то другое написали. Мы не это обсуждаем.
а давайте обсуждать мой код, так интереснее :)
а обсуждать переполнение интов совсем к сабжу не относящаяся тема...
Так, получается нужно прописать стирание после изменения информации на резисторе? Почему тогда первые две строки на дисплее отлично работают?
Мы говорим о конкретном коде. А Вы что-то другое написали. Мы не это обсуждаем.
Вот оно ваше переполнение:
Попробую if( max(i,t)-min(i,t) > interval )
Так, получается нужно прописать стирание после изменения информации на резисторе? Почему тогда первые две строки на дисплее отлично работают?
Уберите функцию display.clearDisplay(); из кода вообще. И пишите поверх предыдущего значения, добивая строку пробелами. А то у вас значения стираются, а потом выводятся. Отсюда и мерцание.
Да, но если писать поверх предыдущего не стирая, то будет ведь наложение цифр?
Да, но если писать поверх предыдущего не стирая, то будет ведь наложение цифр?
С этим дисплеем не работал. На моем перезатирает старые без мерцания и наложения.
Предлагаю вопрос с переходом через ноль вынести в отдельную тему. Надо Okmorа вывести на чистую воду.
Предлагаю вопрос с переходом через ноль вынести в отдельную тему. Надо Okmorа вывести на чистую воду.
В сад! Все в сад!
http://arduino.ru/forum/programmirovanie/zaderzhka-bez-delay-i-perepolneniya-schetchikov
Я попробовал Ваш вариант. Дисплей моргает с частотой 1с :) Почему не моргают первые 2 строки при одинаковой частоте обновления?
покажите весь код?
В первом сообщении
В первом используется команда очистки дисплея. Я не увидел изменений с учётом обсуждений здесь. Так же код можно оптимизировать, убрать дублирующие команды "дисплей" и "установка размера шрифта". Если будет время, я вам вечером скину код скорректированный
Хорошо. Я думаю нет смысла скидывать код с тем, что предложили выше, так как изменилось всего две строки и то без толку.
Размер шрифтра там меняется всего один раз и обратно. А вот без команды дисплей ничего не отображается
//если кнопка "Вперед" нажата ...
078
if
(digitalRead(fwdPin)==HIGH&&!digitalRead(bwdPin)==HIGH)
079
{
080
display.setTextSize(2);
081
084
}
//endif
085
086
//если кнопка "Назад" нажата ...
087
if
(digitalRead(bwdPin)==HIGH&&!digitalRead(fwdPin)==HIGH)
088
{
089
display.setTextSize(2);
090
093
}
//endif
094
095
//если обе кнопки нажаты ...
096
if
(digitalRead(fwdPin)==HIGH&&digitalRead(bwdPin)==HIGH)
097
{
098
display.setTextSize(2);
099
зачем объявлять размер шрифта три раза?
программа выполняется сверху-вниз
Вот пример для одностраничного вывода информации. Если многостраничный режим - статичную информацию из setup перенести в loop