## Introduction: Mandelbrot and Julia Sets on ESP32

You certainly know **fractals**, the most famous of which is the Mandelbrot set.

Here is a program to play with on ESP32. I chose the **ESP32 **because I think it will do the calculations faster than a standard Arduino (higher clock frequency: 240 MHz): about a second to a second and a half for calculation and display.

The code displays on a 480 x 320 TFT touch screen. It calculates Mandelbrot and Julia sets for several parameter values, and allows you to zoom in on areas of interest to see the fractal aspect (i.e. the presence of the same structures at each scale change). The zoom level is limited due to the limited accuracy of the calculations, but a half a dozen zooms can be made before the image degrades.

**Get ready to explore the magic world of fractals...**

## Step 1: What Are Mandelbrot and Julia Sets?

The Mandelbrot set is named after Benoit Mandelbrot (1924-2010), a French and American mathematician who did pionnering work in fractal geometry, initiated at the end of the 19th century by, among others, Peano, Sierpinski and Julia.

**What are fractal objects?**

The irregularities of nature, which may seem chaotic, such as the line of the sea coast, the shape of clouds, a tree, are in fact the expression of a very complex geometry on changing scale. In this context, the notion of *fractional dimension* replaces that of the usual Euclidean dimension (which is always an integer)!

__A fractal object is such that any portion of it is identical to the whole__ (this is called *self-similarity*): its structure is invariant by scale change.

The term "**fractal**" is a neologism created by Benoît Mandelbrot in 1974 from the Latin root *fractus*, which means "broken", "irregular". It's both a noun and an adjective. Many natural phenomena - such as the outline of the coastlines or the appearance of Romanesco cabbage (see picture) - have approximate fractal shapes.

Benoît Mandelbrot's had an somewhat atypical career: after teaching at the University of Lille (France), he took a position at IBM where he quickly became an IBM Fellow, which gave him a great freedom for his scientific studies. In the early 1980s, after he left IBM, he became a professor at Harvard, but settled permanently at Yale.

His work in the 1960s and early 1970s led him to publish a famous article entitled "*Fractal Objects*" in which he showed that these objects, considered by a large part of the mathematical community as mere curiosities, were found everywhere in nature. He gave a lot of examples in a wide variety of fields such as physics, hydrology, finance, meteorology, geography, geology, metallurgy....

**What is the Mandelbrot set?**

To begin, let's say that it's *a nice drawing generated by a program*. And this program is quite simple.

There exist many computer-generated drawings and many computer software to generate them. So what's so special about this one? First, the Mandelbrot set is a *subset of the plan*, a collection of points. It contains areas but also smooth curves, filaments, points from which multiple branches emanate, and other things. Second: it's really fascinating and has a very interesting history.

At the beginning of the 20th century, French mathematicians Pierre Fatou and Gaston Julia developed a sub-domain of maths called *holomorphic dynamics*. They were interested in particular functions, acting on numbers, *using some of the simplest formulas available*. The numbers in question are complex numbers, quantities represented by two coordinates (just like the points of a plane) called real and imaginary parts. They were invented in the 16th century by mathematicians to help find the roots of polynomials and the solution of equations but have found wide and deep applications in mathematics and physical sciences. We can add 2 complex numbers, multiply or divide them, and do many other things.

Fatou and Julia studied the properties of certain dynamic systems where a complex number varies according to **a simple rule repeated over and over again**: no need for complicated maths here (so, you can forget the first image...). They revealed the richness of these systems, defined the sets now called Julia's sets, and studied their self-similarity, therefore **fractal **aspect... but the word did not exist at that time because it was only invented much later, by... Benoît Mandelbrot!

After the founders' work, this domain fell into oblivion. When the computers arrived, they helped to explore a lot of mathematical phenomena requiring intensive computing, including the domain opened by Julia and Fatou.

Thus, when Benoît Mandelbrot decided to use IBM computers in the 1980s to represent a certain mathematical set related to holomorphic dynamics, he obtained a very attractive and very intriguing drawing (first picture of the previous section).

What does the Mandelbrot set represent? Basically, there is an underlying dynamic system associated to each point of the image. The coordinates of the point act as an adjustable parameter. Different points correspond to different sets of Julia and depending on their behavior, **we can decide to color the point in a particular way**. The Mandelbrot set is the set of parameters for which the system has a certain property.

**How to compute Mandelbrot and Julia sets?**

We need to go into a little more detail on how to calculate these sets. Mandelbrot and Julia sets are calculated by the repeated iteration of a simple formula, in our case **z^n+c**. **z** is a complex number that represents the coordinates of a point on the display. **n** is an integer exponent, so z^n is equal to z multiplied by itself n times, and **c** is a constant.

For the Mandelbrot set, for all points in the display area, we initialize z to 0. The constant c is taken equal to the value of** the coordinates of the considered point** and the formula is iterated.

**Here is the ****rule**: a point is part of the set if the repeated application of this formula **does not diverge** (i.e. does not lead to calculations towards large numbers). It can be mathematically shown that if the result of the formula exceeds 2 (in modulus since we are talking about complex numbers) the iteration will diverge. So to quickly obtain pretty colors, we stop the iteration when the modulus of the result exceeds 2 and the color corresponds to the number of that particular iteration. If the number of iterations becomes too large (so if the point is part of the Mandelbrot set) we stop after a given threshold and associate the black color to this point.

The Julia set is calculated in a similar way but the calculations are not initialized at 0 but at the value of the coordinates of the considered point and the constant c is chosen by the user and remains the same for the entire image.

That's it, I hope it's clear... These explanations help to better understand the rest of the instructions for use.

## Step 2: What Do You Need?

Bill of material:

- 1 ESP32 board
- 1 TFT display with touchscreen and stylus
- 1 breadboard and wires

That's it. __Total cost under 10 USD__.

Espressif's **ESP32 **is a dual core microcontroler running at **240 MHz**, which makes it a good candidate for fast and complex repetitive computing. It has WiFi and Bluetooth capacities that I do not use in this project.

The instruction set is 32 bits in size. Computing with 16 and 32 bit variables is very fast which enables accurate computations, *which is fundamental for zooming purpose*. In this application, for a 320 x 240 display, an image is roughly made of 75,000 pixels, each of which is calculated using an iterative process which may run up to 100 times. This may lead to **7,500,000 unitary calculations**, each of which is an exponentiation, i.e. several multiplications...

So computation speed is essential here, **but accuracy is fundamental**. The more you zoom, the smaller the size of the portion of the set to display. This means that each of the 320 x 240 pixels of the image represent a number that is very close to its neighbours. As the zoom increases, this proximity increases.

But fractal images have this property that **they remain unchanged by scaling**. So small details appear everywhere and for any scaling factor. The main shape of the Mandelbrot set, as seen on the display on the above picture, can be found somewhere else in a much smaller version, and be displayed if you zoom close enough (see on the video). But if the coordinate difference between two neighbour pixels is too small to enable the ESP32 to catch their difference in behaviour, due to lack of accuracy, the fractal effect cannot be shown...

To get good precision, the code uses floats, which are coded in **32 bits** by the ESP32. This enables up to 6 or 7 zooming levels. Using double precision (64 bits) would have increased this zooming depth, at the cost of slower computations, thus longer times between 2 images.

To make it double precision, just change all occurences of "float" to "double" in the code and run the code. I recently made a version for a bigger display (HVGA 480 x 320 pixels): 16 bits floats take 3 seconds to display the image, and doubles take between 10 and 20 seconds (3 to 6 times longer) but support **more than 15 zoom levels**. The third image in this chapter shows the zoom level 14 in the right-most part of the Mandelbrot set.

**How to connect the display:**

I used a SPI display, and the parameters are set in the User_Setup.h file (in the TFT_eSPI library folder):

- Driver: uncomment the correct driver for your display. Mine was #define RPI_ILI9486_DRIVER
- Pin numbers: go to the ESP32 section of the file and choose
- #define TFT_MISO 19
- #define TFT_MOSI 23
- #define TFT_SCLK 18
- #define TFT_CS 15 // Chip select control pin
- #define TFT_DC 2 // Data Command control pin
- #define TFT_RST 4 // Reset pin (could connect to RST pin)
- #define TOUCH_CS 22 // Chip select pin (T_CS) of touch screen

- Fonts: no need to change them
- Other options: I selected the following
- #define SPI_FREQUENCY 20000000
- #define SPI_READ_FREQUENCY 20000000
- #define SPI_TOUCH_FREQUENCY 2500000

All the other lines of the file are commented out.

**Calibrate the touch capacity of the display**

If the selection of a screen portion or a button is not accurate, or even totally wrong, run the touch calibration sketch from the TFT_eSPI library and copy / paste into the code the array it provides (be sure to use the correct value for display orientation, 1 or 3 for landscape).

## Step 3: ESP32 Program

The code displays on a 320 x 240 TFT touch screen, and uses the TFT_eSPI library. It calculates Mandelbrot and Julia sets for several exponent values, and allows you to zoom in on areas of interest to see the fractal aspect (i.e. the presence of the same structures at each scale change).

The attached code is a version for 480 x 320 display. In this version, you can change the size (width and heigth in pixels) of the display. The TFT_eSPI library defines the connections in a setup file (attached) which must be put in the library's directory.

**The code starts by displaying the operating instructions (see picture and video).**

Most of the screen is reserved for displaying images, touch buttons are available on the right side of the screen:

**R**: performs a "reset", i. e. displays the image to its maximum scale,**U**: "undo" allows you to go back to the previous step (if the zoomed region is not interesting, you can choose another part of the image to zoom in),**M**or**J**: allows you to switch from Mandelbrot's set to Julia's set and vice versa.

The labels of some keys change according to the context: they display *the function that will be executed if pressed*. So if you currently display the Mandelbrot set, the M/J key displays J since if you press it you will display Julia's set (and vice versa).

The same applies to the choice of the colour palette. We start with the green palette. The key proposes the next palette (the blue one). The palettes are: red, green, blue, grey, palette 1, palette 2 and back to red. The last two are multicolored pallette tests which provide more contrast, allowing to better see some details.

**The key with a number allows you to choose the exponent n**, in a loop from 2 to 7 (and back to 2). In the same spirit, it displays 3 if you are currently at 2...

Finally, when displaying the Julia set, it is necessary to choose the value of the constant c : the **C** key allows you to do this, thanks to a selector (see second picture). The value of this constant is displayed with the set.

**Clicking on the image zooms around the selected point. **A small circle is displayed at the touched point and a rectangle highlights the zoomed zone of the set.

The 3rd picture shows that computing times remain between 0.8 and 1.2 seconds for 320 x 240 pixels, which make it comfortable to zoom and display. It reaches 3 seconds for 480 x 320 pixels, but provides more details.

## Step 4: Some Pictures Explained...

The biggest picture is the well known Mandelbrot set. The complex numbers used in this image range from -2.1 to +0.7 in abscissa, and -1.2 to 1.2 in ordinate. If you zoom on **the very left part of this first image**, chances are you finally get the second one, which displays a smaller version of the original set found in the left-most tip of the set. For both these images, the exponent ('n') is equal to **2**: that's the value normally used to display Mandelbrot sets.

If you change this value to **3** (just click on the key saying 3), you get the third image. One obvious difference is the **symmetry factor**: n=2 gives an axial symmetry (i.e. the set is symmetrical against the median horizontal axis), but with n=3 the image becomes** invariant by rotation of 120°** (one third of 360°, rotation symmetry factor of 3). And it retains its fractal properties, which you can verify by zooming on the edges of the black shape.

The 4th image is a Julia set obtained after **selecting a coefficient value** equal to 0.414 in abscissa and 0.09 in ordinate. The red palette is chosen, as can be seen by the green key on the right (green, being the next colour to be chosen). The fifth image displays the same kind of Julia set, which a **higher imaginary part of the constant **(0.358).

I hope you will enjoy playing with this program and that you will be able to **display nice fractal pictures**. Do not hesitate to explore the Mandelbrot and Julia sets, and play with the palettes: they help identify some details that may not be visible with the simple monochrome ones. **You may even discover some fractal landscapes that no one has ever seen before you...**

____________________________

Want to discover more fractal images? Just click here or explore fractal art or even ascii fractal. Maybe this instructable will make you want to create such great images...

Second Prize in the

Made with Math Contest

## 27 Comments

Question 1 year ago

Hello, I am a little bit confused with the touchscreen pin setup. I am using an Adafruit TFT with resistive touch, and the only pins I see on the the SPI interface are X+, Y+, X-, Y-. How do these correlate with the touchscreen pins you mention in the project?

Excuse my ignorance, it's my first time using a display with Arduino.

Answer 1 year ago

Also, I connected all the other pins as specified to my ESP32, and the code uploads without problem, but when powering up the screen just appears white and remains like that. Any idea why that may be?

Reply 1 year ago

Hi

If it's an Adafruit display, you should first try to make it work by following the instructions on the Adafruit website. When you're done, just try my sketch but with your pin connections.

Question 1 year ago

Here is the circuit diagram which I put together for your page.

Answer 1 year ago

Thanks !

Question 1 year ago

I have the project up and running. Couple of issues with the touch screen.

The zoom function works but zooms in a different place from where I touch.

The R,U,J,3 buttons are unresponsive.

Answer 1 year ago

It's a calibration problem. Please find and run the calibration code from the library of the touch screen or of the tft display. It will give you some parameters that go into my code.

It may also be related to the orientation of the screen. Search which part of the screen acts as the buttons.

Hope it helps.

Reply 1 year ago

I found in the tft_spi library the touch_calibrate example. Could you provide a little extra detail of what parameters to add to the code. I did try several variations for the screen orientation.

Reply 1 year ago

Interestingly it works quite well setting the rotation to 11 including the buttons.

Reply 1 year ago

I am satisfied with the project working nicely. I want to thank you for posting this. It was a great learning curve and appreciate the challenge. I'll be posting the circuit diagram on youtube as it was difficult to find the connections between the esp32 board and the tft touch screen. You may like to add the link to your page which I'll send you. It will make it easier for those that want to tackle this project.

Reply 1 year ago

Good, I'll do this, thanks

1 year ago

hi, i tried uploading my sketch to my esp32 but it says TFT_eSPI has no member named getTouch. How do i fix this?

Thanks.

Reply 1 year ago

Try this

https://github.com/Bodmer/TFT_eSPI/issues/169

Reply 1 year ago

Reply 1 year ago

This is also interesting

https://github.com/Bodmer/TFT_eSPI/issues/117

Reply 1 year ago

Sorry for the late answer.

About the get touch issue,Bodmer (author of the library) provided an answer here : https://github.com/Bodmer/TFT_eSPI/issues/169

If you define a pin for the touch chip select then it should be OK:

https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setup.h#L97

Question 1 year ago

Thank you for this project. Please can you provide the circuit diagram.

I was trying to compile the 2 Mandel programs you provided and made the changes in the User_setup.h file and tried different changes to the lines

#define TOUCH_CS PIN_D0 // Chip select pin (T_CS) of touch screen and

#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen

but still get the "TFT_eSPI' has no member named 'getTouch'" error on line

boolean istouched = tft.getTouch(&xtft, &ytft);

Any help would be greatly appreciated.

Reply 1 year ago

If your problem is related to the TFT_eSPI library, I'd suggest that you first try to run the examples of the library. Then, when you get you display to work, you shouldn't have any problem with my codes.

Reply 1 year ago

About the get touch issue,Bodmer (author of the library) provided an answer here : https://github.com/Bodmer/TFT_eSPI/issues/169

If you define a pin for the touch chip select then it should be OK:

https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setup.h#L97

Reply 1 year ago