12 de abril de 2021

Do bit Ao Byte

Embarcados, Linux e programação

Como usar MicroPython na Raspberry Pi Pico

UART na Raspberry Pi

Parece que realmente a maneira mais fácil de começar é usando MicroPython na Raspberry Pi Pico. Porém, nem todo mundo gosta de usar Python, apesar da simplicidade que é. Mas tem vantagens claras em programar em MicroPython, principalmente quando o foco é agilidade. Usando Python como linguagem, montes de abstrações são feitas, deixando o espaço aberto para a criatividade. Para quem já tem seu nível em C/C++, dificilmente quererá migrar, mas ainda assim seria menos código a escrever.

Características do MicroPython

No Python importamos módulos. A maioria do hardware está acessível através do módulo machine e o segundo núcleo da RP Pico pode ser acessado através do módulo _thread.

O RP Pico tem algumas características de hardware únicas, como o PIO (Programmable I/O), que permite criar novas interfaces de entrada e saída e executá-las em velocidades altas, através desse subsistema. No módulo rp2 encontra-se uma biblioteca PIO expondo em toda a simplicidade do Python os recursos que lhe permitirão escrever programas PIO diretamente no prompt do sistema, interagindo com eles em tempo real, o que é extremamente importante para agilizar o desenvolvimento. Com isso, até um porte para C/C++ fica mais fácil depois, pois já estará comprovado o conceito.

Apenas um subconjunto das funcionalidades do Python3 fora portadas para o MicroPython – não apenas por questão de tamanho, mas por aplicabilidade em sistemas embarcados. Chega de assunto e bora rodar o sistema.

Baixar MicroPython para RP Pico

Vá até a página de download e baixe a versão que desejar. As mais recentes tendem a ser instáveis, mas se for para aprender e experimentar, não deve haver grandes problemas.

Para gravar é aquele padrão mágico: aperte BOOTSEL antes de colocar a placa conectada à USB e solte o botão após a placa ser identificada pelo sistema como dispositivo de massa. Abra esse dispositivo, que se assemelhará a um pendrive, e arraste o arquivo uf2 para dentro desse compartilhamento. A RP Pico reiniciará com o MicroPython após alguns segundos. O compartilhamento deve sair do sistema sozinho previamente.

Usando MicroPython na Raspberry Pi Pico

No Linux, a RP Pico estará disponível através da porta serial /dev/ttyACM0. Usando o comando minicom -o -D /dev/ttyACM0 acessaremos o prompt REPL do MicroPython. Ctrl+D fará um soft reboot.

A partir do momento em que estiver no prompt, já poderá experimentar e testar inflow, como se fosse o bpython.

Para imprimir uma mensagem:

print("Hell low word")

Para piscar um LED:

from machine import Pin
led = Pin(25,Pin.OUT)
led.value(1)
led.value(0)

Um exemplo do uso de timer:

from machine import Pin, Timer
led = Pin(25, Pin.OUT)
tim = Timer()
def tick(timer):
    global led
    led.toggle()

tim.init(freq=2.5, mode=Timer.PERIODIC, callback=tick)

Desse modo o LED se manterá piscando e o prompt liberado para mais interações.

Leitura analógica no RP Pico

Tudo que declaramos em Python vira um objeto. Para ler seu sensor de temperatura interno, podemos fazer o seguinte:

import machine
import utime
temp_sensor = machine.ADC(4)
factor_conv = 3.3 / (65535)
while True:
    value = temp_sensor.read_u16() * factor_conv
    temp  = 27 - (value - 0.706) / 0.001721
    print(temp)
    utime.sleep(2)

Não é nada mágico. A medição vem da tensão Vbe de um diodo bipolar e a regra é:

Vbe = 0.706V a 27 graus Celsius, com decaimento de -1.721mV (0.001721) por grau.

Interrupções na RP Pico

Na documentação tem um exemplo do uso de interrupções usando uma função lambda. Não é algo que vá empolgar quem está começando a testar, mas de qualquer modo é um exemplo:

from machine import Pin

p2 = Pin(2, Pin.IN, Pin.PULL_UP)
p2.irq(lambda pin: print("IRQ with flags:", pin.irq().flags()),
Pin.IRQ_FALLING)

Usar o segundo núcleo da RP Pico

Aqui está um exemplo de criação de task com MicroPython:

import time, _thread, machine

def task(n, delay):
    led = machine.Pin(25, machine.Pin.OUT)
    for i in range(n):
      led.high()
      time.sleep(delay)
      led.low()
      time.sleep(delay)
      print('done')

 _thread.start_new_thread(task, (10, 0.5))

A parte triste aqui é que apenas 1 thread pode ser executada por vez porque não tem um RTOS rodando por trás, apenas temos um segundo núcleo. Em breve devo escrever a respeito.

Scanner I2C na RP Pico

Tão trabalhoso que é escrever um scanner I2C em C++, cujo recurso tenho usado amplamente em diversos artigos. Agora repare a simplicidade de fazê-lo com MicroPython:

from machine import Pin, I2C

i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=100000)
i2c.scan()
i2c.writeto(76, b'123')
i2c.readfrom(76, 4)

i2c = I2C(1, scl=Pin(7), sda=Pin(6), freq=100000)
i2c.scan()
i2c.writeto_mem(76, 6, b'456')
i2c.readfrom_mem(76, 6, 4)

A frequência é um parâmetro opcional.

Leitura SPI na RP Pico

Sei que é quase um clichê, mas a referência não pode faltar.

from machine import SPI

spi = SPI(0)
spi = SPI(0, 100_000)
spi = SPI(0, 100_000, polarity=1, phase=1)

spi.write('test')
spi.read(5)

buf = bytearray(3)
spi.write_readinto('out', buf)

PWM com RP Pico

Lembrando que são exemplos da documentação, filtrados para facilitar nossas referências para artigos posteriores.

# Example using PWM to fade an LED.  
 
import time  
from machine import Pin, PWM  
 
# Construct PWM object, with LED on Pin(25).  
pwm = PWM(Pin(25))  

# Set the PWM frequency. 
pwm.freq(1000) 

# Fade the LED in and out a few times. 
duty = 0 
direction = 1 
for _ in range(8 * 256): 
    duty += direction 
    if duty > 255: 
       duty = 255 
       direction = -1 
    elif duty < 0: 
       duty = 0 
       direction = 1 
    pwm.duty_u16(duty * duty) 
    time.sleep(0.001)

IDE de desenvolvimento Thonny

Para Linux, Mac OSX e Windows, a IDE de desenvolvimento Thonny é a opção mais cômoda para quem quer ir direto ao ponto. Em Linux:

sudo apt-get install thonny

Por alguma razão, não havia a opção RP2040 Pico na seleção do interpretador Python no menu Run > Interpreter. Daí escolhi genérico e a porta ttyACM0, e um segundo prompt abriu, conectado à RP Pico.

pico na thonny - MicroPython na Raspberry

A janela do Thonny deve ficar mais ou menos assim:

MicroPython na Raspberry

Como exemplo, rodei a leitura de temperatura. Basta escrever o código, salvar e ao executar (na seta verde) escolher o dispositivo remoto. O sleep ficou deslocado, deveria estar alinhado com o print para ter efeito de intervalo, mas bastaria subir novamente com a indentação correta; sem esforço nenhum!

MicroPython na Raspberry - pegando temperatura

Como citado anteriormente, o uso de Ctrl+D faz o soft reboot, retornando o prompt pronto para reuso.

MicroPython na Raspberry com Thonny

Execução no boot

Para que seu programa opere de forma permanente, clique em “save as” no menu File e aponte o destino para o dispositivo. O nome do arquivo deverá ser main.py.

Mais exemplos de MicroPython na Raspberry

A partir da página 32 do documento “Raspberry Pi Pico Python SDK” tem um exemplo da utilização de display OLED, depois com um exemplo mais denso usando PIO para controlar um Neo Pixel Ring WS2812. Digo que é “mais denso” porque você verá o uso de decoradores (@) e uns paranauês com label, out, jmp, nop e outros. Lá na última função “começa” a ficar normal de novo, fazendo bitwise.

Onde comprar a Raspberry Pi Pico?

Vimos como colocar MicroPython na Raspberry, agora resta você colocar, hum?

A RoboCore está com um preço espetacular, vale a pena até pegar duas para um artigo que vamos ver em breve, bastante interessante. Se não sofrer uma kibada como de costume, vou apresentar algo interessante com o uso de duas.

Até a próxima!

Revisão: Ricardo Amaral de Andrade