Вопрос по ESP8266 с встроенным OLED
- Войдите на сайт для отправки комментариев
Приобрел на https://ru.aliexpress.com/item/-/32841144473.html?spm=a2g0s.8937460.0.0.11a62e0eqfl3D6 вот такой девайс:
Пришел с залитым скетчем. Всё было норме. Начал искать на просторах интернета примеры, для изучения... тут начались траблы. В цикле до 5000 вывожу цифры... Всё выводиться примерно около минуты, потом дисплей гаснет, но контроллер продолжает работать(диод моргает, в порт данные сыплются). Потом делаю рестарт, и тут уже дело как в лоторее сколько он проработает..но дисплей начинает отрубаться еще раньше(каждый раз по разному)..Ну тут логично предположить, что где то косяк по железу. Заснял видос закинул Китайцу, тот молчит, открыл спор-деньги вернули. !!!Заказал такой же в другом магазине..Специально не заливал скетч, что бы проверить как будет выводиться заводской..работает всё в норме и не обрубается.. Заливаю свой-работает пару сек и гаснет...
#include <ESP8266WiFi.h> #include <String.h> #include <SSD1306.h> #include <SSD1306Wire.h> String str; SSD1306 display(0x3C, 4, 5); //0x3d for the Adafruit 1.3" OLED, 0x3C being the usual address of the OLED void setup () { Serial.begin(115200); // most ESP-01's use 115200 but this could vary display.init(); display.flipScreenVertically(); } void loop() { for (int i=0; i <= 5000; i++) { str=i; display.clear(); // Очищаем экран от предыдущих данных display.setTextAlignment(TEXT_ALIGN_CENTER); // Выравниваем текст по центру display.setFont(ArialMT_Plain_24); // Стандартный шрифт из библиотеки display.drawString(64, 8, "ARDULOG"); // Первая строка в координаты 64 по оси X и 8 по оси Y display.drawString(64, 32, str); // Вторая строка display.display(); // Выводим все на экран delay(200); Serial.println(i); } }
/********************************************************************* This is an example for our Monochrome OLEDs based on SSD1306 drivers Pick one up today in the adafruit shop! ------> http://www.adafruit.com/category/63_98 This example is for a 128x64 size display using I2C to communicate 3 pins are required to interface (2 I2C and one reset) Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. BSD license, check license.txt for more information All text above, and the splash screen must be included in any redistribution *********************************************************************/ #include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define OLED_RESET D4 Adafruit_SSD1306 display(OLED_RESET); #define NUMFLAKES 10 #define XPOS 0 #define YPOS 1 #define DELTAY 2 #define LOGO16_GLCD_HEIGHT 16 #define LOGO16_GLCD_WIDTH 16 static const unsigned char PROGMEM logo16_glcd_bmp[] = { B00000000, B11000000, B00000001, B11000000, B00000001, B11000000, B00000011, B11100000, B11110011, B11100000, B11111110, B11111000, B01111110, B11111111, B00110011, B10011111, B00011111, B11111100, B00001101, B01110000, B00011011, B10100000, B00111111, B11100000, B00111111, B11110000, B01111100, B11110000, B01110000, B01110000, B00000000, B00110000 }; #if (SSD1306_LCDHEIGHT != 64) #error("Height incorrect, please fix Adafruit_SSD1306.h!"); #endif void setup() { Serial.begin(9600); // by default, we'll generate the high voltage from the 3.3v line internally! (neat!) display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64) // init done // Show image buffer on the display hardware. // Since the buffer is intialized with an Adafruit splashscreen // internally, this will display the splashscreen. display.display(); delay(2000); // Clear the buffer. display.clearDisplay(); // draw a single pixel display.drawPixel(10, 10, WHITE); // Show the display buffer on the hardware. // NOTE: You _must_ call display after making any drawing commands // to make them visible on the display hardware! display.display(); delay(2000); display.clearDisplay(); // draw many lines testdrawline(); display.display(); delay(2000); display.clearDisplay(); // draw rectangles testdrawrect(); display.display(); delay(2000); display.clearDisplay(); // draw multiple rectangles testfillrect(); display.display(); delay(2000); display.clearDisplay(); // draw mulitple circles testdrawcircle(); display.display(); delay(2000); display.clearDisplay(); // draw a white circle, 10 pixel radius display.fillCircle(display.width()/2, display.height()/2, 10, WHITE); display.display(); delay(2000); display.clearDisplay(); testdrawroundrect(); delay(2000); display.clearDisplay(); testfillroundrect(); delay(2000); display.clearDisplay(); testdrawtriangle(); delay(2000); display.clearDisplay(); testfilltriangle(); delay(2000); display.clearDisplay(); // draw the first ~12 characters in the font testdrawchar(); display.display(); delay(2000); display.clearDisplay(); // draw scrolling text testscrolltext(); delay(2000); display.clearDisplay(); // text display tests display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0,0); display.println("Hello, world!"); display.setTextColor(BLACK, WHITE); // 'inverted' text display.println(3.141592); display.setTextSize(2); display.setTextColor(WHITE); display.print("0x"); display.println(0xDEADBEEF, HEX); display.display(); delay(2000); display.clearDisplay(); // miniature bitmap display display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1); display.display(); delay(1); // invert the display display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); display.clearDisplay(); // draw a bitmap icon and 'animate' movement testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH); } void loop() { } void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) { uint8_t icons[NUMFLAKES][3]; // initialize for (uint8_t f=0; f< NUMFLAKES; f++) { icons[f][XPOS] = random(display.width()); icons[f][YPOS] = 0; icons[f][DELTAY] = random(5) + 1; Serial.print("x: "); Serial.print(icons[f][XPOS], DEC); Serial.print(" y: "); Serial.print(icons[f][YPOS], DEC); Serial.print(" dy: "); Serial.println(icons[f][DELTAY], DEC); } while (1) { // draw each icon for (uint8_t f=0; f< NUMFLAKES; f++) { display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE); } display.display(); delay(200); // then erase it + move it for (uint8_t f=0; f< NUMFLAKES; f++) { display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK); // move it icons[f][YPOS] += icons[f][DELTAY]; // if its gone, reinit if (icons[f][YPOS] > display.height()) { icons[f][XPOS] = random(display.width()); icons[f][YPOS] = 0; icons[f][DELTAY] = random(5) + 1; } } } } void testdrawchar(void) { display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0,0); for (uint8_t i=0; i < 168; i++) { if (i == '\n') continue; display.write(i); if ((i > 0) && (i % 21 == 0)) display.println(); } display.display(); delay(1); } void testdrawcircle(void) { for (int16_t i=0; i<display.height(); i+=2) { display.drawCircle(display.width()/2, display.height()/2, i, WHITE); display.display(); delay(1); } } void testfillrect(void) { uint8_t color = 1; for (int16_t i=0; i<display.height()/2; i+=3) { // alternate colors display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2); display.display(); delay(1); color++; } } void testdrawtriangle(void) { for (int16_t i=0; i<min(display.width(),display.height())/2; i+=5) { display.drawTriangle(display.width()/2, display.height()/2-i, display.width()/2-i, display.height()/2+i, display.width()/2+i, display.height()/2+i, WHITE); display.display(); delay(1); } } void testfilltriangle(void) { uint8_t color = WHITE; for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) { display.fillTriangle(display.width()/2, display.height()/2-i, display.width()/2-i, display.height()/2+i, display.width()/2+i, display.height()/2+i, WHITE); if (color == WHITE) color = BLACK; else color = WHITE; display.display(); delay(1); } } void testdrawroundrect(void) { for (int16_t i=0; i<display.height()/2-2; i+=2) { display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, WHITE); display.display(); delay(1); } } void testfillroundrect(void) { uint8_t color = WHITE; for (int16_t i=0; i<display.height()/2-2; i+=2) { display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color); if (color == WHITE) color = BLACK; else color = WHITE; display.display(); delay(1); } } void testdrawrect(void) { for (int16_t i=0; i<display.height()/2; i+=2) { display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE); display.display(); delay(1); } } void testdrawline() { for (int16_t i=0; i<display.width(); i+=4) { display.drawLine(0, 0, i, display.height()-1, WHITE); display.display(); delay(1); } for (int16_t i=0; i<display.height(); i+=4) { display.drawLine(0, 0, display.width()-1, i, WHITE); display.display(); delay(1); } delay(250); display.clearDisplay(); for (int16_t i=0; i<display.width(); i+=4) { display.drawLine(0, display.height()-1, i, 0, WHITE); display.display(); delay(1); } for (int16_t i=display.height()-1; i>=0; i-=4) { display.drawLine(0, display.height()-1, display.width()-1, i, WHITE); display.display(); delay(1); } delay(250); display.clearDisplay(); for (int16_t i=display.width()-1; i>=0; i-=4) { display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE); display.display(); delay(1); } for (int16_t i=display.height()-1; i>=0; i-=4) { display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE); display.display(); delay(1); } delay(250); display.clearDisplay(); for (int16_t i=0; i<display.height(); i+=4) { display.drawLine(display.width()-1, 0, 0, i, WHITE); display.display(); delay(1); } for (int16_t i=0; i<display.width(); i+=4) { display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE); display.display(); delay(1); } delay(250); } void testscrolltext(void) { display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(10,0); display.clearDisplay(); display.println("scroll"); display.display(); delay(1); display.startscrollright(0x00, 0x0F); delay(2000); display.stopscroll(); delay(1000); display.startscrollleft(0x00, 0x0F); delay(2000); display.stopscroll(); delay(1000); display.startscrolldiagright(0x00, 0x07); delay(2000); display.startscrolldiagleft(0x00, 0x07); delay(2000); display.stopscroll(); }
А если я расскажу в чём дело, Вы вернёте китайцу деньги?
А если я расскажу в чём дело, Вы вернёте китайцу деньги?
Несомненно)) Он же отвечал на мои сообщения и давал внятные консультации ))
Несомненно)) Он же отвечал на мои сообщения и давал внятные консультации ))
А он должен был и программировать вас учить?
Кстати, когда открывали спор - не забыли сказать. что тестовые скетчи работают, а ваш - нет?
Хорошо.
Я тут как-то выкладывал библиотеку MemoryExplorer. Так вот, я напустил её на Вашу программу, причём не на Вашу, а на её жутко упрощённый обрезок.
Вот текст обрезка
Как видите, я выбросил всё связанное с дисплеем потому, что у меня его нет, оставил только работу со "String". Как у Вас. И даже в таком виде, из-за неаккуратной работы со String, она у Вас в процессе работы отжирает память. Причём неравномерно.
Вот протокол её работы (можете и сами запустить). Неинтересные для нас куски я скоратил и поставил многоточия.
Как вмдите, У Вас сразу же появилась фрагментация памяти (строка №7). Потом она возросла (№17). Потом исчезла (№26). Потом появилась снова (№36).
Само по себе это плохо, но не смертельно - так бы она работала.
Но это ведь только огрызок программы! Теперь давайте посмотрим на Вашу библиотеку (надеюсь, я смотрю на ту же, что и у Вас - и почему вы все никогда ссылок не даёте? Их же много с одинаковыми именами!).
В файле OLEDDisplay.cpp функция drawString получает строку по значению (если Вы прочитали материал на который я сослася в начале, то знаете, что без крайней нужды этого делать нельзя, и знаете почему). Далее она вызывает utf8ascii и ей тоже передаёт строку по значению, делая второй ненужный запрос памяти и создавая вторую ненужную копию Вашей строки! Та, в свою очередь, хапает кусок памяти malloc'ом и, в принципе проверяет выделился ли он, но, после проверки ничего не делает и спокойно возвращает полученный указатель.
Ну, а поскольку вся эта красота происходит на фоне Вашей собственной фрагментации, которую мы видели в моём урезанном примере, в какой-то момент памяти не хватает и программа ломается.
Если вставите мой эксплорер в свою программу и запустите её с ним, Вы наверняка увидите, что память постепенно идёт вразнос. Опять же если Вы вставите в библиотеку реальную проверку выделилась ли память и печать в сериал сообщения, то увидите, что памяти не хватило. Я практически уверен в этом.
Теперь "что делать?". Так трудно говорить, но попробуйте удалить строку 7, а в самое начало строки 22 вставить слово string и пробел. Если не поможет, то тогда уж точно, вставляйте memoryexplorer, печатайте отчёт о памяти в конце цикла (как я это делаю) и выкладывайте получившийся код, протокол работы и ссылку на Вашу библиотеку. Будем смотреть.
Евгений, это красиво. но думаю дело не в этом. Ваш код не обьясняет, почему программа дохнет после пары секугд работы - то есть примерно после 10 циклов.
Похоже, дело все-таки в тех строчках, которые вы выкинули. У ТС в строке 15 стоит поворот дисплея вертикально. Не знаю, как это организовано в библиотеке, но похоже, что координаты Х и У меняются местами... а потом он выводит что-то в кординаты 64,32 на дисплее с размером в 32 пикселя...
Может быть. Надо исключать всё по очереди. Одно за одним. Пусть попробует с памятью для начала.
Несомненно)) Он же отвечал на мои сообщения и давал внятные консультации ))
А он должен был и программировать вас учить?
Кстати, когда открывали спор - не забыли сказать. что тестовые скетчи работают, а ваш - нет?
Так это и не мои скетчи. Они взяты с просторов интернета и у людей работают. Или желязяки разные чуть или заведомо не рабочие вылаживают скетчи. Второй пример, вообще с библиотеки. Когда прикосался пальцем к одному из нижних контактов(scl,d0,a0), не помню точно к какому, то дисплей рубило сразу. Как я писал выше, чем дольше работал контроллер, тем чаще выключался дисплей. По этому я предположил, что гдето не очень хороший контакт. Если дело окажется дийствительно в программной части, то с китайцем спишусь по любому.
Когда прикосался пальцем к одному из нижних контактов(scl,d0,a0), не помню точно к какому, то дисплей рубило сразу.
Вы напишите четче - дисплей отрубается на любых скетчах или только на определенном? - это как бы принцпиально для диагностики... а то мы будем код разбирать, а у вас и правда "сопля" на контактах...
А пальцем в контакты в электронике лучше не лазать - это так и рабочий блок может не рабочим стать.
На любых скетчах. Первая плата значительно дольше работает на тех же скетчах, а вот вторую рубит гдето на 3-4 секунде(т.е сразу). Скоро дам ссылку на видос
По ссылке на видос сразу идет скачивание. Видос 17Мб весит.
Собрал Вашу библиотеку, не проходит компиляцию:
Бибоиотеки(В ней же и библиотека MemoryExplorer.h (мож что не правильно сделал)):
https://cloud.mail.ru/public/LPBW/ysRDTyuMi
Видос(на этом видосе, первый и трнетий раз обрубился экран в одно и тоже время):
https://www.dropbox.com/s/cn8j3swyqcneehh/674_NEW.avi?dl=1
Поянтно. Плата-то у Вас ESP, значит там нет в таких системных пееменных.
"string" переставляли? Не помогло?
Поянтно. Плата-то у Вас ESP, значит там нет в таких системных пееменных.
"string" переставляли? Не помогло?
Имеете ввиду объявить в setup() или loop()?? Если да, то получилось объявить только в loop(); но эфект тот же
Нет, не просто в loop, а в цикл см. последний абзац в #4.
Нет, не просто в loop, а в цикл см. последний абзац в #4.
Не дает объявить, ругается что в цикле должны объявляться только переменные int, или конвертировать как-то надо.
Библтотеки закинуть??
А, ну, конечно, не
String str=i;
а
String str(i);
А, ну, конечно, не
String str=i;
а
String str(i);
Беру плату в руку, контакты не лапаю.. ресет и дисплей-начинает роботать.. убираю руку-сразу гаснет дисплей
У меня такое было, когда на SPI-дисплее контакт SS не был никуда притянут.
Значит надо попробовать резистором от 1К подтянуть к земле или питанию ??? просто надо знать к чему, что бы не вывести из строя ))) Верояно Вы имели ввиду SC??
Значит надо попробовать резистором от 1К подтянуть к земле или питанию ??? просто надо знать к чему, что бы не вывести из строя )))
Я притягивал к GND. Если взять резистор побольше - от 10К - в любом случае ничего не сгорит :)
Но желательно сначала разобраться. что за дисплей у вас... в описании не указан тип подключения - SPI. I2C или еще что... На названия пинов ориентироваться нет смысла - китайцы пишут их от балды.
В описании китаец пишет OLED cp2014.
В библиотеке SSD1306.h, которую использую написано что интерфейс SPI.
// initialize with the I2C addr 0x3D (for the 128x64)
https://robotzero.one/heltec-wifi-kit-8/
У тя на картинке самой первой прям написано. OLED SCL и OLED SDA , какой на.ер SPI?
Запусти I2C сканнер и посмотри адрес дисплею.
У тя на картинке самой первой прям написано. OLED SCL и OLED SDA , какой на.ер SPI?
Запусти I2C сканнер и посмотри адрес дисплею.
Адрес устройства указан в одной из строк первого скетча:
SSD1306 display(0x3C, 4, 5); т.е. 0x3C
Этои же адрес выдают и сканеры
Ну а тада SPI при чем?
Кино и немцы :)
Проблема частично решается.... закоментировал строчку очистки экрана(эт про первый скетч), плата проходит около 300 циклов(старый предел в 24). Но естественно получается каша(надо будет пробовать затирать чисто эту облость в цвет фона). Вероятно всего что библиотеки не совсем подходят под эту платформу, и как предпологалось в верхних сообщениях сильно захломляются ресурсы.
Если выводить одно словоо, то вообще не виснет