{"id":9358,"date":"2021-09-30T06:54:33","date_gmt":"2021-09-30T10:54:33","guid":{"rendered":"https:\/\/itp.nyu.edu\/physcomp\/?page_id=9358"},"modified":"2022-11-06T18:21:08","modified_gmt":"2022-11-06T23:21:08","slug":"lab-oled-screen-display-using-i2c","status":"publish","type":"page","link":"https:\/\/itp.nyu.edu\/physcomp\/lab-oled-screen-display-using-i2c\/","title":{"rendered":"Lab: OLED Screen Display using I2C"},"content":{"rendered":"\n<p>Many common electronic devices feature small screens for status updates, control feedback, and so forth. These displays feature many different technologies. Lately, one of the most common is the OLED display. These  displays are matrices of organic LEDs, each pixel being comprised of one to three LEDS. Small displays typically use either the SPI or I2C synchronous serial protocols. In this lab, you&#8217;ll use I2C to control a monochrome OLED display with an array of 128&#215;64 OLEDs to display text and monochrome graphics. The Solomon Systech SSD1306 OLED driver IC is a popular and inexpensive display driver in lots of display breakouts.<\/p>\n\n\n\n<p>For more on OLEDs, see&nbsp;<a href=\"https:\/\/www.energy.gov\/eere\/ssl\/oled-basics\">this introduction<\/a>&nbsp;from energy.gov. CNET provides this&nbsp;<a href=\"https:\/\/www.cnet.com\/news\/what-is-oled-and-what-can-it-do-for-your-tv\/\">comparison of LCD vs OLED displays<\/a>. This lab is adapted from material from <a href=\"https:\/\/tigoe.github.io\/display-examples\/\">this site<\/a>. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_Youll_Need_to_Know\"><\/span>What You\u2019ll Need to Know<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>To get the most out of this Lab, you should be familiar with the basics of programming an Arduino microcontroller. If you\u2019re not, review the&nbsp;<a href=\"https:\/\/itp.nyu.edu\/physcomp\/labs\/digital-input-and-output-with-an-arduino\/\">Digital Input and Output Lab<\/a>, and perhaps the&nbsp;<a href=\"http:\/\/arduino.cc\/en\/Guide\/HomePage\">Getting Started with Arduino guide<\/a>. You should also understand&nbsp;<a href=\"https:\/\/itp.nyu.edu\/physcomp\/lessons\/serial-communication-the-basics\/\">asynchronous serial communication<\/a>&nbsp;and how it differs from&nbsp;<a href=\"https:\/\/itp.nyu.edu\/physcomp\/lessons\/synchronous-serial-communication-the-basics\/\">synchronous serial communication<\/a>. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Things_Youll_Need\"><\/span>Things You\u2019ll Need<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Figures 1-6 list the components you will need.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-thumbnail\"><img loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/pcomp-kit-f2019-arduino-nano-33-iot-150x150.jpg\" alt=\"Photo of an Arduino Nano 33 IoT module. The USB connector is at the top of the image, and the physical pins are numbered in a U-shape from top left to bottom left, then from bottom right to top right.\" class=\"wp-image-5921\"\/><figcaption>Figure 1. An Arduino Nano 33 IoT.<\/figcaption><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft\"><a href=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/hookup_wire2.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/hookup_wire2-150x150.jpg\" alt=\"Three 22AWG solid core hookup wires. Each is about 6cm long. The top one is black; the middle one is red; the bottom one is blue. All three have stripped ends, approximately 4 to 5mm on each end.\" class=\"wp-image-1203\"\/><\/a><figcaption>Figure 2. 22AWG solid core hookup wires.<\/figcaption><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft\"><a href=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/breadboard_short-e1532116106284.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/breadboard_short-e1532116106284-150x150.jpg\" alt=\"A short solderless breadboard with two rows of holes along each side. There are no components mounted on the board. The board is oriented sideways so that the long rows of holes are on the top and bottom of the image.\" class=\"wp-image-788\"\/><\/a><figcaption>Figure 3. A short solderless breadboard.<\/figcaption><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-thumbnail\"><img loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/SSD1306_OLED-150x150.jpg\" alt=\"Photo of an OLED display, approx. 2.5 cm x 2.5 cm\" class=\"wp-image-9382\"\/><figcaption>Figure 4. SSD1306 OLED display<\/figcaption><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-thumbnail\"><img loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/pcomp-kit-f2019-potentiometer-150x150.jpg\" alt=\"Photo of two potentiometers\" class=\"wp-image-5924\"\/><figcaption>Figure 5. Potentiometer<\/figcaption><\/figure><\/div>\n\n\n\n<hr class=\"wp-block-separator is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Circuit\"><\/span>The Circuit<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The circuit for this lab consists of:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li> the microcontroller<\/li><li>a potentiometer. You can use any analog sensor you choose, however.<\/li><li>an SSD1306 OLED breakout board<\/li><\/ul>\n\n\n\n<p> There are many breakout boards that use the SSD1306 OLED:&nbsp;<a href=\"https:\/\/www.adafruit.com\/product\/661\">Adafruit<\/a>,&nbsp; <a href=\"https:\/\/www.sparkfun.com\/products\/17153\">Sparkfun&nbsp;<\/a>,&nbsp;<a href=\"https:\/\/www.dfrobot.com\/product-1576.html\">DFRobot<\/a>,&nbsp;<a href=\"https:\/\/www.crystalfontz.com\/search.php?q=ssd1306&amp;submit=Search\">Crystalfontz<\/a>,&nbsp;<a href=\"https:\/\/www.makerfocus.com\/collections\/oled\">MakerFocus<\/a>, <a href=\"https:\/\/smile.amazon.com\/s?k=ssd1306+oled+display\">Amazon<\/a>, and many others. It typically comes in a 128&#215;32 pixel version and a 128&#215;64 pixel version. Solomon Systech makes other variations on this display as well, like the SSD1309 or the 1315. They come with different resolutions, different physical sizes, and different features. <\/p>\n\n\n\n<p>Most of the SSD1206 displays have all blue pixels, but there are some models on the market have one section of yellow pixels and the rest blue. You can\u2019t change the color of the pixels, so be aware of what you are buying and choose what you need. If you need a board with all blue pixels, don&#8217;t get the one with the yellow section.<\/p>\n\n\n\n<p>Connect the display&#8217;s voltage and ground pins to your voltage and ground buses, and the I2C clock (SCL) and I2C serial data (SDA) pins to your microcontroller\u2019s corresponding I2C pins as shown in Figure 6-7. The schematic, Figure 6, is the same for both the Uno and the Nano. For the Arduino Uno or the Arduino Nano boards, the I2C pins are pins A4 (SDA) and A5(SCL). This is the same connection for almost any I2C device.<\/p>\n\n\n\n<p>Connect the potentiometer&#8217;s two outside connections to power and ground, respectively. Connect the middle pin (the wiper) to the Arduino&#8217;s pin A0. You&#8217;ll use the potentiometer to generate something to display on the screen. <\/p>\n\n\n\n<p>Once you&#8217;ve got the circuit wired as shown in Figures 6-7, you&#8217;re ready to program the microcontroller.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"256\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/Nano_SSD1306_OLED_bb.png\" alt=\" Breadboard view of a potentiometer and an SSD1306 OLED screen attached to a Nano 33 IoT\" class=\"wp-image-9361\" srcset=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/Nano_SSD1306_OLED_bb.png 800w, https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/Nano_SSD1306_OLED_bb-768x246.png 768w\" sizes=\"(max-width: 800px) 85vw, 800px\" \/><figcaption>Figure 6. Breadboard view of a potentiometer and an SSD1306 OLED screen attached to a Nano 33 IoT. The potentiometer is connected to pin A0. The screen&#8217;s SDA pin is connected to pin A4 and the SCL pin is connected to pin A5.<\/figcaption><\/figure>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"784\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/Nano_SSD1306_OLED_schem.png\" alt=\"Schematic drawing of a potentiometer and an SSD1306 OLED screen attached to a Nano 33 IoT.\" class=\"wp-image-9362\" srcset=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/Nano_SSD1306_OLED_schem.png 800w, https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/Nano_SSD1306_OLED_schem-768x753.png 768w\" sizes=\"(max-width: 800px) 85vw, 800px\" \/><figcaption>Figure 7. Schematic drawing of a potentiometer and an SSD1306 OLED screen attached to a Nano 33 IoT. The schematic is the same for an Uno. The potentiometer is connected to pin A0. The screen&#8217;s SDA pin is connected to pin A4 and the SCL pin is connected to pin A5.<\/figcaption><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Program_the_Microcontroller\"><\/span>Program the Microcontroller<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>There are many libraries available for controlling the SSD1306 OLED screens. <a href=\"https:\/\/github.com\/adafruit\/Adafruit_SSD1306\">Adafruit\u2019s SSD1306 library<\/a>&nbsp;works well with all the SSD1306 displays, both the 128&#215;64 and 128&#215;32 models. Adafruit&#8217;s library is consistent with many of their other display libraries, and they make a lot of them. So it&#8217;s a good place to start. It doesn&#8217;t work with other SSD13xx models though. For example, Sparkfun makes a Micro OLED with the SSD1309, which has a 64&#215;48 resolution. It requires a different library. <\/p>\n\n\n\n<p>The&nbsp;<a href=\"https:\/\/github.com\/olikraus\/u8g2\/wiki\">u8g2 library<\/a>&nbsp;by Oli Kraus, is intended as a universal monochrome display library for OLED, eInk, TFT, and other displays. It supports some SSD130x boards, but not all. It&#8217;s a pretty good library, but lacks some of the features of the Adafruit library. The examples included here use the Adafruit library. You&#8217;ll also need the Adafruit_GFX library which supports graphics across a number of small displays. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Import_the_Libraries\"><\/span>Import the Libraries<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>At the start of your sketch, import the libraries and set up a variable to hold the display driver instance like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: arduino; title: ; notranslate\" title=\"\">\n#include &lt;Wire.h&gt;\n#include &lt;Adafruit_SSD1306.h&gt;\n#include &lt;Adafruit_GFX.h&gt;\n\nconst int SCREEN_WIDTH = 128; \/\/ OLED display width, in pixels\nconst int SCREEN_HEIGHT = 64; \/\/ OLED display height, in pixels\n\n\/\/ initialize the display:\nAdafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT);\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Initialize_the_Display\"><\/span>Initialize the Display<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>In the setup, you need to check that the display is working. If it fails, it&#8217;s a good idea to stop and notify the user. Since there&#8217;s no user interface in this basic sketch, you&#8217;ll use the Serial Monitor. <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: arduino; title: ; notranslate\" title=\"\">\nvoid setup() {\n  \/\/ initialize serial and wait for serial monitor to open:\n  Serial.begin(9600);\n  if (!Serial) delay(3000);\n  \/\/ first parameter of begin() sets voltage source.\n  \/\/ SSD1306_SWITCHCAPVCC is for 3.3V\n  \/\/ second parameter is I2C address, which is\n  \/\/ 0x3C, or 3D for some 128x64 modules:\n  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {\n    Serial.println(&quot;Display setup failed&quot;);\n    while (true);\n  }\n  Serial.println(&quot;Display is good to go&quot;);\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Print_to_the_Display\"><\/span>Print to the Display<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>You can print to the display by giving it a text size and cursor position and then using <code>.print()<\/code> or <code>.println()<\/code>. The loop below reads analog input 0, then prints the time in seconds on the first line and the sensor reading on the second. <\/p>\n\n\n\n<p>The function which actually updates the display is called <code>.display()<\/code>. All of the other functions update a buffer in the microcontroller&#8217;s memory. So you can make all the changes you want with commands like <code>.print()<\/code>, <code>.setCursor()<\/code>, <code>.clearDisplay()<\/code>, and so forth, but you will only see the changes when you call <code>.display()<\/code>. This is typical of many display libraries. <\/p>\n\n\n\n<p>In the code below, you&#8217;ll clear the display, then set the size to twice the default, then move the cursor to the top left. Then you print the seconds since the sketch started, move the cursor down a line, and print the analog 0 sensor reading. Finally, you push it all to the display using <code>.display()<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: arduino; title: ; notranslate\" title=\"\">\nvoid loop() {\n  int sensorReading = analogRead(A0);\n  \/\/ clear the display:\n  display.clearDisplay();\n  \/\/ set the text size to 2:\n  display.setTextSize(2);\n  \/\/ set the text color to white:\n  display.setTextColor(SSD1306_WHITE);\n\n  \/\/ move the cursor to 0,0:\n  display.setCursor(0, 0);\n  \/\/ print the seconds:\n  display.print(&quot;secs:&quot;);\n  display.print(millis() \/ 1000);\n\n  \/\/ move the cursor down 20 pixels:\n  display.setCursor(0, 20);\n  \/\/ print a sensor reading:\n  display.print(&quot;sensor:&quot;);\n  display.print(sensorReading);\n  \/\/ push everything out to the screen:\n  display.display();\n}\n<\/pre><\/div>\n\n\n<p>Here&#8217;s a <a href=\"https:\/\/github.com\/ITPNYU\/physcomp\/tree\/main\/Labs\/LabOLED\/SSD1306_OLED_minimal\">link to the full sketch<\/a>. <\/p>\n\n\n\n<p>The SSD1306 is a monochrome display, but you still have to set the color to see anything display, because the library defaults to no colors. For a list of what <code>SSD1306_WHITE<\/code> and the other constants in the library mean, see <a href=\"https:\/\/github.com\/adafruit\/Adafruit_SSD1306\/blob\/35ad5448ed2428f3d3a86820e2009623e0275c24\/Adafruit_SSD1306.h#L58\">this link<\/a>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Fonts\"><\/span>Fonts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The default font of the library is not terribly attractive, and gets blocky when you increase the size. But you can add fonts. The Adafruit_GFX library includes many fonts compatible with lots of their display libraries. Search for this library in the library manager and include it to use the fonts. They have a good <a href=\"https:\/\/learn.adafruit.com\/adafruit-gfx-graphics-library\/using-fonts\">tutorial on using fonts<\/a> as well. The short version is as follows. First, include the font you want to use with your library includes like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: arduino; title: ; notranslate\" title=\"\">\n#include&lt;Fonts\/FreeSans9pt7b.h&gt;\n<\/pre><\/div>\n\n\n<p>Next, in your <code>setup()<\/code> or whenever you want to switch fonts, use the <code>.setFont()<\/code> function like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: arduino; title: ; notranslate\" title=\"\">\n display.setFont(&amp;FreeSans9pt7b);\n<\/pre><\/div>\n\n\n<p>The text will now appear using your chosen font. Here&#8217;s a <a href=\"https:\/\/github.com\/ITPNYU\/physcomp\/tree\/main\/Labs\/LabOLED\/SSD1306_OLED_font\">link to an example using one of the Adafruit_GFX fonts<\/a>. <\/p>\n\n\n\n<p>One of the nice things about using custom fonts is if you pick the right size for your screen, you don&#8217;t need to use <code>.setTextSize()<\/code>, so you can avoid pixelating your font. Note that custom fonts  generally measure pixel height from the baseline. So, to position a 16-point font at the top of the screen, for example, position it with a few pixels at the top to spare: at (0, 20), not (0,0). <\/p>\n\n\n\n<p>You can also use more custom fonts by generating them from this <a href=\"http:\/\/oleddisplay.squix.ch\/#\/home\">OLED display custom font generator<\/a>. For &#8220;Library Version&#8221; choose &#8220;Adafruit GFX Font&#8221;.  This will generate a custom header file that you include with your sketch. Make a new tab in the IDE, give the tab a name like <code>font.h<\/code>, and include it at the top of your code with the other library header files. The font name will be at the bottom of the header file. For example, if you generated the Dialog Font, Plain, 16 point, the font name would be <code>Dialog_plain_16<\/code> and you&#8217;d include it just like the one above, like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: arduino; title: ; notranslate\" title=\"\">\n display.setFont(&amp;Dialog_plain_16);\n<\/pre><\/div>\n\n\n<p>The text will now appear using your custom font. <meta charset=\"utf-8\">Here&#8217;s a<a href=\"https:\/\/github.com\/ITPNYU\/physcomp\/tree\/main\/Labs\/LabOLED\/SSD1306_OLED_CustomFont\"> link to an example using a custom-generated font<\/a>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Graphics\"><\/span>Graphics<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>There are many libraries for graphics on small displays. Typically these displays don&#8217;t have a fast refresh rate, so you can&#8217;t exactly create fast action games on them, but they can be good for simple graphic informational displays. Different display libraries will have slightingly different naming schemes for their graphics, but you can usually count on being able to draw points, lines, rectangles, circles, and sometimes rounded rects and triangles. You can generally also count on functions like <code>drawRect()<\/code> vs. <code>fillRect()<\/code> depending on whether you want a filled rectangle or not. All libraries will include methods for setting a color, clearing a screen, and filling the screen with a color. Most will also include commands for rotating the graphics display. Here&#8217;s the <a href=\"https:\/\/learn.adafruit.com\/adafruit-gfx-graphics-library\/graphics-primitives\">Adafruit_GFX library graphics primitives<\/a> tutorial as an example.<\/p>\n\n\n\n<p>Remember, all of your commands are only executed when you call <code>.display()<\/code>. <\/p>\n\n\n\n<p>Here&#8217;s a link to a <a href=\"https:\/\/github.com\/ITPNYU\/physcomp\/tree\/main\/Labs\/LabOLED\/SSD1306_OLED_graph\">graphic example that graphs the sensor reading<\/a>. If you haven&#8217;t already included the Adafruit_GFX library, you will need to for this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Displaying_QR_Codes\"><\/span>Displaying QR Codes<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>One way you can use the graphic capabilities of any small display is to show QR codes. QR codes can contain any string of text you want in a machine-readable form. Though we&#8217;re used to generating QR codes to supply web addresses (URLs), you can also send plain text strings, phone numbers, passcodes or other  test-based information as well. On microcontroller-based devices, they can be a way to transfer identifying information like IP or MAC addresses, Bluetooth LE service UUIDs, or anything else your mobile phone or tablet might need to know about your microcontroller device in order to communicate with it.<\/p>\n\n\n\n<p>QR codes can be generated from a text string and translated to a microcontroller display using Richard Moore\u2019s&nbsp;<a href=\"https:\/\/tigoe.github.io\/display-examples\/qrcodes\">qrcode library for Arduino<\/a>&nbsp;and the graphics library for your particular display.<\/p>\n\n\n\n<p>Like any library, you need to include the qrcode library at the top of your code like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: arduino; title: ; notranslate\" title=\"\">\n#include &lt;qrcode.h&gt;\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Determining_QR_Code_Block_Size\"><\/span>Determining QR Code Block Size<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>A QR code&#8217;s <strong>block size<\/strong> is the height and width of each of the blocks in the code. It depends size depends on the number of blocks per side. The length of the string you plan to display and a few other factors affect the block size. <a href=\"https:\/\/www.qrcode.com\/en\/about\/version.html\">Here&#8217;s a table<\/a> which lays out how the string length, error correction, and QR code version affect the the pixel dimensions of a QR code. Here&#8217;s a <a href=\"https:\/\/github.com\/ricmoo\/QRCode#data-capacities\">simpler version<\/a> in the documentation for the qrcode library. A long string or higher levels of error correction can result in largee QR codes than you can fit on a small display. The library&#8217;s <code>.size()<\/code> function can give you the number of blocks in your  QR code. <\/p>\n\n\n\n<p>QR Codes need a &#8220;quiet zone&#8221; around the block in order to be readable to another device, so you can&#8217;t fill your display&#8217;s entire length or width with a QR code. <\/p>\n\n\n\n<p>Here&#8217;s a good rule of thumb to get a block size that you can fit on your display:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Set the QR version and the QR error level<\/li><li>Start with an arbitrary offset. The larger your offset, the smaller the QR code can be.<\/li><li>Subtract twice the offset width (also arbitrary) from the display&#8217;s smallest dimension (64px, in the case of the SSD1306)<\/li><li>divide by the qrcode.size<\/li><\/ul>\n\n\n\n<p>Here&#8217;s a function to generate a QR code. It will take a String object, the QR code version you want to use, and the QR code error level you want, then it will generate a QRCode object, and display it on the display using the display library&#8217;s <code>.fillRect()<\/code> function:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: arduino; title: ; notranslate\" title=\"\">\nvoid displayQrCode(String message) {\n  \/\/ Create the QR code\n  QRCode qrcode;\n  int qrVersion = 3;\n  int qrErrorLevel = ECC_MEDIUM;\n  int offset = 2;\n  int backgroundColor = SSD1306_BLACK;\n  int foregroundColor = SSD1306_WHITE;\n\n  \/\/ allocate QR code memory:\n  byte qrcodeBytes&#x5B;qrcode_getBufferSize(qrVersion)];\n  \/\/ initialize the QR code text:\n  qrcode_initText(&amp;qrcode, qrcodeBytes, qrVersion, qrErrorLevel, message.c_str());\n  \/\/ calculate the QR code block size:\n  int blockSize = (display.height() - (offset * 2)) \/ qrcode.size;\n  \/\/ fill the screen with the background color:\n  display.fillScreen(backgroundColor);\n\n  \/\/ read the bytes of the QR code and set the blocks light or dark, accordingly:\n  \/\/ vertical loop:\n  for (byte y = 0; y &lt; qrcode.size; y++) {\n    \/\/ horizontal loop:\n    for (byte x = 0; x &lt; qrcode.size; x++) {\n      \/\/ calculate the block&#039;s X and Y positions:\n      int blockX = (x * blockSize) + offset;\n      int blockY = (y * blockSize) + offset;\n      \/\/ read the block value from the QRcode:\n      int blockValue = qrcode_getModule(&amp;qrcode, x, y);\n      \/\/ set the default block color:\n      int blockColor = backgroundColor;\n      \/\/ if the block value is 1, set color to foreground color instead:\n      if (blockValue == 1) {\n        blockColor = foregroundColor;\n      }\n      \/\/ display the block on the screen:\n      display.fillRect(blockX, blockY, blockSize, blockSize, blockColor);\n    }\n  }\n  \/\/ refresh the display here, after the nested loops:\n  display.display();\n  \/\/ print the message:\n  Serial.println(message);\n}\n<\/pre><\/div>\n\n\n<p>Here&#8217;s a <a href=\"https:\/\/github.com\/ITPNYU\/physcomp\/tree\/main\/Labs\/LabOLED\/SSD1306_QRCode_example\">link to a full sketch to generate QR codes<\/a> on an SSD1306 display. Upload it to your Nano, then open the serial monitor and enter a string to display. Then  scan the QR Code with your phone&#8217;s QR scanning app. You should be able to read short strings of text, up to 50 or so characters. You can also send URLs, phone numbers, or anything else your phone&#8217;s QR code reader can interpret. <\/p>\n\n\n\n<p>The shorter the string, the easier it is for your QR code scanner to read it. This is why many URLs you see on QR codes in public use URL shorteners.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Even though the SSD1306 is a small, low resolution monochrome display, it packs a lot of potential for the price. Adding an informational display can improve many devices, and by adding a QR code, you have the possibility to add many more features through the web, Bluetooth, and more. For more on microcntroller displays, see <a href=\"https:\/\/tigoe.github.io\/display-examples\">this repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Many common electronic devices feature small screens for status updates, control feedback, and so forth. These displays feature many different technologies. Lately, one of the most common is the OLED display. These displays are matrices of organic LEDs, each pixel being comprised of one to three LEDS. Small displays typically use either the SPI or &hellip; <a href=\"https:\/\/itp.nyu.edu\/physcomp\/lab-oled-screen-display-using-i2c\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Lab: OLED Screen Display using I2C&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":313,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"categories":[41,15,54],"tags":[64,67,65,66],"class_list":["post-9358","page","type-page","status-publish","hentry","category-i2c","category-lab","category-microcontrollers","tag-display","tag-graphics","tag-oled","tag-ssd1306"],"_links":{"self":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/9358"}],"collection":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/comments?post=9358"}],"version-history":[{"count":27,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/9358\/revisions"}],"predecessor-version":[{"id":10749,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/9358\/revisions\/10749"}],"wp:attachment":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/media?parent=9358"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/categories?post=9358"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/tags?post=9358"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}