ArduPy: Use Arduino e MicroPython para programar microcontroladores

Nos últimos anos temos acompanhado a adoção da linguagem Python para programação de microcontroladores. Projetos como MicroPython e CircuitPython estão crescendo bastante em recursos e comunidade. Recentemente a SeeedStudio lançou um projeto similar, chamado de ArduPy. Nesse artigo vou apresentar o ArduPy e os primeiros passos usando a WIO Terminal.

O que é Ardupy?

O ArduPy é uma combinação de Arduino e MicroPython desenvolvido pela SeeedStudio. O MicroPython usa a API Arduino para controlar o hardware. Com a ajuda do gerenciador de pacotes aip que é fornecido pela SeeedStudio, você pode transformar bibliotecas Arduino em uma biblioteca MicroPython. Por meio do ArduPy, você pode usar o Python para verificar suas ideias rapidamente e aprender a programar em Python para desenvolver aplicações de hardware.

O ArduPy consiste em duas partes, uma é o Core e a outra é o empacotador para bibliotecas Arduino. 

Recursos:

  • Use o python3 completo em dispositivos embarcados com recursos limitados
  • Suporte para sistemas de arquivos simples
  • Suporte para execução automática de boot.py ao reiniciar
  • Suporte a interação de terminal serial
  • Biblioteca de terceiros

O projeto é open source e disponível para colaboração da comunidade. Acesse o projeto no Github.
Atualmente é compatível com as placas Wio Terminal e Seeeduino XIAO, ambas com microcontroladores da Família Microchip SAMD.

Testando o ArduPy na WIO Terminal

Agora que já conhecemos o ArduPy vamos explorar alguns exemplos usando a plataforma Wio Terminal. 

O primeiro passo é atualizar o firmware da placa. Para isso, vamos colocar a placa em modo bootloader. No Wio Terminal deve-se fazer a seguinte sequência no botão de power, com a placa conectada ao computador: 

ArduPy

Será criado um unidade de armazenamento com o nome Arduino. 

ArduPy

Baixe o UF2 Firmware e carregue para o drive USB criado. A placa será atualizada e reiniciada automaticamente, criando um novo USB drive, chamado de ArduPy:

ArduPy

Pronto, a WIO Terminal está preparada para ser programada com o ArduPy.

Agora é só abrir o main. py no seu editor favorito e criar sua aplicação.

Existem diversos exemplos no documentação do ArduPy que você pode testar. Como esse kit tem um LCD muito bacana, vamos fazer nosso “Hello, world!” usando ele.

Digite o seguinte código no main.py:

from machine import LCD

lcd = LCD()                            # Initialize LCD and turn the backlight
lcd.fillScreen(lcd.color.BLACK)        # Fill the LCD screen with color black
lcd.setTextSize(3)                     # Setting font size to 2
lcd.setTextColor(lcd.color.GREEN)      # Setting test color to Green
lcd.drawString("Hello World!", 50, 20) # Printing Hello World at (50, 20)

Salve o arquivo. Em apenas alguns segundos o display exibirá a mensagem:

Se você quiser fazer algo mais interessante com o display, pode fazer o seguinte exemplo:

from machine import LCD
import time, math

M_SIZE = 1.3333
LOOP_PERIOD = 35

ltx = 0
osx = M_SIZE * 120
osy = M_SIZE * 120
updateTime = 0
old_analog = -999
d = 0

tft = LCD()
tft.fillScreen(tft.color.BLACK)

def valmap(value, istart, istop, ostart, ostop):
  return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))

def plotNeedle(value, ms_delay):
    global old_analog
    global osx, osy, ltx
    tft.setTextColor(tft.color.BLACK, tft.color.WHITE)
    if (value < -10):
        value = -10   # Limit value to emulate needle end stops

    if (value > 110):
        value = 110

    while(value != old_analog):
        if (old_analog < value):
            old_analog+=1
        else:
            old_analog-=1

        if (ms_delay == 0):
            old_analog = value

        sdeg = valmap(old_analog, -10, 110, -150, -30) # Map value to angle
        # Calculate tip of needle coords
        sx = math.cos(sdeg * 0.0174532925)
        sy = math.sin(sdeg * 0.0174532925)

        # Calculate x delta of needle start (does not start at pivot point)
        tx = math.tan((sdeg + 90) * 0.0174532925)

        # Erase old needle image
        tft.drawLine(int(M_SIZE * (120 + 20 * ltx - 1)), int(M_SIZE * (140 - 20)), int(osx - 1), int(osy), tft.color.WHITE)
        tft.drawLine(int(M_SIZE * (120 + 20 * ltx)), int(M_SIZE * (140 - 20)), int(osx), int(osy), tft.color.WHITE)
        tft.drawLine(int(M_SIZE * (120 + 20 * ltx + 1)), int(M_SIZE * (140 - 20)), int(osx + 1), int(osy), tft.color.WHITE)

        # Re-plot text under needle
        tft.setTextColor(tft.color.BLACK);
        tft.drawCentreString("%RH", int(M_SIZE * 120), int(M_SIZE * 70), 4); # Comment out to avoid font 4

        # Store new needle end coords for next erase
        ltx = tx
        osx = M_SIZE * (sx * 98 + 120)
        osy = M_SIZE * (sy * 98 + 140)

        # Draw the needle in the new postion, magenta makes needle a bit bolder
        # draws 3 lines to thicken needle
        tft.drawLine(int(M_SIZE * (120 + 20 * ltx - 1)),int( M_SIZE * (140 - 20)), int(osx - 1), int(osy), tft.color.RED)
        tft.drawLine(int(M_SIZE * (120 + 20 * ltx)), int(M_SIZE * (140 - 20)), int(osx), int(osy), tft.color.MAGENTA)
        tft.drawLine(int(M_SIZE * (120 + 20 * ltx + 1)), int(M_SIZE * (140 - 20)), int(osx + 1), int(osy), tft.color.RED)

        if(math.fabs(old_analog - value) < 10):
            ms_delay += ms_delay / 5

        time.sleep(ms_delay)

def analogMeter():
    tft.fillRect(0, 0, int(M_SIZE * 239), int(M_SIZE * 126), tft.color.LIGHTGREY)
    tft.fillRect(5, 3, int(M_SIZE * 230), int(M_SIZE * 119), tft.color.WHITE)

    tft.setTextColor(tft.color.BLACK)

    # Draw ticks every 5 degrees from -50 to +50 degrees (100 deg. FSD swing)
    for i in range(-50, 51, 5):
        # Long scale tick length
        tl = 15

        # Coordinates of tick to draw
        sx = math.cos((i - 90) * 0.0174532925)
        sy = math.sin((i - 90) * 0.0174532925)
        x0 = sx * (M_SIZE * 100 + tl) + M_SIZE * 120
        y0 = sy * (M_SIZE * 100 + tl) + M_SIZE * 140
        x1 = sx * M_SIZE * 100 + M_SIZE * 120
        y1 = sy * M_SIZE * 100 + M_SIZE * 140

        # Coordinates of next tick for zone fill
        sx2 = math.cos((i + 5 - 90) * 0.0174532925)
        sy2 = math.sin((i + 5 - 90) * 0.0174532925)
        x2 = sx2 * (M_SIZE * 100 + tl) + M_SIZE * 120
        y2 = sy2 * (M_SIZE * 100 + tl) + M_SIZE * 140
        x3 = sx2 * M_SIZE * 100 + M_SIZE * 120
        y3 = sy2 * M_SIZE * 100 + M_SIZE * 140

        # Yellow zone limits
        if (i >= -50 and i < 0):
          tft.fillTriangle(int(x0), int(y0), int(x1), int(y1), int(x2), int(y2), tft.color.GREEN)
          tft.fillTriangle(int(x1), int(y1), int(x2), int(y2), int(x3), int(y3),tft.color.GREEN)

        # Green Zone limits
        if (i >= 0 and i < 25):
            tft.fillTriangle(int(x0), int(y0), int(x1), int(y1), int(x2), int(y2), tft.color.YELLOW)
            tft.fillTriangle(int(x1), int(y1), int(x2), int(y2), int(x3), int(y3), tft.color.YELLOW)

        # Orange zone limits
        if (i >= 25 and i < 50):
            tft.fillTriangle(int(x0), int(y0), int(x1), int(y1), int(x2), int(y2), tft.color.ORANGE)
            tft.fillTriangle(int(x1), int(y1), int(x2), int(y2), int(x3), int(y3), tft.color.ORANGE)

        # Short scale tick length
        if (i % 25 != 0):
            tl = 8
        # Recalculate coords incase tick length changed
        x0 = sx * (M_SIZE * 100 + tl) + M_SIZE * 120
        y0 = sy * (M_SIZE * 100 + tl) + M_SIZE * 140
        x1 = sx * M_SIZE * 100 + M_SIZE * 120
        y1 = sy * M_SIZE * 100 + M_SIZE * 140

        # Draw tick
        tft.drawLine(int(x0), int(y0), int(x1), int(y1), tft.color.BLACK)

        # Check if labels should be drawn, with position tweaks
        if (i % 25 == 0):
            x0 = sx * (M_SIZE * 100 + tl + 10) + M_SIZE * 120
            y0 = sy * (M_SIZE * 100 + tl + 10) + M_SIZE * 140

            if(i/25 == -2 ):
                tft.drawCentreString("0", int(x0), int(y0) - 12, 2)
            elif (i/25 == -1 ):
                tft.drawCentreString("25", int(x0), int(y0) - 9, 2)
            elif (i/25 == -0 ):
                tft.drawCentreString("50", int(x0), int(y0) - 7, 2)
            elif (i/25 == 1 ):
                tft.drawCentreString("75", int(x0), int(y0) - 9, 2)
            elif (i/25 == 2 ):
                tft.drawCentreString("100", int(x0), int(y0) - 12, 2)

            # Now draw the arc of the scale
            # sx = math.cos((i + 5 - 90) * 0.0174532925)
            # sy = math.sin((i + 5 - 90) * 0.0174532925)
            # x0 = sx * M_SIZE * 100 + M_SIZE * 120
            # y0 = sy * M_SIZE * 100 + M_SIZE * 140
            # # Draw scale arc, don't draw the last part
            # if (i < 50):
            #     tft.drawLine(int(x0), int(y0), int(x1), int(y1), tft.color.BLACK)

        tft.drawString("%RH", int(M_SIZE * (5 + 230 - 40)), int(M_SIZE * (119 - 20)), 2); # Units at bottom right
        tft.drawCentreString("%RH", int(M_SIZE * 120), int(M_SIZE * 70), 4); # Comment out to avoid font 4
        tft.drawRect(5, 3, int(M_SIZE * 230), int(M_SIZE * 119), tft.color.BLACK); # Draw bezel line

        plotNeedle(0, 0)


def initial():
    analogMeter()
    updateTime = time.ticks_ms()

def main():
    global updateTime, d
    if (updateTime <= time.ticks_ms()):
        updateTime = time.ticks_ms() + 100
        d += 4
        if (d >= 360):
            d = 0

        value = 50 + 50 * math.sin((d+0)*0.0174532925)
        print(value)
        plotNeedle(value, 0)


if __name__ == "__main__":
    initial()
    while True:
        main()


Será exibido um medidor analógico:

ArduPy Integrated Platform – aip

Você também pode instalar a interface de linha de comando para o ArduPy, o ArduPy-aip CLI. Veja como instalar para o seu sistema operacional em: ArduPy Wiki.

Essa ferramenta ajudará na instalação de bibliotecas, carregar e atualizar o firmware do ArduPy.

para verificar os recursos disponíveis basta digitar:

aip help

Conclusão

O ArduPy se mostrou uma iniciativa interessante da SeeedStudio. O projeto é relativamente novo e ainda tem muito a melhorar, inclusive com suporte a novas placas. Assim com a Adafruit vem deixando todas as suas placas com suporte ao CircuitPython, acredito que a Seeed deva fazer algo similar com o ArduPy. De qualquer forma é um projeto que dá para estudar sobre a implementação do Python para microcontroladores e o port para diferentes arquiteturas de microcontroladores. 

Referências

Saiba Mais

Wio Terminal – um All-In-One para makers e IoT

MicroPython: Python para microcontrolador

CPBR12 – MicroPython – Python para microcontroladores

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
3 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Andre Dias
Andre Dias
14/06/2022 16:52

Vivi para ver python no Arduino!
Ja tem requests para micropython em Arduino?

Parabens pelo artigo

marjesper
marjesper
11/11/2020 11:23

Artigo excelente! Parabéns!

Home » Software » ArduPy: Use Arduino e MicroPython para programar microcontroladores

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: