New WeatherStation Color Version published

Do you like this post? A regular project like the PlaneSpotter Color takes many hours of my free time to develop and maintain. Would you offer me a beer for my hard work if I was your neighbour? Modern technology called teleportation makes it easy to send me a beer. Just click here. Thank you!

It’s been a while since my last post, but I have been working hard on improving the WeatherStation Color. Read here the engineering challenges I had to overcome and how I solved them

The first version WeatherStation Color was a big success and I got a lot of feedback of hackers all around the world who enjoyed putting it together. While this was great there were still quite some issues which I wanted to resolve. The first issue was the flickering of the screen when you would change the screen or update the time. As an additional side effect there would be sometimes pixel artifacts close to the time where I had not been careful enough to delete the previous image. The second frequently mentioned problem was that the icon downloader which downloaded the icons from my web server sometimes would fail to actually download images to a plethora of reasons. And the third problem was that my implementation was a bit lazy when it came to daylight saving time (DST); I just ignored it and assumed the user would be OK to reprogram the WeatherStation once the DST would change. In this post I will focus only on the first problem, the flickering.

 

Flickering

Getting rid of the flickering was the problem which consumed the most part of the last few months. I decided to write a whole new library to address the issue. In order to understand why I thought this step was necessary we first have to look at the problem I tried to solve. After all you might think that even wasn’t such a big issue!

The  Adafruit GFX library which I used for the first version of the WeatherStation Color writes every pixel you alter directly to the display, in my case a 240×320 pixel TFT screen based on the ILI9341 chip. While this is reasonably fast it is not fast enough to keep your eye from seeing an in-between frame when you delete the screen before drawing the next one. Let’s say you draw some weather icons to the screen you want to remove all traces of the old icon before you draw the next one. So you clear the screen and fill it for example with black. Once this operation has finished you continue by drawing the new icon. Since all operations are directly drawn to the screen your eye can see a very short phase where the whole screen was black. You see a flicker! So how could this problem be addressed?

 

Color Palettes

It turns out that I wasn’t the first one to face this issue. This problem is usually addressed by drawing first to a memory-online (virtual) screen. Once all drawing operations of a iteration have been completed you write everything at once from the virtual screen to the physical screen and your eye will not see the clearing of the screen as a separate step. This virtual screen is often called “frame buffer” or “double buffer” and it has one big drawback: it consumes a lot of memory. When I first set out to rewrite the OLED library I wrote for the classic WeatherStation I quickly realized that the available heap memory of the ESP8266 would not be enough to accommodate a frame buffer with 240x320x2 = 150kb. Each pixel would require 2 bytes of memory since the ILI9341 has a 16 bit color scheme. 5 bits for red, 6 bits for green and 5 again for blue would together build up for the 16bit color information. Internally the ILI9341 uses a palette to expand this 16bits to the full color range available on its TFT screen and this brought me to the solution of my memory problem. If I could somehow reduce the memory consumption per pixel to a few bits the ESP8266 would have enough RAM to hold my frame buffer!

Reducing the bit depth per pixel is commonly implemented with color palettes. Instead of describing the pixel colors in values of red, green and blue you use a limited set of colors and give each of this color a alias number. So when changing the color for drawing you don’t say r:127,g:55,b:255 as you would to in a HTML file. You just tell the graphics library to use color 5 from the palette.  Which color represents index 5 is defined in a data structure called the palette. Before the graphic library writes the buffer to the screen it looks up the real color for each index and replaces the index with the RGB value.  This is actually a very old trick. I just recently read this article by Aaron Bell which nicely explains how the Commodore C64 and other 8bit computers used this trick to get 16 colors onto your CRT screen and how some games used fast color switching to create colors beyond the hard wired palette. If you are interested please read his article. I can recommend it!

So now I had my concepts together: frame buffer plus a palette color scheme would solve the flickering problem and still leave enough memory for the program code and the weather information.. Well, it was still a long journey from the concepts to a actually working implementation. I didn’t just want to write a graphic library which could only be used with one type of display. I wanted to write a versatile and easy to use library which would use some kind of hardware abstraction layer (HAL) to separate drawing routines from the hardware commands. It should also be possible to adjust the bit depth (or bits per pixel) depending on the used display or availability of heap memory.

So I had to do some heavy bit math in order to get it all right. The first real demo was a cube rotating with ~17 frames per second (fps) and using the frame buffer with 16 colors or 4 bits per pixel (2^4 = 16):

I think this is quite impressive for a micro controller! If you like to try it out it is part of the MiniGrafx library as a demo.

 

Memory problems

Once again I thought: almost done, now I “just” have to port the old WeatherStation Color code to the new MiniGrafx library. Turns out that I hadn’t realized how bad the WeatherStation library, which fetches the weather data from Wunderground, was in respect of memory consumption. The WundergroundClient class had become a big monolith which would reserve a lot of memory no matter if the application would use all available methods.

I realized this after my first attempts to run the WeatherStation color. Even before reaching the setup() method the ESP8266 would crash with a strange memory access error message. After a while I figured out that a part of the ESP framework tried to allocate memory and couldn’t do that because the frame buffer had already allocated too much. So I had not only to reduce the color palette from 16 colors to 4 but also re-design the Wunderground client. I broke it up into one class per method (current weather, forecast, astronomy and alerts) and more importantly changed the way the fetched data was stored. The old WundergroundClient class allocated all memory when it was instantiated for all methods. It stored the data as members in the class. After the redesign you have to allocate the structs in your own code and then pass in the objects by reference. This way the application code can control much better how much memory it can and needs to allocate.

 

The Result

I am quite happy with the new version of the WeatherStation color! Even if it only has enough memory to display four different colors (black, white, yellow and blue) it looks very colorful. Sadly I had to kick out the photos of the moon phases and replace it with a font based approach. The moon phases are now icons rather than photos but I think that is not a huge loss for the weather station. On the plus side the WeatherStation Color can now display a 6-day forecast on a side scrolling slider (or carousel), which is quite cool (IMHO).

 

The ESP8266 WiFi Color Display Kit

When I first published the WeatherStation Color many of you approached me since they had problems to find the right display. To make things easier for you my friend Fred helped me to put together a starter kit containing a Wemos D1 Mini Pro (with 16MB!), a ILI9341 with resistive touch screen and a PCB to connect the display and the Wemos module. I am very happy to offer you this kit for a reasonable price in my shop. It will be shipped from a warehouse in Dongguan (Perl delta in China) to almost all countries in the world. By buying the kit you are also supporting further development of the WeatherStation and other applications running on this platform.

Order it now!

Touch screen demo

Posted by squix78

10 comments

  1. @squix Love the new code. Somewhere I saw a video where you touched the TFT and it switched between 24 / 48 hr (I think) or displayed home town… did you? was I imagining this?

  2. Hello,
    It is impresive the work you have done, it’s awsome and great.
    I understand that in weathericons.h each of the chars represent 4 pixels, 2 bit per pixel as we are using only 4 colors. I would like to make some changes on the icons, but unable to find a program to translate correctly a bmp grpah to an array to be used for the pallete or configuration. Could you give a hint on this?
    thanks in advance.

    • Hi Enrique. Thanks for the flowers. I currently use a Java tool and plan to put it on the online tool. If you know your way around Java tools I can put it on Github and you can use it…

  3. Any reason you favor the 2.4″ screen rather than the 2.8″? They seem to be otherwise identical aside from one being a little bigger. I’ve got your old software running on one 2.8″ screen (without the touch-screen) and I’ve built the new touch screen version on a 2.8″ as well but I’ve only gotten it stuck together with jumper wires. I’m giving it a 24 hour burn-in before I solder everything together. I love your projects and I’m so happy I bought your OLED kit!

  4. @Squix,
    Very nice job, I saw on picture PCB plate adapter board (between wemos and TFT) has open hardware logo. Any link on kicad/eagle board or OSHPark/PCBs.io link to make this board? I’m using wemos a lot and adding this TFT is a great idea.
    I can design another one, but since you done it and moreover if you share it will save me some time 😉
    But if you keep it private I’ll understand, no problem.
    Charles

    • Actually my Friend Fred designed it. I will ask him if he can share it, especially with you who has shared so many hardware designs for LoRa and such. He is actually trying to get the single channel gateway to run…

  5. Hi Daniel,
    excellent software, looks really very pretty on the TFT.
    I am going to make a PCB layout and a friend will print a housing…
    One question, after some hours i see the time like 00:00:00. Difficult to say, sometimes it will be ok after while and sometimes it stays at 00:00:00. I also used Wemos D1 mini. TFT connection is fine.
    I looked into simpleDSTadjust but i found nothing, do you have an idea ?
    Thanks in advance,
    Kai

Leave a Reply