{"id":95428,"date":"2020-04-07T14:06:37","date_gmt":"2020-04-07T14:06:37","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=95428"},"modified":"2021-06-30T14:11:29","modified_gmt":"2021-06-30T14:11:29","slug":"micropython-ssd1306-oled-scroll-shapes-esp32-esp8266","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/micropython-ssd1306-oled-scroll-shapes-esp32-esp8266\/","title":{"rendered":"MicroPython: SSD1306 OLED Display Scroll Functions and Draw Shapes (ESP32\/ESP8266)"},"content":{"rendered":"\n<p>This guide shows additional functions to control an OLED display with MicroPython using the ESP32 or ESP8266. You&#8217;ll learn how to scroll the entire screen horizontally and vertically and how to draw shapes.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-SSD1306-OLED-MicroPython-Shapes-Scroll.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"MicroPython: SSD1306 OLED Display Scroll Functions and Draw Shapes ESP32 ESP8266\" class=\"wp-image-95663\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-SSD1306-OLED-MicroPython-Shapes-Scroll.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-SSD1306-OLED-MicroPython-Shapes-Scroll.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-SSD1306-OLED-MicroPython-Shapes-Scroll.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-SSD1306-OLED-MicroPython-Shapes-Scroll.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n\n<p class=\"rntbox rntclgray\">We recommend that you follow this getting started guide for the OLED display with MicroPython, first: <a href=\"https:\/\/randomnerdtutorials.com\/micropython-oled-display-esp32-esp8266\/\">MicroPython OLED Display with ESP32 and ESP8266<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>To follow this tutorial you need MicroPython firmware installed in your ESP32 or ESP8266 boards. You also need an IDE to write and upload the code to your board. We suggest using Thonny IDE or uPyCraft IDE:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Thonny IDE:<ul><li><a href=\"https:\/\/randomnerdtutorials.com\/getting-started-thonny-micropython-python-ide-esp32-esp8266\/\">Installing and getting started with Thonny IDE<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/flashing-micropython-firmware-esptool-py-esp32-esp8266\/\">Flashing MicroPython Firmware with esptool.py<\/a><\/li><\/ul><\/li><li>uPyCraft IDE:<ul><li><a href=\"https:\/\/randomnerdtutorials.com\/getting-started-micropython-esp32-esp8266\/\">Getting Started with uPyCraft IDE<\/a><\/li><li>Install uPyCraft IDE (<a href=\"https:\/\/randomnerdtutorials.com\/install-upycraft-ide-windows-pc-instructions\/\">Windows<\/a>,&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/install-upycraft-ide-mac-os-x-instructions\/\">Mac OS X<\/a>,&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/install-upycraft-ide-linux-ubuntu-instructions\/\">Linux<\/a>)<\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/flash-upload-micropython-firmware-esp32-esp8266\/\">Flash\/Upload MicroPython Firmware to ESP32 and ESP8266<\/a><\/li><\/ul><\/li><\/ul>\n\n\n\n<p>Learn more about MicroPython:&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\">MicroPython Programming with ESP32 and ESP8266 eBook<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Parts Required<\/h2>\n\n\n\n<p>Here\u2019s a list of parts you need for this tutorial:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\">ESP32<\/a>&nbsp;or&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\">ESP8266<\/a>&nbsp;(read&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/esp32-vs-esp8266\/\" target=\"_blank\">ESP32 vs ESP8266<\/a>)<\/li><li><a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/oled-display-128x64-0-96-inch\/\" target=\"_blank\">0.96 inch OLED display<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" style=\"font-size: inherit; background-color: initial;\" href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\">Breadboard<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\">Jumper wires<\/a><\/li><\/ul>\n\n\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Schematic &#8211; ESP32<\/h2>\n\n\n\n<p>Follow the next schematic diagram if you\u2019re using an ESP32 board:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32_OLED.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"873\" height=\"685\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32_OLED.png?resize=873%2C685&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"OLED display SSD1306 with ESP32 MicroPython schematic diagram circuit I2C SCL SDA\" class=\"wp-image-85566\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32_OLED.png?w=873&amp;quality=100&amp;strip=all&amp;ssl=1 873w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32_OLED.png?resize=300%2C235&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32_OLED.png?resize=768%2C603&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 873px) 100vw, 873px\" \/><\/a><\/figure><\/div>\n\n\n\n<p class=\"rntbox rntclblue\"><strong>Recommended reading:<\/strong> <a href=\"https:\/\/randomnerdtutorials.com\/esp32-pinout-reference-gpios\/\">ESP32 Pinout Reference Guide<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Schematic &#8211; ESP8266 NodeMCU<\/h2>\n\n\n\n<p>Follow the next schematic diagram if you\u2019re using an ESP8266 NodeMCU board:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/es8266-oled_bb-1.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"828\" height=\"534\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/es8266-oled_bb-1.png?resize=828%2C534&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"OLED display SSD1306 with ESP8266 NodeMCU MicroPython schematic diagram circuit I2C SCL SDA\" class=\"wp-image-85567\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/es8266-oled_bb-1.png?w=828&amp;quality=100&amp;strip=all&amp;ssl=1 828w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/es8266-oled_bb-1.png?resize=300%2C193&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/es8266-oled_bb-1.png?resize=768%2C495&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 828px) 100vw, 828px\" \/><\/a><\/figure><\/div>\n\n\n\n<p class=\"rntbox rntclblue\"><strong>Recommended reading:<\/strong> <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-pinout-reference-gpios\/\">ESP8266 Pinout Reference Guide<\/a> <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SSD1306 OLED Library<\/h2>\n\n\n\n<p>The library to write to the OLED display isn\u2019t part of the standard MicroPython library by default. So, you need to upload the library to your ESP32\/ESP8266 board. <\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># MicroPython SSD1306 OLED driver, I2C and SPI interfaces created by Adafruit\n\nimport time\nimport framebuf\n\n# register definitions\nSET_CONTRAST        = const(0x81)\nSET_ENTIRE_ON       = const(0xa4)\nSET_NORM_INV        = const(0xa6)\nSET_DISP            = const(0xae)\nSET_MEM_ADDR        = const(0x20)\nSET_COL_ADDR        = const(0x21)\nSET_PAGE_ADDR       = const(0x22)\nSET_DISP_START_LINE = const(0x40)\nSET_SEG_REMAP       = const(0xa0)\nSET_MUX_RATIO       = const(0xa8)\nSET_COM_OUT_DIR     = const(0xc0)\nSET_DISP_OFFSET     = const(0xd3)\nSET_COM_PIN_CFG     = const(0xda)\nSET_DISP_CLK_DIV    = const(0xd5)\nSET_PRECHARGE       = const(0xd9)\nSET_VCOM_DESEL      = const(0xdb)\nSET_CHARGE_PUMP     = const(0x8d)\n\n\nclass SSD1306:\n    def __init__(self, width, height, external_vcc):\n        self.width = width\n        self.height = height\n        self.external_vcc = external_vcc\n        self.pages = self.height \/\/ 8\n        # Note the subclass must initialize self.framebuf to a framebuffer.\n        # This is necessary because the underlying data buffer is different\n        # between I2C and SPI implementations (I2C needs an extra byte).\n        self.poweron()\n        self.init_display()\n\n    def init_display(self):\n        for cmd in (\n            SET_DISP | 0x00, # off\n            # address setting\n            SET_MEM_ADDR, 0x00, # horizontal\n            # resolution and layout\n            SET_DISP_START_LINE | 0x00,\n            SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0\n            SET_MUX_RATIO, self.height - 1,\n            SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0\n            SET_DISP_OFFSET, 0x00,\n            SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,\n            # timing and driving scheme\n            SET_DISP_CLK_DIV, 0x80,\n            SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,\n            SET_VCOM_DESEL, 0x30, # 0.83*Vcc\n            # display\n            SET_CONTRAST, 0xff, # maximum\n            SET_ENTIRE_ON, # output follows RAM contents\n            SET_NORM_INV, # not inverted\n            # charge pump\n            SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,\n            SET_DISP | 0x01): # on\n            self.write_cmd(cmd)\n        self.fill(0)\n        self.show()\n\n    def poweroff(self):\n        self.write_cmd(SET_DISP | 0x00)\n\n    def contrast(self, contrast):\n        self.write_cmd(SET_CONTRAST)\n        self.write_cmd(contrast)\n\n    def invert(self, invert):\n        self.write_cmd(SET_NORM_INV | (invert &amp; 1))\n\n    def show(self):\n        x0 = 0\n        x1 = self.width - 1\n        if self.width == 64:\n            # displays with width of 64 pixels are shifted by 32\n            x0 += 32\n            x1 += 32\n        self.write_cmd(SET_COL_ADDR)\n        self.write_cmd(x0)\n        self.write_cmd(x1)\n        self.write_cmd(SET_PAGE_ADDR)\n        self.write_cmd(0)\n        self.write_cmd(self.pages - 1)\n        self.write_framebuf()\n\n    def fill(self, col):\n        self.framebuf.fill(col)\n\n    def pixel(self, x, y, col):\n        self.framebuf.pixel(x, y, col)\n\n    def scroll(self, dx, dy):\n        self.framebuf.scroll(dx, dy)\n\n    def text(self, string, x, y, col=1):\n        self.framebuf.text(string, x, y, col)\n\n\nclass SSD1306_I2C(SSD1306):\n    def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False):\n        self.i2c = i2c\n        self.addr = addr\n        self.temp = bytearray(2)\n        # Add an extra byte to the data buffer to hold an I2C data\/command byte\n        # to use hardware-compatible I2C transactions.  A memoryview of the\n        # buffer is used to mask this byte from the framebuffer operations\n        # (without a major memory hit as memoryview doesn't copy to a separate\n        # buffer).\n        self.buffer = bytearray(((height \/\/ 8) * width) + 1)\n        self.buffer[0] = 0x40  # Set first byte of data buffer to Co=0, D\/C=1\n        self.framebuf = framebuf.FrameBuffer1(memoryview(self.buffer)[1:], width, height)\n        super().__init__(width, height, external_vcc)\n\n    def write_cmd(self, cmd):\n        self.temp[0] = 0x80 # Co=1, D\/C#=0\n        self.temp[1] = cmd\n        self.i2c.writeto(self.addr, self.temp)\n\n    def write_framebuf(self):\n        # Blast out the frame buffer using a single I2C transaction to support\n        # hardware I2C interfaces.\n        self.i2c.writeto(self.addr, self.buffer)\n\n    def poweron(self):\n        pass\n\n\nclass SSD1306_SPI(SSD1306):\n    def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):\n        self.rate = 10 * 1024 * 1024\n        dc.init(dc.OUT, value=0)\n        res.init(res.OUT, value=0)\n        cs.init(cs.OUT, value=1)\n        self.spi = spi\n        self.dc = dc\n        self.res = res\n        self.cs = cs\n        self.buffer = bytearray((height \/\/ 8) * width)\n        self.framebuf = framebuf.FrameBuffer1(self.buffer, width, height)\n        super().__init__(width, height, external_vcc)\n\n    def write_cmd(self, cmd):\n        self.spi.init(baudrate=self.rate, polarity=0, phase=0)\n        self.cs.high()\n        self.dc.low()\n        self.cs.low()\n        self.spi.write(bytearray([cmd]))\n        self.cs.high()\n\n    def write_framebuf(self):\n        self.spi.init(baudrate=self.rate, polarity=0, phase=0)\n        self.cs.high()\n        self.dc.high()\n        self.cs.low()\n        self.spi.write(self.buffer)\n        self.cs.high()\n\n    def poweron(self):\n        self.res.high()\n        time.sleep_ms(1)\n        self.res.low()\n        time.sleep_ms(10)\n        self.res.high()\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/ESP-MicroPython\/raw\/master\/code\/Others\/OLED\/ssd1306.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Follow the next set of instructions for the IDE you\u2019re using:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>A. Upload OLED library with&nbsp;<strong>uPyCraft IDE<\/strong><\/li><li>B. Upload OLED library with&nbsp;<strong>Thonny IDE<\/strong><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">A. Upload OLED library with uPyCraft IDE<\/h3>\n\n\n\n<p>This section shows how to upload a library using uPyCraft IDE. If you\u2019re using Thonny IDE, read the next section.<\/p>\n\n\n\n<p><strong>1.<\/strong>&nbsp;Create a new file by pressing the&nbsp;<strong>New File<\/strong>&nbsp;button.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"135\" height=\"41\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/uPycraft-ide-tools-menu-new-file.png?resize=135%2C41&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75063\"\/><\/figure><\/div>\n\n\n\n<p><strong>2.<\/strong>&nbsp;Copy the OLED library code into that file. The&nbsp;<a href=\"https:\/\/raw.githubusercontent.com\/RuiSantosdotme\/ESP-MicroPython\/master\/code\/Others\/OLED\/ssd1306.py\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">OLED library code can be found here<\/a>.<\/p>\n\n\n\n<p><strong>Note:<\/strong>&nbsp;the SSD1306 OLED display library was built by Adafruit and will no longer<br>be updated. At the moment, it works fine. However, we\u2019ll update this guide if we<br>find a similar library that works as well as this one.<\/p>\n\n\n\n<p><strong>3.<\/strong>&nbsp;After copying the code, save the file by pressing the&nbsp;<strong>Save&nbsp;<\/strong>button.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"142\" height=\"47\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/uPycraft-ide-tools-menu-save-file.png?resize=142%2C47&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75064\"\/><\/figure><\/div>\n\n\n\n<p><strong>4.<\/strong>&nbsp;Call this new file \u201c<strong>ssd1306.py<\/strong>\u201d and press&nbsp;<strong>ok<\/strong>.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"784\" height=\"704\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/install_ssd1306.png?resize=784%2C704&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"import library upycraft ide save file\" class=\"wp-image-85579\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/install_ssd1306.png?w=784&amp;quality=100&amp;strip=all&amp;ssl=1 784w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/install_ssd1306.png?resize=300%2C269&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/install_ssd1306.png?resize=768%2C690&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 784px) 100vw, 784px\" \/><\/figure><\/div>\n\n\n\n<p><strong>5.<\/strong>&nbsp;Click the&nbsp;<strong>Download and Run<\/strong>&nbsp;button.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"41\" height=\"52\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/download-run.png?resize=41%2C52&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75031\"\/><\/figure><\/div>\n\n\n\n<p>The file should be saved on the device folder with the name \u201c<strong>ssd1306.py<\/strong>\u201d as<br>highlighted in the following figure.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"783\" height=\"704\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ssd1306_installed.png?resize=783%2C704&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"import save library uPyCraft IDE script file\" class=\"wp-image-85580\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ssd1306_installed.png?w=783&amp;quality=100&amp;strip=all&amp;ssl=1 783w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ssd1306_installed.png?resize=300%2C270&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ssd1306_installed.png?resize=768%2C691&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 783px) 100vw, 783px\" \/><\/figure><\/div>\n\n\n\n<p>Now, you can use the library functionalities in your code by importing the library.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">B. Upload OLED library with Thonny IDE<\/h3>\n\n\n\n<p>If you\u2019re using Thonny IDE, follow the next steps:<\/p>\n\n\n\n<p><strong>1.<\/strong>&nbsp;Copy the library code to a new file. The&nbsp;<a href=\"https:\/\/raw.githubusercontent.com\/RuiSantosdotme\/ESP-MicroPython\/master\/code\/Others\/OLED\/ssd1306.py\" target=\"_blank\" rel=\"noreferrer noopener\">OLED library code can be found here<\/a>.<\/p>\n\n\n\n<p><strong>2<\/strong>. Save that file as&nbsp;<em>ssd1306.py<\/em>.<\/p>\n\n\n\n<p><strong>3.<\/strong>&nbsp;Go to&nbsp;<strong>Device&nbsp;<\/strong>&gt;&nbsp;<strong>Upload current script with the current name<\/strong><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"646\" height=\"654\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/upload-current-script-with-current-name-oled.png?resize=646%2C654&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"thonny ide upload library file script micropython\" class=\"wp-image-85582\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/upload-current-script-with-current-name-oled.png?w=646&amp;quality=100&amp;strip=all&amp;ssl=1 646w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/upload-current-script-with-current-name-oled.png?resize=296%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 296w\" sizes=\"(max-width: 646px) 100vw, 646px\" \/><\/figure><\/div>\n\n\n\n<p>And that\u2019s it. The library was uploaded to your board. To make sure that it was uploaded successfully, in the Shell you can type:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>%lsdevice<\/code><\/pre>\n\n\n\n<p>It should return the files currently saved on your board. One of them should be the&nbsp;<em>ssd1306.py<\/em>&nbsp;file.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"720\" height=\"168\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/lsdevice.png?resize=720%2C168&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"show device folder thonny ide\" class=\"wp-image-85584\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/lsdevice.png?w=720&amp;quality=100&amp;strip=all&amp;ssl=1 720w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/lsdevice.png?resize=300%2C70&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 720px) 100vw, 720px\" \/><\/figure><\/div>\n\n\n\n<p>After uploading the library to your board, you can use the library functionalities in your code by importing the library.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">MicroPython OLED Scroll Functions<\/h2>\n\n\n\n<p>The ss1306.py library comes with a <span class=\"rnthl rntliteral\">scroll(x, y)<\/span> function. It scroll x number of pixels to the right and y number of pixels down.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Scroll OLED Screen Horizontally<\/h3>\n\n\n\n<p>Sometimes you want to display different screens on the OLED display. For example, the first screen shows sensor readings, and the second screen shows GPIO states. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Scroll in horizontally<\/h4>\n\n\n\n<p>The following function <span class=\"rnthl rntliteral\">scroll_in_screen(screen)<\/span> scrolls the content of an entire screen (right to left).<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>def scroll_in_screen(screen):\n  for i in range (0, oled_width+1, 4):\n    for line in screen:\n      oled.text(line&#091;2], -oled_width+i, line&#091;1])\n    oled.show()\n    if i!= oled_width:\n      oled.fill(0)<\/code><\/pre>\n\n\n\n<p>This function accepts as argument a list of lists. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>screen1 = &#091;&#091;0, 0 , screen1_row1], &#091;0, 16, screen1_row2], &#091;0, 32, screen1_row3]]<\/code><\/pre>\n\n\n\n<p>Each list of the list contains the x coordinate, the y coordinate and the message <span class=\"rnthl rntliteral\">[x, y, message]<\/span>.<\/p>\n\n\n\n<p>As an example, we&#8217;ll display three rows on the first screen with the following messages.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>screen1_row1 = \"Screen 1, row 1\"\nscreen1_row2 = \"Screen 1, row 2\"\nscreen1_row3 = \"Screen 1, row 3\"<\/code><\/pre>\n\n\n\n<p>Then, to make your screen scrolling from left to right, you just need to call the <span class=\"rnthl rntliteral\">scroll_in_screen()<\/span> function and pass as argument the list of lists:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>scroll_in_screen(screen1)<\/code><\/pre>\n\n\n\n<p>You&#8217;ll get something as follows:<\/p>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/404972602?color=ff9933&title=1&byline=0&portrait=0\" width=\"720\" height=\"405\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><\/div><\/br>\n\n\n\n<h4 class=\"wp-block-heading\">Scroll out horizontally<\/h4>\n\n\n\n<p>To make the screen scroll out, you can use the <span class=\"rnthl rntliteral\">scroll_out_screen(speed)<\/span> function that scrolls the entire screen out of the OLED. It accepts as argument a number that controls the scrolling speed. The speed must be a divisor of 128 (<span class=\"rnthl rntliteral\">oled_width<\/span>)<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>def scroll_out_screen(speed):\n  for i in range ((oled_width+1)\/speed):\n    for j in range (oled_height):\n      oled.pixel(i, j, 0)\n    oled.scroll(speed,0)\n    oled.show()<\/code><\/pre>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/404971374?color=ff9933&title=1&byline=0&portrait=0\" width=\"720\" height=\"405\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><\/div><\/br>\n\n\n\n<p>Now, you can use both functions to scroll between screens. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>scroll_in_screen(screen1)\nscroll_out_screen(4)\nscroll_in_screen(screen2)\nscroll_out_screen(4)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Continuous horizontal scroll<\/h4>\n\n\n\n<p>If you want to scroll the screen in and out continuously, you can use the <span class=\"rnthl rntliteral\">scroll_screen_in_out(screen)<\/span> function instead.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>def scroll_screen_in_out(screen):\n  for i in range (0, (oled_width+1)*2, 1):\n    for line in screen:\n      oled.text(line&#091;2], -oled_width+i, line&#091;1])\n    oled.show()\n    if i!= oled_width:\n      oled.fill(0)<\/code><\/pre>\n\n\n\n<p>You can use this function to scroll between screens, or to scroll the same screen over and over again. <\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>scroll_screen_in_out(screen1)\nscroll_screen_in_out(screen2)\nscroll_screen_in_out(screen3)<\/code><\/pre>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/404971482?color=ff9933&title=1&byline=0&portrait=0\" width=\"720\" height=\"405\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><\/div><\/br>\n\n\n\n<h3 class=\"wp-block-heading\">Scroll OLED Screen Vertically<\/h3>\n\n\n\n<p>We also created similar functions to scroll the screen vertically.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Scroll in vertically<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">scroll_in_screen_v(screen)<\/span> scrolls in the content of the entire screen.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>def scroll_in_screen_v(screen):\n  for i in range (0, (oled_height+1), 1):\n    for line in screen:\n      oled.text(line&#091;2], line&#091;0], -oled_height+i+line&#091;1])\n    oled.show()\n    if i!= oled_height:\n      oled.fill(0)<\/code><\/pre>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/404971318?color=ff9933&title=1&byline=0&portrait=0\" width=\"720\" height=\"405\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><\/div><\/br>\n\n\n\n<h4 class=\"wp-block-heading\"> Scroll out vertically<\/h4>\n\n\n\n<p>You can use the <span class=\"rnthl rntliteral\">scroll_out_screen_v(speed)<\/span> function to scroll out the screen vertically. Similarly to the horizontal function, it accepts as argument, the scrolling speed that must be a number divisor of 64 (<span class=\"rnthl rntliteral\">oled_height<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>def scroll_out_screen_v(speed):\n  for i in range ((oled_height+1)\/speed):\n    for j in range (oled_width):\n      oled.pixel(j, i, 0)\n    oled.scroll(0,speed)\n    oled.show()<\/code><\/pre>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/404971414?color=ff9933&title=1&byline=0&portrait=0\" width=\"720\" height=\"405\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><\/div><\/br>\n\n\n\n<h4 class=\"wp-block-heading\">Continuous vertical scroll<\/h4>\n\n\n\n<p>If you want to scroll the screen in and out vertically continuously, you can use the <span class=\"rnthl rntliteral\">scroll_in_out_screen_v(screen)<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>def scroll_screen_in_out_v(screen):\n  for i in range (0, (oled_height*2+1), 1):\n    for line in screen:\n      oled.text(line&#091;2], line&#091;0], -oled_height+i+line&#091;1])\n    oled.show()\n    if i!= oled_height:\n      oled.fill(0)<\/code><\/pre>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/404971447?color=ff9933&title=1&byline=0&portrait=0\" width=\"720\" height=\"405\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><\/div><\/br>\n\n\n\n<h3 class=\"wp-block-heading\">Scroll OLED Screen MicroPython Script<\/h3>\n\n\n\n<p>The following script applies all the functions we&#8217;ve described previously. You can upload the following code to your board to see all the scrolling effects.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># Complete project details at https:\/\/RandomNerdTutorials.com\/micropython-ssd1306-oled-scroll-shapes-esp32-esp8266\/\r\n\r\nfrom machine import Pin, SoftI2C\r\nimport ssd1306\r\nfrom time import sleep\r\n\r\n# ESP32 Pin assignment\r\ni2c = SoftI2C(scl=Pin(22), sda=Pin(21))\r\n\r\n# ESP8266 Pin assignment\r\n#i2c = SoftI2C(scl=Pin(5), sda=Pin(4))\r\n\r\noled_width = 128\r\noled_height = 64\r\noled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)\r\n\r\nscreen1_row1 = &quot;Screen 1, row 1&quot;\r\nscreen1_row2 = &quot;Screen 1, row 2&quot;\r\nscreen1_row3 = &quot;Screen 1, row 3&quot;\r\n\r\nscreen2_row1 = &quot;Screen 2, row 1&quot;\r\nscreen2_row2 = &quot;Screen 2, row 2&quot;\r\n\r\nscreen3_row1 = &quot;Screen 3, row 1&quot;\r\n\r\nscreen1 = [[0, 0 , screen1_row1], [0, 16, screen1_row2], [0, 32, screen1_row3]]\r\nscreen2 = [[0, 0 , screen2_row1], [0, 16, screen2_row2]]\r\nscreen3 = [[0, 40 , screen3_row1]]\r\n\r\n# Scroll in screen horizontally from left to right\r\ndef scroll_in_screen(screen):\r\n  for i in range (0, oled_width+1, 4):\r\n    for line in screen:\r\n      oled.text(line[2], -oled_width+i, line[1])\r\n    oled.show()\r\n    if i!= oled_width:\r\n      oled.fill(0)\r\n\r\n# Scroll out screen horizontally from left to right\r\ndef scroll_out_screen(speed):\r\n  for i in range ((oled_width+1)\/speed):\r\n    for j in range (oled_height):\r\n      oled.pixel(i, j, 0)\r\n    oled.scroll(speed,0)\r\n    oled.show()\r\n\r\n# Continuous horizontal scroll\r\ndef scroll_screen_in_out(screen):\r\n  for i in range (0, (oled_width+1)*2, 1):\r\n    for line in screen:\r\n      oled.text(line[2], -oled_width+i, line[1])\r\n    oled.show()\r\n    if i!= oled_width:\r\n      oled.fill(0)\r\n\r\n# Scroll in screen vertically\r\ndef scroll_in_screen_v(screen):\r\n  for i in range (0, (oled_height+1), 1):\r\n    for line in screen:\r\n      oled.text(line[2], line[0], -oled_height+i+line[1])\r\n    oled.show()\r\n    if i!= oled_height:\r\n      oled.fill(0)\r\n\r\n# Scroll out screen vertically\r\ndef scroll_out_screen_v(speed):\r\n  for i in range ((oled_height+1)\/speed):\r\n    for j in range (oled_width):\r\n      oled.pixel(j, i, 0)\r\n    oled.scroll(0,speed)\r\n    oled.show()\r\n\r\n# Continous vertical scroll\r\ndef scroll_screen_in_out_v(screen):\r\n  for i in range (0, (oled_height*2+1), 1):\r\n    for line in screen:\r\n      oled.text(line[2], line[0], -oled_height+i+line[1])\r\n    oled.show()\r\n    if i!= oled_height:\r\n      oled.fill(0)\r\n\r\nwhile True:\r\n\r\n  # Scroll in, stop, scroll out (horizontal)\r\n  scroll_in_screen(screen1)\r\n  sleep(2)\r\n  scroll_out_screen(4)\r\n\r\n  scroll_in_screen(screen2)\r\n  sleep(2)\r\n  scroll_out_screen(4)\r\n\r\n  scroll_in_screen(screen3)\r\n  sleep(2)\r\n  scroll_out_screen(4)\r\n\r\n  # Continuous horizontal scroll\r\n  scroll_screen_in_out(screen1)\r\n  scroll_screen_in_out(screen2)\r\n  scroll_screen_in_out(screen3)\r\n\r\n  # Scroll in, stop, scroll out (vertical)\r\n  scroll_in_screen_v(screen1)\r\n  sleep(2)\r\n  scroll_out_screen_v(4)\r\n\r\n  scroll_in_screen_v(screen2)\r\n  sleep(2)\r\n  scroll_out_screen_v(4)\r\n\r\n  scroll_in_screen_v(screen3)\r\n  sleep(2)\r\n  scroll_out_screen_v(4)\r\n\r\n  # Continuous verticall scroll\r\n  scroll_screen_in_out_v(screen1)\r\n  scroll_screen_in_out_v(screen2)\r\n  scroll_screen_in_out_v(screen3)\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/oled\/screen_scroll.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">MicroPython OLED Draw Shapes<\/h2>\n\n\n\n<p>To draw shapes on the OLED display using MicroPython we&#8217;ll use the Adafruit_GFX MicroPython Library.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Adafruit GFX Library<\/h3>\n\n\n\n<p>To draw shapes on the OLED display, we&#8217;ll use the <a href=\"https:\/\/github.com\/adafruit\/micropython-adafruit-gfx\/blob\/master\/gfx.py\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Adafruit GFX Library<\/a>. This library isn\u2019t part of the standard MicroPython library by default. So, you need to upload the library to your ESP32\/ESP8266 board. <\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># Port of Adafruit GFX Arduino library to MicroPython.\r\n# Based on: https:\/\/github.com\/adafruit\/Adafruit-GFX-Library\r\n# Author: Tony DiCola (original GFX author Phil Burgess)\r\n# License: MIT License (https:\/\/opensource.org\/licenses\/MIT)\r\n\r\nclass GFX:\r\n\r\n    def __init__(self, width, height, pixel, hline=None, vline=None):\r\n        # Create an instance of the GFX drawing class.  You must pass in the\r\n        # following parameters:\r\n        #  - width = The width of the drawing area in pixels.\r\n        #  - height = The height of the drawing area in pixels.\r\n        #  - pixel = A function to call when a pixel is drawn on the display.\r\n        #            This function should take at least an x and y position\r\n        #            and then any number of optional color or other parameters.\r\n        #  You can also provide the following optional keyword argument to\r\n        #  improve the performance of drawing:\r\n        #  - hline = A function to quickly draw a horizontal line on the display.\r\n        #            This should take at least an x, y, and width parameter and\r\n        #            any number of optional color or other parameters.\r\n        #  - vline = A function to quickly draw a vertical line on the display.\r\n        #            This should take at least an x, y, and height paraemter and\r\n        #            any number of optional color or other parameters.\r\n        self.width = width\r\n        self.height = height\r\n        self._pixel = pixel\r\n        # Default to slow horizontal &amp; vertical line implementations if no\r\n        # faster versions are provided.\r\n        if hline is None:\r\n            self.hline = self._slow_hline\r\n        else:\r\n            self.hline = hline\r\n        if vline is None:\r\n            self.vline = self._slow_vline\r\n        else:\r\n            self.vline = vline\r\n\r\n    def _slow_hline(self, x0, y0, width, *args, **kwargs):\r\n        # Slow implementation of a horizontal line using pixel drawing.\r\n        # This is used as the default horizontal line if no faster override\r\n        # is provided.\r\n        if y0 &lt; 0 or y0 &gt; self.height or x0 &lt; -width or x0 &gt; self.width:\r\n            return\r\n        for i in range(width):\r\n            self._pixel(x0+i, y0, *args, **kwargs)\r\n\r\n    def _slow_vline(self, x0, y0, height, *args, **kwargs):\r\n        # Slow implementation of a vertical line using pixel drawing.\r\n        # This is used as the default vertical line if no faster override\r\n        # is provided.\r\n        if y0 &lt; -height or y0 &gt; self.height or x0 &lt; 0 or x0 &gt; self.width:\r\n            return\r\n        for i in range(height):\r\n            self._pixel(x0, y0+i, *args, **kwargs)\r\n\r\n    def rect(self, x0, y0, width, height, *args, **kwargs):\r\n        # Rectangle drawing function.  Will draw a single pixel wide rectangle\r\n        # starting in the upper left x0, y0 position and width, height pixels in\r\n        # size.\r\n        if y0 &lt; -height or y0 &gt; self.height or x0 &lt; -width or x0 &gt; self.width:\r\n            return\r\n        self.hline(x0, y0, width, *args, **kwargs)\r\n        self.hline(x0, y0+height-1, width, *args, **kwargs)\r\n        self.vline(x0, y0, height, *args, **kwargs)\r\n        self.vline(x0+width-1, y0, height, *args, **kwargs)\r\n\r\n    def fill_rect(self, x0, y0, width, height, *args, **kwargs):\r\n        # Filled rectangle drawing function.  Will draw a single pixel wide\r\n        # rectangle starting in the upper left x0, y0 position and width, height\r\n        # pixels in size.\r\n        if y0 &lt; -height or y0 &gt; self.height or x0 &lt; -width or x0 &gt; self.width:\r\n            return\r\n        for i in range(x0, x0+width):\r\n            self.vline(i, y0, height, *args, **kwargs)\r\n\r\n    def line(self, x0, y0, x1, y1, *args, **kwargs):\r\n        # Line drawing function.  Will draw a single pixel wide line starting at\r\n        # x0, y0 and ending at x1, y1.\r\n        steep = abs(y1 - y0) &gt; abs(x1 - x0)\r\n        if steep:\r\n            x0, y0 = y0, x0\r\n            x1, y1 = y1, x1\r\n        if x0 &gt; x1:\r\n            x0, x1 = x1, x0\r\n            y0, y1 = y1, y0\r\n        dx = x1 - x0\r\n        dy = abs(y1 - y0)\r\n        err = dx \/\/ 2\r\n        ystep = 0\r\n        if y0 &lt; y1:\r\n            ystep = 1\r\n        else:\r\n            ystep = -1\r\n        while x0 &lt;= x1:\r\n            if steep:\r\n                self._pixel(y0, x0, *args, **kwargs)\r\n            else:\r\n                self._pixel(x0, y0, *args, **kwargs)\r\n            err -= dy\r\n            if err &lt; 0:\r\n                y0 += ystep\r\n                err += dx\r\n            x0 += 1\r\n\r\n    def circle(self, x0, y0, radius, *args, **kwargs):\r\n        # Circle drawing function.  Will draw a single pixel wide circle with\r\n        # center at x0, y0 and the specified radius.\r\n        f = 1 - radius\r\n        ddF_x = 1\r\n        ddF_y = -2 * radius\r\n        x = 0\r\n        y = radius\r\n        self._pixel(x0, y0 + radius, *args, **kwargs)\r\n        self._pixel(x0, y0 - radius, *args, **kwargs)\r\n        self._pixel(x0 + radius, y0, *args, **kwargs)\r\n        self._pixel(x0 - radius, y0, *args, **kwargs)\r\n        while x &lt; y:\r\n            if f &gt;= 0:\r\n                y -= 1\r\n                ddF_y += 2\r\n                f += ddF_y\r\n            x += 1\r\n            ddF_x += 2\r\n            f += ddF_x\r\n            self._pixel(x0 + x, y0 + y, *args, **kwargs)\r\n            self._pixel(x0 - x, y0 + y, *args, **kwargs)\r\n            self._pixel(x0 + x, y0 - y, *args, **kwargs)\r\n            self._pixel(x0 - x, y0 - y, *args, **kwargs)\r\n            self._pixel(x0 + y, y0 + x, *args, **kwargs)\r\n            self._pixel(x0 - y, y0 + x, *args, **kwargs)\r\n            self._pixel(x0 + y, y0 - x, *args, **kwargs)\r\n            self._pixel(x0 - y, y0 - x, *args, **kwargs)\r\n\r\n    def fill_circle(self, x0, y0, radius, *args, **kwargs):\r\n        # Filled circle drawing function.  Will draw a filled circule with\r\n        # center at x0, y0 and the specified radius.\r\n        self.vline(x0, y0 - radius, 2*radius + 1, *args, **kwargs)\r\n        f = 1 - radius\r\n        ddF_x = 1\r\n        ddF_y = -2 * radius\r\n        x = 0\r\n        y = radius\r\n        while x &lt; y:\r\n            if f &gt;= 0:\r\n                y -= 1\r\n                ddF_y += 2\r\n                f += ddF_y\r\n            x += 1\r\n            ddF_x += 2\r\n            f += ddF_x\r\n            self.vline(x0 + x, y0 - y, 2*y + 1, *args, **kwargs)\r\n            self.vline(x0 + y, y0 - x, 2*x + 1, *args, **kwargs)\r\n            self.vline(x0 - x, y0 - y, 2*y + 1, *args, **kwargs)\r\n            self.vline(x0 - y, y0 - x, 2*x + 1, *args, **kwargs)\r\n\r\n    def triangle(self, x0, y0, x1, y1, x2, y2, *args, **kwargs):\r\n        # Triangle drawing function.  Will draw a single pixel wide triangle\r\n        # around the points (x0, y0), (x1, y1), and (x2, y2).\r\n        self.line(x0, y0, x1, y1, *args, **kwargs)\r\n        self.line(x1, y1, x2, y2, *args, **kwargs)\r\n        self.line(x2, y2, x0, y0, *args, **kwargs)\r\n\r\n    def fill_triangle(self, x0, y0, x1, y1, x2, y2, *args, **kwargs):\r\n        # Filled triangle drawing function.  Will draw a filled triangle around\r\n        # the points (x0, y0), (x1, y1), and (x2, y2).\r\n        if y0 &gt; y1:\r\n            y0, y1 = y1, y0\r\n            x0, x1 = x1, x0\r\n        if y1 &gt; y2:\r\n            y2, y1 = y1, y2\r\n            x2, x1 = x1, x2\r\n        if y0 &gt; y1:\r\n            y0, y1 = y1, y0\r\n            x0, x1 = x1, x0\r\n        a = 0\r\n        b = 0\r\n        y = 0\r\n        last = 0\r\n        if y0 == y2:\r\n            a = x0\r\n            b = x0\r\n            if x1 &lt; a:\r\n                a = x1\r\n            elif x1 &gt; b:\r\n                b = x1\r\n            if x2 &lt; a:\r\n                a = x2\r\n            elif x2 &gt; b:\r\n                b = x2\r\n            self.hline(a, y0, b-a+1, *args, **kwargs)\r\n            return\r\n        dx01 = x1 - x0\r\n        dy01 = y1 - y0\r\n        dx02 = x2 - x0\r\n        dy02 = y2 - y0\r\n        dx12 = x2 - x1\r\n        dy12 = y2 - y1\r\n        if dy01 == 0:\r\n            dy01 = 1\r\n        if dy02 == 0:\r\n            dy02 = 1\r\n        if dy12 == 0:\r\n            dy12 = 1\r\n        sa = 0\r\n        sb = 0\r\n        if y1 == y2:\r\n            last = y1\r\n        else:\r\n            last = y1-1\r\n        for y in range(y0, last+1):\r\n            a = x0 + sa \/\/ dy01\r\n            b = x0 + sb \/\/ dy02\r\n            sa += dx01\r\n            sb += dx02\r\n            if a &gt; b:\r\n                a, b = b, a\r\n            self.hline(a, y, b-a+1, *args, **kwargs)\r\n        sa = dx12 * (y - y1)\r\n        sb = dx02 * (y - y0)\r\n        while y &lt;= y2:\r\n            a = x1 + sa \/\/ dy12\r\n            b = x0 + sb \/\/ dy02\r\n            sa += dx12\r\n            sb += dx02\r\n            if a &gt; b:\r\n                a, b = b, a\r\n            self.hline(a, y, b-a+1, *args, **kwargs)\r\n            y += 1<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/oled\/gfx.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Follow the previous instructions on how to install a library, but for the GFX library. Save the GFX library file as <em>gfx.py<\/em>. Then, you can use the library functionalities by importing the library in your code.<\/p>\n\n\n\n<p>In summary, here&#8217;s how to draw shapes. First, you need to include the <span class=\"rnthl rntliteral\">ssd1306<\/span> and <span class=\"rnthl rntliteral\">gfx<\/span> libraries as well as the <span class=\"rnthl rntliteral\">Pin<\/span> and <span class=\"rnthl rntliteral\">SoftI2C<\/span> modules.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>from machine import Pin, SoftI2C\nimport ssd1306\nfrom time import sleep\nimport gfx<\/code><\/pre>\n\n\n\n<p>Then, define the pins for the ESP32.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>i2c = SoftI2C(scl=Pin(22), sda=Pin(21))<\/code><\/pre>\n\n\n\n<p>If you&#8217;re using an ESP8266, use the following pins instead:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>i2c = SoftI2C(scl=Pin(5), sda=Pin(4))<\/code><\/pre>\n\n\n\n<p>We&#8217;re using a 128&#215;64 OLED display. If you&#8217;re using an OLED display with different dimensions, change that on the following lines:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>oled_width = 128\noled_height = 64<\/code><\/pre>\n\n\n\n<p>Create an <span class=\"rnthl rntliteral\">ss1306<\/span> object called <span class=\"rnthl rntliteral\">oled<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)<\/code><\/pre>\n\n\n\n<p>Then, we need to create a <span class=\"rnthl rntliteral\">gfx<\/span> object to draw shapes. In this case, it&#8217;s called <span class=\"rnthl rntliteral\">graphics<\/span>. It takes as arguments, the width and height of the drawing area. In this case, we want to draw in the entire OLED, so we pass the OLED width and height. We should also pass as argument one function of our display that draws pixels, in our case is <span class=\"rnthl rntliteral\">oled.pixel<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>graphics = gfx.GFX(oled_width, oled_height, oled.pixel)<\/code><\/pre>\n\n\n\n<p>Then, you can use the drawing functions we&#8217;ll show you next to display shapes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Draw a Line<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Line.jpg?resize=375%2C315&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Arduino OLED Display Line\" class=\"wp-image-85476\" width=\"375\" height=\"315\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Line.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Line.jpg?resize=300%2C252&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 375px) 100vw, 375px\" \/><\/figure><\/div>\n\n\n\n<p>Use the <span class=\"rnthl rntliteral\">line(x0, y0, x1, y1, color)<\/span> method on the <span class=\"rnthl rntliteral\">gfx<\/span> object to create a line. The (x0, y0) coordinates indicate the start of the line, and the (x1, y1) coordinates indicate where the line ends. You always need to call <span class=\"rnthl rntliteral\">oled.show()<\/span> to actually display the shapes on the OLED. Here&#8217;s an example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>graphics.line(0, 0, 127, 20, 1)\noled.show()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Rectangle<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Rectangle.jpg?resize=375%2C315&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Arduino OLED Display Rectangle\" class=\"wp-image-85478\" width=\"375\" height=\"315\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Rectangle.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Rectangle.jpg?resize=300%2C252&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 375px) 100vw, 375px\" \/><\/figure><\/div>\n\n\n\n<p>To draw a rectangle, you can use the <span class=\"rnthl rntliteral\">rect(x0, y0, width, height, color)<\/span> method on the <span class=\"rnthl rntliteral\">gfx<\/span> object. The (x0, y0) coordinates indicate the top left corner of the rectangle. Then, you need to specify the width, height and color of the rectangle. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>graphics.rect(10, 10, 50, 30, 1)\noled.show()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Filled Rectangle<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Filled.jpg?resize=375%2C315&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Arduino OLED Display Filled\" class=\"wp-image-85472\" width=\"375\" height=\"315\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Filled.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Filled.jpg?resize=300%2C252&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 375px) 100vw, 375px\" \/><\/figure><\/div>\n\n\n\n<p>You can use the <span class=\"rnthl rntliteral\">fill_rect(x0, y0, width, height, color)<\/span> method to draw a filled rectangle. This method accepts the same arguments as <span class=\"rnthl rntliteral\">drawRect()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>graphics.rect(10, 10, 50, 30, 1)\noled.show()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Circle<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Circle.jpg?resize=375%2C315&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Arduino OLED Display Circle\" class=\"wp-image-85470\" width=\"375\" height=\"315\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Circle.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Circle.jpg?resize=300%2C252&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 375px) 100vw, 375px\" \/><\/figure><\/div>\n\n\n\n<p>Draw a circle using the <span class=\"rnthl rntliteral\">circle(x0, y0, radius, color)<\/span> method. The (x0, y0) coordinates indicate the center of the circle. Here&#8217;s an example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>graphics.circle(64, 32, 10, 1)\noled.show()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Filled Circle<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Circle-Filled.jpg?resize=375%2C315&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Arduino OLED Display Circle Filled\" class=\"wp-image-85471\" width=\"375\" height=\"315\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Circle-Filled.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Circle-Filled.jpg?resize=300%2C252&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 375px) 100vw, 375px\" \/><\/figure><\/div>\n\n\n\n<p>Draw a filled circle using the <span class=\"rnthl rntliteral\">fill_circle(x0, y0, radius, color)<\/span> method.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>graphics.fill_circle(64, 32, 10, 1)\noled.show()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Triangle<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Triangle.jpg?resize=375%2C315&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Arduino OLED Display Triangle\" class=\"wp-image-85481\" width=\"375\" height=\"315\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Triangle.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Triangle.jpg?resize=300%2C252&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 375px) 100vw, 375px\" \/><\/figure><\/div>\n\n\n\n<p>There&#8217;s also a method to draw a triangle: <span class=\"rnthl rntliteral\">triangle(x0, y0, x1, y1, x2, y2, color)<\/span>. This method accepts as arguments the coordinates of each corner and the color.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>graphics.triangle(10,10,55,20,5,40,1)\noled.show()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Filled Triangle<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Triangle-Filled.jpg?resize=375%2C315&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Arduino OLED Display Triangle Filled\" class=\"wp-image-85483\" width=\"375\" height=\"315\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Triangle-Filled.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/05\/ESP32-ESP8266-Arduino-OLED-Display-Triangle-Filled.jpg?resize=300%2C252&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 375px) 100vw, 375px\" \/><\/figure><\/div>\n\n\n\n<p>Use the <span class=\"rnthl rntliteral\">fill_triangle(x0, y0, x1, y1, x2, y2, color)<\/span> method to draw a filled triangle.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>graphics.fill_triangle(10,10,55,20,5,40,1)\noled.show()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">MicroPython Script &#8211; Draw Shapes<\/h3>\n\n\n\n<p>The following script implements all the drawing methods shown previously.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># Complete project details at https:\/\/RandomNerdTutorials.com\/micropython-ssd1306-oled-scroll-shapes-esp32-esp8266\/\r\n\r\nfrom machine import Pin, SoftI2C\r\nimport ssd1306\r\nfrom time import sleep\r\nimport gfx\r\n\r\n# ESP32 Pin assignment\r\ni2c = SoftI2C(scl=Pin(22), sda=Pin(21))\r\n\r\n# ESP8266 Pin assignment\r\n#i2c = SoftI2C(scl=Pin(5), sda=Pin(4))\r\n\r\noled_width = 128\r\noled_height = 64\r\noled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)\r\n\r\ngraphics = gfx.GFX(oled_width, oled_height, oled.pixel)\r\n\r\nwhile True:\r\n\r\n  graphics.line(0, 0, 127, 20, 1)\r\n  oled.show()\r\n  sleep(1)\r\n  oled.fill(0)\r\n\r\n  graphics.rect(10, 10, 50, 30, 1)\r\n  oled.show()\r\n  sleep(1)\r\n  oled.fill(0)\r\n\r\n  graphics.fill_rect(10, 10, 50, 30, 1)\r\n  oled.show()\r\n  sleep(1)\r\n  oled.fill(0)\r\n\r\n\r\n  graphics.circle(64, 32, 10, 1)\r\n  oled.show()\r\n  sleep(1)\r\n  oled.fill(0)\r\n\r\n  graphics.fill_circle(64, 32, 10, 1)\r\n  oled.show()\r\n  sleep(1)\r\n  oled.fill(0)\r\n\r\n  graphics.triangle(10,10,55,20,5,40,1)\r\n  oled.show()\r\n  sleep(1)\r\n  oled.fill(0)\r\n\r\n  graphics.fill_triangle(10,10,55,20,5,40,1)\r\n  oled.show()\r\n  sleep(1)\r\n  oled.fill(0)\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/oled\/draw_shapes.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial you&#8217;ve learned how to use more advanced functions to scroll the OLED screen and draw shapes using MicroPython with the ESP32 or ESP8266. To draw shapes you need to import the Adafruit GFX MicroPython library.<\/p>\n\n\n\n<p>We hope you&#8217;ve found this tutorial useful. If this is your first time dealing with the OLED display using MicroPython, we recommend following the getting started guide first:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-oled-display-esp32-esp8266\/\">MicroPython: OLED Display with ESP32 and ESP8266<\/a><\/li><\/ul>\n\n\n\n<p>We have a similar tutorials, but using Arduino IDE: <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-ssd1306-oled-display-arduino-ide\/\">ESP32 OLED Display with Arduino IDE<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-0-96-inch-oled-display-with-arduino-ide\/\">ESP8266 OLED Display with Arduino IDE<\/a><\/li><\/ul>\n\n\n\n<p>If you want to learn more about MicroPython, check our eBook:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\">MicroPython Programming with ESP32 and ESP8266<\/a><\/li><\/ul>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This guide shows additional functions to control an OLED display with MicroPython using the ESP32 or ESP8266. You&#8217;ll learn how to scroll the entire screen horizontally and vertically and how &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"MicroPython: SSD1306 OLED Display Scroll Functions and Draw Shapes (ESP32\/ESP8266)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/micropython-ssd1306-oled-scroll-shapes-esp32-esp8266\/#more-95428\" aria-label=\"Read more about MicroPython: SSD1306 OLED Display Scroll Functions and Draw Shapes (ESP32\/ESP8266)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":95663,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[276,310,309,264],"tags":[],"class_list":["post-95428","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32","category-micropython","category-0-esp32-micropython","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-SSD1306-OLED-MicroPython-Shapes-Scroll.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/95428","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=95428"}],"version-history":[{"count":2,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/95428\/revisions"}],"predecessor-version":[{"id":104868,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/95428\/revisions\/104868"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/95663"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=95428"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=95428"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=95428"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}