Ви не увійшли.
Доброго вечора. Бібліотека GyverOLED та OLED дисплей SSH1106 не працює.
Брав приклад:
// дефайн перед подключением либы - использовать microWire (лёгкая либа для I2C)
//#define USE_MICRO_WIRE
// дефайн перед подключением либы - скорость SPI
//#define OLED_SPI_SPEED 4000000ul
#include <GyverOLED.h>
// инициализация:
// GyverOLED<модель, буфер, интерфейс, CS, DC, RST> oled;
// "по умолчанию" - можно не указывать
// модель дисплея:
// SSD1306_128x32
// SSD1306_128x64
// SSH1106_128x64 (ТОЛЬКО С БУФЕРОМ)
// буфер:
// OLED_NO_BUFFER (без буфера)
// OLED_BUFFER (с буфером на стороне МК) - по умолчанию
// интерфейс:
// OLED_I2C - по умолчанию
// OLED_SPI (указать пины CS, DC, RST/RES)
// примеры:
//GyverOLED<SSD1306_128x32, OLED_BUFFER> oled;
//GyverOLED<SSD1306_128x32, OLED_NO_BUFFER> oled;
//GyverOLED<SSD1306_128x64, OLED_BUFFER> oled;
//GyverOLED<SSD1306_128x64, OLED_NO_BUFFER> oled;
//GyverOLED<SSD1306_128x64, OLED_BUFFER, OLED_SPI, 8, 7, 6> oled;
GyverOLED<SSH1106_128x64> oled;
// для I2C можно передать адрес: GyverOLED oled(0x3C);
// битмап создан в ImageProcessor https://github.com/AlexGyver/imageProcessor
// с параметрами вывода vertical byte (OLED)
const uint8_t bitmap_32x32[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0xF0, 0x70, 0x70, 0x30, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0x70, 0x30, 0x30, 0x20, 0x00, 0x00,
0x00, 0x30, 0x78, 0xFC, 0x7F, 0x3F, 0x0F, 0x0F, 0x1F, 0x3C, 0x78, 0xF0, 0xE0, 0xC0, 0x80, 0x80, 0x80, 0x40, 0xE0, 0xF0, 0xF8, 0xFC, 0xFF, 0x7F, 0x33, 0x13, 0x1E, 0x1C, 0x1C, 0x0E, 0x07, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xF7, 0xEF, 0x5F, 0x3F, 0x7F, 0xFE, 0xFD, 0xFB, 0xF1, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x1E, 0x33, 0x33, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x1F, 0x0E, 0x04, 0x00, 0x00, 0x00, 0x00,
};
void setup() {
Serial.begin(9600);
oled.init(); // инициализация
// --------------------------
// настройка скорости I2C
//Wire.setClock(800000L); // макс. 800'000
// --------------------------
oled.clear(); // очистить дисплей (или буфер)
oled.update(); // обновить. Только для режима с буфером! OLED_BUFFER
// --------------------------
oled.home(); // курсор в 0,0
oled.print("Hello!"); // печатай что угодно: числа, строки, float, как Serial!
oled.update();
delay(2000);
// --------------------------
oled.setCursor(5, 1); // курсор в (пиксель X, строка Y)
oled.setScale(2);
oled.print("Hello!");
oled.update();
delay(2000);
// --------------------------
oled.setCursorXY(15, 30); // курсор в (пиксель X, пиксель Y)
oled.setScale(3);
oled.invertText(true); // инвертируй текст!
oled.print("Привет!");
oled.update();
delay(2000);
// --------------------------
oled.clear();
oled.home();
oled.setScale(1);
oled.invertText(false);
oled.autoPrintln(true); // автоматически переносить текст
oled.print(F("Lorem ipsum dolor sit amet, лорем ипсум долор сит амет привет народ ё, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam"));
oled.update();
delay(2000);
// --------------------------
oled.home();
oled.textMode(BUF_ADD);
// BUF_ADD - наложить текст
// BUF_SUBTRACT - вычесть текст
// BUF_REPLACE - заменить (весь прямоугольник буквы)
oled.home();
oled.setScale(3);
oled.print("KEK!");
oled.update();
delay(2000);
// --------------------------
// СЕРВИС
//oled.setContrast(10); // яркость 0..15
//oled.setPower(true); // true/false - включить/выключить дисплей
//oled.flipH(true); // true/false - отзеркалить по горизонтали
//oled.flipV(true); // true/false - отзеркалить по вертикали
//oled.isEnd(); // возвращает true, если дисплей "кончился" - при побуквенном выводе
// --------------------------
oled.clear();
oled.dot(0, 0); // точка на x,y
oled.dot(0, 1, 1); // третий аргумент: 0 выкл пиксель, 1 вкл пиксель (по умолч)
oled.line(5, 5, 10, 10); // линия x0,y0,x1,y1
//oled.line(5, 5, 10, 10, 0); // пятый аргумент: 0 стереть, 1 нарисовать (по умолч)
oled.fastLineH(0, 5, 10); // горизонтальная линия (y, x1, x2)
//oled.fastLineH(0, 5, 10, 0); // четвёртый аргумент: 0 стереть, 1 нарисовать (по умолч)
oled.fastLineV(0, 5, 10); // аналогично верт. линия (x, y1, y2)
oled.rect(20, 20, 30, 25); // прямоугольник (x0,y0,x1,y1)
oled.rect(5, 35, 35, 60, OLED_STROKE); // прямоугольник (x0,y0,x1,y1)
// параметры фигуры:
// OLED_CLEAR - очистить
// OLED_FILL - залить
// OLED_STROKE - нарисовать рамку
oled.roundRect(50, 5, 80, 25, OLED_STROKE); // аналогично скруглённый прямоугольник
oled.circle(60, 45, 15, OLED_STROKE); // окружность с центром в (x,y, с радиусом)
oled.circle(60, 45, 5, OLED_FILL); // четвёртый аргумент: параметр фигуры
// битмап
oled.drawBitmap(90, 16, bitmap_32x32, 32, 32, BITMAP_NORMAL, BUF_ADD);
//oled.drawBitmap(90, 16, bitmap_32x32, 32, 32); // по умолч. нормал и BUF_ADD
// x, y, имя, ширина, высота, BITMAP_NORMAL(0)/BITMAP_INVERT(1), BUF_ADD/BUF_SUBTRACT/BUF_REPLACE
oled.update();
}
void loop() {
}
Дисплей OLED 1.3 SPI. Підключав до Ардуін UNO. Дисплей чорний. У чому може бути причина?
Остання редакція chipaka (2025-04-28 21:39:55)
Неактивний
Мені розшифровувати цю простиню влом але мені здається що в коді вибрано і2с.
Доброго вечора!
по перше спробуйте простий код. Наприклад код с сайту Gyver
#include <GyverOLED.h> // беремо уже відому бібліотеку
GyverOLED<SSD1106_128x64, OLED_NO_BUFFER> oled;
void setup() {
oled.init(); // ініціалізцємо
oled.clear(); // стираємо все
oled.setScale(3); // маштабування тексту
oled.home(); // курсор в 0,0
oled.print("Hello!");
delay(1000);
oled.setScale(1);
// курсор на початок 3 строки
oled.setCursor(0, 3);
oled.print("Arduino");
// курсор на (20, 50)
oled.setCursorXY(20, 50);
float pi = 3.14;
oled.print("PI = ");
oled.print(pi);
}
void loop() {
}
Як що працює шукаємо що не так в коду, як що ні треба копати далі.
Перевірте вірність підключення проводів
Остання редакція HelloArduino (2025-05-01 20:01:11)
Неактивний
маю ще рекомендацію
#include <Wire.h>
#include <U8g2lib.h>
// SH1106 128x64 I2C, аппаратный I2C (для Uno: SDA = A4, SCL = A5)
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);
void setup() {
u8g2.begin();
}
void loop() {
u8g2.clearBuffer(); // чистемо буфер
u8g2.setFont(u8g2_font_ncenB08_tr); // вибір шрифту
u8g2.drawStr(0, 24, "Hello Arduino!"); // відображаємо напис
u8g2.sendBuffer(); // відправка на дисплей
delay(1000);
}
Если дисплей ничего не показывает, попробуй другие конструкторы дисплея, например:
Як що дисплей ні чого не відображає спробуйте
U8G2_SH1106_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ A5, /* data=*/ A4, /* reset=*/ U8X8_PIN_NONE);
(цей код I2C, для нестандартних підключень)
Використовуйте I2C Scanner скетч, для перевірки адреси пристрою (зазвичай 0x3C):
Неактивний
Це просто приклад. Пробував розкоментувати рядок GyverOLED<SSD1306_128x64, OLED_BUFFER, OLED_SPI, 8, 7, 6> oled;
Але нічого не вийшло
І не вийде, Вам потрібно зробити самі прості кроки
Переконайтесь що все підключено вірно.
Спробуйте прості приклати, без рушників коду, 10-15 строк
тоді буде видно що не так
Неактивний
Всяке може бути. Може помилка в бібліотеці. Може в монтажі. Може дисплей мертвий.
Я б порекомендував взяти щось простіше, не таке універсальне. І запустити якийсь мінімальний приклад. І з'єднання перевірити. Осцилографом чи логічним аналізатором потикати, чи всі сигнали доходять.
Ви ж рівно рік тому щось робили з тим дисплеєм. Нічого не вийшло?
А то можна і інший дисплей взяти; і2с зручніше.
А взагалі можна з цією бібліотекою використовувати SPI дисплеї або вона лише під I2C
По readme вказано можна.
Неактивний
Доброго вечора. Бібліотека GyverOLED та OLED дисплей SSH1106 не працює.
GyverOLED<SSH1106_128x64> oled;
Ви ініціалізуєте I2C-варіант, а не SPI. Дивіться дефолтові значення параметрів шаблона.
Пробував розкоментувати рядок GyverOLED<SSD1306_128x64, OLED_BUFFER, OLED_SPI, 8, 7, 6> oled;
Чому SSD1306, якщо у вас SSH1106?
Спробував з бібліотекою Adafruit_SH1106 через SPI, то все працює
Так і користувались би цією бібліотекою, а не тим гіверном.
Неактивний
Гувер любить магію плюсових шаблонів. А я не люблю
Є такий код, і у мене є OLED дисплей SPI SSH1106. Хотів його прикрутити
#define OLED_SOFT_BUFFER_64 // Буфер на стороне МК
#include <GyverOLED.h> // Библиотека дисплея
GyverOLED<SSD1306_128x64> oled; // Обьект дисплея
#include <GyverButton.h> // Либа кнопок
GButton up(3, HIGH_PULL); // Кнопки
GButton down(4, HIGH_PULL);
GButton ok(2, HIGH_PULL);
#define ITEMS 24 // Общее кол во пунктов (больше 8 - нужно несколько страниц)
// Битмап с картинкой стрелочки (Если нужен)
const uint8_t ptr_bmp[] PROGMEM = {
0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0xFF, 0xFF, 0x7E, 0x3C, 0x18,
};
void setup() {
oled.init(); // Инциализация дисплея
oled.setContrast(255); // Макс. яркость
}
void loop() {
static int8_t pointer = 0; // Переменная указатель
/* Кнопки */
up.tick(); // Опрос кнопок
down.tick();
ok.tick();
if (up.isClick() or up.isHold()) { // Если кнопку нажали или удерживают
pointer = constrain(pointer - 1, 0, ITEMS - 1); // Двигаем указатель в пределах дисплея
}
if (down.isClick() or down.isHold()) {
pointer = constrain(pointer + 1, 0, ITEMS - 1);
}
if (ok.isClick()) { // Нажатие на ОК - переход в пункт меню
switch (pointer) { // По номеру указателей располагаем вложенные функции (можно вложенные меню)
case 0: func(); break; // По нажатию на ОК при наведении на 0й пункт вызвать функцию
case 1: break;
case 2: break;
case 3: break;
case 4: break;
case 5: break;
case 6: break;
case 7: break;
// И все остальные
}
}
/* меню */
oled.clear(); // Очищаем буфер
oled.home(); // Курсор в левый верхний угол
if (pointer < 8) { // Первая страница
oled.print // Вывод всех пунктов
(F(
" Parameter 0:n" // Не забываем про 'n' - символ переноса строки
" Parameter 1:n"
" Parameter 2:n"
" Parameter 3:n"
" Parameter 4:n"
" Parameter 5:n"
" Parameter 6:n"
" Parameter 7:n"
));
} else if (pointer < 16) {// Вторая страница
oled.print
(F(
" Parameter 8:n"
" Parameter 9:n"
" Parameter 10:n"
" Parameter 11:n"
" Parameter 12:n"
" Parameter 13:n"
" Parameter 14:n"
" Parameter 15:n"
));
} else { // Последняя страница
oled.print
(F(
" Parameter 16:n"
" Parameter 17:n"
" Parameter 18:n"
" Parameter 19:n"
" Parameter 20:n"
" Parameter 21:n"
" Parameter 22:n"
" Parameter 23:n"
));
}
printPointer(pointer); // Вывод указателя
oled.update(); // Выводим кадр на дисплей
}
void printPointer(uint8_t pointer) {
// Символьный указатель - лучший выбор в многостраничном меню
// Указатель в начале строки
oled.setCursor(0, pointer);
oled.print(">");
// Можно еще в конце
/*oled.setCursor(20, pointer);
oled.print("<");*/
// Указатель в виде прямоугольной рамки со скругленными углами
/*oled.roundRect(0, pointer * 8, 127, (pointer * 8) + 6);*/
// Указатель в виде битмапа (картинки)
/*oled.drawBitmap(0, pointer * 8, ptr_bmp, 10, 8);*/
}
/* пример вложеной функции, которую можно вызвать из под меню */
void func(void) {
oled.clear();
oled.home();
oled.print(F("Press OK to return"));
oled.update();
while (1) {
ok.tick();
if (ok.isClick()) return; // return возвращает нас в предыдущее меню
}
}
Неактивний
Ну особисто я не заперечую
Якби мені захотілось такого, як би я робив?
GyverOLED<SSD1306_128x64> oled; // Обьект дисплея
Мабуть спробував би шаблон, який підходить до мого дисплея, 1306 i2c і 1106 SPI мабуть чимсь відрізняються. Але перед тим обов"язково запустив би якусь мінімальну демку, щоб впевнитись, що ця ліба дійсно пряцює з моїм дисплеєм.
Або переписав би під ту лібу, яка точно працює.
Або купив би підходящий дисплей. 120 грн в Україні зразу, чи 1 бакс на Алі за 2 тижні.
Десь так.
А говнокод без синтаксичної розмітки я б взагалі нікому не показував. Тим більше що вмикається вона одною кнопкою. Мені це не коштує нічого, а людям приємно.
#define OLED_SOFT_BUFFER_64 // Буфер на стороне МК
#include <GyverOLED.h> // Библиотека дисплея
GyverOLED<SSD1306_128x64> oled; // Обьект дисплея
#include <GyverButton.h> // Либа кнопок
GButton up(3, HIGH_PULL); // Кнопки
GButton down(4, HIGH_PULL);
GButton ok(2, HIGH_PULL);
#define ITEMS 24 // Общее кол во пунктов (больше 8 - нужно несколько страниц)
Правда, краще ?
Неактивний
Гувер любить магію плюсових шаблонів. А я не люблю
Будь-яка достатньо розвинена технологія не відрізняється від магії - це ще Артур Кларк казав
Яка проблема з шаблонами? Якраз шаблони тут могли би бути правильним рішенням. Це краще, ніж передавати купу параметрів чи структуру в конструктор, сподіваючись, що оптимізатор повикидає їх з рантайма. Але, звісно, не так, як воно у Гувера реалізовано. Судячи по тому корявому коду, він цю "магію" ще не опанував.
Є такий код, і у мене є OLED дисплей SPI SSH1106. Хотів його прикрутити
Цей код ініціалізує I2C-шну SSD1306:
GyverOLED<SSD1306_128x64> oled; // Обьект дисплея
Вам, мабуть, потрібно _TYPE = SSH1106_128x64, _CONN = OLED_SPI, а також піни _CS та _DC відповідно до вашої схеми підключення.
Ще зверніть увагу на коментар:
SSH1106 (только буфер)!
Я гадки не маю, що це значить в тому контексті.
Неактивний
>> Яка проблема з шаблонами?
Мені здається, що шаблони придумані для чогось іншого. ifdef це просто, і зразу видно, що відбувається. Нормальні люди так роблять. А в те що там написано у Гувера, треба спеціально врюхувати.
На ifdef теж можна писати незрозуміло, кнчн
Мені здається, що шаблони придумані для чогось іншого.
Так, для узагальнення алгоритмів та відвʼязки від конкретних типів.
Мали би бути окремі класи з імплементацією для SSD1306 та SSH1106, а також для SPI та I2C, які надають абстрактні інтерфейси. Той самий поліморфізм, тільки гарантовано під час компіляції.
ifdef це просто, і зразу видно, що відбувається.
Це просто, поки у вас один макрос з булевим значенням (defined / not defined). Якщо їх два, то кількість комбінацій уже чотири.
Крім того, добре, якщо автори фреймворку встановили конвенцію про іменування макросів, а автори коду її притримуються. Бо коли у вас зʼявляється дві бібліотеки з однаково названими макросами, то привіт.
Вже не кажу про бідолашних користувачів Arduino IDE, де нема штатного способа визначити макрос опціями компілятора.
У макросів є свої застосування, але не для поліморфізму в C++.
А в те що там написано у Гувера, треба спеціально врюхувати.
Звісно, якщо параметри шаблона використовуються тільки для розгалуження в if'ах, а їх значення визначаються тими ж макросами
Неактивний
З поліморфізмом було б простіше. Може автор таким чином пам'ять економив?
А щодо define/ifdef - на цьому весь Arduino core побудований, і нічого, працює якось В будь яку функцію Ctrl click - і зразу видно, як воно побудоване всередині, що буде білдитись, що ні.
А щодо define/ifdef - на цьому весь Arduino core побудований, і нічого, працює якось
Так отож, що "якось". В core умовна компіляція в основному для різних цільових платформ, які взаємовиключні при збірці.
Поблимати світлодіодом та намалювати прямокутник на єдиному дисплеї - це ще ок. А коли потрібно більше одного інстанса з різними параметрами?
В будь яку функцію Ctrl click - і зразу видно, як воно побудоване всередині, що буде білдитись, що ні.
Де, в Platform IO? Так з шаблонами те ж саме, навести курсор на ідентифікатор, і спливає підказка, з якими параметрами клас інстанційовано. А в імплементації самого класу по-хорошому не має бути ніяких драбин з if ... else if ... else.
Неактивний
>> А коли потрібно більше одного інстанса з різними параметрами?
Я погано уявляю смисл саморобки з 2 різними, але дисплеями Але не бачу проблем, якщо спеціально не робити собі погано.
До речі, ліба Adafruit_SSD1306 всередині на ifdef
Я якось робив саморобку, з цим дисплеєм, енкодером і аналоговими кнопками. І якось так вийшло, що ліба від Гувера для дисплея конфліктувала з лібою від нього ж, але для кнопок Розбиратись було влом - де дисплей, де кнопки, і не розумію я цей його стиль, взяв лібу для дисплея від Adafruit - все завелось. Мораль в цій байці відсутня
Неактивний
Я погано уявляю смисл саморобки з 2 різними, але дисплеями
Для саморобки можна хоч в коді самої "бібліотеки" цвяхами прибити те що потрібно тут і зараз. Головне, не тягнути такі методи в продакшн. Ардуіно як навчальна платформа мала би сприяти грамотному підходу до розробки ПЗ, але ж там інша мета. Піонери купляють модулі, бо "все просто і зрозуміло", а більше і не треба. Потім ці піонери пишуть в резюме "я знаю кунг-фу".
Неактивний
До речі, ліба Adafruit_SSD1306 всередині на ifdef
Не дуже розумію, що значить "всередині на ifdef". Застосовуються директиви препроцесора для умовної компіляції? Так це нормально, так забезпечується кросплатформенність. Тим більше, коли фреймворк не надає інших засобів. Та й ліби від Adafruit - теж далеко не взірець хорошого коду.
Неактивний