Smart Weather App

[work in progress…]

Just got this nice Waveshare 2.9″ e-Paper module as a present. It looks like an ideal display for a weather station. An esp8266 board could update the display with information from the web before entering deep sleep mode for an hour or so. A unique feature of these displays is that they only draw power during update. This means that last updated weather information remains visible, even if the esp8266 is sleeping.






Searching for a free web service that offers actual weather data, as well as weather forecasts, I noticed that their reliability can be as unpredictable as the weather. So my new project is to build a ‘smart’ weather station for esp8266. It will retrieve weather information from 6* independent sources on an hourly basis, and initially show averaged values for all items of interest.

The ‘smart’ part is that the algorithm accepts feedback. Firstly, there’s automatic feedback from a calibrated BME280 sensor that measures the actual temperature, humidity and air pressure at my location. These measurements will constantly be compared with the predicted values, resulting in weight factors being assigned to the source values for the prediction. When I’m satisfied with the result, the BME280 sensor can be removed.

Secondly, in my prototype version for TFT touchscreen, the screen has a manual feedback option: clicking on the ‘actual weather’ icon will display all possible weather condition icons. If necessary, an icon that describes the actual conditions more accurately can be clicked to overrule the algorithm’s choice and adjust the weight factors accordingly.

The feedback from the weather station will learn de (php) algorithm how to weigh all externally retrieved data in order to send the best fitting results to the display. Eventually, this will result in a weather station that shows more – and more reliable – information than each of the individual sources.

Meanwhile, the php part of the project is finished. A video of the station in action will follow after the esp8266 sketch is ready as well.


* Apart from global services Wunderground and Openweathermap, I use two Dutch weather services (KNMI and Buienradar), as well as METAR/TAF info from two nearby airfields. Although the esp8266 could probably handle all json/xml decoding, I decided to leave that to a php script on my webserver. On request, it returns the weighted averages to the esp8266, or processes its feedback.

More fractals…

At the end of my exploration of the fractal-universe, I had my tireless Arduino Uno create a couple of ‘classics’. The video shows the growth of the famous Barnsley Fern.

This is a special IFS fractal: each iteration step transforms just one single pixel (instead of the usual geometric shape), using one out of four possible transformations. By changing the parameters and/or the probabilities of the transformations, different kinds of fern patterns will appear.

After I’d finished the sketch (the simplest of all my fractal sketches), I could hardly believe that it could generate such a beautiful image (after 50,000 iterations).

And then, of course, there is the mother of all fractals, named after the (disputed) father of all fractalists: Mandelbrot. The sketch to produce it is much simpler than most backtracking sketches, but it may take up to 256 iterative function calls for every pixel to calculate its color. With 153,600 pixels, it took the Uno a couple of minutes to finish the picture.

The black area is a 2D representation of the actual Mandelbrot Set, but the fascinating stuff is happening at its border. By changing the coordinates and zoom level inside the sketch, you can zoom in at any area. Key factors for getting spectacular results are: selection of the area, maximum number of iterations and color mapping.


This short exploration wouldn’t be complete without mentioning the elegant Julia fractals. Like Mandelbrot fractals, they are created by iteration of the function f(z) = z² + c  (in the complex plane). For Julia fractals, c is fixed and we examine the function’s behaviour for all z values within our range of interest. So there’s a Julia set Jc for every c in the complex plane, but the most visually appealing Julia fractals will arise from c values at the border of the Mandelbrot set.

Julia fractal (c = -0.79 -0.15i) produced by an esp8266 on a 480×320 TFT display

IFS fractals

The use of backtracking in my Pythagorean tree sketch made me realize that it can be useful for creating other IFS fractals as well (fractals produced by Iterated Function Systems). These fractals are very ‘geometric’ by nature (and can actually be found in nature). Classic examples are the Sierpinski Gasket and the Koch Snowflake.

Memory usage for backtracking is O(d), where d is the chosen recursion depth. For my purpose (displaying contractive fractals on a 480×320 display), d will usually be quite small (<15) in order to prevent objects from becoming single pixels. That means that most sketches will run fine on an Arduino Uno.

The above video shows a (slightly randomized) Binary Tree fractal

Generating Binary Tree fractals resembles the growth of a plant. Starting with a vertical trunk, branches recursively split into two new branches, growing in directions determined by θ (0°<θ<180°) while their length is reduced by a factor r (0<r<1).

In symmetric binary trees, θ and r are fixed. In order to produce more naturally looking ‘plants’, I applied some randomization to both θ and r for every new branch. The drawing order of splitting branches is randomized as well. As a finishing touch, branches with lengths smaller than a treshold value will be drawn in red.



Another famous IFS fractal is the Sierpinski Carpet. The largest square in the picture is 243×243 pixels wide. Iteration depth is 5, so the smallest black squares become single pixels (you may have to zoom in to see them).





And this is the Sierpinski Gasket (or Triangle) with iteration depth 6. It’s interesting that the same pattern can also be generated by elementary cellular automaton Rule 30, by a Lindenmayer system or by a Chaos game method.




Next is the Koch Snowflake (actually a triangle of three Koch curves) with iteration depth 4.

After writing a familiar backtracking based algorithm, I also wrote a far more compact sketch for drawing a Koch curve. It’s the second sketch at the bottom of this page.



My last example is the space-filling (pseudo) Hilbert curve. It took me some time to understand why a backtracking approach is less suitable in this case. Each level consists of more than just four transformations of its parent’s pattern, because these transformations have to be interconnected as well. Moreover, since levels don’t share any lines with previous levels (see video below), you can’t use the display to preserve lines.

So I went for a solution that iteratively builds an array of drawing instructions. This results in a very simple algorithm, but the size of the instructions array is equal to  4n – 1, where n is the desired iteration depth. With some bitwise tricks, an Arduino Uno can draw the Hilbert curve for up to n=6, which happens to make sense for my 480×320 display anyway, because line distances would become smaller than a pixel for n>6.



This is the sketch that generated the fractal in the Binary Tree video:


And here’s my newest sketch for drawing a Koch Snowflake. It superimposes the same pattern of rotation instructions with a different offset and periodicity for each level. I like the elegance of this algorithm. It kind of generates and processes the final string of an L-system on the fly, without any rewriting or intermediate data storage. The sketch is for iteration depth 4 on a 320×240 display.


Pythagorean Tree

This fractal was first drawn by Albert Bosman, a Dutch mathematics teacher.

It takes its name from the right-angled triangles between the generated squares, illustrating the Pythagorean theorem. The choice of the remaining angles determines the skewness of the tree.

The sketch runs on an Arduino Uno and draws the tree for 3 different angles on a 480×320 TFT display. The color of the squares depends on their size, trying to simulate trunks and leafs.

The algorithm uses backtracking, very similar to the maze generator & solver in my previous post. Recursion depth was limited to 10 levels deep, in order to prevent the smallest squares from becoming single pixels.

To speed up drawing, I use the display’s symmetry when the tree is generated from an isosceles triangle. The rest is just basic goniometry.

[Comments are in Dutch. Sorry…]