Библиотека UG8LIB, особенности обращения к дисплею

AKOTb
Offline
Зарегистрирован: 24.01.2017

Друзья, добрый день!

Возник вопрос с использованием библиотеки UG8LIB для графическго дисплея 128х64 с ардуино уно на 328 микросхеме.

Я только осваиваю параллельное выполнение ардуиной нескольких задач и решил организовать прорисовку дисплея 3 раза в секунду, чтобы больше ресурсов оставить на получение иобработку параметров, которые в дальнейшем собираюсь выводить на экран.

#include <U8glib.h>                                            // Подключаем библиотеку U8glib
U8GLIB_ST7920_128X64_1X u8g(10);                               // Создаём объект u8g для работы с дисплеем, указывая номер вывода CS для аппаратной шины SPI
int FPS = 3;                                                    // частота обновления экрана

void loop() {

  static uint32_t drawTimer = millis();
  if(millis() - drawTimer >= (1000 / FPS)) {  // все рисования разместим в этом Ифе
       	u8g.firstPage();
  	do {
      		u8g.setColorIndex(1); // делаем курсор белого цвета
      		u8g.setFont(rus5x8);
		u8g.setPrintPos(3, 8);
          	u8g.setPrintPos(99, 28);
      		u8g.print(F("ВРЕМЯ"));
       }

На дисплее выводится слово "время" практически мгновенно, решил проверить, что будет если внутрь поместить считывание кнопки, по нажатию которой на экране должен загораться символ:

#include "GyverButton.h"
#include <U8glib.h>                                            // Подключаем библиотеку U8glib
U8GLIB_ST7920_128X64_1X u8g(10);                               // Создаём объект u8g для работы с дисплеем, указывая номер вывода CS для аппаратной шины SPI
int FPS = 3;                                                    // частота обновления экрана
GButton myButt1;						//у меня подключено на один аналоговый вывод A1 5 кнопок, через резисторы, в данном примере привожу только одну для упрощения восприятия кода

void setup() {
myButt1.setType(LOW_PULL);
}

void loop() {
  int analog = analogRead(1);
  myButt1.tick(analog < 200 && analog > 190); // диапазон значений для гарантированного срабатывания кнопки
 
  static uint32_t drawTimer = millis();
  if(millis() - drawTimer >= (1000 / FPS)) {  // все рисования разместим в этом Ифе
       	u8g.firstPage();
  	do {
      		u8g.setColorIndex(1); // делаем курсор белого цвета
      		u8g.setFont(rus5x8);
          	u8g.setPrintPos(90, 20);
      		u8g.print(F("ВРЕМЯ"));
		if (myButt1.state()) {u8g.setPrintPos(90, 20); u8g.print(F("КНОПКА"));
       }

Я предполагал, что такая конструкция вызовет проблему с отлавливанием сигнала с кнопки, т.к. дисплей обновляется 3 раза в секунду, но отражение слова "КНОПКА" происходит мгновенно. Также попробовал уменьшить значение переменной FPS до 1, ничего не меняется.
Я понимаю, что принцип отрисовки этой библиотекой достаточно сложный, происходит построчная отрисовка в цикле DO...WHILE. Но почему при попытке уменьшить количество обращений к данному циклу, нет разницы в отображении информации на дисплее?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Вы бы сначала "особенности" своего кода изучили :-) или хотя бы выложили не эти обрубки ...

b707
Offline
Зарегистрирован: 26.05.2017

AKOTb пишет:

почему при попытке уменьшить количество обращений к данному циклу, нет разницы в отображении информации на дисплее?

потому что на самом деле вы не меняете число обращений к циклу - он у вас опрашивается не три или один раз в секунду, а непрерывно, насколько хватает скорсти контроллера.

Причина - вы неправильно работаете с миллис, таймер надо не только проверять, но и запоминать, а в коде этого нет.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:

а в коде этого нет.

а ТС уверен, что есть

Artist666
Offline
Зарегистрирован: 26.02.2022
uint32_t drawTimer = 0;

void loop()
{
	static uint32_t drawMillis = millis();

	if(drawTimer <= drawMillis)
	{
		drawTimer = drawMillis + (1000 / FPS)
		
		// Код
	}
}

 

 

b707
Offline
Зарегистрирован: 26.05.2017

Artist666, уж лучше бы вы не высовывались :)

Ваш код - пример того. КАК НЕ НАДО ДЕЛАТЬ. Попытайтесь представить, что произойдет с этим кодом. когда миллис приблизится к своему максимуму 0xFF FF FF FF

Artist666
Offline
Зарегистрирован: 26.02.2022

Через  50 суток со старта программы?  DD
Да ничего, не будет.
Переменная drawTimer так же сбросится как и таймер.
Но выполнится код в последнюю секунду без учёта ограничения.

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:
Да ничего, не будет.

а, ну да, вы правы. Действительно, ничего не будет. В том смысле, что код вообще не рабочий :)

Ошибка та же, как и у предыдущего оратора - не запоминаете значение миллис. Более того, даже не читаете его...

Artist666
Offline
Зарегистрирован: 26.02.2022

А это что?
drawTimer = drawMillis + (1000 / FPS)

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

А это что?
drawTimer = drawMillis + (1000 / FPS)

К чему этот вопрос?

вы у меня спрашиваете, что значит эта строчка в ВАШЕМ коде?

b707
Offline
Зарегистрирован: 26.05.2017

дел

 

Artist666
Offline
Зарегистрирован: 26.02.2022

Хорошо, я вам скажу, эта строчка, где глобальная переменная drawTimer "запоминает" millis.

Кстати ради интереса загуглил, думал увижу "правильный" код.
Наткнулся на тутор алекса гайвера(блогер) не последний человек в программировании.

 

uint32_t myTimer1;

void loop() {
  if (millis() - myTimer1 >= 500) {   // ищем разницу (500 мс)
    myTimer1 = millis();              // сброс таймера
    // выполнить действие
  }
}

Минусы этого кода - в условии при каждой итерации loop происходит сложение.

1й вызов происходит не сразу же, а после задержки.

Когда millis переполнится и произойдёт сброс, код перестанет  выполняться навсегда.

Теперь может покажите, правильный и рабочий код?

Artist666
Offline
Зарегистрирован: 26.02.2022

b707 пишет:
Более того, даже не читаете его...

Типа не так:
static uint32_t drawMillis = millis();
А так:

static uint32_t drawMillis; drawMillis = millis();

?

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

Хорошо, я вам скажу, эта строчка, где глобальная переменная drawTimer "запоминает" millis.

давайте сначала закончим с вашим кодом, а потом перейдем к разбору "минусов" чужого...

Значит вы считаете. что эта строчка "запоминает" миллис? - ок, пусть так. Но откуда этот миллис берется - строчку можете показать?

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

Типа не так:
static uint32_t drawMillis = millis();
А так:

static uint32_t drawMillis; drawMillis = millis();

?

не плодите бред, отвечайте на вопросы.

Artist666
Offline
Зарегистрирован: 26.02.2022

b707 пишет:
Но откуда этот миллис берется - строчку можете показать?

 

static uint32_t drawMillis = millis();

Возможно я ошибся в синтаксисе, и нельзя сразу при объявлении статичной переменной забивать в неё данные.
Но это компилятор скорее всего заметил бы. и уведомил.
Это не суть. Такая ошибка мелочная, даже не стоит внимания.

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

b707 пишет:
Но откуда этот миллис берется - строчку можете показать?

 

static uint32_t drawMillis = millis();

отлично.

Даю сразу ответ - это неверно, миллис в этой строке не читается, точнее он читается, но только один единственный раз - при старте микроконтроллера.

Теперь возьмите учебник и прочитайте, как работают статик переменные.

 

И на будущее - пока вы не начнете четко понимать, что означают ключевые слова static volatile inline const - не используйте их.

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

Это не суть. Такая ошибка мелочная, даже не стоит внимания.

Слушайте, вы, мой недалекий друг!  если вы не перестанете нести чушь - я перестану давать вам ответы. Не надо ничего выдумывать, берите учебник и читайте.

Эта "мелочная ошибка" делает ваш код ПОЛНОСТЬЮ НЕРАБОЧИМ.

Artist666
Offline
Зарегистрирован: 26.02.2022

Бугаг, вы мне только сделаете одолжение.
Перестаньте меня оскорблять, вы себя позорите. ))
Я прекрасно знаю что такое статичная переменная.
В отличии от обычной, которая создаётся и удаляется после выполнения кода, статичная создаётся 1 раз и удаляется после выполнения всей программы.
 

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

Я прекрасно знаю что такое статичная переменная.

по твоему коду этого не видно.

Спорить я с тобой не собираюсь, придешь домой - запусти что-то типа такого кода

void loop() {
static uit32_t timer = millis();
Serial.println(timer);
}

понаблюдай за цифирьками в Сериал, подумай..

 

UPD И да - если ты ведешь себя как болван - я так тебя и стану называть, на вежливость не рассчитывай.

Artist666
Offline
Зарегистрирован: 26.02.2022

Так что, где код с таймерами?
Типа такого:
 

float value = 253;                  	//Preload timer value (0,3 секунды)

void setup()
{
  noInterrupts();                       // отключаем все прерывания
  TCCR1A = 0;							// инициализируем Timer1
  TCCR1B = 0;
  TCNT1 = value;                        // preload timer
  TCCR1B |= (1 << CS10)|(1 << CS12);    // 1024 prescaler (коэффициент деления предделителя)
  TIMSK1 |= (1 << TOIE1);               // enable timer overflow interrupt ISR (разрешаем вызов процедуры обработки прерывания переполнения счетчика)
  interrupts();                         // разрешаем все прерывания
}
ISR(TIMER1_OVF_vect)                    // процедура обработки прерывания переполнения счетчика
{
  TCNT1 = value;                        // preload timer
  
  // Пихать код сюда
}
void loop(){ }

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Artist666 пишет:

Хорошо, я вам скажу, эта строчка, где глобальная переменная drawTimer "запоминает" millis.

Кстати ради интереса загуглил, думал увижу "правильный" код.
Наткнулся на тутор алекса гайвера(блогер) не последний человек в программировании.

 

uint32_t myTimer1;

void loop() {
  if (millis() - myTimer1 >= 500) {   // ищем разницу (500 мс)
    myTimer1 = millis();              // сброс таймера
    // выполнить действие
  }
}

Минусы этого кода - в условии при каждой итерации loop происходит сложение.

1й вызов происходит не сразу же, а после задержки.

Когда millis переполнится и произойдёт сброс, код перестанет  выполняться навсегда.

Теперь может покажите, правильный и рабочий код?

дополню, пожалуй.  Фееричесский идиот. 

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

Так что, где код с таймерами?

ты с темы не сваливай, иди учебник читай.

А таймера с тебя пока зватит и Гайверовского, из #11 - хоть тут гайвера и не любят, но в этом процитированном отрывке ошибок нет.

Тебе домашнее задание - разобрать по пунктам. почему все. что ты написал о "минусах" этого кода - невероятная чушь.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Филин, здаёцца мне, здесь видно уши Северноговетра. 

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

дополню, пожалуй.  Фееричесский идиот. 

и я о том же :)

Забавно. что когда-то гайвер на этом же форуме сам выступал против этого же кода ровно с этими же бредовыми аргументами про лишнюю арифметическую операцию :) А увот глядишь-ко, поумнел.

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

Филин, здаёцца мне, здесь видно уши Северноговетра. 

вполне возможно, хотя для северного ветра это комплимент, тот про статик вряд ли хоть что-то знает и вообще туп как полено

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Дак и этот выточен из цельного куска стоеросового дерева.  Зато апломбу-то скока. 

Artist666
Offline
Зарегистрирован: 26.02.2022

Вот так тоже можно:
 

void setup()
{
	FPS = 1000 \ FPS
}
void loop()
{
	if((millis() % FPS) == 0)
	{
		
		// Код
	}
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

иоптваюмать.  

b707
Offline
Зарегистрирован: 26.05.2017

Artist666

еще один глупый кривой код

 

Артист, пойди отдохни... пока учебник не прочитаешь - чтоб я тебя не видел.

ты уже свою норму глупости на сегодня перевыполнил.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Артист, я ж тебе говорил, админы потёрли, правда,  ты пока хоть маленько знаний не наберешься, ну не лезь ты никому с программированием помогать, ну пожалуйста...  Выглядит это жалко...

Artist666
Offline
Зарегистрирован: 26.02.2022

b707 пишет:
Тебе домашнее задание - разобрать по пунктам. почему все. что ты написал о "минусах" этого кода - невероятная чушь.


uint32_t myTimer1; // По умолчанию равен 0

void loop() {
  // Итак, 1й минус, вы видите, что в условии производится операция сложения? Я надеюсь нет сомнений, что она производится при каждом вызове функции loop
  if (millis() - myTimer1 >= 500) {   // Второй минус, первые вызовы функции, таймер равен от 0 до 499, код условия выполнится? Нет!!!
    myTimer1 = millis();              // 3й минус - миллис вернула значение 4294967295(максимальное), в следующем вызове loop она = 0.
    // Вопрос, 0 - 4294967295 больше или равно 500?
    // А 500 - 4294967295 больше или равно 500?
    // Конечно это маловероятно, что миллис вернёт именно максимально число.
    // Пусть оно будет на 499 меньше, считай, умник.
  }
}
Надеюсь кашка достаточно пережевана?
Artist666
Offline
Зарегистрирован: 26.02.2022

Извиняюсь, uint32_t без знака минус.
Но, 2 минуса остались, 2 из 3х - это не всё.

b707
Offline
Зарегистрирован: 26.05.2017

Конечно, отвечать бы не стоило, поэтому только на два КЛЮЧЕВЫХ вопроса

// Вопрос, 0 - 4294967295 больше или равно 500?

если считать в размерности uint32_t , то 0 - 4294967295 равно 1, значит меньше 500

// А 500 - 4294967295 больше или равно 500? - а это равно 501

По итогу это выражение одинаково правильно работает ДО, ВО ВРЕМЯ и ПОСЛЕ ПЕРЕПОЛНЕНИЯ.

Почитай что-нибудь про беззнаковую арифметику. тупень

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

от часа ночи, дебил, отними 2 часа.  Будет не -1 час, а 23.  Надеюсь, на этом у тебя межушный ганглий сломается. 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Это просто пи...ц. Еще один "свидетель переполнения millis"

b707
Offline
Зарегистрирован: 26.05.2017

Артист, ты мой проверочный код для статик переменной из сообщения #19 запустил? Убедился. что ты болван и не знаешь, что такое статик?

Так чего ж ты споришь тогда? ты во всем остальном ровно так же плаваешь...

Artist666
Offline
Зарегистрирован: 26.02.2022

b707 пишет:
еще один глупый кривой код

И чем он так глуп и крив?
Тело условия будет выполняться при каждом случае, когда миллис делится без остатка, т.е. каждые 333 миллисекунды.
2 минуса, деление в условии, и когда будет переполнение счётчика, возможен пропуск выполнения кода до 332 миллисекунд.

b707
Offline
Зарегистрирован: 26.05.2017

Komandir пишет:

Это просто пи...ц. Еще один "свидетель переполнения millis"

диагноз уже поставлен - "феерический долбоеп".

Ща если будет еще выступать -  добьем и забаним :)

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Да пусть повеселит форумчан ... другим будет неповадно

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

И чем он так глуп и крив?

а ты уверен, что заслужил, чтоб тебе еще один код обьяснили? ты хоть раз сказал спасибо? Или извинился за тупые наезды?

mixail844
Offline
Зарегистрирован: 30.04.2012

Artist666 пишет:

b707 пишет:
еще один глупый кривой код

И чем он так глуп и крив?
Тело условия будет выполняться при каждом случае, когда миллис делится без остатка, т.е. каждые 333 миллисекунды.
2 минуса, деление в условии, и когда будет переполнение счётчика, возможен пропуск выполнения кода до 332 миллисекунд.

он плох тем что вы неможете гарантировать что ваш код от проверки до порверки будет исполняться <= 1 миллисекуны

Artist666
Offline
Зарегистрирован: 26.02.2022

Во первых, я ни на кого не наезжал, во вторых, глазки подними выше своего поста, где я извинился за то, что uint32_t не имеет знака "-", тупанул, бывает.
Ну а на объяснение кода - тут дело не во мне, если ты хочешь меня убедить, что он тупой - пожалуйста.
Если ты писал, что код тупой не для меня, а для публики - пожалуйста, я не обижусь, можешь не объяснять.

Artist666
Offline
Зарегистрирован: 26.02.2022

mixail844 пишет:
тем что вы неможете гарантировать что ваш код от проверки до порверки будет исполняться <= 1 миллисекуны

Ааа, теперь понятно, спасибо. ))

А так гарантировано?

 

uint32_t drawTimer;

void setup()
{
	FPS = 1000 \ FPS
}
void loop()
{
	drawTimer++:
	
	if((drawTimer % FPS) == 0)
	{
		
		// Код
	}
}

Единственно нужно посчитать частоту проца, подогнать модуль, и наверное при выполнении каких-то рассчётов, частота вызовов loop может проседать.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

Во первых, я ни на кого не наезжал, во вторых, глазки подними выше своего поста, где я извинился за то, что uint32_t не имеет знака "-", тупанул, бывает.

а за то, что ты якобы знаешь, как устроен статик?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

DetSimen А большая печать какой конторы ???

Artist666
Offline
Зарегистрирован: 26.02.2022

DetSimen пишет:

Отмечал,  когда получил? DD

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

А так гарантировано?

не-а :)

Это уже просто смешно.

Ну не позорься, дурень. Ну не умеешь ты программировать - что с того? девки же любят не за это :))))

Artist666
Offline
Зарегистрирован: 26.02.2022

b707 пишет:

Artist666 пишет:

Во первых, я ни на кого не наезжал, во вторых, глазки подними выше своего поста, где я извинился за то, что uint32_t не имеет знака "-", тупанул, бывает.

а за то, что ты якобы знаешь, как устроен статик?

В смысле "якобы"?
Я вот думаю, что ты мелочный, и докопался до того, что я вместо:
 

static uint32_t drawTimer: drawTimer = millis();

Написал:
 

static uint32_t drawTimer = millis();

Я признаю, что я ошибся, но не признаю, что это такая важная ошибка, что стоило раздувать скандал.
Я уже писал, что я 4 года не занимался программированием, и многое забыл.

b707
Offline
Зарегистрирован: 26.05.2017

Artist666 пишет:

Я вот думаю, что ты мелочный, и докопался до того, что я вместо:
 

static uint32_t drawTimer: drawTimer = millis();

Написал:
 

static uint32_t drawTimer = millis();

Я признаю, что я ошибся, но не признаю, что это такая важная ошибка, что стоило раздувать скандал.

совсем мимо.

Давай так - ты пока код из сообщения #19 не запустишь - не пиши ничего больше.