Programação com Raspberry Pi Pico: Fundamentos, Código e Aplicação em Sistemas Embarcados


Introdução

O Raspberry Pi Pico pode ser programado de forma direta e eficiente utilizando linguagens voltadas a sistemas embarcados.

As duas abordagens principais são:

  • MicroPython → produtividade e rapidez
  • C/C++ → controle total e performance máxima

Este artigo foca em fundamentos sólidos de programação embarcada, com aplicação prática e estrutura profissional.


Modelo de Execução (Firmware)

Diferente de sistemas com OS, o Pico executa um único fluxo principal:

while True:
read_inputs()
process_logic()
update_outputs()

Interpretação modular:

  • read_inputs() → sensores / entradas
  • process_logic() → regras
  • update_outputs() → atuadores

✔ Separação clara: entrada ≠ lógica ≠ saída


MicroPython: Camada de Abstração Produtiva

https://images.openai.com/static-rsc-4/JyCd2uqVioWSAY2E_lazwDdq19W71fwqzXADplPcxPWUxHzCSerjGhTpxx6Jvrxp8Bik-2DdtBBCm1HKDC2REcPjdoPgKNxRqa7WhCjaDVB_ji3PQFNwUY1coLqYeFdSCRImxm7hMe_E0Zor-l6gQ1L3ctap3jEygVKY1aRyNSZvfIm6SA7ItFt_O16F50Mw?purpose=fullsize
https://images.openai.com/static-rsc-4/Pygfv_Q6_5fz6M0tTGhtfUn-bVlD5lkd9bD93nXUUy2c2OtfJ8L596Swi5VHzlAsOl_rl98bns2abI1CvsDGW9YQ8YKUat9S6IweAjw-OPlS_9HBymX-fP0s5qe3cnz4WtZamnrKmJ1dG6uTWIUBFklM-Zq-DvoXYcS2QfQKFdEHODL5mLwlSMU1sgyukh46?purpose=fullsize
https://images.openai.com/static-rsc-4/9vkSbZ_eNhz8EBehttE4sjPpflCrXjidNhOYb-SMMiApkiJSyrXRL_SU_mncVlz8tQm46CHFpOKojgEsV7Wk096GQUGksm_ncBdpUUi_ArR9OC_0IiDwAnv3rN19lWBrZ_gxT0syDjszryxoBkf7g5q-PmhHnjLdgOyNGYD-JBinWmFdfjqW5ZddhEIe4laL?purpose=fullsize

O MicroPython permite programar o Pico com sintaxe simples e rápida.

Vantagens:

  • Curva de aprendizado baixa
  • Código limpo e legível
  • Testes rápidos

Exemplo básico:

from machine import Pin
import utimeled = Pin(16, Pin.OUT)while True:
led.toggle()
utime.sleep(1)

✔ Ideal para prototipação


C/C++: Controle Total do Hardware

https://images.openai.com/static-rsc-4/7KWAj1VisazyE5Z1j9WRSproDxv0Af-I3aKjSDtcJb_wCfDiZkSswgobajVgdueTULzfukNqKB1xeTe0upaGfEy906ldO4jmbHSowbL9TIvOvKiSB4vnVIO0k5TA1cupO0Cks8dCd0mFGAKzref5lVwDLTgWRR6Huc43qxCRptWRqo8VLSY3IMlawrqjEGXA?purpose=fullsize
https://images.openai.com/static-rsc-4/LqkVd_8NtHcyECe-DAYsR_imCO_W-UrK3PdeDcZtTL-_v9U1lZRkc0p1wsjacu9oNcJMUjAEbEmqhMuhZqvj5Ub_MyQOIzhPPYwNf8LgqxxG05B8MT6mNwo5uFx770BqMX2yp3js0sCS5LlCVFlKnkX1mO9PWRk2-F1BSxKRb67DMz7y5IuGi3mhOYZyEveu?purpose=fullsize
https://images.openai.com/static-rsc-4/HlTqnk5EXMuS_lmyMxctFVvemLsbgZ--ygzorwiiXPtssQXGoX_TEwXuTBuaGWfAS5NtlvM94YpiUyLwKalCqAj-3BxtrXGqBf2sc6xxGihm31byikPMTKxmPtnfD1nDlzR7z2s5LkWKyFIQKIBsmhcdcSqTDxzgysa4YtIM0urzbrohG4-FRRTvRfDst3XQ?purpose=fullsize

Para aplicações críticas, usa-se o SDK oficial em C/C++.

Vantagens:

  • Máxima performance
  • Controle de memória
  • Acesso direto ao hardware

Exemplo (conceitual):

gpio_init(16);
gpio_set_dir(16, GPIO_OUT);while (true) {
gpio_put(16, 1);
sleep_ms(1000);
gpio_put(16, 0);
sleep_ms(1000);
}

✔ Indicado para produção


Estrutura de Código Profissional

Aplicando separação modular:

def read_inputs():
passdef process_logic():
passdef update_outputs():
passwhile True:
read_inputs()
process_logic()
update_outputs()

Benefícios:

  • Testável
  • Reutilizável
  • Escalável

Manipulação de Tempo

Tempo em sistemas embarcados é crítico.

Funções comuns:

  • sleep() → bloqueante
  • ticks_ms() → controle preciso
  • timers → eventos periódicos

Exemplo não bloqueante:

import utimelast = utime.ticks_ms()while True:
now = utime.ticks_ms()

if utime.ticks_diff(now, last) > 1000:
print("1 segundo")
last = now

✔ Evita travamentos


Controle de Estado

Evitar lógica linear rígida → usar estados:

state = "OFF"while True:
if state == "OFF":
# lógica
state = "ON"
elif state == "ON":
# lógica
state = "OFF"

✔ Base para sistemas complexos


Entrada e Saída (I/O)

Programação embarcada é essencialmente:

  • Ler sinais
  • Processar
  • Acionar hardware

Tipos de I/O:

  • Digital (GPIO)
  • Analógico (ADC)
  • Comunicação (UART, SPI, I2C)

Tratamento de Erros

Mesmo em sistemas simples:

try:
sensor_value = read_sensor()
except:
sensor_value = 0

✔ Garante robustez


Persistência de Dados

Microcontroladores não têm banco de dados.

Alternativas:

  • Arquivos simples (quando disponível)
  • EEPROM (em outros MCUs)
  • Flash controlada

✔ Persistência deve ser planejada


Boas Práticas

  • Código simples e direto
  • Evitar loops bloqueantes
  • Separar lógica por função
  • Testar cada módulo isoladamente
  • Minimizar uso de memória

Aplicações Práticas

Cenários reais práticos:

  • Piscar LED com lógica condicional
  • Controle de relé por botão
  • Leitura de sensor e decisão local
  • Temporizadores embarcados

Integração com Sistemas Maiores

O Pico pode atuar como:

  • Executor local
  • Coletor de dados
  • Interface física

Arquitetura típica:

Sensor → Pico → Comunicação → Sistema maior (API / IA / servidor)

Encaminhamento

Agora que a base de programação está estabelecida, avançamos para o controle físico direto:

GPIO, LEDs e controle de hardware