{"id":142,"date":"2019-02-02T20:38:31","date_gmt":"2019-02-02T20:38:31","guid":{"rendered":"https:\/\/ryan.hattie.codes\/?p=142"},"modified":"2021-12-31T05:47:12","modified_gmt":"2021-12-31T05:47:12","slug":"displaying-live-weather-data-with-my-low-level-ssd1327-library","status":"publish","type":"post","link":"https:\/\/raelynn.hattie.codes\/blog\/2019\/02\/02\/displaying-live-weather-data-with-my-low-level-ssd1327-library\/","title":{"rendered":"Displaying Live Weather Data with my Low Level SSD1327 Library"},"content":{"rendered":"\n<p>Having your own <a href=\"https:\/\/raelynn.hattie.codes\/blog\/2019\/01\/28\/year-round-weather-station\/\" data-type=\"URL\" data-id=\"https:\/\/raelynn.hattie.codes\/blog\/2019\/01\/28\/year-round-weather-station\/\">personal weather station<\/a> is great and all, but what if you want to actually see what the current conditions are without having to open up your <a href=\"https:\/\/python.raelynn.hattie.codes\/weather\/\" data-type=\"URL\" data-id=\"https:\/\/python.raelynn.hattie.codes\/weather\/\">live dashboard<\/a>? What if you could just look at a display in the kitchen for an instantaneous dose of meteorological goodness? That&#8217;s where cheapo OLED modules come in.<\/p>\n\n\n\n<p>At first, I had tried the ubiquitous SSD1306. They&#8217;re cheap, crisp, and supported by a plethora of libraries for every platform and language you can think of (I&#8217;m quite fond of the <a href=\"https:\/\/github.com\/ThingPulse\/esp8266-oled-ssd1306\">ThingPulse library<\/a> for the ESP8266, the UI features are really handy). I have a number of projects around the house using these little modules. However, they have a major problem: readability at a distance. I ended up needing to make each number its own page on a scrolling layout, which means that you need to stand fairly close to the display to read it, and wait for the pages to scroll through to the value you actually wanted to read.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/01\/IMG_20190131_155942-1024x576.jpg\" alt=\"\" class=\"wp-image-143\" srcset=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/01\/IMG_20190131_155942-1024x576.jpg 1024w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/01\/IMG_20190131_155942-300x169.jpg 300w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/01\/IMG_20190131_155942-768x432.jpg 768w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/01\/IMG_20190131_155942-830x467.jpg 830w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/01\/IMG_20190131_155942-230x129.jpg 230w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>My first attempt at a weather display, using the SSD1306.<\/figcaption><\/figure>\n\n\n\n<p>Thankfully, the SSD1306 has a bigger brother: the SSD1327. While the SSD1306 can only drive 128&#215;64 pixels with 1 bit of color depth (i.e. each pixel is either on or off) the SSD1327 can drive 128&#215;128 pixels with 16 levels of grayscale. In addition, SSD1327 modules like the one sold by Waveshare are 1.5&#8243; diagonally, compared to the 0.97&#8243; panels generally found on SSD1306 boards. Sounds like a perfect upgrade, right? Buy the new module, tweak some code, and you&#8217;re ready to go! That&#8217;s what I thought, until I started trying to actually write firmware for this thing.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/OLED_Screen_Sizes-1024x593.png\" alt=\"\" class=\"wp-image-150\" srcset=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/OLED_Screen_Sizes-1024x593.png 1024w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/OLED_Screen_Sizes-300x174.png 300w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/OLED_Screen_Sizes-768x444.png 768w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/OLED_Screen_Sizes-830x480.png 830w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/OLED_Screen_Sizes-230x133.png 230w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>A 0.97&#8243; SSD1306 breakout next to the Waveshare 1.5&#8243; SSD1327 board.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">The Problem with the SSD1327: Nobody Supports it<\/h2>\n\n\n\n<p>As far as I could tell, there were 2 main libraries available for this board: <a href=\"https:\/\/github.com\/olikraus\/u8g2\">u8g2<\/a> and the<a href=\"https:\/\/www.waveshare.com\/wiki\/File:1.5inch_OLED_Moudle.7z\"> Waveshare official Arduino sketch<\/a> (you know it&#8217;s going to be quality when they call it a &#8220;moudle&#8221;). Unfortunately, u8g2 doesn&#8217;t support greyscale (it&#8217;s designed for 1 bit displays like graphical LCDs), and wouldn&#8217;t even output to my unit properly.<\/p>\n\n\n\n<p>Meanwhile, the Waveshare sketch is a real adventure to dissect. The variables are written in title case with underscores. Macros are created for simple digitalwrite calls. Functions are created to wrap delay() and delayMicroseconds() without adding anything useful. It didn&#8217;t take long for me to realise that it would be way faster to simply build a library from scratch based on the datasheet than to try and work with the example sketch.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Solution: Write a New Library from Scratch<\/h2>\n\n\n\n<p>So I dove into the <a href=\"https:\/\/www.generationrobots.com\/media\/Ecran_OLED_0_96\/SSD1327_datasheet.pdf\">datasheet<\/a>. A couple hundred lines of code and a lot of experimentation later, and I was drawing pixels and scrolling gradients to the display. <\/p>\n\n\n\n<p>The next step was to draw text. For 8&#215;8 characters I used <a href=\"https:\/\/github.com\/dhepper\/font8x8\">font8x8<\/a>, but I quickly wanted more options for font sizes. I ended up hacking together a quick and dirty font to header converter using Processing. It&#8217;s not pretty, it&#8217;s not efficient, and it doesn&#8217;t even generate proper header files, but it&#8217;s good enough for what I needed.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>char thisChar = 0;\nString code = \"char font16&#91;128]&#91;32] = {\\n\";\n\nvoid setup(){\n  size(16,32);\n  textSize(32);\n  noSmooth();\n  textFont(createFont(\"Ubuntu Mono\", 32));\n  background(0);\n  fill(255);\n  frameRate(10);\n}\n\nvoid draw(){\n  background(0);\n  text(thisChar,0,26);\n  loadPixels();\n  code += \"{ \";\n  for(int i = 0; i &lt; 512; i+=8){\n    byte thisByte = 0;\n    for(int bit = 0; bit &lt; 8; bit++){\n      if(pixels&#91;i+bit] == color(255)){\n        thisByte += 1&lt;&lt;bit;\n      }\n    }\n    code += \"0x\" + String.format(\"%02X\", thisByte);\n    if(i!=504){\n      code += \", \";\n    }\n  }\n  code += \"},\\n\";\n  thisChar++;\n  if(thisChar &gt; 128){\n    code+=\"};\";\n    print(code);\n    String&#91;] fileStrings = new String&#91;1];\n    fileStrings&#91;0] = code;\n    saveStrings(\"font.h\", fileStrings);\n    exit();\n  }\n}<\/code><\/pre>\n\n\n\n<p>This let me generate Ubuntu Mono font files in 8&#215;16 and 16&#215;32 character sizes. After writing some simple code to draw text, I was able to print char arrays and strings to the display in multiple font sizes. At this point, I deemed the library usable enough for my purposes. Is it a perfect library? Heck no. Fonts are handled poorly, there are no functions for circles or lines, and I don&#8217;t have any bitmap functions. However, it can display text and basic custom graphics to a display easily, which is all I (and I suspect many other people) need.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"805\" src=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/Live_Display-1024x805.png\" alt=\"\" class=\"wp-image-152\" srcset=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/Live_Display-1024x805.png 1024w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/Live_Display-300x236.png 300w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/Live_Display-768x604.png 768w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/Live_Display-830x652.png 830w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/Live_Display-230x181.png 230w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/Live_Display.png 1766w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>It&#8217;s alive! A simple Thingspeak client, complete with text and rectangles!<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Building the Display Unit<\/h2>\n\n\n\n<p>Unlike some of my other projects, I wanted this project to be something that anyone with a 3D printer and some basic fasteners could put together cheaply. As a result, the only parts used were the display module, a NodeMCU board, 2 standoffs, some screws, and some nuts. The housing is a single, easy to print file only requiring support in one spot (the screen bezel). No soldering is required.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"544\" src=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/1327_Internals-1024x544.png\" alt=\"\" class=\"wp-image-149\" srcset=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/1327_Internals-1024x544.png 1024w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/1327_Internals-300x159.png 300w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/1327_Internals-768x408.png 768w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/1327_Internals-830x441.png 830w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/1327_Internals-230x122.png 230w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>The internals of the display unit. Yep, it really is just a NodeMCU and an OLED module.<\/figcaption><\/figure>\n\n\n\n<p>The assembled unit can be mounted to a cabinet, shelf, etc by adhering the triangular surfaces on either side to the mounting surface. I decided to use 3M&#8217;s Command &#8220;Picture Hanging Strips&#8221; (essentially some Dual-Lock with a removable adhesive backing) so that I can easily detach the unit for servicing, firmware flashing, etcetera.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"690\" src=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/SSD1327_Mounted-1024x690.png\" alt=\"\" class=\"wp-image-155\" srcset=\"https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/SSD1327_Mounted-1024x690.png 1024w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/SSD1327_Mounted-300x202.png 300w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/SSD1327_Mounted-768x518.png 768w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/SSD1327_Mounted-830x560.png 830w, https:\/\/raelynn.hattie.codes\/blog\/wp-content\/uploads\/2019\/02\/SSD1327_Mounted-230x155.png 230w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>The finished product, adhered to the underside of a kitchen cabinet.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Links<\/h2>\n\n\n\n<p>The SSD1327 library can be found on <a href=\"https:\/\/github.com\/hexaguin\/SSD1327\">Github<\/a>, and the STL for the housing is on <a href=\"https:\/\/www.thingiverse.com\/thing:3397089\">Thingiverse<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Having your own personal weather station is great and all, but what if you want to actually see what the current conditions are without having to open up your live dashboard? What if you could just look at a display in the kitchen for an instantaneous dose of meteorological goodness? That&#8217;s where cheapo OLED modules<\/p>\n<div class=\"blog-grid-button\"><a class href=\"https:\/\/raelynn.hattie.codes\/blog\/2019\/02\/02\/displaying-live-weather-data-with-my-low-level-ssd1327-library\/\">Read More <i class=\"fa fa-arrow-right\"><\/i><\/a><\/div>\n","protected":false},"author":1,"featured_media":152,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,10,4],"tags":[6,7,24,28],"class_list":["post-142","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-3d-printing","category-code","category-hardware","tag-3d-printing","tag-arduino","tag-esp8266","tag-oled"],"_links":{"self":[{"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/posts\/142"}],"collection":[{"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/comments?post=142"}],"version-history":[{"count":11,"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/posts\/142\/revisions"}],"predecessor-version":[{"id":226,"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/posts\/142\/revisions\/226"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/media\/152"}],"wp:attachment":[{"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/media?parent=142"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/categories?post=142"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/raelynn.hattie.codes\/blog\/wp-json\/wp\/v2\/tags?post=142"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}