Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
project:esp8266_oledx32 [2019/03/05 21:03]
cyberian úvodní pokec
project:esp8266_oledx32 [2019/03/07 10:20] (current)
cyberian [Kód programu] zvýraznění řádku41
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í.+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: 
 +  * ESP8266 (Nodemcu nebo např. Wemos mini D1) 
 +  * 2x 2K7 rezistor 
 +  * OLED-091 diymore 128x32 I2C dispej 
 +  * nepájivé kontaktní pole, případně pájitelné 
 + 
 +Prakticky všechny zapojení, která jsem našel, byli bez pull up rezistorů. Pokud o nich nic nevíte doporučuji si něco načíst. 
 +Pull up rezistory (4K7) jsou v našem případě již na spodku desky OLED displeje. Bohužel však nestačili, což jsme zjistili v Labce na osciloskopu,​ kde místo obdélníkového signálu byla pila. 
 +V našem případě vedou pull up rezisotry napětí 3,3 V na D1 a D2, kde D1 vede na hodiny displeje(SCL) a D2 na data(SDA). V počtu pochých dvou linek je výhoda v I2C sběrnici narozdíl od SPI sběrnice, kde potřebujete na samotnou komunikaci více pinů. 
 + 
 +===== 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 |}} 
 + 
 +===== 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) 
 + 
 +V kódu je komentář "ZDE VLOZIT hexaznaky bitmapy"​. 
 +Pro zkopírování kód stačí dvojklik na kód a ctrl+c 
 + 
 +<sxh cpp;​highlight:​ [41]>/​* 
 +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 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. 
 +*/ 
 + 
 +#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);​ 
 +
 +</​sxh>​
  
  
  • project/esp8266_oledx32.1551816232.txt.gz
  • Last modified: 2019/03/05 21:03
  • by cyberian