WEH001602 Winstar: стабильная библиотека.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

внешний вид индикатора:

описалово здесь https://www.winstar.com.tw/ru/products/oled-module/oled-character-display/weh001602a.html

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

ищется стабильная библиотека.

изначально приобретался для проекта где стабильно работал в графическом режиме в связке с немодифицированной библиотекой LiquidCrystal.

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

смотрел на хабре статьи с рекомендациями:

- увеличить таймаут инициализации - бессмысленное телодвиженние: путает нулевую и первую строки.

- следом посылать толи четыре, толи пять комманд с 0x00: вообще всё ломается.

- ресетить индикатор, отключая питание - влом нагромождать ненужное.

~~~~

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


#include <LiquidCrystal.h>
// LiquidCrystal OLED(RS,  E, D4, D5, D6, D7)
   LiquidCrystal OLED( 5, 18, 19, 21, 22, 23);

void OLED_Graphic_Mode() {
// графический режим OLED:
OLED.command(0x08); // выключить экран
OLED.command(0x1F); // переключиться в графический режим
OLED.command(0x01); // очистить ОЗУ
OLED.command(0x08 | 0x04); // включить экран
}

void OLED_Graphic_Cursor(uint8_t x, uint8_t y) {
OLED.command(LCD_SETDDRAMADDR | x);
OLED.command(LCD_SETCGRAMADDR | y);
}

void OLED_Text_Mode() {
// текстовый режим OLED:
OLED.command(0x08); // выключить экран
OLED.command(0x17); // переключиться в текстовый режим
OLED.command(0x01); // очистить ОЗУ
for (int i = 0; i < 32; i++) delayMicroseconds(16000);
OLED.command(0x04 | 0x08); // включить экран
}

void setup() {
OLED.begin(16, 2);
// OLED_Graphic_Mode();
OLED_Text_Mode();
}

void loop() {}

*с кодом выше индикатор работает с ESP32 при напряжении питания 3.3V.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

а, если добавить в код пин RW:

// LiquidCrystal OLED(RS, RW,  E, D0, D1, D2, D3);
   LiquidCrystal OLED( 4,  5, 18, 19, 21, 22, 23);

то это

for (int i = 0; i < 32; i++) delayMicroseconds(16000);

не обязательно.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

Клапауций 003 пишет:

а, если добавить в код пин RW:

// LiquidCrystal OLED(RS, RW,  E, D0, D1, D2, D3);
   LiquidCrystal OLED( 4,  5, 18, 19, 21, 22, 23);

то это

for (int i = 0; i < 32; i++) delayMicroseconds(16000);

не обязательно.

таки, нет - отваливается первая строка дисплея.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

боле-менее корректный ресет, переключение графический-текстовый режимы на лету.

/*OLED1602 WEH001602ALPP5N00001 & ESP32 & LiquidCrystal*/

#include <LiquidCrystal.h>
// LiquidCrystal OLED(RS, RW,  E, D0, D1, D2, D3);
   LiquidCrystal OLED( 4,  5, 18, 19, 21, 22, 23);

void OLED_Graphic_Cursor(uint8_t x, uint8_t y) {
OLED.command(LCD_SETDDRAMADDR | x);
OLED.command(LCD_SETCGRAMADDR | y);
}

void OLED_Graphic_Mode() {
// графический режим OLED:
OLED.command(0x08); // выключить экран
OLED.command(0x1F); // переключиться в графический режим
OLED.command(0x01); // очистить ОЗУ
for (int i = 0; i < 32; i++) delayMicroseconds(16000);
OLED.command(0x08 | 0x04); // включить экран
}

void OLED_Text_Mode() {
// текстовый режим OLED:
OLED.command(0x08); // выключить экран
OLED.command(0x17); // переключиться в текстовый режим
OLED.command(0x01); // очистить ОЗУ
for (int i = 0; i < 32; i++) delayMicroseconds(16000);
OLED.command(0x04 | 0x08); // включить экран
}
​
void setup() {
OLED_Graphic_Mode();
OLED.begin(16, 2);
}

void loop() {
if (/*событие*/) {
// test Graphic OLED
OLED_Graphic_Mode();
OLED_Graphic_Cursor( 0, 0);
OLED.write(0b11011011);
OLED_Graphic_Cursor(79, 1);
OLED.write(0b11011011);
} 

if (/*событие*/) {
// test Text OLED
OLED_Text_Mode();
OLED.setCursor(0, 0);
OLED.print("Test OLED. OK! 0");
OLED.setCursor(0, 1);
OLED.print("Test OLED. OK! 1");
}
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Клапауций 003 пишет:

Клапауций 003 пишет:

а, если добавить в код пин RW:

// LiquidCrystal OLED(RS, RW,  E, D0, D1, D2, D3);
   LiquidCrystal OLED( 4,  5, 18, 19, 21, 22, 23);

то это

for (int i = 0; i < 32; i++) delayMicroseconds(16000);

не обязательно.

таки, нет - отваливается первая строка дисплея.

А если банально: delay(512); ?

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

andriano пишет:

А если банально: delay(512); ?

я тоже так думаю, но подозреваю, что рекомендатель того цикла с делаями микросекунд руководствовался чем то ещё, ускользающим от моего скромного понимания.

https://habr.com/ru/post/400833/

sadman41
Offline
Зарегистрирован: 19.10.2016

Я думаю, что надо научиться думать.

Исходя из этого:

-------------------

В библиотеке для этого используется функция delayMicroseconds(50000) (строка 120 файла LiquidCrystalRus_OLED.cpp). Для контроллера WS0010 нужно иметь задержку в десять раз больше — не менее 500 мс (см. последнюю страницу даташита по указанной выше ссылке).
-------------------

И этого:

-------------------

delayMicroseconds()

Currently, the largest value that will produce an accurate delay is 16383. This could change in future Arduino releases. For delays longer than a few thousand microseconds, you should use delay() instead.

-------------------

Следует вывод - у автора поста имеются определённые проблемы.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

вспомнил, почему delayMicroseconds() , а не банальный delay().

Начиная с версии Arduino 0018, функция delayMicroseconds() больше не отключает прерывания.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

sadman41 пишет:

Следует вывод - у автора поста имеются определённые проблемы.

строка delayMicroseconds(50000); присутсвует в библиотеке LiquidCrystal.

sadman41
Offline
Зарегистрирован: 19.10.2016

Исходя из руководства - она бессмысленна в текущих IDE. И автор поста об этом не задумывается.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

sadman41 пишет:

Исходя из руководства - она бессмысленна в текущих IDE. И автор поста об этом не задумывается.

автору поста об этом задумываться нет смысла, т.к. он меняет в коде библиотеки 50000 микросекунд на 32 раза по 16000, что есть корректно для данного типа дисплея и не выходит за рамки требований максимального значения delayMicroseconds().

*но сам факт грубой ошибки в популярной библиотеке дуино - рвёт эмбедеров на клочки.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

посмотрел в Arduino.h

void delayMicroseconds(unsigned int us);

что там пишут про четвёртую часть от unsigned int - не совсем понятно.

максимальное значение принимаемое delayMicroseconds() - 65535

возможно, имелось ввиду, что в первой четверти значений диапазона 0-65535 можно надеяться на более-менее точность, а далее - нет, но то, что строка: delayMicroseconds(50000) - верна по сути. факт.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Интересно не то, какое максимальное значение помещается в unsigned int, а то, как это значение потом запихивается в аппаратный таймер для обеспечения нужной величины задержки.

sadman41
Offline
Зарегистрирован: 19.10.2016
#elif F_CPU >= 16000000L
	// for the 16 MHz clock on most Arduino boards

	// for a one-microsecond delay, simply return.  the overhead
	// of the function call takes 14 (16) cycles, which is 1us
	if (us <= 1) return; //  = 3 cycles, (4 when true)

	// the following loop takes 1/4 of a microsecond (4 cycles)
	// per iteration, so execute it four times for each microsecond of
	// delay requested.
	us <<= 2; // x4 us, = 4 cycles

	// account for the time taken in the preceeding commands.
	// we just burned 19 (21) cycles above, remove 5, (5*4=20)
	// us is at least 8 so we can substract 5
	us -= 5; // = 2 cycles,

 

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

andriano пишет:

Интересно не то, какое максимальное значение помещается в unsigned int, а то, как это значение потом запихивается в аппаратный таймер для обеспечения нужной величины задержки.

как как это значение потом запихивается в аппаратный таймер для обеспечения нужной величины задержки?

как-то мне это не очевидно, а в контексте того что на дуино ESP32 void delayMicroseconds(uint32_t us), то совсем не понятно - что делать и в какую сторону бечь. 

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

sadman41 пишет:

#elif F_CPU >= 16000000L
	// for the 16 MHz clock on most Arduino boards

	// for a one-microsecond delay, simply return.  the overhead
	// of the function call takes 14 (16) cycles, which is 1us
	if (us <= 1) return; //  = 3 cycles, (4 when true)

	// the following loop takes 1/4 of a microsecond (4 cycles)
	// per iteration, so execute it four times for each microsecond of
	// delay requested.
	us <<= 2; // x4 us, = 4 cycles

	// account for the time taken in the preceeding commands.
	// we just burned 19 (21) cycles above, remove 5, (5*4=20)
	// us is at least 8 so we can substract 5
	us -= 5; // = 2 cycles,

 

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

sadman41
Offline
Зарегистрирован: 19.10.2016

Тебе, Клопоуций, лечиться надо. Кидаешься на всех, как злая собака за калиткой.

Камменты в коде тебе объясняют, почему больше 1/4 от uint16_t использовать вредно. Но ты давай, размышляй дальше про точность за пределами 16383 и о корректности вызова функции с аргументом 50000. И используй циклы по 16000 мкс, потому что кто-то там где-то их тоже использовал.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Клапауций 003 пишет:

что делать и в какую сторону бечь. 

видимо бежать

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

sadman41 пишет:

Тебе, Клопоуций, лечиться надо. Кидаешься на всех, как злая собака за калиткой.

т.е. это Я в теме, которую сам же и создал - как собака, кидаюсь на флудеров?

ок. гав!, бродяги! - нечего тут без толку околачиваться.

sadman41 пишет:

Камменты в коде тебе объясняют, почему больше 1/4 от uint16_t использовать вредно.

мало того, что камменты в коде меня не убеждают, что delayMicroseconds(50000) - вредно(где и почему вредно?)

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

sadman41 пишет:

Исходя из руководства - она(delayMicroseconds(50000)) бессмысленна в текущих IDE. И автор поста об этом не задумывается.

а, теперь ты поменял своё мнение с "бессмысленна" на "вредна".

sadman41 пишет:

Но ты давай, размышляй дальше про точность за пределами 16383 и о корректности вызова функции с аргументом 50000. И используй циклы по 16000 мкс, потому что кто-то там где-то их тоже использовал.

пока тебя здесь не появилось - всё находилось в состоянии равновесия: delayMicroseconds(50000) в коде библиотеки LiquidCrystal, таймаут фикса - в моём коде. и, какая в хера разница, как он(таймаут) реализован, если - корректно и, даже, ты-блоха до него не можешь докопаться.

сгинь, не раздражай меня.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

ua6em пишет:

Клапауций 003 пишет:

что делать и в какую сторону бечь.

видимо бежать

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

Клапауций! Ты зачем-то защищаешь явный кусок говнокода. ИМХО.

for (int i = 0; i < 32; i++) delayMicroseconds(16000);

Вот такой херни не может быть в нормальном коде никогда! Это костыль.

Правильно сказано, что (исключительно для AVR) не стоит использовать более 16383 в delayMicroseconds(). Автор просто взял по 16 тыщ столько раз, сколько ему надо.

delayMicroseconds(50000) в AVR ядре полность эквивалентно delayMicroseconds(848) **). ( ;)) для смеха уточню, что в 1.8.7 всё еще так). Там просто для тактовой в 16МГц аргумент на 4 делится ;))).

(** много раз пересчитывал, что будет с 50000 после (50000<<2)>>2) $))) )

Мне казалось, что ты повзрослел, чтобы спорить без уверенности в правоте... жаль.

void delayMicroseconds(unsigned int us)
// Я стер все варианты с FCPU != 16000000
{
	if (us <= 1) return; //  = 3 cycles, (4 when true)
	us <<= 2; // x4 us, = 4 cycles
	us -= 5; // = 2 cycles,
	__asm__ __volatile__ (
		"1: sbiw %0,1" "\n\t" // 2 cycles
		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
	);
}

В ArduinoIDE функция delay() не гарантирует длительность задержки, лишь "не меньше чем", а delayMicroseconds() предоставляет системную задержку в фиксированное время, достаточно аккуратно приближенное к заданному. Вот и разница. Поэтому и такой странный костыль. Но это не повод его тиражировать. Это костыль времени разработки.

-------------------------------------

Кроме того, ты и твои оппоненты забыли (как мне кажется), что ты теперь пишешь под ЕСП. А там вообще всё иначе - просто delay(), запускает таймер для измерения интервала,  а delayMicroseconds() - обращение к функции API os_delay_us(), реализация которой за пределами досигаемости "ембеддеров", и лежит на ответственности компании Еспрессив. ;))

Мне так показалось, потому, что вся аргументация свелась к цитированию wiring.c от ядра AVR.

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

Клапауций 003 пишет:

sadman41 пишет:

#elif F_CPU >= 16000000L
	// for the 16 MHz clock on most Arduino boards

	// for a one-microsecond delay, simply return.  the overhead
	// of the function call takes 14 (16) cycles, which is 1us
	if (us <= 1) return; //  = 3 cycles, (4 when true)

	// the following loop takes 1/4 of a microsecond (4 cycles)
	// per iteration, so execute it four times for each microsecond of
	// delay requested.
	us <<= 2; // x4 us, = 4 cycles

	// account for the time taken in the preceeding commands.
	// we just burned 19 (21) cycles above, remove 5, (5*4=20)
	// us is at least 8 so we can substract 5
	us -= 5; // = 2 cycles,

 

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

Да, delayMicroseconds(50000) === delayMicroseconds(848) ПОЛНОСТЬЮ эквивалентно. (для AVR)

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

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

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

wdrakula пишет:

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

за что извиняться?

выскочило что-то - докопалось до delayMicroseconds(50000) в библиотеке LiquidCrystal.

почему оно не идёт на https://www.arduino.cc/ и не занимается этим там?

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

 

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

wdrakula пишет:

Кроме того, ты и твои оппоненты забыли (как мне кажется), что ты теперь пишешь под ЕСП. 

А там вообще всё иначе - 

ты, вообще, читал название и содержание первых постов темы?

здесь выясняется, как всё на самом деле(с) или я тут пытаюсь запустить дисплей?

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

всем, кто ещё недоговорил о delayMicroseconds() - прошу последовать всюда Великое Недополнение: delayMicroseconds();

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

wdrakula пишет:

Клапауций! Ты зачем-то защищаешь явный кусок говнокода. ИМХО.

for (int i = 0; i < 32; i++) delayMicroseconds(16000);

Вот такой херни не может быть в нормальном коде никогда! Это костыль.

Совершенно верно!

Ну ведь правда, гораздо изящнее:

for (int i = 0; i < 31; i++) delayMicroseconds(16516);

 

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

andriano пишет:

delayMicroseconds(16516);

зря ты это написал - щаз набегут...

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

andriano пишет:
Ну ведь правда, гораздо изящнее:

for (int i = 0; i < 31; i++) delayMicroseconds(16516);

Вот ведь издалека видно человека с хорошим вкусом! Мазл тов!

Zeerz85
Offline
Зарегистрирован: 24.09.2019

Подскажите купил такой дисплей его можно подключить и проверить через l2c?