Conjunto de Mandelbrot em Pi Pico / ILI9341

Tempo de leitura: 3 minutes

Mandelbrot Set é IMHO o fractal mais famoso. Leia aqui para obter informações adicionais: https://en.wikipedia.org/wiki/Mandelbrot_set

Este projeto foi inspirado em https://hackaday.io/project/177884-mandelbrot-on-p … Reutilizei a maior parte do código original, mas decidi implementá-lo com 2.8″ ILI9341 SPI tft usando o driver de micropython Pico de https://github.com/jeffmer/micropython-ili9341. Este é meu novo projeot com o  Raspberry Pi Pico e micropython.

 

Iniciando

Presumo que você tenha o Pi Pico com micropython carregado, Thonny IDE instalado e esteja um pouco familiarizado com o Pico e o micropython. Caso contrário, há uma ótima introdução sobre todos os assuntos relacionados em https://www.raspberrypi.org/blog/new-book-get-started-with-micropython-on-raspberry-pi-pico/ ou pode ver no nosso artigo aqui.

Obtenha o software.

Instale os drivers ILI9341 no diretório lib de Pi Pico usando IDE. Baixe o arquivo anexado e abra-o no IDE.

 

ili9341_spi_mandelbrot_set.py

from machine import Pin, SPI, ADC
from ili934xnew import ILI9341, color565
import time
import math
import _thread

WIDTH=320
HEIGHT=240
ROTATION=1

# Pinos TFT são conectados de acordo
TFT_CLK_PIN = const(10)
TFT_MOSI_PIN = const(11)
TFT_MISO_PIN = const(12)
TFT_CS_PIN = const(13)
TFT_RST_PIN = const(14)
TFT_DC_PIN = const(11) 

def init_tft():
    spi = SPI(1,baudrate=40000000,miso=Pin(TFT_MISO_PIN),mosi=Pin(TFT_MOSI_PIN),sck=Pin(TFT_CLK_PIN))
    display = ILI9341(spi,cs=Pin(TFT_CS_PIN),dc=Pin(TFT_DC_PIN),rst=Pin(TFT_RST_PIN),w=WIDTH,h=HEIGHT,r=ROTATION)
    display.erase()
    return display
    
MAX_ITER = 80
def mandelbrot(c):
    z,n = 0,0
    while abs(z) <= 2 and n < MAX_ITER:
        z = z*z + c
        n += 1
    return n

xOffset = -0.8
RE_START = -2 + xOffset
RE_END = 2 + xOffset
IM_START = -1
IM_END = 1

ZOOM_IM = 1.2 #1=100% 0.5=200%
ZOOM_RE = 0.8 #1=100% 0.5=200%
OFFSET_IM = 0
OFFSRT_RE = 0

BLACK = color565(0,0,0)   
WHITE = color565(255,255,255)
RED = color565(255,0,0)
GREEN = color565(0,255,0)
BLUE = color565(0,255,0)
YELLOW = color565(255,255,0)
CIAN = color565(0,255,255)
MAGENTA = color565(255,9,255)
colors = (WHITE,YELLOW,RED,GREEN,BLUE,CIAN,BLACK,MAGENTA)

building = False 
def buildFractal():
    global building
    global buf
    if building==True:
        return
    building=True
    display = init_tft();
    RE_START_OFF    = RE_START + OFFSET_RE
    RE_WIDTH        = RE_END - RE_START
    IM_START_OFF    = IM_START + OFFSET_IM
    IM_WIDTH        = IM_END - IM_START
    ticks_start = time.ticks_ms()
    for x in range(0, WIDTH):
        xx = (RE_START_OFF + (x / WIDTH) * RE_WIDTH) * ZOOM_RE
        for y in range(0, HEIGHT):
            yy = (IM_START_OFF + (y / HEIGHT) * IM_WIDTH) * ZOOM_IM
            c = complex(xx, yy) # Convert pixel coordinate to complex number
            m = mandelbrot(c)   # Compute the number of iterations
            colorIndex = int(m/11) #colors[m//12]
            if colorIndex > 0:
                display.pixel(x, y, colors[colorIndex]) # Plot the point
    print("Total Time={}!!!!!".format(time.ticks_diff(time.ticks_ms(), ticks_start)))
    building = False
      
display = init_tft();      

#button é usado para iniciar a construção do Conjunto Mandelbrot
button=Pin(9, Pin.IN, Pin.PULL_DOWN)

#Os 3 potenciômetros são usados para parametrizar zom, fazer zoom panorâmico x e panorâmico y
# eles estão ligados ao aterramento e a voltagem de 3,3 V e do pino do meio vai para
#ADC para obter valor varing no pico.
zoom = ADC(28)
pan_x = ADC(27)
pan_y = ADC(26)
while True:
    if button.value()==1:       
        print("button pressed")
        buildFractal()
    time.sleep_ms(500 Z)
    ZOOM_RE = 1 * (zoom.read_u16() / 65535.0) #full signal=no zoom
    ZOOM_IM = 1.5 * (zoom.read_u16() / 65535.0) #full signal=no zoom
    OFFSET_RE = ((pan_x.read_u16() / 65535.0) - 0.5) * 5.5
    OFFSET_IM = ((pan_y.read_u16() / 65535.0) - 0.5) * 2.7
    print("zoom_re={}, zoom_im={}".format(ZOOM_RE,ZOOM_IM))
    print("offset_re ={}, offset_im={}".format(OFFSET_RE,OFFSET_IM))

 

Conecte o Hardware …

O código contém a definição da ligação para botão, potenciômetros e tft (consulte os comentários e as definições dos pinos no arquivo de origem). O botão é conectado com pull-down, de forma que quando pressionado define o pino do Pico para 3,3V. Botão de fio, tft e potenciômetros conforme definido no código. Eu tinha tft que tinha regulador de tensão a bordo, então tive que ligar o tft de 5V. Se o seu não tem regulador, alimente-o de 3,3V (o Pico tem saídas para ambos quando alimentado por usb).

Esquema completo (Feito para melhor entender o projeto)

 

Carregar e executar …

Use o IDE para fazer upload do arquivo para o pico. Ao iniciar, você verá na janela do console serial do IDE como os valores dos potenciômetros são convertidos em valores de zoom e panorâmica exibidos a cada meio segundo. Bons valores iniciais são 0 para pan_x e pan_y e 1 para zoom. Quando você pressiona o botão, o conjunto de mandelbrot é construído e exibido no tft, parecendo com a primeira imagem. Você pode jogar com zoom e panorâmica para ver partes ampliadas do conjunto, como mostrado na segunda foto.