Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
project:esp8266_oledx32 [2019/03/06 08:30] cyberian přidání img |
project:esp8266_oledx32 [2019/03/06 13:58] cyberian |
||
---|---|---|---|
Line 7: | Line 7: | ||
===== Úvod ===== | ===== Úvod ===== | ||
- | Cílem je připojit výše zmíněný displej. Popsat první zkušenosti pro lidi, kteří teprve začínají, zkusit si vyrobit bitmapu a úspěšně ji zobrazit. Předpokladem je základní znalost jazyka C++ a elementární znalost elektroniky. Nemusíte umět vyloženě základy číslicových obvodů, ale měli by jste vědět, základní info o součástkách a neodpálit si ESP8266 hned při prvním zapojení. Arduino IDE, by jse měli mít již nastaveno na správnou desku. | + | Cílem je připojit výše zmíněný displej. Popsat první zkušenosti pro lidi, kteří teprve začínají, zkusit si vyrobit bitmapu a úspěšně ji zobrazit. Předpokladem je základní znalost jazyka Cpp a elementární znalost elektroniky. Nemusíte umět vyloženě základy číslicových obvodů, ale měli by jste vědět, základní info o součástkách a neodpálit si ESP8266 hned při prvním zapojení. Arduino IDE, by jse měli mít již nastaveno na správnou desku. |
Co bude potřeba: | Co bude potřeba: | ||
Line 20: | Line 20: | ||
===== Zapojení obvodu ===== | ===== Zapojení obvodu ===== | ||
+ | Kapacitor, který vidíte u napájecí větve není potřeba. Mívám ho standardně ze zvyku u všeho u čeho mám podezření, že by mohlo spičkově odebírat proud, což není tento případ, ale zvyk je zvyk :) | ||
{{ :project:esp8266_nodemcu_v0.9_oled_web.jpg?400 |}} | {{ :project:esp8266_nodemcu_v0.9_oled_web.jpg?400 |}} | ||
+ | |||
+ | ===== Vytvoření bitmapy ===== | ||
+ | Některé konvertory mají problém s určitými rozměry obrázků. | ||
+ | Obrázek je nutno zmenšit ještě před koverzí a ideální je převést ho na stupně šedi nebo monochromatický taktéž před vlastní konverzí. Jako na potvoru pro konverzi malého obrázku 32x29 px fungoval jen Image2Code, který je trochu obtížnější získat | ||
+ | |||
+ | Seznam konvertorů: | ||
+ | * GIMP [[https://www.gimp.org/downloads/]] | ||
+ | * LCD Assisant [[http://en.radzio.dxp.pl/bitmap_converter/]] | ||
+ | * Image2Code https://github.com/adafruit/Adafruit-GFX-Library#useful-resources | ||
+ | |||
+ | Konvertory krom gimpu jsem prověřil na virustotal.com, nicméně i tak doporučuji překontrolovat je znovu. | ||
+ | Image2Code je nástroj poskytnutý v sekci použitelných zdrojů ke knihovně Adafruit GFX napsaný v javě. Je nutno ho zkompilovat přes příkaz "gradle build". Pokud vám to nepůjde, mohu vám v případě windows poslat již sestavenou verzi | ||
+ | |||
+ | Pokud se nepovede konverze z nějakého důvodu ani tak, pak vložte do pole tento obsah: | ||
+ | <code> | ||
+ | { | ||
+ | 0x20,0x0,0x0,0x20, | ||
+ | 0x70,0x0,0x0,0x70, | ||
+ | 0x50,0x0,0x0,0x50, | ||
+ | 0xd8,0x0,0x0,0xd8, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x1,0xc0,0x0,0x0, | ||
+ | 0x3,0x60,0x0,0x0, | ||
+ | 0x2,0x20,0x78,0x0, | ||
+ | 0x2,0x20,0x48,0x0, | ||
+ | 0x2,0x20,0x48,0x0, | ||
+ | 0x3,0x60,0x48,0x0, | ||
+ | 0x1,0xc0,0x38,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x0,0x0,0x0,0x0, | ||
+ | 0x1,0x0,0x8,0x0, | ||
+ | 0x1,0x80,0x8,0x0, | ||
+ | 0x0,0x88,0x98,0x0, | ||
+ | 0x0,0xc5,0x10,0x0, | ||
+ | 0x0,0x42,0x10,0x0, | ||
+ | 0x0,0x65,0x30,0x0, | ||
+ | 0x0,0x28,0xa0,0x0, | ||
+ | 0x0,0x20,0x20,0x0 | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ===== Kód programu ===== | ||
+ | Na začátku je nutno nainstalovat si v Arduino IDE v menu: Nástroje/Spravovat knihovny následující knihovny: | ||
+ | * SSD1306 by adafruit(v mé době ver. 1.28) | ||
+ | * Adafruit GFX by adafruit (v mé době ver. 1.36) | ||
+ | |||
+ | Kód je upraveným příkladem pro SSD1306. V místě, kde je komentář "// ZDE VLOZIT hexaznaky bitmapy" je nutno vložit kód bitmapy, jehož získání bude popsáno níže. | ||
+ | </br> | ||
+ | |||
+ | Kód: | ||
+ | <file cpp oled.ino> | ||
+ | |||
+ | // This is an example for our Monochrome OLEDs based on SSD1306 drivers | ||
+ | </file> | ||
+ | Pick one up today in the adafruit shop! | ||
+ | ------> http://www.adafruit.com/category/63_98 | ||
+ | |||
+ | This example is for a 128x32 pixel display using I2C to communicate | ||
+ | 3 pins are required to interface (two 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, | ||
+ | with contributions from the open source community. | ||
+ | BSD license, check license.txt for more information | ||
+ | All text above, and the splash screen below must be | ||
+ | included in any redistribution. | ||
+ | </file> | ||
+ | #include <Wire.h> | ||
+ | #include <Adafruit_GFX.h> | ||
+ | #include <Adafruit_SSD1306.h> | ||
+ | |||
+ | #define SCREEN_WIDTH 128 // šírka OLED displeje v pixelech | ||
+ | #define SCREEN_HEIGHT 32 // výška OLED displeje | ||
+ | |||
+ | // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) | ||
+ | #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) | ||
+ | // vytvoreni instance objektu typu display jmenem display | ||
+ | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); | ||
+ | |||
+ | //definice velikosti bitmapy | ||
+ | #define MARI_WIDTH 128 | ||
+ | #define MARI_HEIGHT 64 | ||
+ | |||
+ | //bitmapa | ||
+ | |||
+ | static const unsigned char PROGMEM Mari_pole [] = | ||
+ | { | ||
+ | // ZDE VLOZIT hexaznaky bitmapy | ||
+ | }; | ||
+ | |||
+ | void setup() { // v setup() je zvykem nastavit vše potřebné, než skočíme do loop() | ||
+ | Serial.begin(9600); | ||
+ | //Wire.pins(4,5); není nutno nastavovat komunikaci na piny 4 a 5 (D1, D2) | ||
+ | Wire.begin(); // Defaultně Wire.begin použije piny 4 a 5 | ||
+ | delay(2000); | ||
+ | |||
+ | if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { //náš displej má def. adresu 0x3C, pozor pro 128x64 je to 0x3D | ||
+ | Serial.println(F("SSD1306 alokace selhala")); | ||
+ | for(;;); // prasecký druh věčné smyčky | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | display.clearDisplay(); //vymaže buffer displeje. Po startu tam bývají náhodné pixely | ||
+ | // na pozici 0,0 vykresli bitmapu Mari_pole o dané šírce a výšce s hloubkou barev 1 bit. | ||
+ | display.drawBitmap(0,0,Mari_pole, MARI_WIDTH, MARI_HEIGHT, 1); | ||
+ | display.display(); //pošle obsah bufferu displeje do zobrazení na displeji | ||
+ | delay(1000); | ||
+ | //scrolling obrazu. Provádí je sám HW displeje, my zadáváme pouze parametry | ||
+ | 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(); | ||
+ | delay(1000); | ||
+ | |||
+ | /* zde jsem vám nechal na hraní zakomentované různé funkce, které knihovna Adafruit GFX nabízí | ||
+ | * rozhodně doporučuji se podívat do manuálu nebo si zkusit příklad v menu Soubor/Příklady/Adafruit SSD1306/SSD1306_128x32_i2c | ||
+ | */ | ||
+ | |||
+ | // Draw a single pixel in white | ||
+ | /* display.drawPixel(10, 10, WHITE); | ||
+ | |||
+ | // Show the display buffer on the screen. You MUST call display() after | ||
+ | // drawing commands to make them visible on screen! | ||
+ | display.display(); | ||
+ | delay(2000); | ||
+ | // display.display() is NOT necessary after every single drawing command, | ||
+ | // unless that's what you want...rather, you can batch up a bunch of | ||
+ | // drawing operations and then update the screen all at once by calling | ||
+ | // display.display(). These examples demonstrate both approaches... | ||
+ | |||
+ | testdrawline(); // Draw many lines | ||
+ | display.display(); | ||
+ | delay(2000); | ||
+ | testdrawrect(); // Draw rectangles (outlines) | ||
+ | |||
+ | testfillrect(); // Draw rectangles (filled) | ||
+ | |||
+ | testdrawcircle(); // Draw circles (outlines) | ||
+ | |||
+ | testfillcircle(); // Draw circles (filled) | ||
+ | |||
+ | testdrawroundrect(); // Draw rounded rectangles (outlines) | ||
+ | |||
+ | testfillroundrect(); // Draw rounded rectangles (filled) | ||
+ | |||
+ | testdrawtriangle(); // Draw triangles (outlines) | ||
+ | |||
+ | testfilltriangle(); // Draw triangles (filled) | ||
+ | |||
+ | testdrawchar(); // Draw characters of the default font | ||
+ | |||
+ | testdrawstyles(); // Draw 'stylized' characters | ||
+ | |||
+ | testscrolltext(); // Draw scrolling text | ||
+ | |||
+ | testdrawbitmap(); // Draw a small bitmap image | ||
+ | |||
+ | // Invert and restore display, pausing in-between | ||
+ | display.invertDisplay(true); | ||
+ | delay(1000); | ||
+ | display.invertDisplay(false); | ||
+ | delay(1000); | ||
+ | |||
+ | testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps | ||
+ | */ | ||
+ | } | ||
+ | |||
+ | //zde jsou definice funkcí výše zakomentovaných | ||
+ | void testdrawline() { | ||
+ | int16_t i; | ||
+ | |||
+ | display.clearDisplay(); // Clear display buffer | ||
+ | |||
+ | for(i=0; i<display.width(); i+=4) { | ||
+ | display.drawLine(0, 0, i, display.height()-1, WHITE); | ||
+ | display.display(); // Update screen with each newly-drawn line | ||
+ | delay(1); | ||
+ | } | ||
+ | for(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(i=0; i<display.width(); i+=4) { | ||
+ | display.drawLine(0, display.height()-1, i, 0, WHITE); | ||
+ | display.display(); | ||
+ | delay(1); | ||
+ | } | ||
+ | for(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(i=display.width()-1; i>=0; i-=4) { | ||
+ | display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE); | ||
+ | display.display(); | ||
+ | delay(1); | ||
+ | } | ||
+ | for(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(i=0; i<display.height(); i+=4) { | ||
+ | display.drawLine(display.width()-1, 0, 0, i, WHITE); | ||
+ | display.display(); | ||
+ | delay(1); | ||
+ | } | ||
+ | for(i=0; i<display.width(); i+=4) { | ||
+ | display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE); | ||
+ | display.display(); | ||
+ | delay(1); | ||
+ | } | ||
+ | |||
+ | delay(2000); // Pause for 2 seconds | ||
+ | } | ||
+ | |||
+ | void testdrawrect(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | 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(); // Update screen with each newly-drawn rectangle | ||
+ | delay(1); | ||
+ | } | ||
+ | |||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testfillrect(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | for(int16_t i=0; i<display.height()/2; i+=3) { | ||
+ | // The INVERSE color is used so rectangles alternate white/black | ||
+ | display.fillRect(i, i, display.width()-i*2, display.height()-i*2, INVERSE); | ||
+ | display.display(); // Update screen with each newly-drawn rectangle | ||
+ | delay(1); | ||
+ | } | ||
+ | |||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testdrawcircle(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) { | ||
+ | display.drawCircle(display.width()/2, display.height()/2, i, WHITE); | ||
+ | display.display(); | ||
+ | delay(1); | ||
+ | } | ||
+ | |||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testfillcircle(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) { | ||
+ | // The INVERSE color is used so circles alternate white/black | ||
+ | display.fillCircle(display.width() / 2, display.height() / 2, i, INVERSE); | ||
+ | display.display(); // Update screen with each newly-drawn circle | ||
+ | delay(1); | ||
+ | } | ||
+ | |||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testdrawroundrect(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | 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); | ||
+ | } | ||
+ | |||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testfillroundrect(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | for(int16_t i=0; i<display.height()/2-2; i+=2) { | ||
+ | // The INVERSE color is used so round-rects alternate white/black | ||
+ | display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, | ||
+ | display.height()/4, INVERSE); | ||
+ | display.display(); | ||
+ | delay(1); | ||
+ | } | ||
+ | |||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testdrawtriangle(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | for(int16_t i=0; i<max(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); | ||
+ | } | ||
+ | |||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testfilltriangle(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) { | ||
+ | // The INVERSE color is used so triangles alternate white/black | ||
+ | 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, INVERSE); | ||
+ | display.display(); | ||
+ | delay(1); | ||
+ | } | ||
+ | |||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testdrawchar(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | display.setTextSize(1); // Normal 1:1 pixel scale | ||
+ | display.setTextColor(WHITE); // Draw white text | ||
+ | display.setCursor(0, 0); // Start at top-left corner | ||
+ | display.cp437(true); // Use full 256 char 'Code Page 437' font | ||
+ | |||
+ | // Not all the characters will fit on the display. This is normal. | ||
+ | // Library will draw what it can and the rest will be clipped. | ||
+ | for(int16_t i=0; i<256; i++) { | ||
+ | if(i == '\n') display.write(' '); | ||
+ | else display.write(i); | ||
+ | } | ||
+ | |||
+ | display.display(); | ||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testdrawstyles(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | display.setTextSize(1); // Normal 1:1 pixel scale | ||
+ | display.setTextColor(WHITE); // Draw white text | ||
+ | display.setCursor(0,0); // Start at top-left corner | ||
+ | display.println(F("Hello, world!")); | ||
+ | |||
+ | display.setTextColor(BLACK, WHITE); // Draw 'inverse' text | ||
+ | display.println(3.141592); | ||
+ | |||
+ | display.setTextSize(2); // Draw 2X-scale text | ||
+ | display.setTextColor(WHITE); | ||
+ | display.print(F("0x")); display.println(0xDEADBEEF, HEX); | ||
+ | |||
+ | display.display(); | ||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void testscrolltext(void) { | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | display.setTextSize(2); // Draw 2X-scale text | ||
+ | display.setTextColor(WHITE); | ||
+ | display.setCursor(10, 0); | ||
+ | display.println(F("scroll")); | ||
+ | display.display(); // Show initial text | ||
+ | delay(100); | ||
+ | |||
+ | // Scroll in various directions, pausing in-between: | ||
+ | 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(); | ||
+ | delay(1000); | ||
+ | } | ||
+ | </file> | ||
+ | |||