Você está na página 1de 128

Primeiros passos com

MICROPYTHON
NA RASPBERRY PI PICO
Primeira publicação em 2021 pela Raspberry Pi Trading Ltd,
Maurice Wilkes Building, St. John's Innovation Park,
Cowley Road, Cambridge, CB4 0DS

Diretor de publicação: Russell Barnes • Editor: Phil King •


Subeditor: Nicola King • Editor Técnico: Jo Hinchliffe •
Design: Critical Media • Ilustrações: Sam Alder

CEO: Eben Upton

ISBN: 978-1-912047-86-4

O editor e os colaboradores não aceitam qualquer


responsabilidade em relação a quaisquer omissões ou
erros relacionados a bens, produtos ou serviços
mencionados ou anunciados neste livro.

Exceto onde indicado de outra forma, o conteúdo deste


livro está licenciado sob Creative Commons
Attribution-NonCommercial- ShareAlike 3.0 Unported
(CC BY - NC - SA 3.0)

Traduzido por Gedeane Kenshima, uma iniciativa FilipeFlop.

REVENDEDOR OFICIAL RASPBERRY PI NO BRASIL


Bem-vindo!
Você pode pensar em computadores como coisas que você coloca em sua mesa e
digita, e este é certamente um tipo de computador, mas não é o único tipo. Neste
livro, estamos examinando microcontroladores - pequenas unidades de
processamento com um pouco de memória que são boas para controlar outro
hardware. Você provavelmente já tem muitos microcontroladores em sua casa.
Há uma boa chance de que sua máquina de lavar seja controlada por um
microcontrolador; talvez o seu relógio esteja; você pode encontrar um em sua
máquina de café ou micro-ondas. Claro, todos esses microcontroladores já têm seus
programas e os fabricantes dificultam a mudança do software em execução neles.
Uma Raspberry Pi Pico, por outro lado, pode ser facilmente reprogramada por
meio de uma conexão USB.
Neste livro, veremos como começar a usar esse hardware e como trabalhar com
outros componentes eletrônicos. Ao final do livro, você saberá como criar suas
próprias engenhocas eletrônicas programáveis. O que você faz com eles é com você.

Ben Everard
Sobre os autores

Gareth Halfacree é jornalista Ben Everard é um geek que


freelance de tecnologia, escritor e tropeçou em uma carreira que o
ex-administrador de sistemas no setor permite brincar com novos hardwares.
educacional. Apaixonado por software Como editor da revista HackSpace
e hardware open source (código (hsmag.cc), ele passa mais tempo do
aberto), ele foi um dos primeiros a que realmente deveria
adotar a plataforma Raspberry Pi e experimentando a mais recente (e não
escreveu várias publicações sobre a única) tecnologia DIY. Ele mora em
seus recursos e flexibilidade. Ele pode Bristol com sua esposa e duas filhas
ser encontrado no Twitter como em uma casa que está lentamente se
@ghalfacree ou por meio de seu enchendo de equipamentos
website freelance.halfacree.co.uk. eletrônicos e impressoras 3D.
Conteúdo
Capítulo 1: Conheça a sua Raspberry Pi Pico
Familiarize-se totalmente com sua nova e poderosa placa microcontrolada e
aprenda como conectar barra de pinos e instalar o MicroPython para
programá-la

Capítulo 2: Programando com MicroPython


Conecte um computador e comece a escrever programas para a sua
Raspberry Pi Pico usando a linguagem MicroPython

Capítulo 3: Computação física


Saiba mais sobre os pinos da Raspberry Pi Pico e os componentes eletrônicos
que você pode conectar e controlar

Capítulo 4: Computação física com sua Raspberry Pi Pico


Comece conectando componentes eletrônicos básicos a sua Raspberry Pi
Pico e escrevendo programas para controlá-los e senti-los

Capítulo 5: Controlador de semáforo


Crie o seu próprio sistema de mini travessia de pedestres usando vários LEDs
e um botão de pressão

Capítulo 6: Jogo de reação


Construa um jogo de tempo de reação simples usando um LED e botões de
pressão, para um ou dois jogadores

Capítulo 7: Alarme contra roubo


Use um sensor de movimento para detectar intrusos e soar o alarme com
uma luz piscando e sirene

Capítulo 8: Medidor de temperatura


Use o ADC integrado da Raspberry Pi Pico para converter entradas analógicas
e ler seu sensor de temperatura embutido

Capítulo 9: Registrador de dados


Transforme a Raspberry Pi Pico em um dispositivo de registro de dados de
temperatura e desconecte-o do computador para torná-lo totalmente portátil

Capítulo 10: Protocolos de comunicação digital: I2C e SPI


Explore esses dois protocolos de comunicação populares e use-os para exibir
dados em um LCD

APÊNDICES
Apêndice A: Especificações Raspberry Pi Pico
Apêndice B: Diagrama de pinos
Apêndice C: Entradas e saídas programáveis
Capítulo 1
Conheça a sua
Raspberry Pi
Pico
Familiarize-se totalmente com sua nova e
poderosa placa microcontrolada e aprenda
como conectar barra de pinos e instalar o
MicroPython para programá-la

Raspberry Pi Pico é uma maravilha em placa: um microcontrolador RP2040.


miniatura, colocando a mesma tecnologia A Raspberry Pi Pico não foi projetada para
que sustenta tudo, desde sistemas substituir a Raspberry Pi, que é uma classe
domésticos inteligentes a fábricas diferente de dispositivo conhecido como
industriais na palma da sua mão. computador de placa única. Enquanto
Esteja você procurando aprender sobre a você pode usar a Raspberry Pi para jogar,
linguagem de programação MicroPython, escrever histórias e navegar na web, a
dar seus primeiros passos na computação Raspberry Pi Pico é projetada para
física ou deseja construir um projeto de projetos de computação física em que
hardware, Raspberry Pi Pico - e sua controla qualquer coisa, desde LEDs e
incrível comunidade - irá apoiá-lo em botões a sensores, motores e até mesmo
cada etapa do caminho. outros microcontroladores.
Raspberry Pi Pico é conhecida como uma Ao longo deste livro, você aprenderá tudo
placa de desenvolvimento com sobre a Raspberry Pi Pico, mas as
microcontrolador, o que significa habilidades que você aprender também se
simplesmente que é uma placa de circuito aplicarão a qualquer outra placa de
impresso que aloja um tipo especial de desenvolvimento baseada em seu
processador projetado para computação microcontrolador RP2040 - e até mesmo
física: o microcontrolador. Do tamanho de outros dispositivos, desde que sejam
uma goma de mascar, Raspberry Pi Pico compatíveis com a linguagem de
contém uma quantidade surpreendente programação MicroPython.
de potência graças ao chip no centro da
Uma visita guiada a
Raspberry Pi Pico
Raspberry Pi Pico - "Pico" para abreviar - é muito
menor que até mesmo uma Raspberry Pi Zero, a mais
compacta da família de computadores de placa única
da Raspberry Pi. Apesar disso, ela inclui muitos
recursos - todos acessíveis através dos pinos ao redor Figura 1-1:
da borda da placa. Parte superior da placa

A Figura 1-1 mostra a Raspberry Pi Pico vista de cima.


Se você olhar para as bordas mais longas, verá seções
douradas que se parecem um pouco com pequenos
astronautas. Esses são os pinos que fornecem ao
microcontrolador RP2040 conexões com o mundo
externo - conhecidos como entrada/saída (IO).
Os pinos em sua Pico são muito semelhantes aos pinos
que compõem os pinos de entrada/saída de uso geral
(GPIO) em sua Raspberry Pi - mas enquanto a maioria
dos computadores de placa única Raspberry Pi vêm
com pinos de metal físicos já conectados, sua Pico não.
Há um bom motivo para isso: olhe para a borda externa
da placa de circuito e você verá que é irregular, com
pequenos recortes circulares (Figura 1-2).
Essas saliências criam o que é chamado de placa de
circuito castelado, que pode ser fixada em cima de
outras placas de circuito por meio de solda sem nunca
ter nenhum pino de metal físico instalado - o que ajuda
a manter a altura baixa, tornando o projeto acabado Figura 1-2:
menor. Se você comprar um gadget pronto para uso Furos castelados
com Raspberry Pi Pico, quase certamente será usado
com os furos castelados.
Os furos apenas para dentro das saliências são para
guias de pinos machos de 2,54 mm - o mesmo tipo de
pinos usados em seus GPIO da Raspberry Pi.
Soldando-os no lugar apontando para baixo, você pode
colocar sua Pico em uma protoboard sem solda para
tornar a conexão e desconexão de um novo hardware o
mais fácil possível - ótimo para experimentos!
O chip no centro da sua Pico (Figura 1-3) é um
microcontrolador RP2040. Este é um circuito integrado
personalizado (CI), projetado e construído
especificamente pelos engenheiros da Raspberry Pi
para alimentar sua Pico e outros dispositivos baseados
em microcontroladores. Se você o segurar contra a luz,
verá um logotipo da Raspberry Pi gravado na parte
superior do chip, juntamente com uma série de letras e
números que permitem aos engenheiros rastrear Figura 1-3:
quando e onde o chip foi feito. Chip RP2040
Uma visita guiada a
Raspberry Pi Pico
Na parte superior da sua Pico está uma porta micro
USB (Figura 1-4). Isso fornece energia para fazer sua
Pico funcionar e também permite que a Pico converse
com sua Raspberry Pi ou outro computador através de
Figura 1-4: sua porta USB - que é como você carregará seus
Porta micro USB programas em sua Pico. Se você segurar sua Pico para
cima e olhar para a porta micro USB de frente, verá que
seu formato é mais estreito na parte inferior e mais
largo na parte superior. Pegue um cabo micro USB e
você verá que o conector é o mesmo.
O cabo micro USB só entrará na porta micro USB da sua
Pico uma vez para cima. Ao conectá-lo, certifique-se de
alinhar os lados estreitos e largos ao redor - ou você
pode danificar sua Pico tentando travar o cabo micro
USB de forma errada!
Logo abaixo da porta micro USB há um pequeno botão
Figura 1-5:
marcado como ‘BOOTSEL’ (Figura 1-5). ‘BOOTSEL’ é a
Botão de seleção boot
abreviação de ‘boot selection’ (seleção de
inicialização), que alterna sua Pico entre dois modos
de inicialização quando é ligado pela primeira vez.
Você usará o botão de seleção de inicialização mais
tarde, conforme você deixa sua Pico pronta ou
programando com MicroPython.
Na parte inferior da sua Pico estão três pads dourados
menores com a palavra ‘DEBUG’ acima delas (Figura
1-6). Estes são projetados para debugging, ou encontrar
erros, em programas em execução na Pico, usando
uma ferramenta especial chamada debugger. Você não
usará o princípio de debugging neste livro, mas pode
achá-lo útil ao escrever programas maiores e mais
complicados.
Figura 1-6:
Pads para debug Vire sua Pico e você verá que o lado inferior tem algo
escrito nela (Figura 1-7). Isso é conhecido como
camada de silk-screen e rotula cada um dos pinos com
sua função central. Você verá coisas como ‘GP0’ e ‘GP1’,
‘GND’, ‘RUN’ e ‘3V3’. Se você esquecer qual pino é qual,
essas etiquetas irão dizer a você - mas você não será
capaz de vê-los quando a Pico for colocada em uma
protoboard, então você encontrará diagramas de pinos
completos impressos neste livro para referência mais
fácil.

Figura 1-7:
Face inferior etiquetada
Você deve ter notado que nem todas as etiquetas se alinham com seus pinos: os pequenos
furos na parte superior e inferior da placa são furos de montagem, projetados para permitir
que você prenda sua Pico a projetos de forma mais permanente usando parafusos ou porcas
e parafusos. Onde os furos atrapalham as etiquetas, as marcações são deslocadas para cima
ou para baixo na placa: olhando para o canto superior direito, 'VBUS' é o primeiro pino à
esquerda, 'VSYS' o segundo e 'GND' o terceiro.
Você também verá alguns pads planos dourados marcados com ‘TP’ e um número. Esses são
pontos de teste e são projetados para que os engenheiros verifiquem rapidamente se uma
Raspberry Pi Pico está funcionando depois de ser montada na fábrica. Dependendo do bloco
de teste, o engenheiro pode usar uma ferramenta chamada multímetro ou osciloscópio para
verificar se a Pico está funcionando corretamente antes de ser embalada e enviada para
você.
Por fim, você verá um pequeno adesivo com um código de barras. Contém o número de série
da sua Pico, bem como informações sobre a versão e a data de fabricação.

Soldando os pinos
Ao desembalar a Raspberry Pi Pico, você pode usá-la para tornar o processo de
notará que ele é completamente plano: não soldagem mais fácil.
há pinos de metal saindo das laterais, como Às vezes, pinos machos de 2,54 mm são
você encontraria nos GPIOs da Raspberry fornecidos em barras com mais de 20 pinos.
Pi. Isso no caso de você querer usar os furos Se os seus forem maiores, basta contar 20
castelados para conectar sua Pico à outra pinos de uma das extremidades e olhar
placa de circuito ou para soldar fios para o plástico entre o 20º e o 21º pinos:
diretamente. você verá que tem um pequeno recorte em
A maneira mais fácil de usar sua Pico, cada lado. Este é um ponto de quebra:
porém, é anexá-la a uma protoboard - e para coloque suas miniaturas no recuo com os
isso, você precisará soldar barras de pinos. pinos nas mãos esquerda e direita e dobre a
Você precisará de um ferro de solda com tira. Ele se quebrará de forma limpa,
suporte, um pouco de solda, uma esponja de deixando você com uma tira de exatamente
limpeza, sua Pico e duas barras de pino 20 pinos. Se a barra de pinos restante tiver
macho de 2,54 mm com 20 pinos cada. Se mais de 20 pinos, faça o mesmo novamente
você já tem uma protoboard sem solda, para obter duas barras de 20 pinos.

ATENÇÃO
Ferros de solda não são brinquedos: eles ficam muito, muito quentes e
1
permanecem quentes por muito tempo depois de serem desconectados. Se
você é um aprendiz mais jovem, certifique-se de ter supervisão de um adulto;
quer você seja jovem ou velho, certifique-se de colocar o ferro no suporte
quando não o estiver usando e nunca toque nas partes de metal - mesmo
depois de desconectado.
Figura 1-8: Você pode segurar os cabeçalhos no lugar com massa pegajosa antes de soldar

Vire sua Pico de cabeça para baixo, para que Tack ou outra massa pegajosa (Figura 1-8).
você possa ver os números dos pinos do Solde um pino e verifique o alinhamento: se
silk-screen e os pontos de teste na parte os pinos estiverem em ângulo, derreta a
inferior. Pegue uma das duas barras de solda enquanto os ajusta cuidadosamente
pinos e empurre-a suavemente nos furos do para alinhar tudo.
lado esquerdo da sua Pico. Certifique-se de
Se você tiver uma protoboard,
que ela esteja inserida corretamente nos
simplesmente vire a Pico de cabeça para
furos, e não apenas apoiada nos furos
baixo - lembrando-se de manter as guias
castelados, e que todos os 20 pinos estejam
presas - e empurre as duas barras e a Pico
no lugar, então pegue a outra barra de pinos
nos furos da protoboard. Continue
e insira no lado direito. Quando você
empurrando até que a Pico esteja plana,
terminar, os blocos de plástico nos pinos
com os blocos de plástico dos pinos
devem ser empurrados contra a placa de
prensados entre a Pico e a protoboard
circuito da Pico.
(Figura 1-9).
Aperte sua Pico nas laterais para segurar a
Olhe para o topo da sua Pico: você verá um
placa de circuito e os dois conectores de
pequeno comprimento de cada pino saindo
pino. Não solte, ou os pinos cairão! Se você
dos furos dos pinos. Esta é a parte que você
ainda não tem uma protoboard, precisará
vai soldar - o que significa aquecer os pinos
de alguma forma para segurar as barras no
e os pads na Pico e derreter uma pequena
lugar enquanto estiver soldando - e não use
quantidade de um metal especial, solda,
os dedos ou irá queimá-los. Você pode
neles.
segurar as barras no lugar com pequenas
garras jacaré ou uma pequena gota de Blu
Figura 1-9: Como alternativa, usar uma protoboard para segurar as guias no lugar para soldar

ATENÇÃO
Soldar é uma ótima habilidade para aprender, mas requer prática. Leia as
1
instruções a seguir cuidadosamente e na íntegra antes mesmo de ligar o
ferro de solda e lembre-se de fazer as coisas devagar e com cuidado. Evite
usar muita solda também: é fácil adicionar mais a uma junta com pouca
solda, mas pode ser mais difícil remover o excesso de solda - especialmente
se ela respingar em outras partes da sua Pico.

Coloque o ferro de solda em seu suporte, certificando-se de que a ponta de metal não esteja
encostada em nada, e conecte-o. A ponta do ferro vai demorar alguns minutos para
esquentar; enquanto você espera, desenrole um pequeno pedaço de solda - cerca de duas
vezes mais longo que seu dedo indicador. Você deve conseguir quebrar a solda puxando e
torcendo-a; é um metal muito macio.

ATENÇÃO
Embora a solda moderna seja feita sem chumbo, ela ainda é venenosa graças
1
a uma substância especial chamada fluxo. Este é um gel corrosivo que serve
para queimar a sujeira da junta enquanto você está soldando. Não vai
prejudicá-lo se colocar nos dedos, mas pode fazer mal se você o comer.
Manuseie a solda apenas quando estiver usando-a ativamente e sempre lave
as mãos depois - especialmente antes de comer qualquer coisa.
Se o seu suporte de solda tiver uma esponja vegetal de
limpeza, leve a esponja até a pia e coloque um pouco de
água fria em cima para amolecer. Esprema o excesso
de água da esponja, de modo que fique úmido, mas não
pingando, e coloque-o de volta no suporte. Se você
estiver usando uma esponja metálica feita de fio de
latão em espiral, não precisará de água.
Pegue o ferro de solda pelo manipulador,
certificando-se de que o cabo não prenda em nada Figura 1-10: Aqueça o pino e o pad
enquanto você o movimenta. Segure-o como um lápis,
mas certifique-se de que seus dedos só toquem na área
do manipulador de plástico ou borracha: as partes de
metal, até mesmo a haste à frente da ponta de ferro
real, estarão extremamente quentes e podem queimar
você muito rapidamente.
Antes de começar a soldar, limpe a ponta do ferro:
passe ao longo da esponja vegetal ou esponja metálica.
Pegue o pedaço de solda, segurando-o em uma
extremidade, e empurre a outra extremidade na ponta
do seu ferro: ele deve derreter rapidamente em uma
bolha. Se isso não acontecer, deixe o ferro de solda
aquecer por mais tempo - ou tente limpar a ponta
novamente. Figura 1-11: Adicione um pouco de solda

Colocar uma gota de solda na ponta é conhecido como


estanhar o ferro. O fluxo na solda ajuda a queimar
qualquer sujeira que ainda esteja na ponta do ferro e o
deixa pronto. Limpe o ferro em sua esponja vegetal ou
metálica novamente para limpar o excesso de solda; a
ponta deve ficar brilhante e limpa.
Coloque o ferro de volta no suporte, onde deve estar
sempre, a menos que você o esteja usando ativamente,
e mova sua Pico para que fique na sua frente. Pegue o
ferro com uma das mãos e a solda com a outra.
Pressione a ponta do ferro contra o pino mais próximo
de você, de modo que toque o pino de metal vertical e o
Figura 1-12: Agora remova o ferro
pad dourado em sua Pico ao mesmo tempo (Figura
1-10).
É importante que o pino e o pad sejam aquecidos, então
mantenha seu ferro pressionado contra ambos
enquanto conta até três. Quando você chegar ao três,
ainda mantendo o ferro no lugar, pressione a ponta da
solda suavemente contra o pino e o pad, mas no lado
oposto da ponta do ferro (Figura 1-11). Assim como
quando você estanha a ponta, a solda deve derreter
rapidamente e começar a fluir.

Figura 1-13: Um pino bem soldado


A solda fluirá ao redor do pino e do pad, mas não mais: isso porque a placa de circuito da Pico
é revestida com uma camada chamada resistência de solda que mantém a solda onde ela
precisa estar. Certifique-se de não usar muita solda: um pouco é muito útil.
Puxe a parte restante da solda para longe da junção, certificando-se de manter o ferro no
lugar. Se você puxar o ferro primeiro, a solda endurecerá e você não conseguirá remover a
peça em sua mão; se isso acontecer, basta colocar o ferro de volta no lugar para derretê-lo
novamente. Depois que a solda derretida se espalhar ao redor do pino e do pad (Figura 1-12),
o que deve levar apenas um segundo ou mais, remova o ferro de solda. Parabéns: você soldou
seu primeiro pino!
Limpe a ponta do ferro na esponja vegetal ou metálica e coloque-o de volta no suporte. Pegue
sua Pico e olhe para sua junção de solda: ela deve preencher o pad e subir para encontrar o
pino suavemente, parecendo um pouco com a forma de um vulcão com o pino preenchendo
o buraco onde a lava estaria, conforme mostrado na Figura 1-13.

C
E

A B D

Figura 1-14: Exemplos de problemas de solda

Se a solda está aderindo ao pino, mas não aderindo ao pad de cobre, como no exemplo A na
Figura 1-14, então o pad não foi aquecido o suficiente. Não se preocupe, é fácil de consertar:
pegue seu ferro de solda e coloque-o onde o pad e o pino se encontram, certificando-se de que
está pressionando contra ambos. Após alguns segundos, a solda deve refluir e formar uma
boa junção.
Por outro lado, se a solda estiver muito quente, ela não fluirá bem e você obterá uma junção
superaquecida com algum fluxo queimado (exemplo B na Figura 1-14). Isso pode ser
removido com um pouco de raspagem cuidadosa com a ponta de uma faca ou uma escova de
dentes e um pouco de álcool isopropílico.
Se a solda estiver cobrindo inteiramente o pino, como no exemplo C na Figura 1-14, você usou
muito. Isso não vai necessariamente causar um problema, embora não pareça muito
atraente: contanto que nenhuma solda toque em qualquer um dos pinos em torno dela, ainda
deve funcionar. Se estiver tocando em outros pinos (como no exemplo D da Figura 1-14), você
criou uma ponte que causará um curto-circuito.
Novamente, as pontes são fáceis de primeiro. Não tenha pressa, não se apresse
consertar. Primeiro, tente refluir a solda na e lembre-se de que os erros sempre podem
junção que você estava fazendo; se isso não ser corrigidos. Lembre-se de limpar a ponta
funcionar, coloque o ferro contra o pino e o do seu ferro regularmente durante a
pad do outro lado da ponte para fluir um soldagem também, e se você achar que as
pouco para a junta. Se ainda houver solda coisas estão ficando difíceis, derreta um
demais, você precisará remover o excesso pouco da solda para estanhar novamente a
antes de usar a Pico: você pode comprar ponta. Certifique-se de atualizar o
uma malha dessoldadora, que pressiona comprimento da solda também: se for
contra a solda derretida para sugar o muito curto e seus dedos estiverem muito
excesso, ou um sugador de solda para sugar próximos da ponta do ferro de solda, você
fisicamente a solda derretida. pode facilmente se queimar.
Outro erro comum é pouca solda: se você Quando terminar, e verificar todos os pinos
ainda puder ver o pad de cobre, ou se houver para ver se há boas junções de solda e para
uma lacuna entre o pino e o pad que não se certificar de que não estão ligados a
está preenchido com solda, você usou nenhum pino próximo, limpe e estanhe a
muito pouca solda (exemplo E na Figura ponta do ferro uma última vez antes de
1-14). Coloque o ferro de volta no pino e no colocá-lo de volta no suporte e desligá-lo.
pad, conte até três e adicione um pouco Certifique-se de deixar o ferro esfriar antes
mais de solda. Muito pouco é sempre mais de guardá-lo: os ferros de solda podem ficar
fácil de consertar do que muito, então quentes o suficiente para queimar você por
lembre-se de pegar leve com a solda! um longo tempo depois de serem
Quando estiver satisfeito com o primeiro desconectados!
pino, repita o processo para todos os 40 Finalmente, certifique-se de lavar as mãos -
pinos em sua Pico - deixando os furos de e comemorar sua nova habilidade como um
três pinos ‘DEBUG’ vazio na parte inferior. supremo soldador!
Dica: solde os quatro pinos de canto

Instalando MicroPython
Agora que você soldou os conectores em sua Pico (Figura 1-15), só resta uma coisa a fazer
para deixá-lo pronto: instalar o MicroPython nele. Comece conectando um cabo micro USB
na porta micro USB em sua Pico, certificando-se de que está do lado certo antes de
empurrá-lo suavemente para dentro.

Figura 1-15: Todos os pinos soldados corretamente


ATENÇÃO
Para instalar o MicroPython em sua Pico, você precisará baixá-lo da Internet.
1
Se você não tiver uma conexão com a Internet na sua Raspberry Pi, você
precisará conectar a Pico a um sistema que tenha uma conexão com a
Internet para concluir a configuração. Você só terá que fazer isso uma vez:
depois que MicroPython for instalado, ele permanecerá em sua Pico, a menos
que você decida substituí-lo por outra coisa no futuro.

Mantenha pressionado o botão ‘BOOTSEL’ na parte superior da sua Pico; em seguida,


enquanto o mantém pressionado, conecte a outra extremidade do cabo micro USB a uma das
portas USB da Raspberry Pi ou de outro computador. Conte até três e, em seguida, solte o
botão ‘BOOTSEL’.
Após mais alguns segundos, você deverá ver sua Pico aparecer como uma unidade
removível - como se você tivesse conectado um pen drive ou HD externo. Na sua Raspberry
Pi, você verá um pop-up perguntando se deseja abrir a unidade no Gerenciador de arquivos.
Na janela do Gerenciador de Arquivos, você verá dois arquivos em sua Pico (Figura 1-16):
INDEX.HTM e INFO_UF2.TXT. O segundo arquivo contém informações sobre a sua Pico, como
a versão do bootloader que está em execução. O primeiro arquivo, INDEX.HTM, é o que você
deseja: aponte o cursor do mouse para ele e clique duas vezes nele para abri-lo em seu
navegador.
Quando o navegador for aberto, você verá uma página de boas-vindas com tudo sobre a sua
Pico. Leia as informações na página e clique na guia MicroPython para carregar a seção
específica do MicroPython da página.

Figura 1-16: Você verá dois arquivos em sua Raspberry Pi Pico


Clique no botão ‘Baixar arquivo UF2’ (Figura 1-17, verso) para baixar o firmware MicroPython
- um pequeno arquivo que contém MicroPython para sua Pico. Não vai demorar muito para
baixar- é um arquivo muito pequeno. Depois de fazer o download, feche a janela do
navegador clicando no ícone de cruz no canto superior direito.

Figura 1-17: Clique no botão para baixar o firmware MicroPython

Abra uma nova janela do Gerenciador de arquivos clicando no menu do ícone da Raspberry,
indo para Acessórios e clicando em Gerenciador de arquivos. Encontre a pasta Downloads
usando a lista de pastas à esquerda da janela do Gerenciador de arquivos. Pode ser
necessário rolar a lista para encontrá-lo, dependendo de quantas pastas você tem na sua
Raspberry Pi. Abra a pasta Downloads e encontre o arquivo que você acabou de baixar - ele se
chamará ‘micropython’ seguido por uma data e a extensão ‘uf2’.
Clique e segure o botão do mouse no arquivo UF2 e arraste-o para a outra janela do
Gerenciador de Arquivos aberta na unidade de armazenamento removível da Pico. Passe o
mouse sobre a janela e solte o botão do mouse para soltar o arquivo em sua Pico (Figura 1-18).
Figura 1-18: Arraste o arquivo de firmware MicroPython para sua Raspberry Pi Pico

Após alguns segundos, você verá sua Pico desaparecer do Gerenciador de arquivos e também
poderá ver um aviso de que uma unidade foi removida sem ser ejetada: não se preocupe, isso
deveria acontecer! Quando você arrastou o arquivo de firmware MicroPython para sua Pico,
você disse a ele para atualizar o firmware em seu armazenamento interno. Para fazer isso,
sua Pico sai do modo especial em que você o colocou com o botão ‘BOOTSEL’, atualiza o novo
firmware e o carrega - o que significa que sua Pico agora está executando MicroPython.
Parabéns: agora você está pronto para começar a usar MicroPython na sua Raspberry Pi Pico!

OUTRAS LEITURAS
A página da Web vinculada a INDEX.HTM não é apenas um lugar para baixar
1
MicroPython; também inclui uma riqueza de recursos adicionais. Clique nas
abas e role para acessar guias, projetos e a coleção de livros de dados - uma
estante de documentação técnica detalhada cobrindo tudo, desde o
funcionamento interno do microcontrolador RP2040 que alimenta sua Pico
até a programação nas linguagens Python e C/C ++.
Capítulo 2
Programando
com MicroPython
Conecte um computador e comece a
escrever programas para a sua
Raspberry Pi Pico usando a
linguagem MicroPython

Desde o seu lançamento em 1991, a É aí que entra o MicroPython.


linguagem de programação Python - Originalmente desenvolvido por Damien
batizada com o nome do famoso grupo de George e lançado pela primeira vez em
comédia Monty Python, em vez da cobra - 2014, MicroPython é uma linguagem de
cresceu e se tornou uma das mais programação compatível com Python
populares do mundo. Sua popularidade, desenvolvida especificamente para
porém, não significa que não haja microcontroladores. Ele inclui muitos dos
melhorias que possam ser feitas - recursos do Python convencional, ao
principalmente se você estiver mesmo tempo que adiciona uma
trabalhando com um microcontrolador. variedade de novos recursos projetados
A linguagem de programação Python foi para aproveitar as vantagens dos recursos
desenvolvida para sistemas de disponíveis na Raspberry Pi Pico e em
computador como desktops, laptops e outras placas com microcontrolador.
servidores. Placas com Se você já programou com Python antes,
microcontroladores como Raspberry Pi achará o MicroPython imediatamente
Pico são menores, mais simples e com familiar. Se não, não se preocupe: é uma
consideravelmente menos memória - o linguagem amigável para aprender!
que significa que não podem executar a
mesma linguagem Python que suas
contrapartes maiores.
A

Figura 2-1: A IDE Thonny Python

Apresentando a IDE Thonny Python


A Barra de ferramentas - a barra de ferramentas oferece um sistema de acesso rápido
baseado em ícones para funções de programa comumente usadas - como salvar, carregar e
executar programas.
B Área de script - A área de script é onde seus programas Python são escritos. Ele é
dividido em uma área principal para seu programa e uma pequena margem lateral para
mostrar os números das linhas.
C Python Shell - O Python Shell permite que você digite instruções individuais que são
executadas assim que você pressiona a tecla ENTER e também fornece informações sobre a
execução de programas. Isso também é conhecido como REPL, para ‘read, evaluate, print, and
loop’ (ler, avaliar, imprimir e fazer um loop).
D Interpretador - O canto inferior direito da janela Thonny mostra e permite que você
altere o interpretador Python atual - a versão do Python usada para executar seus programas.

Conectando Thonny à Pico


Antes de começar a programar a Pico com MicroPython, você precisará configurar o que é
chamado de ambiente de desenvolvimento integrado (IDE). Thonny, uma IDE popular para
Python e MicroPython, vem pré-carregada no Raspberry Pi OS; se estiver usando a Pico com
uma distribuição Linux diferente, Windows ou MacOS, abra seu navegador da web, visite
thonny.org e clique no link de download na parte superior da página para baixar o instalador
do pacote Thonny e Python para seu sistema operacional.
Como um ambiente de desenvolvimento integrado, Thonny reúne, ou integra, todas as
diferentes ferramentas de que você precisa para escrever ou desenvolver software em uma
única interface de usuário ou ambiente. Existem muitas IDEs diferentes: alguns permitem
que você desenvolva em várias linguagens de programação diferentes, enquanto outros,
como Thonny, se concentram em uma única linguagem.
Comece carregando o Thonny: no Raspberry Pi OS, você pode carregá-lo clicando no menu
da Raspberry no canto superior esquerdo da tela, movendo o mouse para a seção
Programação e clicando em Thonny. Se você ainda não fez isso, pegue sua Pico e conecte um
cabo micro USB entre ele e uma das portas USB da Raspberry Pi - não importa qual.
Com a Pico conectada à Raspberry Pi, clique na palavra "Python" seguida por um número de
versão no canto inferior direito da janela Thonny - a área marcada como D na Figura 2-1.
Mostra o seu interpretador atual, que é responsável por seguir as instruções, você os digita e
os transforma em código que o computador, ou microcontrolador, pode entender e executar.
Normalmente, o interpretador é uma cópia do Python rodando na Raspberry Pi, mas precisa
ser alterado para rodar seus programas em MicroPython na sua Pico.
Na lista que aparece, procure ‘MicroPython (Raspberry Pi Pico)’ (Figura 2-2) e clique nele. Se
você não conseguir vê-lo na lista, verifique novamente se a Pico está conectada
corretamente ao cabo micro USB e se o cabo micro USB está conectado corretamente à
Raspberry Pi ou outro computador.

Figura 2-2: Escolhendo um interpretador Python

PROFISSIONAIS DE PYTHON
Se você já trabalhou no capítulo sobre Python no The Official Raspberry Pi
1
Beginner’s Guide, muito do que você vai ler neste capítulo lhe será muito
familiar. Ainda assim, trabalhe com os primeiros exemplos, para se
acostumar com as diferenças na execução de programas no interpretador
Python em sua Raspberry Pi e no interpretador MicroPython em sua Pico,
então fique à vontade para pular para o próximo capítulo.
NENHUMA OPÇÃO DE RASPBERRY PI PICO?
O interpretador Raspberry Pi Pico está disponível apenas na versão mais
recente do Thonny. Se você estiver executando uma versão mais antiga e
1 não puder atualizá-la, procure "MicroPython (genérico)". Se a sua versão do
Thonny for mais antiga ainda e não tiver opção de intérprete no canto
inferior direito da janela e você não puder atualizá-la, clique em 'Alternar
para o modo normal' no canto superior direito, reinicie o Thonny, clique no
menu Executar e clique em "Selecionar intérprete". Clique na seta suspensa
ao lado de "O mesmo interpretador que está executando o Thonny (padrão)",
clique em "MicroPython (genérico)" na lista e, em seguida, clique na seta
suspensa ao lado de 'Porta' e clique em 'Board in FS mode' nessa lista antes
de clicar em OK para confirmar as suas alterações.

Olhe para o Python Shell na parte inferior da janela Thonny: você verá que agora se lê
‘MicroPython’ e informa que está sendo executado na ‘Raspberry Pi Pico’. Parabéns: você está
pronto para começar a programar.

Seu primeiro programa


MicroPython: Hello, World!
Para começar a escrever seu primeiro programa, clique na área do Python Shell na parte
inferior da janela Thonny, logo à direita dos símbolos ‘>>>’ inferiores, e digite a seguinte
instrução antes de pressionar a tecla ENTER.

print("Hello, World!")

Ao pressionar ENTER, você verá que seu programa começa a ser executado
instantaneamente: o Python responderá, na mesma área do Shell, com a mensagem ‘Hello,
World!’ (Figura 2-3), exatamente como você pediu. Isso porque o Shell é uma linha direta com
o interpretador MicroPython em execução na sua Pico, cujo trabalho é olhar para suas
instruções e interpretar o que significam. Isso é conhecido como modo interativo, e você
pode pensar nisso como uma conversa cara a cara com alguém: assim que você terminar o
que está dizendo, a outra pessoa responderá e espere o que você disser em seguida.

ERRO DE SINTAXE
Se seu programa não funcionar, mas em vez disso imprimir uma mensagem de
1
"erro de sintaxe" na área do Shell, há um erro em algum lugar do que você
escreveu. O MicroPython precisa que suas instruções sejam escritas de uma
maneira muito específica: falhe um colchete ou uma aspa, escreva 'print'
errado ou dê um P maiúsculo, ou adicione símbolos extras em algum lugar da
instrução e ela não funcionará. Tente digitar a instrução novamente e verifique
se ela corresponde à versão neste livro antes de pressionar a tecla ENTER!
Figura 2-3: MicroPython imprime a mensagem ‘Hello, World!’ Na área do Shell

Programar sua Pico usando o Shell é um pouco como ter uma conversa telefônica: quando
você pressiona a tecla ENTER, sua instrução é enviada através do cabo micro USB para o
interpretador MicroPython rodando em sua Pico; o interpretador examina sua instrução, faz
tudo o que ela diz e, em seguida, envia o resultado de volta por meio do cabo micro USB para
Thonny.
Você não precisa programar no modo interativo por meio do Shell, no entanto. Clique na área
de programação no meio da janela Thonny e digite seu programa novamente:

print("Hello, World!")

Ao pressionar a tecla ENTER desta vez, nada acontece - exceto que você obtém uma nova
linha em branco na área do script. Para fazer esta versão do seu programa funcionar, você
terá que clicar no ícone Executar na barra de ferramentas Thonny ou clicar no menu
Executar seguido de ‘Executar programa atual’.
Clique no ícone Executar agora: você será questionado se deseja salvar seu programa em
‘Este computador’, ou seja, sua Raspberry Pi, ou ‘Raspberry Pi Pico’, ou seja, sua Pico, como na
Figura 2-4. Clique em ‘Raspberry Pi Pico’, digite um nome descritivo como Hello_World.py e
clique no botão OK.
Figura 2-4: Salvando um programa na Pico

NOMES DE ARQUIVOS
Ao salvar arquivos MicroPython em sua Pico, lembre-se sempre de digitar a
extensão do arquivo: um ponto final seguido pelas letras ‘p’ e ‘y’ - para ‘Python’ -
1 no final do arquivo. Isso ajuda você a lembrar que cada arquivo é um programa
e evita que se misturem com quaisquer outros arquivos que você possa salvar
na sua Pico.
Você pode usar quase qualquer nome que desejar para seus programas, mas
tente torná-lo descritivo do que o programa faz - e não o chame de boot.py ou
main.py, pois esses são nomes de arquivos especiais sobre os quais você
aprenderá mais tarde no livro.

Assim que o seu programa for salvo, ele será executado automaticamente na sua Pico. Você
verá duas mensagens aparecerem na área Shell na parte inferior da janela Thonny:

>>> %Run -c $EDITOR_CONTENT


Hello, World!

A primeira dessas linhas é uma instrução de Thonny dizendo ao interpretador MicroPython


em sua Pico para executar o conteúdo da área de script - o ‘EDITOR_CONTENT’. A segunda é
a saída do programa - a mensagem que você disse ao MicroPython para imprimir. Parabéns:
agora você escreveu dois programas MicroPython, em modo interativo e de script, e os
executou com sucesso em sua Pico!
Há apenas mais uma peça no quebra-cabeça: carregar seu programa novamente. Feche o
Thonny pressionando o X no canto superior direito da janela e carregue-o novamente. Desta
vez, em vez de escrever um novo programa, clique no ícone Abrir na barra de ferramentas
Thonny. Como quando salvou seu programa, será perguntado se deseja salvá-lo em 'Este
computador' ou em 'Raspberry Pi Pico' - clique em 'Raspberry Pi Pico' e você verá uma lista
de todos os programas que você salvou na sua Pico.
Encontre Hello_World.py na lista - se a sua Pico for nova, será o único arquivo lá - e clique
nele para selecioná-lo, depois clique em OK. Seu programa será carregado no Thonny, pronto
para ser editado ou para você executá-lo novamente.

UMA PICO CHEIA DE PROGRAMAS


Quando você diz ao Thonny para salvar seu programa na Raspberry Pi Pico,
1
isso significa que os programas estão armazenados na própria Pico. Se você
desconectar sua Pico e levá-lo para a casa de um amigo, um evento escolar
ou um clube de programação e conectá-lo a um de seus computadores, seus
programas ainda estarão onde você os salvou - em sua própria Pico.

DESAFIO: NOVA MENSAGEM


1
Você pode alterar a mensagem que o programa Python imprime como sua
saída? Se você quisesse adicionar mais mensagens, usaria o modo interativo
ou o modo script? O que acontece se você remover os colchetes ou as aspas
do programa e tentar executá-lo novamente?

Próximas etapas: loops e recuo de código


Um programa MicroPython, assim como um programa Python padrão, normalmente é
executado de cima para baixo: ele passa por cada linha por vez, passando pelo interpretador
antes de passar para a próxima, como se você estivesse digitando linha por linha no Shell.
Um programa que apenas executa uma lista de instruções linha por linha não seria muito
inteligente, no entanto - então MicroPython, assim como Python, tem sua própria maneira de
controlar a sequência em que seus programas são executados: indentação.
Crie um novo programa clicando no ícone Novo na barra de ferramentas Thonny. Você não
perderá seu programa existente; em vez disso, Thonny criará uma nova aba acima da área de
script. Inicie seu programa digitando as duas linhas a seguir:

print("Loop starting!")
for i in range(10):
A primeira linha imprime uma mensagem simples para o Shell, assim como seu programa
Hello World. O segundo começa um loop definido, que repetirá - loop - uma ou mais
instruções um determinado número de vezes. Uma variável, i, é atribuída ao loop e dada uma
série de números - a instrução de range, que é informada para começar no número 0 e
trabalhar para cima, mas nunca alcançando, o número 10 - para contar. O símbolo de dois
pontos (:) diz ao MicroPython que o próprio loop começa na próxima linha.
Variáveis são ferramentas poderosas: como seu nome sugere, variáveis são valores que
podem mudar - ou variar - ao longo do tempo e sob o controle do programa. Em sua forma
mais simples, uma variável tem dois aspectos: seu nome e os dados que armazena. No caso
do seu loop, o nome da variável é ‘i’ e seus dados são definidos pela instrução range -
começando em 0 e aumentando em 1 cada vez que o loop termina e começa novamente.
Para realmente incluir uma linha de código no loop, ela deve ser indentada - movida do lado
esquerdo da área de script. A próxima linha começa com quatro espaços em branco, que
Thonny terá adicionado automaticamente quando você pressionou ENTER após a linha 2.
Digite agora:

print("Loop number", i)

Os quatro espaços em branco empurram essa linha para dentro em comparação com as
outras linhas do programa. Esse recuo é como o MicroPython diz a diferença entre as
instruções fora do loop e as instruções dentro do loop: o código recuado, formando o interior
do loop, é conhecido como aninhado.
Você notará que quando pressionou ENTER no final da terceira linha, Thonny
automaticamente recuou a próxima linha - presumindo que ela faria parte do loop. Para
remover esse recuo, basta pressionar a tecla BACKSPACE uma vez antes de digitar a quarta
linha:

print("Loop finished!")

Seu programa de quatro linhas agora está completo. A primeira linha fica fora do loop e será
executada apenas uma vez; a segunda linha configura o loop; o terceiro fica dentro do loop e
será executado uma vez para cada vez que o loop for executado; e a quarta linha fica fora do
loop novamente.

print("Loop starting!")
for i in range(10):
print("Loop number", i)
print("Loop finished!")

Clique no ícone Executar, escolha salvar o programa na sua Pico clicando em ‘Raspberry Pi
Pico’ e chame-o de Indentation.py. O programa será executado assim que for salvo: verifique
sua saída na área do Shell (Figura 2-5, verso).
Loop starting!
Loop number 0
Loop number 1
Loop number 2
Loop number 3
Loop number 4
Loop number 5
Loop number 6
Loop number 7
Loop number 8
Loop number 9
Loop finished!
Figura 2-5: Executando um loop

CONTAGEM DE ZERO
Python é uma linguagem indexada por zero - o que significa que começa a
1
contar de 0, não de 1. É por isso que seu programa imprime os números de 0
a 9 em vez de 1 a 10. Se você quiser, pode alterar esse comportamento
mudando o range (10) instrução para range (1, 11) - ou quaisquer outros
números que você desejar.

A indentação é um dos motivos mais comuns para um programa não funcionar como você
esperava. Ao procurar problemas em um programa, um processo conhecido como debugging,
sempre verifique a indentação - especialmente quando você começa a aninhar loops dentro
de loops.
MicroPython também oferece suporte a loops infinitos, que são executados sem fim. Para
mudar seu programa de um loop definido para um loop infinito, edite a linha 2 para ler:

while True:

Como não usaremos mais a variável i, mude a linha 3 para ler:

print("Loop running!")
Para evitar que o programa seja executado muito rapidamente, também adicionaremos um
pequeno atraso importando a biblioteca utime no início e adicionando um atraso de sleep de
um segundo ao loop (você aprenderá mais sobre esta biblioteca em capítulos posteriores).
Seu programa agora deve ter a seguinte aparência:

import utime
print("Loop starting!")
while True:
print("Loop running!")
utime.sleep(1)
print("Loop finished!")

Figura 2-6: Um loop infinito, que continua até você parar o programa

DESAFIO: FAZER O LOOP


1
Você pode mudar o loop de volta para um loop definitivo novamente? Você
pode adicionar um segundo loop definido ao programa? Como você
adicionaria um loop dentro de um loop e como você espera que isso
funcione?

Condicionais e variáveis
As variáveis no MicroPython, como em todas as linguagens de programação, existem para
mais do que apenas controlar loops. Inicie um novo programa clicando no ícone Novo na
barra de ferramentas Thonny e digite o seguinte na área de script:

user_name = input("What is your name?")


Figura 2-7: A função de entrada permite que você peça a um usuário alguma entrada de texto

Clique no ícone Executar, escolha salvar seu programa em sua Pico clicando em ‘Raspberry
Pi Pico’, dê a ele o nome Name_Test.py e observe o que acontece na área Shell: seu nome será
solicitado. Digite seu nome na área Shell, seguido de ENTER. Como essa é a única instrução
em seu programa, nada mais acontecerá (Figura 2-7, no verso). Se você realmente quiser
fazer qualquer coisa com os dados que colocou na variável, precisará de mais linhas em seu
programa.

USANDO = E ==
1 A chave para usar variáveis é aprender a diferença entre = e ==. Lembre-se: =
significa ‘torne esta variável igual a este valor’, enquanto == significa
‘verifique se a variável é igual a este valor’. Misturá-los é uma maneira segura
de acabar com um programa que não funcione!
Figura 2-8: Você não deveria estar salvando o mundo?

Para fazer seu programa fazer algo útil com o nome, adicione uma instrução condicional
digitando o seguinte a partir da linha 2:

if user_name == "Clark Kent":


print("You are Superman!")
else:
print("You are not Superman!")

Lembre-se de que quando Thonny vir que seu código precisa ser indentado, ele o fará
automaticamente - mas não sabe quando seu código precisa parar de ser recuado, então você
mesmo terá que excluir os espaços.
Clique no ícone Executar e digite seu nome na área Shell. A menos que seu nome seja Clark
Kent, você verá a mensagem ‘You are not Superman!’. Clique em Executar novamente e, desta
vez, digite o nome 'Clark Kent' - certificando-se de escrevê-lo exatamente como no programa,
com C e K maiúsculos. Desta vez, o programa reconhece que você é, de fato, o Superman
(Figura 2-8).
Os símbolos == dizem ao Python para fazer uma comparação direta, procurando ver se a
variável user_name corresponde ao texto - conhecido como string - em seu programa. Se
você estiver trabalhando com números, existem outras comparações que você pode fazer: >
para ver se um número é maior que outro número, < para ver se é menor que, >= para ver se é
maior ou igual a, <= para ver se é menor ou igual a.
Figura 2-9: O programa continuará perguntando seu nome até que você diga que é ‘Clark Kent’

Há também ! =, que significa diferente de - é exatamente o oposto de ==. Esses símbolos são
tecnicamente conhecidos como operadores de comparação.
Os operadores de comparação também podem ser usados em loops. Exclua as linhas 2 a 5 e
digite o seguinte em seu lugar:

while user_name != "Clark Kent":


print("You are not Superman - try again!")
user_name = input("What is your name?")
print("You are Superman!")

DESAFIO: ADICIONE MAIS PERGUNTAS


1
Você pode alterar o programa para fazer mais de uma pergunta,
armazenando as respostas em várias variáveis? Você pode fazer um
programa que usa condicionais e operadores de comparação para imprimir
se um número digitado pelo usuário é maior ou menor que 5?

Clique no ícone Executar novamente. Desta vez, em vez de encerrar, o programa continuará
perguntando por seu nome até confirmar que você é o Superman (Figura 2-9) - uma espécie
de senha muito simples. Para sair do loop, digite "Clark Kent" na área de script ou clique no
ícone Parar na barra de ferramentas Thonny. Parabéns: agora você sabe usar condicionais e
operadores de comparação!
Capítulo 3
Computação
física
Saiba mais sobre os
pinos da Raspberry Pi
Pico e os componentes
eletrônicos que você pode
conectar e controlar.

Quando as pessoas pensam em Esses dispositivos são normalmente


‘programação’ ou ‘codificação’, geralmente controlados por um microcontrolador
estão - e naturalmente - pensando em muito parecido com o da sua Raspberry Pi
software. Porém, a codificação pode Pico - e é inteiramente possível para você
envolver mais do que apenas software: ela criar seus próprios sistemas de controle
pode afetar o mundo real por meio do aprendendo a tirar proveito das
hardware. Isso é conhecido como capacidades da sua Pico, tão facilmente
computação física. Como o nome sugere, a quanto você aprendeu a escrever software
computação física trata de controlar que corre na sua Pico.
coisas no mundo real com seus
programas: hardware, em vez de software.
Quando você define o programa na
máquina de lavar, altera a temperatura no
termostato programável ou pressiona um
botão nos semáforos para atravessar a rua
com segurança, você está usando
computação física.
Seus pinos da Pico
Sua Pico se comunica com o hardware por meio de uma série de pinos ao longo de ambas as
bordas. A maioria desses pinos funciona como um pino de entrada/ saída de uso geral (GPIO),
o que significa que podem ser programados para atuar como uma entrada ou uma saída e não
têm um propósito fixo próprio. Alguns pinos têm recursos extras e modos alternativos para
comunicação com hardware mais complicado; outros têm um propósito fixo, fornecendo
conexões para coisas como energia.
Os 40 pinos da Raspberry Pi Pico são rotulados na parte inferior da placa, com três também
rotulados com seus números na parte superior da placa: Pino 1, Pino 2 e Pino 39. Essas
marcações superiores ajudam você a lembrar como funciona a numeração: Pino 1 está no
canto superior esquerdo quando você olha para a placa de cima com a porta micro USB no
lado superior, o pino 20 é o canto inferior esquerdo, o pino 21 o canto inferior direito e o pino
39 um abaixo do canto superior direito com o pino 40 sem marcação acima dele.

Figura 3-1: Os pinos da Raspberry Pi Pico, vistos do topo da placa


PINO GP0
1
Como na contagem em Python, os pinos GPIO da sua Pico começam no
número 0 em vez de no número 1. Rotulados na parte inferior da placa, eles
vão de 0 a 29, embora alguns deles não sejam marcados como pinos físicos.

PINOS EM FALTA
1
Os pinos de entrada / saída de uso geral na Pico são numerados com base nos
pinos do chip que o alimenta, um microcontrolador RP2040. Nem todos os
pinos disponíveis no RP2040 são trazidos para os pinos do seu Pico, no
entanto - é por isso que há uma lacuna na numeração entre o último pino de
uso geral básico GP22 e o primeiro pino com capacidade analógica
GP26_ADC0.

ATENÇÃO
Os pinos da Pico são projetados para ser uma maneira divertida e segura de
1 experimentar a computação física, mas sempre devem ser tratados com
cuidado. Tenha cuidado para não entortar os pinos, especialmente ao inserir
a Pico em uma protoboard. Nunca conecte dois pinos diretamente juntos,
acidentalmente ou deliberadamente, a menos que você seja instruído a fazer
isso nas instruções de um projeto: isso é conhecido como um curto-circuito
e, dependendo dos pinos, pode danificar permanentemente sua Pico.

Componentes eletrônicos
Sua Pico é apenas parte do que você precisa para começar a trabalhar com computação
física; a outra metade é composta de componentes elétricos, os dispositivos que você
controlará dos pinos GPIO da Pico. Existem milhares de componentes diferentes disponíveis,
mas a maioria dos projetos de computação física são feitos usando as seguintes partes
comuns.
Uma protoboard, também conhecida como placa de ensaio sem solda, pode tornar os projetos
de computação física consideravelmente mais fáceis. Em vez de ter um monte de
componentes separados que precisam ser conectados com fios, uma protoboard permite
inserir componentes e conectá-los por meio de trilhos de metal que estão escondidos sob sua
superfície. Muitas protoboards também incluem seções para distribuição de energia,
tornando mais fácil construir seus circuitos. Você não precisa de uma protoboard para
começar com a computação física, pois você pode usar fios especiais para conectar
componentes diretamente aos pinos GPIO da sua Pico, mas certamente torna as coisas mais
simples e estáveis.

Jumpers, também conhecidos como cabos jumpers, conectam componentes a sua Pico e, se
você não estiver usando uma protoboard, entre si. Eles estão disponíveis em três versões:
macho-fêmea (M-F); fêmea-fêmea (F-F), que pode ser usado para conectar componentes
individuais a sua Pico se você não estiver usando uma protoboard; e macho-macho (M-M),
que é usado para fazer conexões de uma parte de uma protoboard para outra. Dependendo do
seu projeto, você pode precisar dos três tipos de fio jumper; se você estiver usando uma
protoboard, geralmente pode se safar com apenas cabos jumpers M-F e M-M.
Um botão de pressão, também conhecido como chave momentânea, é o tipo de interruptor
que você usaria para controlar um console de jogos. Normalmente disponível com dois ou
quatro terminais - qualquer tipo funcionará com sua Pico - o botão de pressão é um
dispositivo de entrada: você pode dizer ao seu programa para ficar atento se ele está sendo
empurrado e então executar uma tarefa. Outro tipo de botão comum é um botão com trava;
enquanto um botão de pressão fica ativo apenas enquanto você o mantém pressionado, um
botão com trava - como você encontraria em um interruptor de luz - é ativado quando você o
alterna uma vez e permanece ativo até que você alterne novamente.

Um diodo emissor de luz (LED) é um dispositivo de saída; você o controla diretamente de seu
programa. Um LED acende quando está ligado e você os encontrará por toda a sua casa,
desde os pequenos que avisam quando você deixou sua máquina de lavar ligada até os
grandes que você pode ter iluminando seus quartos. Os LEDs estão disponíveis em uma
ampla variedade de formas, cores e tamanhos, mas nem todos são adequados para uso com
a sua Pico: evite dizer que eles são projetados para fontes de alimentação de 5 V ou 12 V.

Os resistores são componentes que controlam o fluxo da corrente elétrica e estão disponíveis
em diferentes valores medidos por meio de uma unidade chamada ohms (Ω). Quanto maior o
número de ohms, mais resistência é fornecida. Para projetos de computação física da Pico,
seu uso mais comum é evitar que os LEDs consumam muita corrente e danifiquem a si
próprios ou a Pico; para isso, você vai querer resistores classificados em torno de 330 Ω,
embora muitos vendedores de itens elétricos vendam pacotes úteis contendo uma série de
diferentes valores comumente usados que lhe dão mais flexibilidade.
Um buzzer piezoelétrico, geralmente chamado apenas de buzzer ou sirene, é outro
dispositivo de saída. Enquanto um LED produz luz, um buzzer produz um ruído - um
zumbido, na verdade. Dentro da caixa de plástico do buzzer há um par de placas de metal;
quando ligadas, essas placas vibram umas contra as outras para produzir o som de zumbido.
Existem dois tipos de buzzer: buzzers ativos e buzzers passivos. Certifique-se de obter um
buzzer ativo, pois são os mais simples de usar.

Um potenciômetro é o tipo de componente que


você pode encontrar como um controle de
volume em um reprodutor de música e pode
funcionar como dois componentes diferentes.
Com dois de seus três terminais conectados, ele
atua como um resistor variável, um tipo de
resistor que pode ser ajustado a qualquer
momento girando o botão. Com todos os três
terminais devidamente conectados, ele se torna
um divisor de tensão e produz desde 0 V até a
entrada de tensão total, dependendo da posição
do botão.

Um sensor infravermelho passivo (PIR) é um de


uma variedade de dispositivos de entrada
conhecidos como sensores, projetados para
relatar mudanças em tudo o que estão
monitorando. No caso de um sensor PIR, ele
monitora o movimento: o sensor observa
mudanças na área coberta por sua lente de
plástico e envia um sinal quando detecta
movimento. Os sensores PIR são comumente
encontrados em alarmes contra roubo, para
localizar pessoas se movendo no escuro.
Um display I2C é uma tela que se comunica com sua Pico através de um sistema de
comunicação especial chamado de barramento inter-integrated circuit (I2C). Este
barramento permite que sua Pico controle o painel de exibição, enviando tudo, desde a
escrita até as imagens para exibição. Existem muitos tipos de display disponíveis, embora
um popular - e o encontrado neste livro - seja o SerLCD da SparkFun, que possui interfaces
I2C e SPI. Observe que alguns monitores usam apenas o barramento de serial peripheral
interface (SPI) em vez de I2C; eles ainda funcionarão com a sua Pico, mas precisam que o
programa seja alterado.
Outros componentes elétricos comuns incluem motores, que precisam de um componente
especial de driver antes de serem conectados a sua Pico, sensores de corrente que podem
detectar quanta energia um circuito está usando, unidades de medição inercial (IMUs) que
rastreiam o movimento e orientação, e resistores dependentes de luz (LDRs) - dispositivos de
entrada que operam como um LED reverso, detectando luz em vez de emiti-la.
Os vendedores em todo o mundo fornecem componentes para computação física com
Raspberry Pi, como peças individuais ou em kits que fornecem tudo que você precisa para
começar. Para encontrar vendedores, visite rpf.io/products, clique em Raspberry Pi 4 e você
obterá uma lista de lojas online parceiras da Raspberry Pi (revendedores aprovados) para seu
país ou região.
Para concluir os projetos neste livro, você deve ter pelo menos:

Uma Raspberry Pi Pico com barra de pinos macho soldados


Um cabo micro USB
Uma protoboard
Uma Raspberry Pi ou outro computador para programação
Cabos jumpers macho-fêmea (M-F) e macho-macho (M-M)
3 x LEDs de cor única: vermelho, verde e amarelo
1 × buzzer ativo
1 x Potenciômetro de 10 kΩ, linear ou logarítmico
3 x 330 Ω resistores
Pelo menos um sensor HC-SR501 PIR
1 x módulo SerLCD
LEDs WS2812B

Você também achará útil comprar uma caixa de armazenamento barata com vários
compartimentos, para que possa manter os componentes que não está usando em seu
projeto seguros e organizados. Se puder, tente encontrar um que também se encaixe na
protoboard - dessa forma, você pode arrumar tudo toda vez que terminar.
Lendo códigos de cores do resistor
Os resistores vêm em uma ampla gama de valores, desde versões com resistência zero, que
são efetivamente apenas pedaços de fio, até versões do tamanho de um terminal, usadas em
usinas de energia. Muito poucos desses resistores têm seus valores impressos em números:
em vez disso, eles usam um código especial impresso como listras coloridas ou faixas ao
redor do corpo do resistor.
Para ler o valor de um resistor, posicione-o de forma que o grupo de faixa fique à esquerda e a
faixa solitária à direita. Começando na primeira faixa, procure sua cor na coluna ‘1ª / 2ª Faixa’
da tabela para obter o primeiro e o segundo dígitos. Este exemplo tem duas faixas laranja, que
significam um valor de '3' para um total de '33'. Se o seu resistor tiver quatro faixas agrupadas
em vez de três, anote o valor da terceira faixa também - e para resistores de cinco ou seis
bandas, consulte rpf.io/5-6band.
Movendo-se para a última faixa agrupada - a terceira ou quarta, dependendo do seu resistor
- veja sua cor na coluna ‘Multiplicador’. Isso informa por qual número você precisa
multiplicar seu número atual para obter o valor real do resistor. Este exemplo tem uma faixa
marrom, o que significa ‘× 10¹’. Isso pode parecer confuso, mas é simplesmente notação
científica: '× 10¹' significa simplesmente 'adicionar um zero ao final do seu número'. Se fosse
azul, para × 106 ', significaria 'adicionar seis zeros ao final do seu número'.
33, das faixas laranja, mais o zero adicionado da faixa marrom nos dá 330 - que é o valor do
resistor, medido em ohms. A faixa final, à direita, é a tolerância do resistor. Isso é
simplesmente o quão perto de seu valor nominal é provável que seja. Resistores mais baratos
podem ter uma faixa prateada, indicando que pode ser 10% maior ou menor do que sua
classificação, ou nenhuma última faixa, indicando que pode ser 20% maior ou menor; os
resistores mais caros têm uma faixa cinza, indicando que estará dentro de 0,05% de sua
classificação. Para a maioria dos projetos amadores, a precisão não é tão importante:
qualquer tolerância geralmente funcionará bem.
Se o valor do seu resistor ficar acima de 1000 ohms (1000 Ω), geralmente é avaliado em
kilohms (kΩ); se ultrapassar um milhão de ohms, são megohms (MΩ). Um resistor de 2200 Ω
seria escrito como 2,2 kΩ; um resistor de 2200000Ω seria escrito como 2,2 MΩ.

1
VOCÊ PODE RESOLVER ISSO?
Quais faixas de cores um resistor de 100 Ω teria? Quais faixas de cores um
resistor de 2,2 M teria? Se você quisesse encontrar os resistores mais baratos
para o seu projeto, que faixa de tolerância de cor você procuraria?
Capítulo 4
Computação física
com sua Raspberry
Pi Pico
Comece conectando componentes eletrônicos
básicos à sua Raspberry Pi Pico e escrevendo
programas para controlá-los e senti-los.

Raspberry Pi Pico, com seu microcontrolador RP2040, foi projetada com a computação
física em mente. Seus numerosos pinos de entrada/saída de uso geral (GPIO) permitem que
ele se comunique com um grupo de componentes, permitindo que você crie projetos, desde
iluminação de LEDs até o registro de dados sobre o mundo ao seu redor.
A computação física não é mais difícil de aprender do que a computação tradicional: se você
pudesse seguir os exemplos no Capítulo 2, você seria capaz de construir seus próprios
circuitos e programá-los para cumprir suas ordens.
Seu primeiro programa de
computação física: Olá, LED!
Assim como imprimir 'Hello, World' na tela é um primeiro passo fantástico para aprender
uma linguagem de programação, acender um LED é a introdução tradicional para aprender
computação física. Você também pode começar sem quaisquer componentes adicionais: a
Raspberry Pi Pico tem um pequeno LED, conhecido como LED de dispositivo de montagem
em superfície (SMD), na parte superior.
Comece encontrando o LED: é o pequeno componente retangular à esquerda da porta
micro-USB na parte superior da placa (Figura 4-1), marcado com uma etiqueta que diz ‘LED’.
Este pequeno LED funciona como qualquer outro: quando está ligado, acende; quando está
desligado, permanece escuro.

Figura 4-1: O LED integrado é encontrado à esquerda do conector micro-USB

O LED integrado está conectado a um dos pinos de entrada / saída de uso geral do RP2040,
GP25. Este, você deve se lembrar dos capítulos anteriores, é um dos pinos GPIO "esquecidos"
presentes no RP2040, mas não marcado em um pino físico na borda de sua Pico. Embora
você não possa conectar nenhum hardware externo ao pino, exceto o LED on-board, ele pode
ser tratado da mesma forma que qualquer outro pino GPIO em seus programas - e é uma
ótima maneira de adicionar uma saída a seus programas sem precisar de nenhum
componente extra.
Carregue Thonny e, se ainda não o fez, configure-o para se conectar a sua Pico conforme
mostrado no Capítulo 2. Clique na área de script e inicie seu programa com a seguinte linha:

import machine
Esta curta linha de código é a chave para trabalhar com MicroPython em sua Pico: ele
carrega, ou importa, uma coleção de código MicroPython conhecido como uma biblioteca -
neste caso, a biblioteca "machine". A biblioteca machine contém todas as instruções de que
o MicroPython precisa para se comunicar com a Pico e outros dispositivos compatíveis com
MicroPython, estendendo a linguagem para computação física. Sem esta linha, você não será
capaz de controlar nenhum dos pinos GPIO da sua Pico - e você não será capaz de fazer o LED
on-board acender.

IMPORTAÇÕES SELETIVAS
Tanto no MicroPython quanto no Python, é possível importar parte de uma
1 biblioteca, em vez de toda a biblioteca. Isso pode fazer com que seu programa
use menos memória e permite que você misture e combine funções de
diferentes bibliotecas. Os programas deste livro importam toda a biblioteca;
em outro lugar, você pode ver programas com linhas como from machine
import Pin; isso diz ao MicroPython para importar apenas a função ‘Pin’ da
biblioteca ‘machine’, em vez de toda a biblioteca.

A biblioteca machine expõe o que é conhecido como interface de programação de aplicativos


(API). O nome parece complicado, mas descreve exatamente o que faz: ele fornece uma
maneira para o seu programa, ou aplicativo, se comunicar com a Pico através de uma
interface.
A próxima linha de seu programa fornece um exemplo de API da biblioteca machine:

led_onboard = machine.Pin(25, machine.Pin.OUT)

Esta linha define um objeto chamado led_onboard, que oferece um nome amigável que você
pode usar para se referir ao LED integrado posteriormente em seu programa. É tecnicamente
possível usar qualquer nome aqui - como susan, gupta ou fish_sandwich - mas é melhor ficar
com nomes que descrevam o propósito da variável, para tornar o programa mais fácil de ler
e entender.
A segunda parte da linha chama a função Pin na biblioteca da máquina. Esta função, como o
nome sugere, é projetada para lidar com os pinos GPIO da sua Pico. No momento, nenhum
dos pinos GPIO - incluindo GP25, o pino conectado ao LED on-board - sabe o que eles
deveriam estar fazendo. O primeiro argumento, 25, é o número do pino que você está
configurando; o segundo, machine.Pin.OUT, diz a Pico que o pino deve ser usado como uma
saída em vez de uma entrada.
Essa linha por si só é suficiente para configurar o pino, mas não acenderá o LED. Para fazer
isso, você precisa dizer a Pico para realmente ligar o pino. Digite o seguinte código na
próxima linha:

led_onboard.value(1)
Pode não parecer, mas esta linha também está usando a API da biblioteca da máquina. Sua
linha anterior criou o objeto led_onboard como uma saída no pino GP25; esta linha pega o
objeto e define seu valor para 1 para 'ligado' - ela também pode definir o valor para 0, para
'desligado'.

NÚMEROS DE PINOS
1 Ao falar sobre os pinos GPIO em sua Pico, eles geralmente são referidos
usando seus nomes completos: GP25 para o pino conectado ao LED on-board,
por exemplo. No MicroPython, porém, as letras G e P são descartadas - então
certifique-se de escrever '25' em vez de 'GP25' em seu programa, ou não
funcionará!

Clique no botão Executar e salve o programa na sua Pico como Blink.py. Você verá o LED
acender. Parabéns - você escreveu seu primeiro programa de computação física!
Você notará, no entanto, que o LED permanece aceso: isso porque seu programa diz à Pico
para ligá-lo, mas nunca diz para desligá-lo. Você pode adicionar outra linha na parte inferior
do seu programa:

led_onboard.value(0)

Execute o programa desta vez, porém, e o LED nunca parecerá acender. Isso porque a Pico
funciona muito, muito rapidamente - muito mais rápido do que você pode ver a olho nu. O
LED está aceso, mas por um curto período de tempo parece permanecer escuro. Para
consertar isso, você precisa desacelerar seu programa introduzindo um delay.
Volte ao início do seu programa: clique no final da primeira linha e pressione ENTER para
inserir uma nova segunda linha. Nesta linha, digite:

import utime

Como import machine, esta linha importa uma nova biblioteca para MicroPython: a
biblioteca ‘utime’. Esta biblioteca trata de tudo relacionado ao tempo, desde medi-lo até
inserir atrasos em seus programas.
Vá para o final do seu programa e clique no final da linha led_onboard.value (1), então
pressione ENTER para inserir uma nova linha. Digite:

utime.sleep(5)

Isso chama a função sleep da biblioteca utime, o que faz seu programa pausar por qualquer
número de segundos que você digitou - neste caso, cinco segundos.
Clique no botão Executar novamente. Desta vez, você verá o LED integrado na sua Pico
acender, permanecer aceso por cinco segundos - tente contar junto - e apagar novamente.
UTIME VS TIME
1 Se você já programou em Python antes, estará acostumado a usar a
biblioteca "time". A biblioteca utime é uma versão projetada para
microcontroladores como o Pico - o 'u' significa 'μ', a letra grega 'mu', que é
usada como uma abreviação para 'micro'. Se você esquecer e usar import
time, não se preocupe: o MicroPython usará automaticamente a biblioteca
utime.

Finalmente, é hora de fazer o LED piscar. Para fazer isso, você precisará criar um loop.
Reescreva seu programa para que corresponda ao seguinte:

import machine
import utime

led_onboard = machine.Pin(25, machine.Pin.OUT)

while True:
led_onboard.value(1)
utime.sleep(5)
led_onboard.value(0)
utime.sleep(5)

Lembre-se de que as linhas dentro do loop precisam ser recuadas por quatro espaços, então
MicroPython sabe que elas formam o loop. Clique no ícone Executar novamente e você verá
o LED acender por cinco segundos, desligar por cinco segundos e ligar novamente -
repetindo constantemente em um loop infinito. O LED continuará a piscar até você clicar no
ícone Parar para cancelar seu programa e reiniciar o Pico.
Há outra maneira de lidar com o mesmo trabalho também: usando um toggle, em vez de
definir a saída do LED para 0 ou 1 explicitamente. Exclua as últimas quatro linhas de seu
programa e substitua-as para que tenham a seguinte aparência:

import machine
import utime
led_onboard = machine.Pin(25, machine.Pin.OUT)
while True:
led_onboard.toggle()
utime.sleep(5)

Execute seu programa novamente. Você verá a mesma atividade de antes: o LED integrado
acenderá por cinco segundos, depois apagará por cinco segundos e acenderá novamente em
um loop infinito. Desta vez, porém, seu programa é duas linhas mais curto: você o otimizou.
Disponível em todos os pinos de saída digital, toggle() simplesmente alterna entre ligado e
desligado: se o pino estiver atualmente ligado, toggle() o desliga; se estiver desligado, toggle()
liga.
1
DESAFIO: ILUMINAÇÃO MAIS LONGA
Como você mudaria seu programa para que o LED permanecesse aceso por
mais tempo? Que tal ficar fora por mais tempo? Qual é o menor atraso que
você pode usar enquanto ainda vê o LED ligar e desligar?

Conectando Thonny à Pico


Os projetos a seguir neste capítulo serão muito mais fáceis de concluir se você estiver
usando uma protoboard para segurar os componentes e fazer as conexões elétricas.

Todos os furos em cada


trilho estão conectados

Os cinco furos em cada


linha estão conectados

Figura 4-2: As conexões internas em uma protoboard

Uma protoboard é coberta com furos - espaçados, para combinar com os componentes,
separados por 2,54 mm. Sob esses furos estão tiras de metal que agem como os fios de ligação
que você tem usado até agora. Eles correm em fileiras ao longo da placa, com a maioria das
placas tendo uma lacuna no meio para dividi-los em duas metades.
Muitas protoboards também têm letras na parte superior e números nas laterais. Eles
permitem que você encontre um furo específico: A1 é o canto superior esquerdo, B1 é o buraco
imediatamente à direita, enquanto B2 é um furo abaixo dali. A1 é conectado a B1 pelas tiras
de metal ocultas, mas nenhum furo marcado com 1 é conectado a qualquer furo marcado
com 2, a menos que você mesmo adicione um fio de ponte.
Protoboards maiores também têm tiras de orifícios nas laterais, normalmente marcadas com
listras vermelhas e pretas ou vermelhas e azuis. Estes são os trilhos de alimentação e são
projetados para tornar a fiação mais fácil: você pode conectar um único fio de um dos pinos
de aterramento da Pico a um dos trilhos de alimentação - normalmente marcado com uma
faixa azul ou preta e um símbolo de menos - para fornecer um GND comum para muitos
componentes na protoboard, e você pode fazer o mesmo se o seu circuito precisar de 3,3 V ou
5 V de tensão. Nota: Todos os furos unidos por uma faixa estão conectados; uma lacuna
indica uma quebra.
Adicionar componentes eletrônicos a uma protoboard é simples: apenas alinhe seus
terminais (as peças de metal adesivas) com os furos e empurre suavemente até que o
componente esteja no lugar. Para conexões que você precisa fazer além das que a placa de
ensaio faz para você, você pode usar cabos jumpers macho-macho (M-M); para conexões da
protoboard com dispositivos externos, como a Raspberry Pi Pico, use cabos jumpers
macho-fêmea (M-F).
Nunca tente enfiar mais de um fio condutor ou jumper em qualquer furo da protoboard.
Lembre-se: os furos são conectados em linhas, além da divisão no meio, então um condutor
do componente em A1 é conectado eletricamente a qualquer coisa que você adicionar a B1,
C1, D1 e E1.
Empurre sua Pico na protoboard de forma que ela ocupe o espaço do meio e a porta micro
USB fique bem no topo da placa (veja a Figura 4-3). O pino superior esquerdo, Pino 0, deve
estar na linha da protoboard marcada com um 1, se a sua protoboard for numerada. Antes de
empurrar a Pico para baixo, certifique-se de que os pinos da plataforma estejam todos
posicionados corretamente - se você entortar um pino, pode ser difícil endireitá-lo
novamente sem quebrar.

Figura 4-3: Sua Pico é projetada para se assentar com segurança em uma protoboard sem solda
Empurre suavemente a Pico para baixo até que as partes de plástico dos pinos-guia estejam
tocando a protoboard. Isso significa que as peças de metal dos pinos do conector estão
totalmente inseridas e fazendo um bom contato elétrico com a protoboard.

Próximos passos: um LED externo


Até agora, você tem trabalhado com sua Pico por conta própria - executando programas
MicroPython em seu microcontrolador RP2040 e ligando e desligando o LED integrado.
Microcontroladores são normalmente usados com componentes externos - e sua Pico não é
exceção.
Para este projeto, você precisará de uma protoboard, cabos jumpers macho-macho (M-M), um
LED e um resistor de 330 Ω - ou o mais próximo de 330 Ω que você tiver disponível. Se você
não tiver uma protoboard, pode usar cabos jumper fêmea-fêmea (F-F), mas o circuito será
frágil e fácil de quebrar.

RESISTÊNCIA É VITAL
O resistor é um componente vital neste circuito: ele protege a sua Pico e o
LED, limitando a quantidade de corrente elétrica que o LED pode consumir.
1 Sem ele, o LED pode puxar muita corrente e queimar-se - ou a sua Pico - para
fora. Quando usado dessa forma, o resistor é conhecido como um resistor
limitador de corrente. O valor exato do resistor que você precisa depende do
LED que você está usando, mas 330 Ω funciona para a maioria dos LEDs
comuns. Quanto mais alto o valor, mais escuro é o LED; quanto menor o valor,
mais brilhante é o LED. Nunca conecte um LED a sua Pico sem um resistor
limitador de corrente, a menos que você saiba que o LED possui um resistor
embutido de valor apropriado.

Segure o LED em seus dedos: você verá que um de seus terminais é mais longo que o outro. O
terminal mais longo é conhecido como ânodo e representa o lado positivo do circuito; o
terminal mais curto é o cátodo e representa o lado negativo. O ânodo precisa ser conectado a
um dos pinos GPIO da Pico através do resistor; o cátodo precisa ser conectado a um pino de
GND.
Comece conectando o resistor: pegue uma extremidade (não importa qual) e insira-a na
protoboard na mesma linha do pino GP15 da sua Pico no canto inferior esquerdo - se você
estiver usando uma protoboard numerada com a sua Pico inserido na parte superior, deve ser
a linha 20. Empurre a outra extremidade em uma linha livre mais para baixo na protoboard -
estamos usando a linha 24.
Pegue o LED e empurre o terminal mais longo - o ânodo - na mesma linha que a extremidade
do resistor. Empurre o terminal mais curto - o cátodo - na mesma linha, mas através da
lacuna central na protoboard, para que seja alinhada, mas não eletricamente conectada ao
terminal mais longo, exceto através do próprio LED. Por fim, insira um cabo jumper
macho-macho (M-M) na mesma linha que o terminal mais curto do LED e, em seguida,
conecte-o diretamente a um dos pinos de GND da Pico (por meio de outro furo em sua linha)
ou ao negativo lado do barramento de alimentação da sua protoboard. Se você o conectar ao
barramento de alimentação, termine o circuito conectando o trilho a um dos pinos de GND da
Pico. Seu circuito concluído deve ser semelhante à Figura 4-4 (no verso).
Figura 4-4: O circuito concluído, com um LED e um resistor

Controlar um LED externo no MicroPython não é diferente de controlar o LED interno da Pico:
apenas o número do pino muda. Se você fechou o Thonny, reabra-o e carregue o programa
Blink.py do início deste capítulo. Encontre a linha:

led_onboard = machine.Pin(25, machine.Pin.OUT)

Edite o número do pino, alterando-o de 25 - o pino conectado ao LED interno do Pico - para 15,
o pino ao qual você conectou o LED externo. Edite também o nome que você criou: você não
está mais usando o LED on-board, então diga led_external. Você também terá que alterar o
nome em outro lugar no programa, até que fique assim:

import machine
import utime

led_external = machine.Pin(15, machine.Pin.OUT)

while True:
led_external.toggle()
utime.sleep(5)

CONVENÇÕES DE NOME
1 Você realmente não precisa mudar o nome no programa: ele seria executado
da mesma forma se você tivesse deixado em led_onboard, já que é apenas o
número do pino que realmente importa. Quando você voltar ao programa
mais tarde, no entanto, seria muito confuso ter um objeto chamado
led_onboard que acende um LED externo - então, tente adquirir o hábito de
certificar-se de que seus nomes correspondam a seus propósitos!
DESAFIO: MÚLTIPLOS LEDS
1 Você pode modificar o programa para acender os LEDs internos e externos ao
mesmo tempo? Você pode escrever um programa que acenda o LED
integrado quando o LED externo for desligado e vice-versa? Você pode
estender o circuito para incluir mais de um LED externo? Lembre-se, você
precisará de um resistor limitador de corrente para cada LED que usar!

Entradas: lendo um botão


Saídas como LEDs são uma coisa, mas a parte ‘entrada/saída’ de ‘GPIO’ significa que você
também pode usar pinos como entradas. Para este projeto, você precisará de uma protoboard,
cabos jumpers macho-macho e um de botão de pressão. Se você não tiver uma protoboard,
pode usar cabos jumpers fêmea-fêmea (F-F), mas o botão será muito mais difícil de
pressionar sem quebrar o circuito acidentalmente.
Remova todos os outros componentes de sua protoboard, exceto sua Pico, e comece
adicionando o botão. Se o seu botão tiver apenas dois terminais, certifique-se de que eles
estejam em fileiras com números diferentes na placa de ensaio em algum lugar abaixo da
sua Pico. Se ele tiver quatro terminais, vire-o de forma que os lados de onde vêm os terminais
fiquem ao longo das fileiras da protoboard e os lados planos sem terminais fiquem na parte
superior e inferior antes de empurrá-lo para o furo de forma que fique na divisão central da
protoboard.
Conecte o barramento de alimentação positivo de sua protoboard ao pino 3V3 da Pico e, a
partir daí, a um dos terminais do botão; em seguida, conecte o outro terminal ao pino GP14 em
sua Pico - é aquele logo acima do pino que você usou para o projeto de LED e deve estar na
linha 19 da sua protoboard.
Se você estiver usando o botão com quatro terminais, seu circuito só funcionará se você usar
o par de terminais correto: os terminais são conectados aos pares, então você precisa usar os
dois terminais do mesmo lado ou (como visto na Figura 4-5) terminais diagonalmente
opostos.

Figura 4-5: Conectando um botão de quatro terminais para GP14


RESISTÊNCIA ESTÁ OCULTA
Ao contrário de um LED, um botão momentâneo não precisa de um resistor
1
limitador de corrente. Porém, ele ainda precisa de um resistor: ele precisa do
que é conhecido como resistor pull-up ou pull-down, dependendo de como o
circuito funciona. Sem um resistor pull-up ou pull-down, uma entrada é
conhecida como flutuante - o que significa que tem um sinal "ruidoso" que
pode disparar mesmo quando você não está pressionando o botão.
Então, onde está o resistor neste circuito? Escondido na sua Pico. Assim
como tem um LED on-board, sua Pico inclui um resistor programável
on-board conectado a cada pino GPIO. Eles podem ser configurados no
MicroPython para resistores pull-down ou resistores pull-up, conforme
exigido pelo seu circuito.
Qual é a diferença? Um resistor pull-down conecta o pino ao GND, o que
significa que quando o botão não é pressionado, a entrada será 0. Um resistor
pull-up conecta o pino a 3V3, ou seja, quando o botão não é pressionado, a
entrada será 1.
Todos os circuitos neste livro usam os resistores programáveis no modo
pull-down.

Carregue Thonny, se ainda não o fez, e inicie um novo programa com a linha usual:

import machine

Em seguida, você precisa usar a API da máquina para configurar um pino como entrada, em
vez de saída:

button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

sso funciona da mesma maneira que seus projetos de LED: um objeto chamado 'button' é
criado, que inclui o número do pino - GP14, neste caso - e o configura como uma entrada com
o resistor definido para pull-down. Criar o objeto, porém, não significa que ele fará alguma
coisa por si mesmo - assim como criar os objetos de LED anteriormente não fazia os LEDs
acenderem.
Para realmente ler o botão, você precisa usar a API da máquina novamente - desta vez
usando a função value para ler, em vez de definir, o valor do pino. Digite a seguinte linha:

print(button.value())
Clique no ícone Executar e salve seu programa como Button.py - lembrando-se de ter certeza
de que ele será salvo na Raspberry Pi Pico. Seu programa imprimirá um único número: o
valor da entrada em GP14.
Como a entrada está usando um resistor pull-down, este valor será 0 - informando que o
botão não foi pressionado. Mantenha pressionado o botão com o dedo e pressione o ícone
Executar novamente. Desta vez, você verá o valor 1 impresso no Shell: apertar o botão
completou o circuito e alterou o valor lido do pino.
Para ler o botão continuamente, você precisará adicionar um loop ao seu programa. Edite o
programa para que fique como abaixo:

import machine
import utime

button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

while True:
if button.value() == 1:
print("You pressed the button!")
utime.sleep(2)

Clique no botão Executar novamente. Desta vez, nada acontecerá até que você pressione o
botão; ao fazer isso, você verá uma mensagem impressa na área do Shell. O atraso,
entretanto, é importante: lembre-se, a sua Pico funciona muito mais rápido do que você
consegue ler e, sem o atraso, mesmo um breve toque no botão pode imprimir centenas de
mensagens para o Shell!
Você verá a mensagem impressa sempre que pressionar o botão. Se você mantiver o botão
pressionado por mais do que o atraso de dois segundos, a mensagem será impressa a cada
dois segundos até que você solte o botão.

Entradas e saídas: juntando tudo


A maioria dos circuitos tem mais de um componente, e é por isso que sua Pico tem tantos
pinos GPIO. É hora de juntar tudo o que você aprendeu para construir um circuito mais
complexo: um dispositivo que liga e desliga um LED com um botão.

Figura 4-6: O circuito concluído, com um botão e um LED


Com efeito, este circuito combina os dois circuitos anteriores em um. Você deve se lembrar
que usou o pino GP15 para acionar o LED externo e o pino GP14 para ler o botão; agora
reconstrua seu circuito de forma que o LED e o botão estejam na protoboard ao mesmo
tempo, ainda conectados ao GP15 e GP14 (veja a Figura 4-6). Não se esqueça do resistor
limitador de corrente para o LED!
nicie um novo programa em Thonny e comece a importar as duas bibliotecas de que seu
programa precisará:

import machine
import utime

Em seguida, configure os pinos de entrada e saída:

led_external = machine.Pin(15, machine.Pin.OUT)


button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

Em seguida, crie um loop que leia o botão:

while True:
if button.value() == 1:

Em vez de imprimir uma mensagem ao Shell, porém, desta vez você vai alternar o pino de
saída e o LED conectado a ele com base no valor do pino de entrada. Digite o seguinte,
lembrando que precisará ser indentado por oito espaços - o que Thonny deve ter tratado
automaticamente quando você pressionou ENTER no final da linha acima:

led_external.value(1)
utime.sleep(2)

Isso é o suficiente para ligar o LED, mas você também precisará desligá-lo novamente
quando o botão não estiver sendo pressionado. Adicione a seguinte nova linha, usando a
tecla BACKSPACE para excluir quatro dos oito espaços - o que significa que a linha não fará
parte da instrução if, mas fará parte do loop infinito:

led_external.value(0)

Seu programa concluído deve ser semelhante a este:

import machine
import utime

led_external = machine.Pin(15, machine.Pin.OUT)


button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

while True:
if button.value() == 1:
led_external.value(1)
utime.sleep(2)
led_external.value(0)
Clique no ícone Executar e salve o programa como Switch.py em sua Pico. No início, nada
acontecerá; aperte o botão, porém, e você verá o LED acender. Solte o botão; após dois
segundos, o LED apagará novamente até que você pressione o botão novamente.
Parabéns: você construiu seu primeiro circuito que controla um pino com base na entrada de
outro - um bloco de construção para coisas maiores!

DESAFIO: CONSTRUINDO MAIS


1
Você pode modificar seu programa para que acenda o LED e imprime uma
mensagem de status para o Shell? O que você precisa alterar para fazer o LED
permanecer ligado quando o botão não é pressionado e desligar quando está?
Você pode adicionar mais botões e LEDs ao circuito?
Capítulo 5
Controlador
de semáforo
Crie o seu próprio sistema de mini faixa de pedestres usando vários
LEDs e um botão de pressão.

Microcontroladores podem ser em miniatura movido por sua Raspberry


encontrados em quase todos os itens Pi Pico. Com este projeto, você verá como
eletrônicos que você usa diariamente - controlar vários LEDs, definir diferentes
incluindo semáforos. Um controlador de tempos e como monitorar uma entrada de
semáforo é um sistema especialmente botão enquanto o resto do programa
construído que muda as luzes em um continua a ser executado usando uma
temporizador, observa os pedestres que técnica conhecida como threading.
procuram atravessar e pode até ajustar o Para este projeto, você precisará da sua
tempo dos semáforos dependendo da Pico; uma protoboard; um LED vermelho,
quantidade de tráfego - conversando com um amarelo e um verde; três resistores de
sistemas de semáforos próximos para 330 Ω; um buzzer ativo; e uma seleção de
garantir o toda a rede de tráfego continua cabos jumpers macho-macho (M-M). Você
fluindo sem problemas. também precisará de um cabo micro USB
Embora construir um sistema de para conectar sua Pico a Raspberry Pi ou
gerenciamento de tráfego em grande outro computador executando o Thonny
escala seja um projeto bastante avançado, MicroPython IDE.
é muito simples construir um simulador
Um simples semáforo
Comece construindo um sistema de semáforo simples, conforme mostrado na Figura 5-1.
Pegue o LED vermelho e insira-o na protoboard de modo que fique na divisão central. Use um
dos resistores de 330 Ω e um cabo jumper se precisar fazer uma conexão mais longa, para
conectar o terminal mais longo - o ânodo - do LED ao pino na parte inferior esquerda da sua
Pico, visto de cima com o cabo micro USB na parte superior, GP15. Se você estiver usando
uma protoboard numerada e tiver sua Pico inserida na parte superior, esta será a linha 20 da
protoboard.

Figura 5-1: Um sistema básico de semáforo com três luzes

AVISO
1 Lembre-se sempre de que um LED precisa de um resistor limitador de
corrente antes de ser conectado a sua Pico. Se você conectar um LED sem um
resistor limitador de corrente instalado, o melhor resultado é o LED queimará
e não funcionará mais; o pior resultado é que pode fazer o mesmo com a sua
Pico.

Pegue um jumper e conecte o terminal mais curto - o cátodo - do LED vermelho ao trilho de
GND da protoboard. Pegue outro e conecte o trilho de GND a um dos pinos de GND da Pico
(terra) - na Figura 5-1, usamos o pino de GND na terceira linha da protoboard.
Você agora tem um LED conectado a sua Pico, mas um semáforo real tem pelo menos mais
dois para um total de três: uma luz vermelha para dizer ao motorista para parar, uma luz
amarela para dizer ao motorista que está prestes a mudar, e um LED verde para informar ao
motorista que ele pode ir novamente.
Pegue seu LED amarelo e conecte-o à Pico da mesma forma que o LED vermelho,
certificando-se de que o terminal mais curto seja o que está conectado ao trilho de GND da
protoboard e que você tenha o resistor de 330 Ω no lugar para protegê-lo. Desta vez, porém,
conecte o terminal mais longo - por meio do resistor - ao pino próximo àquele ao qual você
conectou o LED vermelho, GP14.
Finalmente, pegue o LED verde e conecte-o da mesma maneira novamente - lembrando do
resistor de 330 Ω - ao pino GP13. Este não é o pino ao lado do pino GP14, no entanto - esse pino
é um pino de aterramento (GND), que você pode ver se olhar atentamente para sua Pico: todos
os pinos de aterramento têm uma forma quadrada em seus pads, enquanto os outros pinos
são redondos.
Quando terminar, seu circuito deve corresponder à Figura 5-1: um LED vermelho, um amarelo
e um verde, todos conectados a diferentes pinos GPIO em sua Pico por meio de resistores de
330 Ω individuais e conectados a um pino de GND compartilhado por meio da linha da sua
protoboard.
Para programar seu semáforo, conecte sua Pico à Raspberry Pi ou outro computador e
carregue o Thonny. Crie um novo programa e comece importando a biblioteca machine para
que você possa controlar seus pinos GPIO da Pico:

import machine

Você também precisará importar a biblioteca utime, para que possa adicionar delays entre as
luzes acender e apagar:

import utime

Como acontece com qualquer programa que usa os pinos GPIO da Pico, você precisará
configurar cada pino antes de controlá-lo:

led_red = machine.Pin(15, machine.Pin.OUT)


led_amber = machine.Pin(14, machine.Pin.OUT)
led_green = machine.Pin(13, machine.Pin.OUT)

Essas linhas definem os pinos GP15, GP14 e GP13 como saídas, e cada um recebe um nome
descritivo para facilitar a leitura do código: 'led', para que você saiba que os pinos controlam
um LED e a cor do LED.
Semáforos de verdade não passam uma vez e param - eles continuam indo, mesmo quando
não há tráfego e todos estão dormindo. Para que seu programa faça o mesmo, você precisará
configurar um loop infinito:

while True:

Cada uma das linhas abaixo precisa ser indentada por quatro espaços, para que MicroPython
saiba que fazem parte do loop; quando você pressiona a tecla ENTER, Thonny
automaticamente indenta as linhas para você.

led_red.value(1)
utime.sleep(5)
led_amber.value(1)
utime.sleep(2)
led_red.value(0)
led_amber.value(0)
led_green.value(1)
utime.sleep(5)
led_green.value(0)
led_amber.value(1)
utime.sleep(5)
led_amber.value(0)
Clique no ícone Executar e salve seu programa na Pico como Traffic_Lights.py. Observe os
LEDs: primeiro o LED vermelho acenderá, informando ao motorista para parar; a seguir, o LED
amarelo acenderá para avisar ao motorista que as luzes estão prestes a mudar; em seguida,
os dois LEDs se desligam e o LED verde se acende para que o motorista saiba que pode passar;
em seguida, o LED verde apaga e o amarelo acende para avisar os motoristas que as luzes
estão prestes a mudar novamente; finalmente, o LED amarelo apaga - e o loop é reiniciado
desde o início, com o LED vermelho acendendo.
O padrão fará um loop até que você pressione o botão Parar, porque ele forma um loop
infinito. É baseado no padrão de semáforo usado em sistemas de controle de tráfego do
mundo real no Reino Unido e na Irlanda, mas acelerou - dar aos carros apenas cinco
segundos para passar pelos semáforos não deixaria o trânsito fluir muito livremente!
No entanto, semáforos reais não existem apenas para veículos rodoviários: eles também
existem para proteger os pedestres, dando-lhes a oportunidade de atravessar uma estrada
movimentada com segurança. No Reino Unido, o tipo mais comum dessas luzes é conhecido
como travessias inteligentes de fácil operação operadas por pedestres ou puffin crossings
(faixa de pedestres inteligente).
Para transformar seu semáforo em uma faixa de pedestres inteligente, você precisará de
duas coisas: um botão momentâneo, para que o pedestre possa pedir ao semáforo para
atravessar a via; e um buzzer, para que o pedestre saiba quando é sua vez de atravessar.
Conecte-os em sua protoboard como na Figura 5-2, com o botão conectado ao pino GP16 e o
trilho 3V3 de sua protoboard e o buzzer conectado ao pino GP12 e ao trilho de GND de sua
protoboard.

Figura 5-2: Um sistema de semáforo para faixa de pedestres inteligente

Se você executar o programa novamente, verá que o botão e o buzzer não fazem nada. Isso
porque você ainda não disse ao seu programa como usá-los. Em Thonny, volte para as linhas
onde você configurou seus LEDs e adicione as seguintes duas novas linhas abaixo:

button = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_DOWN)


buzzer = machine.Pin(12, machine.Pin.OUT)

Isso define o botão no pino GP16 como uma entrada e o buzzer no pino GP12 como uma saída.
Lembre-se de que sua Raspberry Pi Pico possui resistores programáveis integrados para suas
entradas, que estamos configurando para o modo pull-down para os projetos neste livro. Isso
significa que a tensão do pino é reduzida para 0 V (e seu nível lógico é 0), a menos que esteja
conectado à alimentação de 3,3 V (neste caso, seu nível lógico será 1 até desconectado).
Em seguida, você precisa de uma maneira para seu programa monitorar constantemente o
valor do botão. Anteriormente, todos os seus programas funcionavam passo a passo por meio
de uma lista de instruções - sempre fazendo uma coisa de cada vez. Seu programa de
semáforo não é diferente: conforme é executado, o MicroPython percorre suas instruções
passo a passo, ligando e desligando os LEDs.
Para um conjunto básico de semáforos, isso é o suficiente; para uma faixa de pedestre
inteligente, no entanto, seu programa precisa ser capaz de registrar se o botão foi
pressionado de uma forma que não interrompa os semáforos. Para fazer isso funcionar, você
precisará de uma nova biblioteca: _thread. Volte para a seção de seu programa onde você
importa as bibliotecas machine e utime e importe a biblioteca _thread:

import _thread

Um thread ou thread de execução é, efetivamente, um programa pequeno e parcialmente


independente. Você pode pensar no loop que você escreveu anteriormente, que controla as
luzes, como o thread principal do seu programa - e usando a biblioteca _thread você pode
criar um thread adicional, executando ao mesmo tempo.
Uma maneira fácil de visualizar os threads é pensar em cada um como um funcionário
separado em uma cozinha: enquanto o chef prepara o prato principal, outra pessoa está
trabalhando em um molho. No momento, seu programa tem apenas um thread - aquele que
controla os semáforos. O microcontrolador RP2040 que alimenta sua Pico, no entanto, tem
dois núcleos de processamento - ou seja, como o chef e o chef auxiliar na cozinha, você pode
executar dois threads ao mesmo tempo para fazer mais trabalho.
Antes de fazer outro thread, você precisará encontrar uma maneira para o novo thread
passar informações de volta ao thread principal - e você pode fazer isso usando variáveis
globais. As variáveis com as quais você trabalhou antes disso são conhecidas como variáveis
locais e funcionam apenas em uma seção de seu programa; uma variável global funciona em
qualquer lugar, o que significa que um thread pode alterar o valor e outro pode verificar se ele
foi alterado.
Para começar, você precisa criar uma variável global. Abaixo de sua linha buzzer = , adicione
o seguinte:

global button_pressed
button_pressed = False

Isso configura button_pressed como uma variável global e dá a ele um valor padrão False - o
que significa que quando o programa é iniciado, o botão ainda não foi pressionado. A próxima
etapa é definir seu segmento, adicionando as seguintes linhas diretamente abaixo -
adicionando uma linha em branco, se desejar, para tornar seu programa mais legível:

def button_reader_thread():
global button_pressed
while True:
if button.value() == 1:
button_pressed = True
utime.sleep(0.01)
A primeira linha que você adicionou define seu tópico e dá a ele um nome descritivo: é um
tópico para ler a entrada do botão. Como ao escrever um loop, o MicroPython precisa que
tudo contido no thread seja recuado por quatro espaços - para que ele saiba onde o thread
começa e termina.
A próxima linha permite ao MicroPython saber que você mudará o valor da variável global
button_pressed. Se você deseja apenas verificar o valor, você não precisa desta linha - mas
sem ela você não pode fazer nenhuma alteração na variável.
Em seguida, você configurou um novo loop - o que significa que um novo recuo de quatro
espaços precisa seguir, para oito no total, então MicroPython sabe que o loop é parte do
thread e o código abaixo é parte do loop. Esse aninhamento de código em vários níveis de
indentação é muito comum no MicroPython, e Thonny fará o possível para ajudá-lo
adicionando automaticamente um novo nível sempre que for necessário - mas cabe a você
lembrar de excluir os espaços que ele adiciona quando você terminou com uma seção
específica do programa.
A próxima linha é uma condicional que verifica se o valor do botão é 1. Como sua Pico está
usando um resistor pull-down interno, quando o botão não está sendo pressionado, o valor
lido é 0 - o que significa que o código sob o condicional nunca é executado. Somente quando
o botão é pressionado, a linha final do seu thread é executada: uma linha que define a variável
button_pressed como True, permitindo que o resto do seu programa saiba que o botão foi
pressionado. Finalmente, adicionamos um delay muito curto (0,01 segundo) para evitar que o
loop while seja executado muito rápido.
Você pode notar que não há nada no tópico para redefinir a variável button_pressed de volta
para False quando o botão é liberado após ser pressionado. Há uma razão para isso: embora
você possa apertar o botão de uma faixa inteligente de pedestres a qualquer momento
durante o ciclo do semáforo, isso só terá efeito quando o semáforo ficar vermelho e for seguro
para você atravessar. Tudo o que seu novo tópico precisa fazer é alterar a variável quando o
botão for pressionado; seu thread principal cuidará da redefinição para False quando o
pedestre tiver cruzado a via com segurança.
Definir um thread não o define em execução: é possível iniciar um thread em qualquer ponto
do seu programa e você precisará informar especificamente à biblioteca _thread quando
deseja iniciar o thread. Ao contrário de executar uma linha normal de código, executar o
thread não para o resto do programa: quando o thread é iniciado, MicroPython continuará e
executará a próxima linha de seu programa, mesmo enquanto executa a primeira linha de
seu novo thread.
Crie uma nova linha abaixo do seu tópico, excluindo toda a indentação que Thonny
adicionou automaticamente para você, que diz:

_thread.start_new_thread(button_reader_thread, ())

Isso diz à biblioteca _thread para iniciar o thread que você definiu anteriormente. Neste
ponto, o thread começará a ser executado e rapidamente entrará em seu loop - verificando o
botão milhares de vezes por segundo para ver se ele já foi pressionado. O tópico principal, por
sua vez, continuará com a parte principal de seu programa.
Clique no botão Executar agora. Você verá que as luzes seguem seu padrão exatamente como
antes, sem atrasos ou pausas. Se você pressionar o botão, porém, nada acontecerá - porque
você ainda não adicionou o código para reagir de fato ao botão.
Vá para o início de seu loop principal, diretamente abaixo da linha while True: e adicione o
seguinte código - lembrando-se de prestar atenção à indentação aninhada e excluindo a
indentação que Thonny adicionou quando não for mais necessária:
if button_pressed == True:
led_red.value(1)
for i in range(10):
buzzer.value(1)
utime.sleep(0.2)
buzzer.value(0)
utime.sleep(0.2)
global button_pressed
button_pressed = False

Este pedaço de código verifica a variável global button_pressed para ver se o botão do botão
foi pressionado a qualquer momento desde a última execução do loop. Se tiver, conforme
relatado pelo tópico de leitura de botão que você fez anteriormente, ele começa a executar
uma seção de código que começa ligando o LED vermelho para parar o trânsito e, em seguida,
apita o buzzer dez vezes - informando ao pedestre que é hora de atravessar.
Finalmente, as duas últimas linhas redefinem a variável button_pressed de volta para False
- então, da próxima vez que o loop for executado, ele não acionará o código para travessia de
pedestres, a menos que o botão seja pressionado novamente. Você verá que não precisava da
linha global button_pressed para verificar o status da variável na condicional; é necessário
apenas quando você deseja alterar a variável e fazer com que essa alteração afete outras
partes do seu programa.
Seu programa concluído deve ser semelhante a este:

import machine
import utime
import _thread

led_red = machine.Pin(15, machine.Pin.OUT)


led_amber = machine.Pin(14, machine.Pin.OUT)
led_green = machine.Pin(13, machine.Pin.OUT)
button = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_DOWN)
buzzer = machine.Pin(12, machine.Pin.OUT)

global button_pressed
button_pressed = False

def button_reader_thread():
global button_pressed
while True:
if button.value() == 1:
button_pressed = True
utime.sleep(0.01)
_thread.start_new_thread(button_reader_thread, ())

while True:
if button_pressed == True:
led_red.value(1)
for i in range(10):
buzzer.value(1)
utime.sleep(0.2)
buzzer.value(0)
utime.sleep(0.2)
global button_pressed
button_pressed = False
led_red.value(1)
utime.sleep(5)
led_amber.value(1)
utime.sleep(2)
led_red.value(0)
led_amber.value(0)
led_green.value(1)
utime.sleep(5)
led_green.value(0)
led_amber.value(1)
utime.sleep(5)
led_amber.value(0)

Clique no ícone Executar. A princípio, o programa funcionará normalmente: as luzes


acendem e apagam no padrão normal. Pressione o botão de pressão: se o programa estiver
atualmente no meio de seu loop, nada acontecerá até que chegue ao fim e volte novamente -
nesse ponto, a luz ficará vermelha e a campainha emitirá um bipe para informá-lo é seguro
atravessar a rua.
A seção condicional do código para atravessar a estrada é executada antes do código que
você escreveu anteriormente para ligar e desligar as luzes em um padrão cíclico: depois de
concluído, o padrão começará como de costume com o LED vermelho permanecendo aceso
por mais cinco segundos na maior parte do tempo, estava aceso enquanto o buzzer tocava.
Isso imita o funcionamento de uma faixa de pedestres inteligente real: a luz vermelha
permanece acesa mesmo depois que o buzzer parou de soar, então qualquer pessoa que
começou a atravessar a rua enquanto o buzzer estava tocando tem tempo de chegar ao outro
lado antes que o trânsito seja liberado.
Deixe que os semáforos percorram o ciclo mais algumas vezes e pressione o botão
novamente para acionar outra parada. Parabéns: você construiu sua própria faixa de
pedestres inteligente!
1
DESAFIO: VOCÊ PODE MELHORAR?
Você pode alterar o programa para dar ao pedestre mais tempo para
atravessar? Você pode encontrar informações sobre os padrões de semáforos
de outros países e reprogramar suas luzes para corresponder? Você pode
adicionar um segundo botão para que o pedestre do outro lado da via possa
sinalizar que deseja atravessar também?
Capítulo 6
Jogo de reação
Construa um jogo de tempo de reação simples usando um LED e botões
de pressão, para um ou dois jogadores.

Os microcontroladores não são encontra- sinais para que algo aconteça - é medido
dos apenas em dispositivos industriais: em milissegundos: o tempo médio de
eles acionam muitos aparelhos eletrôni- reação humana é de cerca de 200-250
cos em casa, incluindo brinquedos e jogos. milissegundos, embora algumas pessoas
Neste capítulo, você vai construir um jogo gostem muito mais rápido tempos de
simples de tempo de reação, vendo quem reação que lhes darão uma vantagem real
entre seus amigos será o primeiro a pres- no jogo!
sionar um botão quando uma luz se Para este projeto, você precisará da sua
apagar. Pico; uma protoboard; um LED de qualquer
O estudo do tempo de reação é conhecido cor; um único resistor de 330 Ω; dois botões
como cronometria mental e, embora seja momentâneos; e uma seleção de jumpers
uma ciência sólida, também é a base de macho-macho (M-M). Você também preci-
muitos jogos baseados em habilidades - sará de um cabo micro USB para conectar
incluindo aquele que você está prestes a sua Pico à Raspberry Pi ou outro computa-
construir. Seu tempo de reação - o tempo dor executando Thonny MicroPython IDE.
que seu cérebro leva para processar a
necessidade de fazer algo e enviar os
Versão para um jogador
Comece colocando seu LED em sua protoboard de forma que ele fique na divisão central.
Lembre-se de que os LEDs só funcionam quando estão do jeito certo: certifique-se de saber
qual é o terminal mais longo, ou ânodo, e qual é o terminal mais curto, o cátodo.
Usando um resistor limitador de corrente de 330 Ω, para proteger o LED e sua Pico, conecte o
terminal mais longo do LED ao pino GP15 no canto inferior esquerdo da sua Pico, visto de
cima com o cabo micro USB voltado para cima. Se você estiver usando uma protoboard
numerada e tiver sua Pico inserida na parte superior, esta será a linha 20 da protoboard.

1
AVISO
É importante repetir que um LED sempre precisa de um resistor limitador de
corrente antes de ser conectado à sua Pico. Sem o resistor, o LED pode
queimar - ou a sua Pico pode ser danificada.

Pegue um jumper e conecte o terminal mais curto do LED ao trilho de GND da protoboard.
Pegue outro jumper e conecte o trilho de GND a um dos pinos de GND da Pico (terra) - na
Figura 6-1, usamos o pino de GND na terceira linha da protoboard.

Figura 6-1: Um jogo de reação modo um jogador

Em seguida, adicione o botão conforme mostrado na Figura 6-1. Pegue um jumper e conecte
um dos botões de pressão ao pino GP14, bem ao lado do pino que você usou para o seu LED.
Use outro jumper para conectar o outro terminal - aquele diagonalmente oposto ao primeiro,
se você estiver usando um de botão de quatro terminais - ao barramento de alimentação da
protoboard. Finalmente, pegue o último jumper e conecte o barramento de alimentação ao
pino 3V3 da sua Pico.

1
POR QUE 3V3?
Lembre-se de que botões, como LEDs, precisam de resistores para operar
corretamente e que sua Pico tem resistores programáveis em todos os seus
pinos GPIO. Nos projetos deste livro, estamos configurando-os para resistores
pull_down, o que significa que o pino deve ser puxado para cima quando o
botão é pressionado - que é o que fazer a fiação do botão ao pino 3V3 por meio
do barramento de alimentação da protoboard.
Seu circuito agora tem tudo de que precisa para funcionar como um simples jogo modo um
jogador: o LED é o dispositivo de saída, ocupando o lugar da TV que você normalmente usaria
com um console de jogos; o botão é o controlador; e sua Pico é o console de jogos, embora
consideravelmente menor do que você normalmente veria!
Agora você precisa realmente escrever o jogo. Como sempre, conecte sua Pico à Raspberry Pi
ou outro computador e carregue o Thonny. Crie um novo programa e inicie-o importando a
biblioteca machine para que você possa controlar seus pinos GPIO da Pico:

import machine

Você também vai precisar da biblioteca utime:

import utime
Além disso, você precisará de uma nova biblioteca: urandom, que lida com a criação de
números aleatórios - uma parte essencial para tornar um jogo divertido, e usada neste jogo
para evitar que um jogador que o tenha jogado antes simplesmente conte um número fixo de
segundos após clicar no botão Executar.
Em seguida, defina uma variável pressionada como False (mais sobre isso depois) e
configure os dois pinos que você está usando: GP15 para o LED e GP14 para o botão
momentâneo.

pressed = False
led = machine.Pin(15, machine.Pin.OUT)
button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

Nos capítulos anteriores, você lidou com botões no programa principal ou em um thread
separado. Desta vez, porém, você usará uma abordagem diferente e mais flexível:
solicitações de interrupção ou IRQs. O nome parece complexo, mas é muito simples: imagine
que você está lendo um livro, página por página, e alguém vem até você e faz uma pergunta.
Essa pessoa está executando um pedido de interrupção: pedindo que você pare o que está
fazendo, responda à pergunta e, em seguida, permitindo que você volte a ler seu livro.
Uma solicitação de interrupção MicroPython funciona exatamente da mesma maneira: ela
permite que algo, neste caso, o pressionamento de um botão, interrompa o programa
principal. De certa forma, é semelhante a um thread, pois há um pedaço de código que fica
fora do programa principal. Ao contrário de um thread, porém, o código não está em
execução constante: ele só é executado quando a interrupção é acionada.
Comece definindo um handler para a interrupção. Isso, conhecido como função callback, é o
código executado quando a interrupção é acionada. Como acontece com qualquer tipo de
código aninhado, o código do handler - tudo após a primeira linha - precisa ser identado por
quatro espaços para cada nível; Thonny fará isso por você automaticamente.

def button_handler(pin):
global pressed
if not pressed:
pressed=True
print(pin)
Este handler começa verificando o status da variável pressed e, em seguida, configurando-a
como True para ignorar outros pressionamentos de botão (encerrando assim o jogo). Em
seguida, ele imprime informações sobre o pino responsável por disparar a interrupção. Isso
não é muito importante no momento - você só tem um pino configurado como uma entrada,
GP14, então a interrupção sempre virá desse pino - mas permite que você teste sua
interrupção facilmente.
Continue seu programa abaixo, lembrando-se de excluir a indentação que Thonny criou
automaticamente - o código a seguir não faz parte do handler:

led.value(1)
utime.sleep(urandom.uniform(5, 10))
led.value(0)

Este código será imediatamente familiar para você: a primeira linha liga o LED, conectado ao
pino GP15; a próxima linha pausa o programa; a última linha desliga o LED novamente - o
sinal do jogador para apertar o botão. Em vez de usar um atraso fixo, no entanto, ele usa a
biblioteca urandom para pausar o programa por entre cinco e dez segundos - a parte
'uniforme' referindo-se a uma distribuição uniforme entre esses dois números.
No momento, porém, não há nada observando o botão sendo pressionado. Você precisa
configurar a interrupção para isso, digitando a seguinte linha na parte inferior do seu
programa:

button.irq(trigger=machine.Pin.IRQ_RISING, handler=button_handler)

Configurar uma interrupção requer duas coisas: um trigger e um handler. O trigger diz a sua
Pico o que ela deve procurar como um sinal válido para interromper o que está fazendo; o
handler, que você definiu anteriormente em seu programa, é o código executado após o
disparo da interrupção. Neste programa, seu trigger é IRQ_RISING: isso significa que a
interrupção é disparada quando o valor do pino vai do nível baixo para alto, seu estado padrão
graças ao resistor pull-down embutido, para alto, quando o botão conectado a 3V3 é
pressionado. Um acionador de IRQ_FALLING faria o oposto: acionaria a interrupção quando
o pino vai do nível alto para baixo. No caso do seu circuito, IRQ_RISING irá disparar assim que
o botão for pressionado; IRQ_FALLING seria acionado apenas quando o botão fosse liberado.

O SOBE E DESCE DE IRQS


1 Se você precisa escrever um programa que dispara uma interrupção sempre
que um pino muda, sem se importar se está subindo ou descendo, você pode
combinar os dois triggers usando um símbolo de barra vertical (|):
button.irq (trigger = machine.Pin.IRQ_RISING | machine.Pin.IRQ_FALLING,
handler = button_handler)

Seu programa deve se parecer com este:

import machine
import utime
import urandom
pressed = False
led = machine.Pin(15, machine.Pin.OUT)
button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

def button_handler(pin):
global pressed
if not pressed:
pressed=True
print(pin)

led.value(1)
utime.sleep(urandom.uniform(5, 10))
led.value(0)
button.irq(trigger=machine.Pin.IRQ_RISING, handler=button_handler)

Clique no botão Executar e salve o programa em sua Pico como Reaction_Game.py. Você verá
o LED acender: esse é o seu sinal para se preparar com o dedo no botão. Quando o LED apagar,
pressione o botão o mais rápido possível.
Quando você pressiona o botão, ele aciona o código do handler que você escreveu
anteriormente. Olhe para a área do Shell: você verá que sua Pico imprimiu uma mensagem,
confirmando que a interrupção foi acionada pelo pino GP14. Você também verá outro detalhe:
mode = IN informa que o pino foi configurado como uma entrada. Essa mensagem não
contribui muito para o jogo: para isso, você precisa encontrar uma forma de cronometrar a
velocidade de reação do jogador. Comece excluindo a linha print (pin) de seu handler de
botão - você não precisa mais dela.
Vá até o final do seu programa e adicione uma nova linha, logo acima de onde você
configurou a interrupção

timer_start = utime.ticks_ms()

Isso cria uma nova variável chamada timer_start e a preenche com a saída da função
utime.ticks_ms(), que conta o número de milissegundos decorridos desde que a biblioteca
utime começou a contar. Isso fornece um ponto de referência: o tempo logo após o LED
apagar e pouco antes de o trigger de interrupção ficar pronto para ler o pressionamento do
botão.
Em seguida, volte para o handler de botão e adicione as duas linhas a seguir, lembrando que
elas precisarão ser indentadas por quatro espaços para que MicroPython saiba que fazem
parte do código aninhado:

timer_reaction = utime.ticks_diff(utime.ticks_ms(), timer_start)


print("Your reaction time was " + str(timer_reaction) +
" milliseconds!")
A primeira linha cria outra variável, desta vez para quando a interrupção foi realmente
acionada - em outras palavras, quando você pressionou o botão. Em vez de simplesmente
fazer uma leitura de utime.ticks_ms() como antes, ele usa utime.ticks_diff() - uma função
que fornece a diferença entre quando esta linha de código é disparada e o ponto de referência
mantido na variável timer_start.
A segunda linha imprime o resultado, mas usa concatenação para formatá-lo de maneira
adequada. O primeiro bit de texto, ou string, informa ao usuário o que significa o número a
seguir; o + significa que tudo o que vier a seguir deve ser impresso ao lado dessa string. Nesse
caso, o que vem a seguir é o conteúdo da variável timer_reaction - a diferença, em
milissegundos, entre quando você tomou o ponto de referência para o temporizador e
quando o botão foi pressionado e a interrupção disparada.
Finalmente, a última linha concatena mais uma string para que o usuário saiba que o
número é medido em milissegundos, e não em alguma outra unidade como segundos ou
microssegundos. Prestar atenção no espaçamento: você verá que há um espaço à direita
depois de 'era' e antes da citação final da primeira string, e um espaço à esquerda após a aspa
aberta da segunda string e antes da palavra 'milissegundos'. Sem eles, a string concatenada
imprimirá algo como " Your reaction time was323milliseconds".
Seu programa agora deve se parecer com isto:

import machine
import utime
import urandom
pressed = False
led = machine.Pin(15, machine.Pin.OUT)
button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

def button_handler(pin):
global pressed
if not pressed:
pressed=True
timer_reaction = utime.ticks_diff(utime.ticks_ms(), timer_start)
print("Your reaction time was " + str(timer_reaction) + " milliseconds!")

led.value(1)
utime.sleep(urandom.uniform(5, 10))
led.value(0)
timer_start = utime.ticks_ms()
button.irq(trigger=machine.Pin.IRQ_RISING, handler=button_handler)

DESAFIO: PERSONALIZAÇÃO
1
Você pode ajustar seu jogo para que o LED permaneça aceso por mais tempo?
Que tal ficar aceso por menos tempo? Você pode personalizar a mensagem
que é impressa na área do Shell e adicionar uma segunda mensagem
parabenizando o jogador?

Clique no botão Executar novamente, espere o LED apagar e pressione o botão. Desta vez, em
vez de um relatório sobre o pino que acionou a interrupção, você verá uma linha informando
a rapidez com que pressionou o botão - uma medida do seu tempo de reação. Clique no botão
Executar novamente e veja se você puder apertar o botão mais rapidamente desta vez - neste
jogo, você está tentando a pontuação mais baixa possível!
Figura 6-2: O circuito para um jogo de reação modo dois jogadores

Modo para dois jogadores


Os jogos para um jogador são divertidos, mas envolver os seus amigos é ainda melhor. Você
pode começar convidando-os para jogar o seu jogo e comparando suas pontuações altas - ou
melhor, baixas - para ver quem tem o tempo de reação mais rápido. Então, você pode
modificar seu jogo para deixá-lo frente a frente!
Comece adicionando um segundo botão ao seu circuito. Conecte-o da mesma forma que o
primeiro botão, com um terminal indo para o barramento de alimentação de sua protoboard,
mas com o outro indo para o pino GP16 - o pino transversal da placa de GP14 onde o LED está
conectado, no canto oposto de sua Pico. Certifique-se de que os dois botões estejam
espaçados o suficiente para que cada jogador tenha espaço para colocar o dedo no botão. Seu
circuito concluído deve ser semelhante à Figura 6-2.
Embora o segundo botão agora esteja conectado a Pico, ele ainda não sabe o que fazer com
ele. Volte para o seu programa em Thonny e descubra onde você configurou o primeiro botão.
Diretamente abaixo desta linha, adicione:

right_button = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_DOWN)

Você notará que o nome agora especifica com qual botão você está trabalhando: o botão
direito na protoboard. Para evitar confusão, edite a linha acima para que você deixe claro qual
era o único botão do quadro agora é o botão esquerdo:

left_button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

Você também precisará fazer a mesma alteração em outras partes do programa. Role até o
final do seu código e altere a linha que configura o trigger de interrupção para:

left_button.irq(trigger=machine.Pin.IRQ_RISING, handler=button_handler)

Adicione outra linha abaixo dela para configurar um gatilho de interrupção em seu novo
botão também:

right_button.irq(trigger=machine.Pin.IRQ_RISING, handler=button_handler)
Seu programa agora deve se parecer com este:
import machine
import utime
import urandom

pressed = False
led = machine.Pin(15, machine.Pin.OUT)
left_button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)
right_button = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_DOWN)

def button_handler(pin):
global pressed
if not pressed:
pressed=True
timer_reaction = utime.ticks_diff(utime.ticks_ms(), timer_start)
print("Your reaction time was " + str(timer_reaction) + " milliseconds!")

led.value(1)
utime.sleep(urandom.uniform(5, 10))
led.value(0)
timer_start = utime.ticks_ms()
right_button.irq(trigger=machine.Pin.IRQ_RISING, handler=button_handler)
left_button.irq(trigger=machine.Pin.IRQ_RISING, handler=button_handler)

INTERRUPÇÕES E HANDLERS
1 Cada interrupção que você cria precisa de um handler, mas um único handler
pode lidar com quantas interrupções você quiser. No caso deste programa,
você tem duas interrupções indo para o mesmo handler - o que significa que
qualquer interrupção acionada, eles executarão o mesmo código. Um
programa diferente pode ter dois handlers, permitindo que cada interrupção
execute um código diferente - tudo depende do que você precisa que seu
programa faça.

Clique no ícone Executar, espere o LED apagar e pressione o botão do lado esquerdo: você
verá que o jogo funciona da mesma forma que antes, imprimindo seu tempo de reação na
área do Shell. Clique no ícone Executar novamente, mas desta vez quando o LED apagar,
pressione o botão direito: o jogo funcionará da mesma forma, imprimindo seu tempo de
reação normalmente.
Para tornar o jogo um pouco mais emocionante, você pode solicitar que ele informe qual dos
dois jogadores foi o primeiro a apertar o botão. Volte ao início do seu programa, logo abaixo
de onde você configurou o LED e os dois botões, e adicione o seguinte:

fastest_button = None
Isso configura uma nova variável, fastest_button, e configura seu valor inicial para None -
porque nenhum botão foi pressionado ainda. Em seguida, vá até a parte inferior do handler
de botão e exclua as duas linhas que controlam o cronômetro e a impressão - em seguida,
substitua-as por:

global fastest_button
fastest_button = pin

Lembre-se de que essas linhas precisarão ser indentadas por quatro espaços para que o
MicroPython saiba que fazem parte da função. Essas duas linhas permitem que sua função
mude, ao invés de apenas ler, a variável fastest_button, e a configure para conter os detalhes
do pino que acionou a interrupção - os mesmos detalhes que seu jogo imprimiu na área do
Shell no início do capítulo, incluindo o número do pino de acionamento.
Agora vá direto ao final do seu programa e adicione estas duas novas linhas:

while fastest_button is None:


utime.sleep(1)
Isso cria um loop, mas não é um loop infinito: aqui, você disse ao MicroPython para executar
o código no loop apenas quando a variável fastest_button ainda for zero - o valor com o qual
foi inicializado no início do programa. Na verdade, isso pausa o thread principal do seu
programa até que o handler de interrupção mude o valor da variável. Se nenhum dos
jogadores pressionar um botão, o programa simplesmente fará uma pausa.
Finalmente, você precisa encontrar uma maneira de determinar qual jogador venceu - e de
parabenizá-lo. Digite o seguinte na parte inferior do programa, certificando-se de excluir a
indentação de quatro espaços que Thonny terá criado para você na primeira linha - essas
linhas não fazem parte do loop:

if fastest_button is left_button:
print("Left Player wins!")
elif fastest_button is right_button:
print("Right Player wins!")
A primeira linha configura uma condicional ‘if’ que procura ver se a variável fastest_button é
left_button - significando que o IRQ foi acionado pelo botão esquerdo. Se for assim, ele
imprimirá uma mensagem - com a linha abaixo recuada por quatro espaços para que
MicroPython saiba que deve executá-lo apenas se a condicional for verdadeira -
parabenizando o jogador esquerdo, cujo botão está conectado ao GP14.
A próxima linha, que não deve ser indentada, estende a condicional como um "elif" -
abreviação de "else if", uma forma de dizer "se a primeira condicional não for verdadeira,
verifique esta condicional a seguir". Desta vez, ele verifica se a variável fastest_button é
right_button - e, em caso afirmativo, imprime uma mensagem parabenizando o jogador da
direita, cujo botão está conectado ao GP16.
Seu programa concluído deve ser semelhante a este:
import machine
import utime
import urandom
pressed = False
led = machine.Pin(15, machine.Pin.OUT)
left_button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)
right_button = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_DOWN)
fastest_button = None

def button_handler(pin):
global pressed
if not pressed:
pressed=True
global fastest_button
fastest_button = pin

led.value(1)
utime.sleep(urandom.uniform(5, 10))
led.value(0)
timer_start = utime.ticks_ms()
left_button.irq(trigger=machine.Pin.IRQ_RISING, handler=button_handler)
right_button.irq(trigger=machine.Pin.IRQ_RISING, handler=button_handler)

while fastest_button is None:


utime.sleep(1)
if fastest_button is left_button:
print("Left Player wins!")
elif fastest_button is right_button:
print("Right Player wins!")

Pressione o botão Executar e espere que o LED apague - mas não pressione nenhum dos
interruptores de botão ainda. Você verá que a área do Shell permanece em branco e não traz
de volta o prompt >>>; isso ocorre porque o thread principal ainda está em execução, no loop
que você criou.
Agora pressione o botão esquerdo, conectado ao pino GP14. Você verá uma mensagem de
parabéns impressa para a Shell - sua mão esquerda foi a vencedora! Clique em Executar
novamente e tente empurrar o botão direito depois que o LED apaga: você verá outra
mensagem impressa, desta vez parabenizando sua mão direita. Clique em Executar
novamente, desta vez com um dedo em cada botão: empurre os dois ao mesmo tempo e veja
se sua mão direita ou esquerda é mais rápida!
Agora que você criou um jogo para dois jogadores, pode convidar seus amigos para jogar e
ver qual de vocês tem o tempo de reação mais rápido!

1
DESAFIO: TEMPOS
Você pode modificar as mensagens que são impressas? Você pode adicionar
um terceiro botão, para que três pessoas possam jogar ao mesmo tempo?
Existe um limite máximo para quantos botões você pode adicionar? Você
pode adicionar o cronômetro de volta ao seu programa, para que ele diga ao
jogador vencedor quão rápido foi o tempo de reação dele?
Capítulo 7
Alarme contra roubo
Use um sensor de movimento para detectar intrusos e soar o alarme
com uma luz piscando e sirene.

Outro uso real de microcontroladores é em tentando manter seus irmãos fora de seu
sistemas de alarme. Desde o despertador quarto, um alarme contra roubo
que levanta você pela manhã para certamente será útil.
disparar alarmes, alarmes contra roubo e Para este projeto, você precisará da sua
até mesmo os alarmes que soam quando Pico; uma protoboard; um LED de qualquer
há um problema em uma usina nuclear, os cor; um resistor de 330 Ω; um buzzer ativo;
microcontroladores ajudam a nos manter um ou mais sensores infravermelhos
seguros. passivos (PIR) HC-SR501; e uma seleção de
Neste capítulo, você vai construir seu jumpers macho-macho (M-M) e
próprio alarme contra roubo, que funciona macho-fêmea (M-F). Você também
exatamente da mesma maneira que uma precisará de um cabo micro USB para
versão comercial: um sensor de conectar sua Pico à Raspberry Pi ou outro
movimento especial vigia quem entra na computador executando o Thonny
sala quando não deveria estar e pisca uma MicroPython IDE.
luz enquanto soar uma sirene para alertar
as pessoas sobre a invasão. Esteja você
protegendo um cofre de banco ou apenas
O sensor HC-SR501 PIR
Nos capítulos anteriores, você trabalhou de quebra de vidro que podem dizer quando
com componentes de entrada simples na uma janela foi quebrada, sensores
forma de interruptores de botão. Desta vez, magnéticos que monitoram se uma porta
você usará uma entrada especializada está aberta ou fechada, sensores acústicos
conhecida como sensor infravermelho que podem detectar os passos de um ladrão
passivo ou PIR. Existem centenas de e sensores de vibração para dizer se uma
sensores PIR diferentes disponíveis; o fechadura está sendo aberta. Um sensor
HC-SR501 tem baixo custo, alto PIR simples, porém, costuma ser suficiente
desempenho e funciona perfeitamente com para uma área de baixa segurança - pense
a sua Pico. em uma sala de recepção, em vez de um
cofre de banco.
Se você escolheu um modelo diferente de
sensor, verifique sua documentação para Pegue seu sensor HC-SR501 agora e dê uma
verificar quais pinos são; também se olhada nele. A primeira coisa a notar é que
certifique de que ele opera em um nível ele tem uma placa de circuito própria, muito
lógico 3V3, assim como sua Pico - se você parecida com a sua Pico - só que menor.
conectar um sensor que usa uma tensão Além do sensor e da lente, existem vários
mais alta, como um sensor de 12 V, ele outros componentes: um pequeno circuito
danificará sua Pico irremediavelmente. integrado preto (CI) que aciona o sensor,
Alguns sensores podem precisar de uma alguns capacitores e minúsculos resistores
pequena chave ou mudança de jumper para SMD. Você também pode ver alguns
mover entre os níveis lógicos de tensão; pequenos potenciômetros que podem ser
isso será observado na documentação. girados com uma chave de fenda para
ajustar a sensibilidade do sensor e quanto
Um sensor infravermelho passivo é
tempo ele permanece ativo quando
projetado para detectar movimento, em
acionado; deixe-os como estão por
particular o movimento de pessoas e outros
enquanto.
seres vivos. Funciona um pouco como uma
câmera, mas em vez de capturar a luz Você também verá três pinos machos,
visível, procura o calor emitido por um exatamente como os pinos na parte inferior
corpo vivo na forma de radiação da sua Pico. No entanto, você não pode
infravermelha. É conhecido como um colocá-los diretamente na protoboard, pois
sensor infravermelho passivo, em vez de os componentes da placa atrapalharão. Em
ativo, porque, assim como um sensor de vez disso, pegue três cabos jumper
câmera, ele não envia nenhum sinal macho-fêmea (M-F) e insira as
infravermelho próprio. extremidades fêmeas nos pinos do
HC-SR501.
O sensor real está enterrado sob uma lente
de plástico, normalmente em forma de Em seguida, pegue as pontas masculinas e
meia bola. A lente não é tecnicamente conecte-as à protoboard e a sua Pico. Você
necessária para o sensor funcionar, mas precisará verificar a documentação do seu
serve para fornecer um campo de visão sensor ao conectá-lo à Pico: muitas
mais amplo (field of vision - FOV); sem a empresas diferentes fazem sensores
lente, o sensor PIR só seria capaz de ver o HC-SR501 e nem sempre usam os mesmos
movimento em um ângulo muito estreito pinos para os mesmos fins. Para o sensor
diretamente na frente do sensor. A lente ilustrado na Figura 7-1 (no verso), os pinos
serve para puxar o infravermelho de um são configurados de forma que o pino de
ângulo muito mais amplo, o que significa aterramento (GND) fique na parte inferior, o
que um único sensor PIR é capaz de pino de sinal ou trigger no meio e o pino de
monitorar o movimento na maior parte da alimentação à direita; seu sensor pode
sala. precisar que os fios sejam colocados em
uma ordem diferente!
Em sistemas comerciais de alarme contra
roubo, um sensor PIR é apenas um dos
sensores usados; outros incluem sensores
Figura 7-1: Conectando um sensor HC-SR501 PIR a sua Pico

Comece com o GND: ele precisa ser conectado a qualquer um dos pinos de aterramento da
sua Pico. Na Figura 7-1, ele é conectado ao primeiro pino de GND na linha 3. Em seguida,
conecte o fio de sinal: ele deve ser conectado ao pino GP28 da sua Pico.
Finalmente, você precisa conectar o cabo de alimentação. Porém, não conecte isso ao pino
3V3 da sua Pico: o HC-SR501 é um dispositivo de 5V, o que significa que ele precisa de 5V de
alimentação para funcionar. Se você conectar o sensor ao pino 3V3 da sua Pico, ele não
funcionará - o pino simplesmente não fornece energia suficiente.
Para dar ao seu sensor a tensão de 5V de que necessita, ligue-o ao pino superior direito da sua
Pico - VBUS. Este pino é conectado à porta micro USB em sua Pico e se conecta à linha de
alimentação 5V USB antes de ser convertido para 3,3V para executar o microprocessador da
Pico. Todos os três pinos HC-SR501 agora devem ser conectados à sua Pico: GND, sinal e
alimentação.

Programando seu alarme


Você precisará programar sua Pico para reconhecer o sensor. Com folga, isso não é mais
difícil do que ler um botão - na verdade, você pode usar o mesmo código. Comece criando um
novo programa e importando a biblioteca machine para que você possa configurar o pino
GPIO da sua Pico, junto com a biblioteca utime que usaremos para definir delays no
programa:

import machine
import utime

Em seguida, configure o pino ao qual você conectou seu sensor HC-SR501, GP28:

sensor_pir = machine.Pin(28, machine.Pin.IN, machine.Pin.PULL_DOWN)

Como o jogo de reação que você fez, as entradas de um alarme contra roubo devem atuar
como uma interrupção - pare o programa fazendo o que quer que esteja fazendo e reaja
sempre que o sensor for acionado. Como antes, comece definindo uma função callback para
lidar com a interrupção:

def pir_handler(pin):
utime.sleep_ms(100)
if pin.value():
print("ALARM! Motion detected!")
Certifique-se de ter a correta indentação. As linhas utime.sleep_ms(100) e if pin.value(): são
usadas para evitar que o alarme seja disparado por qualquer oscilação no sinal do sensor PIR.
O processo de suavizar as flutuações, como fizemos aqui, é conhecido como debouncing.
Finalmente, configure a própria interrupção. Lembre-se de que isso não faz parte da função
de handler, então você precisará excluir todos os espaços extras que Thonny inserir
automaticamente:

sensor_pir.irq(trigger=machine.Pin.IRQ_RISING, handler=pir_handler)

Isso é o suficiente por enquanto: lembre-se de que as interrupções permanecem ativas


independentemente do que o resto do programa está fazendo, então não há necessidade de
adicionar um loop infinito para manter seu programa em execução. Clique no ícone Executar
e salve o programa em sua Pico como Burglar_Alarm.py.

ESTREITANDO O FOV
1 Os sensores PIR são projetados para cobrir o maior campo de visão (FOV)
possível, para que os ladrões não possam simplesmente escapar pelas
bordas de uma sala. Se você descobrir que seu sensor está disparando
quando você não quer, há uma maneira simples de consertar: pegue o tubo
interno de papelão de um rolo de papel higiênico e coloque o sensor na parte
inferior. O tubo funcionará como antolhos de cavalo, impedindo o sensor de
ver as coisas de lado para que possa se concentrar nas coisas mais adiante.

Acene com a mão sobre o sensor PIR: uma mensagem será impressa na área do Shell
confirmando que o sensor viu você. Se você continuar acenando com a mão, a mensagem
continuará sendo impressa - mas com um atraso entre cada vez que for impressa.
Esse atraso não faz parte do seu programa, mas embutido no próprio hardware HC-SR501: o
sensor envia o sinal de gatilho para o pino GPIO da sua Pico quando o movimento é detectado
e mantém esse sinal ligado por vários segundos antes de deixá-lo cair. Na maioria dos
sensores HC-SR501, esse atraso é ajustado usando um dos pequenos potenciômetros: você
pode inserir uma chave de fenda e girá-la para um lado para diminuir o atraso e para o outro
para aumentá-lo. Verifique a documentação do seu sensor para saber qual potenciômetro
controla o atraso.
Como o trigger de interrupção está definido para disparar na borda ascendente do sinal, a
mensagem é impressa assim que o sensor PIR envia seu sinal de 1 ou 'alto'. Mesmo se mais
movimento for detectado, a interrupção não disparará novamente até que o atraso integrado
tenha passado e o sinal tenha retornado a 0, ou 'baixo'.
Imprimir uma mensagem para o Shell é o suficiente para provar que seu sensor está
funcionando, mas não é muito um alarme. Alarmes contra roubo reais têm luzes e sirenes
que alertam a todos ao redor que algo está errado - e você pode adicionar o mesmo ao seu
próprio alarme.
Comece ligando um LED, de qualquer cor, a sua Pico conforme mostrado na Figura 7-2. O
terminal mais longo, o ânodo, precisa se conectar ao pino GP15 por meio de um resistor de
330 Ω - lembre-se de que, sem esse resistor no lugar para limitar a quantidade de corrente que
passa pelo LED, você pode danificar o LED e a Pico. O terminal mais curto, o cátodo, precisa
ser conectado a um dos pinos de GND da Pico - use o trilho de GND da protoboard e dois
jumpers macho-macho (M-M) para isso.
Figura 7-2: Adicionando um LED ao alarme contra roubo

Para configurar a saída de LED, adicione uma nova linha logo abaixo de onde você configurou
o pino do sensor PIR:

led = machine.Pin(15, machine.Pin.OUT)


Isso é o suficiente para configurar o LED, mas você precisará acendê-lo. Adicione a seguinte
nova linha à sua função de handler de interrupção, sob a linha print (deve ser indentada por
oito espaços para corresponder a isso):

for i in range(50):
Você acabou de criar um loop finito, que será executado 50 vezes. A letra i representa um
incremento, um valor que sobe cada vez que o loop é executado, e que é preenchido pela
instrução range (50).
Dê ao seu novo loop algo para fazer, lembrando que essas linhas abaixo precisarão ser
recuadas por mais quatro espaços (doze ao todo), pois elas formam parte do loop que você
acabou de abrir e a função de handler de interrupção:

led.toggle()
utime.sleep_ms(100)
A primeira dessas linhas é um recurso da biblioteca machine que permite simplesmente
alterar o valor de um pino de saída, em vez de definir um valor - então, se o pino for
atualmente 1, ou alto, alterná-lo irá defini-lo como 0 ou baixo; se o pino já for 0 ou baixo,
alterná-lo o definirá como alto. Essas duas linhas de código acendem e apagam o LED com
um delay de 100 milissegundos - um décimo de segundo. O resultado é semelhante ao
programa de LED piscando que você escreveu no Capítulo 4.

VALOR VS TOGGLE
1 Há momentos em que usar a função toggle sobre a definição de um valor faz
sentido, como ao piscar um LED - mas certifique-se de que você pensou no
que está tentando alcançar primeiro. Se o seu projeto depende de uma saída
definitivamente ser ligada ou desligada em um determinado momento -
como uma luz de aviso ou uma bomba que drena um tanque de água - sempre
defina explicitamente o valor, em vez de depender de um toggle.
Seu programa agora ficará assim:

import machine
import utime

sensor_pir = machine.Pin(28, machine.Pin.IN, machine.Pin.PULL_DOWN)


led = machine.Pin(15, machine.Pin.OUT)

def pir_handler(pin):
utime.sleep_ms(100)
if pin.value():
print("ALARM! Motion detected!")
for i in range(50):
led.toggle()
utime.sleep_ms(100)

sensor_pir.irq(trigger=machine.Pin.IRQ_RISING, handler=pir_handler)

Clique no botão Executar e acene com a mão sobre o sensor PIR novamente: você verá a
mensagem de alarme usual impressa na área do Shell e o LED começará a piscar
rapidamente como um alerta visual. Aguarde até que o LED pare de piscar e, em seguida,
balance a mão sobre o sensor PIR novamente: a mensagem será impressa novamente e o
LED repetirá seu padrão de piscar.
Para tornar o seu alarme contra roubo ainda mais de um impedimento, você pode fazê-lo
piscar lentamente, mesmo quando nenhum movimento for detectado - alertando os
possíveis intrusos de que seu quarto está sob observação. Vá até o final do seu programa e
adicione as seguintes linhas:

while True:
led.toggle()
utime.sleep(5)
Clique em Executar novamente, mas deixe o sensor PIR sozinho: você verá que o LED está
acendendo por cinco segundos e depois apagando por cinco segundos. Este padrão
continuará enquanto o sensor não for acionado; acene com a mão sobre o sensor PIR e você
verá o LED piscando rapidamente novamente, antes de voltar ao padrão de flash lento.
Isso destaca uma diferença importante entre threads e interrupções: se você tivesse escrito
este programa usando threads, seu programa ainda estaria tentando alternar o LED ligado e
desligado em um intervalo de cinco segundos, mesmo enquanto seu handler PIR está
ligando e desligando em um intervalo de 100 milissegundos. Isso ocorre porque os threads
são executados simultaneamente, lado a lado.
Com interrupções, o programa principal é pausado enquanto o handler de interrupções é
executado - então o código de toggle de cinco segundos que você escreveu para até que o
handler termine de piscar o LED e, em seguida, continue de onde parou. Se você precisa que
seu código pause ou continue em execução é a chave para saber se você precisa usar threads
ou interrupções, e vai depender exatamente do que seu projeto está tentando fazer.
Entradas e saídas: juntando tudo
Seu alarme contra roubo agora tem um LED piscando para alertar os intrusos e uma maneira
de ver quando ele foi disparado sem ter que observar a área do Shell em busca de uma
mensagem. Agora tudo o que precisa é uma sirene - ou, pelo menos, um buzzer, que emita
som sem ensurdecer seus vizinhos.
Dependendo do modelo que você comprou, seu buzzer terá pinos saindo da parte inferior ou
fios curtos presos nas laterais. Se o buzzer tiver pinos, insira-os em sua protoboard de forma
que o buzzer ocupe a divisão central; se houver fios, coloque-os na protoboard e
simplesmente coloque o buzzer na protoboard.
Se o seu buzzer tiver fios longos o suficiente, você poderá conectá-los à protoboard ao lado
dos pinos GPIO da sua Pico; caso contrário, use fios de jumper macho-macho (M-M) para
conectar o buzzer conforme mostrado na Figura 7-3. O fio vermelho, ou o pino positivo
marcado com um símbolo +, deve ser conectado ao pino GP14 na parte inferior esquerda da
sua Pico, logo acima do pino que você está usando para o LED. O fio preto, ou o pino negativo
marcado com um símbolo de menos (-) ou as letras GND, precisa ser conectado ao trilho de
aterramento de sua protoboard.
Se seu buzzer tiver três pinos, conecte o terminal marcada com um símbolo de menos (-) ou
as letras GND ao trilho de GND de sua protoboard, o pino marcado com S ou SIGNAL (sinal)
para pino GP14 em sua Pico, e o terminal restante - que geralmente é o terminal do meio -
para o pino 3V3 em sua Pico.
Se você executar seu programa agora, nada mudará: a campainha soará apenas quando
receber energia dos pinos GPIO da sua Pico. Volte ao início do seu programa e configure o
buzzer logo abaixo de onde você configurou o LED:

Figura 7-3: Conectando um buzzer de dois fios

buzzer = machine.Pin(14, machine.Pin.OUT)


Em seguida, mude seu handler de interrupção para adicionar uma nova linha abaixo de
led.toggle() - lembrando de indentar 12 espaços para corresponder:

buzzer.toggle()
Seu programa agora ficará assim:

import machine
import utime
sensor_pir = machine.Pin(28, machine.Pin.IN, machine.Pin.PULL_DOWN)
led = machine.Pin(15, machine.Pin.OUT)
buzzer = machine.Pin(14, machine.Pin.OUT)

def pir_handler(pin):
utime.sleep_ms(100)
if pin.value():
print("ALARM! Motion detected!")
for i in range(50):
led.toggle()
buzzer.toggle()
utime.sleep_ms(100)

sensor_pir.irq(trigger=machine.Pin.IRQ_RISING, handler=pir_handler)

while True:
led.toggle()
utime.sleep(5)

Clique em Executar e acene com a mão sobre o sensor PIR: o LED piscará rapidamente, como
antes, mas desta vez será acompanhado por um sinal sonoro da campainha. Parabéns: isso
deve ser mais do que suficiente para assustar um intruso para longe de saquear seu
esconderijo secreto de doces!
Se você achar que seu buzzer está emitindo cliques, em vez de emitir bipes, então você está
usando um buzzer passivo em vez de ativo. Um buzzer ativo possui um componente interno
conhecido como oscilador, que move rapidamente a placa de metal para fazer o som de
zumbido; um buzzer passivo não possui esse componente, o que significa que você precisa
substituí-lo por algum código próprio.

AVISO
1 Ao usar um buzzer ativo, ele continuará a soar enquanto o pino ao qual está
conectado estiver alto - em outras palavras, tem um valor de 1. Como seu loop
é executado um número par de vezes, ele termina com o buzzer desligado;
mude o loop para executar um número ímpar de vezes, no entanto, e ele
terminará com o buzzer ainda tocando - e pressionar o botão Parar não o
desligará. Se isso acontecer, simplesmente desconecte o cabo micro USB da
Pico e conecte-o novamente - então mude seu programa para que isso não
aconteça novamente!

Se você estiver usando um buzzer passivo, tente esta versão do programa - ele ativa e
desativa o pino conectado ao buzzer muito rapidamente, imitando o efeito do oscilador em
um buzzer ativo:
import machine
import utime

sensor_pir = machine.Pin(28, machine.Pin.IN, machine.Pin.PULL_DOWN)


led = machine.Pin(15, machine.Pin.OUT)
buzzer = machine.Pin(14, machine.Pin.OUT)

def pir_handler(pin):
utime.sleep_ms(100)
if pin.value():
print("ALARM! Motion detected!")
for i in range(50):
led.toggle()
for j in range(25):
buzzer.toggle()
utime.sleep_ms(3)

sensor_pir.irq(trigger=machine.Pin.IRQ_RISING, handler=pir_handler)

while True:
led.toggle()
utime.sleep(5)

Observe que o novo loop, que controla o buzzer, não usa a letra i para rastrear o incremento;
isso é porque você já está usando aquela letra para o loop externo - então ele usa a letra j. O
curto atraso de apenas três milissegundos, entretanto, significa que o pino conectado ao
buzzer liga e desliga rápido o suficiente para fazer um zumbido.
Tente alterar o atraso para quatro milissegundos em vez de três e você encontrará o som do
buzzer em um tom mais baixo. Alterar o atraso muda a frequência de oscilação do buzzer: um
delay mais longo significa que ele oscila em uma frequência mais baixa, tornando-o um som
de tom mais baixo; um delay mais curto o faz oscilar em uma frequência mais alta,
tornando-o um som mais agudo.

Prolongando seu alarme


Os alarmes contra roubo raramente cobrem uma única sala: em vez disso, eles usam uma
rede de vários sensores para monitorar várias salas a partir de um único sistema de alarme.
Seu alarme contra roubo baseado na Pico pode funcionar exatamente da mesma maneira,
adicionando vários sensores para cobrir várias áreas ao mesmo tempo.
Você precisará de um sensor HC-SR501 para cada área que deseja cobrir; neste exemplo, você
adicionará mais um sensor para um total de dois, mas pode continuar e adicionar quantos
sensores precisar.
Ambos os seus sensores precisam de 5V de alimentação para funcionar, mas você já usou o
pino VUSB em seu Pico para o primeiro sensor. Se sua protoboard tiver espaço suficiente,
você pode colocar um cabo jumper macho-fêmea (M-F) próximo ao que está conectado ao
primeiro sensor e usá-lo no segundo; uma abordagem mais limpa, entretanto, é usar o
barramento de alimentação em sua protoboard.
Desconecte o cabo de alimentação do primeiro sensor da extremidade da protoboard e
insira-o no barramento de alimentação de cor vermelha ou marcado com um símbolo de
mais (+). Pegue um cabo jumper macho-macho (M-M) e conecte o mesmo barramento de
alimentação ao pino VUSB da sua Pico. Em seguida, pegue um cabo jumper macho-fêmea
(M-F) e conecte o barramento de alimentação ao pino de entrada de alimentação do segundo
sensor PIR.
Finalmente, conecte o pino de GND e o pino de sinal de seu segundo sensor PIR como antes
- mas desta vez conecte o pino de sinal ao pino GP22 em sua Pico, conforme mostrado na
Figura 7-4 (verso). Seu circuito agora tem dois sensores, cada um conectado a um pino
separado.
Configure seu programa para ler o segundo sensor e também o primeiro é tão simples quanto
adicionar duas novas linhas. Comece configurando o segundo sensor, adicionando uma nova
linha abaixo de onde você configurou o primeiro sensor:

sensor_pir2 = machine.Pin(22, machine.Pin.IN, machine.Pin.PULL_DOWN)

Em seguida, crie uma nova interrupção, novamente abaixo de sua primeira interrupção:

sensor_pir2.irq(trigger=machine.Pin.IRQ_RISING, handler=pir_handler)

Lembre-se de que você pode ter várias interrupções com um único handler, portanto, não há
necessidade de alterar essa parte do seu programa.

Figura 7-4: Adicionando um segundo sensor PIR para cobrir outra sala

Clique em Executar e acene com a mão sobre o primeiro sensor PIR: você verá a mensagem
de alerta, o flash do LED e o som do buzzerr normalmente. Espere até que terminem e, em
seguida, acene com a mão sobre o segundo sensor PIR: você verá o alarme contra roubo
responder exatamente da mesma maneira.
Para tornar seu alarme realmente inteligente, você pode personalizar a mensagem
dependendo de qual pino foi responsável pela interrupção - e funciona exatamente da
mesma maneira que no jogo de reação para dois jogadores que você escreveu anteriormente.
Volte para seu handler de interrupção e modifique-o para que se pareça com:

def pir_handler(pin):
utime.sleep_ms(100)
if pin.value():
if pin is sensor_pir:
print("ALARM! Motion detected in bedroom!")
elif pin is sensor_pir2:
print("ALARM! Motion detected in living room!")
for i in range(50):
led.toggle()
buzzer.toggle()
utime.sleep_ms(100)

Assim como no projeto do jogo de reação no Capítulo 6, este código usa o fato de que uma
interrupção relata qual pino foi disparada por: se o sensor PIR conectado ao pino GP28 for o
responsável, ele imprimirá uma mensagem; se for o sensor PIR conectado ao pino GP22, ele
imprimirá outro.
Seu programa concluído ficará assim:

import machine
import utime

sensor_pir = machine.Pin(28, machine.Pin.IN, machine.Pin.PULL_DOWN)


sensor_pir2 = machine.Pin(22, machine.Pin.IN, machine.Pin.PULL_DOWN)
led = machine.Pin(15, machine.Pin.OUT)
buzzer = machine.Pin(14, machine.Pin.OUT)

def pir_handler(pin):
utime.sleep_ms(100)
if pin.value():
if pin is sensor_pir:
print("ALARM! Motion detected in bedroom!")
elif pin is sensor_pir2:
print("ALARM! Motion detected in living room!")
for i in range(50):
led.toggle()
buzzer.toggle()
utime.sleep_ms(100)
sensor_pir.irq(trigger=machine.Pin.IRQ_RISING, handler=pir_handler)
sensor_pir2.irq(trigger=machine.Pin.IRQ_RISING, handler=pir_handler)

while True:
led.toggle()
utime.sleep(5)

Se você estiver usando um buzzer passivo, em vez de ativo, lembre-se de que você precisará
alterar o buzzer para um loop para que ele apite. Clique em Executar e acene com a mão sobre
um sensor, depois sobre o outro, para ver as duas mensagens impressas na área do Shell.
Parabéns: agora você sabe como construir um alarme anti-roubo modular capaz de cobrir
quantas áreas você precisar!

1
DESAFIO: PERSONALIZAÇÃO
Você pode estender o alarme contra roubo com outro sensor PIR? Que tal
adicionar outro LED ou outro buzzer? Você pode alterar as mensagens que
são impressas para corresponder às áreas que você está cobrindo com cada
sensor? Você pode fazer o buzzer tocar por mais ou menos tempo? Você
consegue pensar em algum outro sensor, além de um sensor PIR, que possa
funcionar bem em um alarme contra roubo?
Capítulo 8
Medidor de
temperatura
Use o ADC integrado da Raspberry Pi Pico para converter entradas
analógicas e ler seu sensor de temperatura embutido

Nos capítulos anteriores, você usou as meio de uma peça de hardware conhecida
entradas digitais em sua Raspberry Pi como conversor analógico-digital (ADC).
Pico. Uma entrada digital está ligada ou Neste capítulo, você aprenderá como usar
desligada, um estado binário. Quando um o ADC em sua Pico - e como tocar em seu
botão de pressão é pressionado, ele muda sensor de temperatura interno para
um pino de baixo, desligado, para alto, construir um dispositivo de medição de
ligado; quando um sensor infravermelho calor de registro de dados. Você também
passivo detecta movimento, ele faz o aprenderá uma técnica para criar uma
mesmo. saída analógica. Para isso, você precisará
Porém, sua Pico pode aceitar outro tipo de da sua Pico; um LED de qualquer cor e
sinal de entrada: entrada analógica. resistor de 330 Ω; um potenciômetro de 10
Enquanto o digital está sempre ligado ou kΩ; e uma seleção de cabos jumpers
desligado, um sinal analógico pode ser macho-macho (M-M). Você também
qualquer coisa de completamente precisará de um cabo micro USB para
desligado a completamente ligado - um conectar sua Pico à Raspberry Pi ou outro
intervalo de valores possíveis. As entradas computador executando o Thonny
analógicas são usadas para tudo, desde MicroPython IDE.
controles de volume a sensores de gás,
umidade e temperatura - e funcionam por
O conversor analógico-digital
O microcontrolador RP2040 da Raspberry Pi Pico é um dispositivo digital, como todos os
microcontroladores convencionais: ele é formado por milhares de transistores, pequenos
dispositivos parecidos com interruptores que estão ligados ou desligados. Como resultado,
não há como sua Pico entender verdadeiramente um sinal analógico - um que pode ser
qualquer coisa em um espectro entre totalmente desligado e totalmente ligado - sem
depender de uma peça adicional de hardware: o conversor analógico-digital (ADC )
Como o nome sugere, um conversor analógico-digital pega um sinal analógico e muda para
um digital. Você não verá o ADC em sua Pico, não importa o quão perto você olhe: ele é
integrado ao próprio RP2040. Muitos microcontroladores têm seus próprios ADCs, assim
como RP2040, e aqueles que não podem usar um ADC externo conectado a uma ou mais de
suas entradas digitais.
Um ADC tem dois recursos principais: sua resolução, medida em bits digitais, e seus canais,
ou quantos sinais analógicos ele pode aceitar e converter de uma vez. O ADC em sua Pico
tem uma resolução de 12 bits, o que significa que ele pode transformar um sinal analógico em
um sinal digital como um número que varia de 0 a 4095 - embora isso seja tratado em
MicroPython transformado para um número de 16 bits que varia de 0 a 65.535, para que se
comporte da mesma forma que o ADC em outros microcontroladores MicroPython. Ele tem
três canais trazidos para os pinos GPIO: GP26, GP27 e GP28, que também são conhecidos
como GP26_ADC0, GP27_ADC1 e GP28_ADC2 para canais analógicos 0, 1 e 2. Há também um
quarto canal ADC, que está conectado ao um sensor de temperatura integrado ao RP2040;
você descobrirá mais sobre isso posteriormente no capítulo.

1
POR QUE 65.535?
O número ’65.535 ’parece estranho à primeira vista - por que isso, e por que
não simplesmente 0-100? A resposta está ligada ao fato de sua Pico trabalhar
em um sistema numérico binário, onde os únicos valores possíveis para um
dígito são 0 ou 1. Um número binário de 16 bits é composto de 16 dígitos, e o
valor máximo possível é 16 unidades: 1111111111111111. Se você converter isso
de volta em números decimais, o sistema de contagem de 0-9 que os
humanos usam, você obtém 65.535.

Lendo um potenciômetro
Cada pino conectado ao conversor analógico-digital da sua Pico também pode ser usado
como uma entrada ou saída digital simples; para usá-lo como uma entrada analógica, você
precisará de um sinal analógico - e você pode facilmente fazer um com um potenciômetro.
Existem vários tipos de potenciômetro disponíveis: alguns, como os do sensor infravermelho
passivo HC-SR501 que você usou no Capítulo 7, são projetados para serem ajustados com
uma chave de fenda; outros, geralmente usados para controles de volume e outras entradas,
têm botões ou controles deslizantes. O tipo mais comum tem um botão pequeno, geralmente
de plástico, saindo da parte superior ou frontal: isso é conhecido como potenciômetro
rotativo.
Pegue seu potenciômetro e vire-o: você verá que ele tem três pinos que se encaixam na
protoboard. Dependendo de como você conecta esses pinos, o potenciômetro funciona de
duas maneiras diferentes. Comece inserindo o potenciômetro na protoboard, tomando
cuidado para não entortar os pinos. Conecte o pino do meio ao pino GP26_ADC0 em sua Pico
usando um cabo jumper macho-macho (M-M), conforme mostrado na Figura 8-1 - se a sua
Pico for inserida na placa de ensaio no topo, ele estará na linha 10. Finalmente, pegue mais
dois cabos jumper e conecte um dos pinos externos do potenciômetro - não importa qual - ao
barramento de alimentação da sua protoboard e o barramento de alimentação ao pino 3V3 da
sua Pico.

Figura 8-1: Um potenciômetro conectado com dois pinos

Abra o Thonny IDE e comece um novo programa:

import machine
import utime

Como os pinos de entrada / saída digital de uso geral (GPIO), os pinos de entrada analógica
são controlados pela biblioteca machine - e, assim como os pinos digitais, eles precisam ser
configurados antes de serem usados. Continue seu programa:

potentiometer = machine.ADC(26)

sso configura o pino GP26_ADC0 como o primeiro canal, ADC0, no conversor


analógico-digital. Para ler a partir do pino, configure um loop:

while True:
print(potentiometer.read_u16())
utime.sleep(2)

Neste loop, ler o valor do pino e imprimi-lo ocorre em uma única linha: esta é uma alternativa
mais compacta para ler o valor em uma variável e depois imprimir a variável, mas só
funciona se você não quiser qualquer coisa com a leitura além de imprimi-la - que é
exatamente o que este programa precisa no momento.
Ler uma entrada analógica é quase idêntico a ler uma entrada digital, exceto por uma coisa:
ao ler uma entrada digital, você usa read(), mas esta entrada analógica é lida com read_u16().
A última parte, u16, simplesmente avisa que, em vez de receber um resultado binário 0 ou 1,
você receberá um inteiro sem sinal de 16 bits - um número inteiro entre 0 e 65.535.
Clique no ícone Executar e salve seu programa como potentiometer.py. Observe o Shell: você
verá seu programa imprimir um grande número, provavelmente mais de 60.000.
Experimente girar o potenciômetro totalmente em uma direção: dependendo da direção em
que você girou o botão e do terminal externa usada no circuito, o número aumentará ou
diminuirá. Vire para o outro lado: o valor mudará na direção oposta.
Não importa para que lado você o vire, no entanto, ele nunca chegará perto de 0. Isso porque,
com apenas dois terminais conectados, o potenciômetro está atuando como um
componente conhecido como resistor variável. Um resistor variável é um resistor com um
valor que você pode alterar - no caso de um potenciômetro de 10 kΩ, entre 0 Ω e 10.000 Ω.
Quanto maior a resistência, menor a tensão do pino 3V3 em sua entrada analógica - então o
número diminui. Quanto mais baixa a resistência, mais tensão atinge sua entrada analógica
- então o número aumenta.
Um potenciômetro funciona tendo uma fita condutiva dentro, conectada aos dois pinos
externos, e um limpador ou escova conectada ao pino interno (Figura 8-2). Conforme você
gira o botão, o limpador se move para mais perto de uma extremidade da faixa e se
distanciando da outra. Quanto mais longe o limpador chega da extremidade da tira que você
conectou ao pino 3V3 da sua Pico, maior a resistência; quanto mais perto fica, menor é a
resistência.

Alojamento

Elemento resistivo

Alavanca

3x terminais elétricos

Figura 8-2: Como funciona um potenciômetro

Resistores variáveis são componentes extremamente úteis, mas há uma desvantagem: você
notará não importa o quão longe você gire o botão em qualquer direção, você nunca pode
obter um valor de 0 - ou em qualquer lugar próximo a ele. Isso ocorre porque um resistor de
10 kΩ não é forte o suficiente para diminuir a saída do pino 3V3 para 0 V. Você poderia
procurar um potenciômetro maior com uma resistência máxima mais alta ou simplesmente
conectar seu potenciômetro existente como um circuito divisor de tensão.
Um potenciômetro como um divisor
de tensão
O pino não utilizado em seu potenciômetro não está lá para ser exibido: adicionar uma
conexão a esse pino em seu circuito muda completamente a forma como o potenciômetro
funciona. Clique no ícone Parar para interromper seu programa e pegue dois cabos jumper
macho-macho (M-M). Use um para conectar o pino não utilizado do seu potenciômetro ao
trilho de GND da protoboard, conforme mostrado na Figura 8-3. Pegue a outra e conecte o
trilho de GND a um pino GND em sua Pico.

Figura 8-3: Conectando o potenciômetro como um divisor de tensão

Clique no ícone Executar para reiniciar seu programa. Gire o botão do potenciômetro
novamente, totalmente para uma direção e depois totalmente para a outra. Observe os
valores que são impressos na área da Shell: ao contrário de antes, eles agora estão indo de
quase zero para quase um total de 65.535 - mas por quê?
Adicionar a conexão de GND à outra extremidade da faixa condutiva do potenciômetro criou
um divisor de tensão: enquanto antes o potenciômetro agia simplesmente como um resistor
entre o pino 3V3 e o pino de entrada analógica, ele agora está dividindo a tensão entre a saída
de 3,3 V pelo pino 3V3 e o 0 V do pino GND. Gire o botão totalmente em uma direção, você
obterá 100% de 3,3 V; vire totalmente para o outro lado, 0%.

ZERO É O NÚMERO MAIS DIFÍCIL


1 Se você não consegue fazer com que a entrada analógica do Pico leia
exatamente zero ou exatamente 65.535, não se preocupe - você não fez nada
de errado! Todos os componentes eletrônicos são construídos com uma
tolerância, o que significa que qualquer valor reivindicado não será preciso.
No caso do potenciômetro, provavelmente nunca atingirá exatamente 0 ou
100 por cento de sua entrada - mas você chegará muito perto!

O número que você vê impresso no Shell é uma representação decimal da saída bruta do
conversor analógico-digital - mas não é a maneira mais amigável de vê-lo, especialmente se
você esquecer que 65.535 significa "tensão total".
Porém, há uma maneira fácil de consertar isso: uma equação matemática simples. Volte para
o seu programa e adicione o seguinte acima do seu loop:

conversion_factor = 3.3 / (65535)

Isso configura uma forma matemática de converter o número que o conversor


analógico-digital fornece em uma aproximação justa da tensão real que ele representa. O
primeiro número é a tensão máxima possível que o pino pode esperar: 3,3V, do pino 3V3 da
sua Pico; o segundo número é o valor máximo que a leitura da entrada analógica pode ser,
65.535.
Tomados em conjunto, o fator de conversão é um número criado por ‘3,3 dividido por 65.535’
- a tensão máxima possível dividida pela faixa de valores que o conversor analógico-digital
reporta, que por sua vez é uma característica de sua resolução em bits.
Com seu fator de conversão configurado, você simplesmente precisa usá-lo em seu
programa. Volte para o seu loop e edite-o para ler:

while True:
voltage = potentiometer.read_u16() * conversion_factor
print(voltage)
utime.sleep(2)

A primeira linha dentro do loop faz uma leitura do potenciômetro por meio do pino de
entrada analógica e o multiplica - o símbolo * - pelo fator de conversão que você configurou
anteriormente no programa, armazenando o resultado como a tensão variável. Essa variável
é então impressa no Shell, no lugar da leitura bruta que você usou anteriormente.
Seu programa concluído ficará assim:

import machine
import utime

potentiometer = machine.ADC(26)

conversion_factor = 3.3 / (65535)

while True:
voltage = potentiometer.read_u16() * conversion_factor
print(voltage)
utime.sleep(2)
LINEAR VS LOG
1 Se você achar que girar o potenciômetro lentamente entre um limite e o
outro faz os números mudarem lentamente no início, em seguida, começar a
mudar mais rapidamente, ou o contrário, é quase certo que você está usando
um potenciômetro log ou logarítmico. Enquanto um potenciômetro linear
muda suavemente em toda a sua faixa, um potenciômetro logarítmico
começa a fazer pequenas mudanças, então rapidamente aumenta a
velocidade de mudança. Os potenciômetros logarítmicos são comumente
usados para controles de volume em amplificadores, enquanto os
potenciômetros lineares são mais comuns para dispositivos baseados em
microcontroladores como a Pico.

Clique no ícone Executar. Gire o potenciômetro totalmente em uma direção e depois na outra.
Observe os números sendo impressos na área do Shell: você verá que quando o
potenciômetro está totalmente em uma direção, os números ficam muito próximos de zero;
quando é totalmente ao contrário, eles chegam muito perto de 3,3. Esses números
representam a tensão real lida pelo pino - e conforme você gira o botão do potenciômetro,
você está dividindo a tensão suavemente entre o mínimo e o máximo, 0 V a 3,3 V.
Parabéns: agora você sabe como conectar um potenciômetro como resistor variável e divisor
de tensão, e como ler entradas analógicas tanto como valor bruto quanto como tensão!

Medindo temperaturas
O microcontrolador RP2040 da Raspberry Pi Pico tem um sensor de temperatura interno, que
é lido no quarto canal do conversor analógico para digital. Como o potenciômetro, a saída do
sensor é uma tensão variável: conforme a temperatura muda, a tensão também muda.
Inicie um novo programa e importe as bibliotecas machine e utime:

import machine
import utime

Configure o conversor analógico-digital novamente, mas desta vez, em vez de usar o número
de um pino, use o número do canal conectado ao sensor de temperatura:

sensor_temp = machine.ADC(4)

Você precisará de seu fator de conversão novamente, para alterar a leitura bruta do sensor
em um valor de tensão, então adicione que:

conversion_factor = 3.3 / (65535)

Em seguida, configure um loop para fazer leituras da entrada analógica, aplique o fator de
conversão e armazene-as em uma variável:

while True:
reading = sensor_temp.read_u16() * conversion_factor
Em vez de imprimir a leitura diretamente, no entanto, você precisa fazer uma segunda
conversão - para pegar a tensão informada pelo conversor analógico-digital e convertê-la em
graus Celsius:

temperature = 27 - (reading - 0.706)/0.001721

Esta é outra equação matemática e específica para o sensor de temperatura no RP2040. Os


valores são retirados de um documento técnico denominado datasheet (folha de dados) ou
data book (livro de dados): todos os componentes eletrônicos possuem um datasheet, que
normalmente está disponível a pedido do fabricante. Você pode ver a planilha de dados do
RP2040 na documentação do Pico em rptl.io/rp2040-get-started - ela está repleta de
informações sobre como o microcontrolador funciona, embora seja voltado para
engenheiros, por isso é profundamente técnico.
Finalmente, termine o seu loop:

print(temperature)
utime.sleep(2)

Seu programa agora ficará assim:

import machine
import utime

sensor_temp = machine.ADC(4)

conversion_factor = 3.3 / (65535)

while True:
reading = sensor_temp.read_u16() * conversion_factor
temperature = 27 - (reading - 0.706)/0.001721
print(temperature)
utime.sleep(2)

Clique no ícone Executar e salve seu programa como Temperature.py. Observe a área de
Shell: você verá números impressos que representam a temperatura informada pelo sensor
em graus Celsius.

CALOR E RP2040
1 Se você tiver um termômetro tradicional, poderá ver que o valor relatado pelo
sua Pico é um pouco mais alto: isso porque o sensor de temperatura está
localizado dentro do chip RP2040 da Pico, que está muito ocupado
executando seu programa. Quando o microcontrolador é ligado, ele está
gerando calor por conta própria - e esse calor é suficiente para distorcer o
resultado. Para um programa simples como este, a inclinação pode não ser
muito alta; se seu programa faz muitos cálculos complexos, a distorção
provavelmente será maior.
Experimente pressionar suavemente a ponta do seu dedo no RP2040, a maior parte preta no
meio da sua Pico, e segurá-la ali: o calor de seu dedo deve deixar a parte mais quente e a
temperatura vai subir. Tire o dedo do chip e a temperatura cairá novamente.
Parabéns - você transformou sua Pico em um termômetro!

Desvanecimento de um LED com PWM


O conversor analógico-digital na sua Pico só funciona de uma maneira: ele pega um sinal
analógico e o converte em um sinal digital que o microcontrolador pode entender. Se você
quiser ir por outro caminho, e seu microcontrolador digital criar uma saída analógica,
normalmente precisará de um conversor digital para analógico (DAC) - mas há uma maneira
de 'falsificar' um sinal analógico, usando algo chamado pulse-width modulation (modulação
por largura de pulso) ou PWM.
A saída digital de um microcontrolador só pode ser ligada ou desligada, 0 ou 1. Ligar e desligar
uma saída digital é conhecido como pulso e, alterando a rapidez com que o pino liga e
desliga, você pode alterar ou modular a largura deles pulsos - daí 'modulação por largura de
pulso'.
Cada pino GPIO em sua Pico é capaz de realizar o PWM, mas o bloco de modulação de largura
de pulso do microcontrolador é feito de oito fatias, cada uma com duas saídas. Observe a
Figura 8-4: você verá que cada pino tem uma letra e um número. O número representa a fatia
PWM conectada a esse pino; a letra representa qual saída da fatia é usada.

CONFLITOS PWM
1 Você saberá se acidentalmente usar a mesma saída PWM duas vezes, porque
toda vez que alterar os valores de PWM em um pino, isso afetará o pino em
conflito também. Se isso acontecer, dê uma olhada no diagrama de pinos na
Figura 8-4 e em seu circuito e encontre uma saída PWM que você ainda não
usou.
Figura 8-4: Os pinos de modulação de largura de pulso

Se isso parece confuso, não se preocupe: tudo isso significa que você precisa se certificar de
manter o controle das fatias e saídas PWM que está usando, certificando-se de conectar
apenas aos pinos com uma combinação de letras e números que você não tenha já usado. Se
você estiver usando PWM_A [0] no pino GP0 e PWM_B [0] no pino GP1, as coisas funcionarão
bem e continuarão a funcionar se você adicionar PWM_A [1] no pino GP2; se você tentar usar
o canal PWM no pino GP0 e pino GP16, no entanto, você terá problemas, pois ambos estão
conectados a PWM_A [0].

Figura 8-5: Adicionando um LED


Pegue um LED e um resistor limitador de corrente de 330 Ω e coloque-os na protoboard,
conforme mostrado na Figura 8-5. Conecte o terminal mais longo do LED, o ânodo, ao pino
GP15 por meio do resistor 330 Ω, e conecte o terminal mais curto ao pino de GND da sua Pico.
Volte para o seu primeiro programa clicando em sua guia logo abaixo da barra de
ferramentas de Thonny; se já o tiver fechado, clique no ícone Abrir e carregue
Potentiometer.py a partir da sua Pico. Logo abaixo de onde você configurou o potenciômetro
como uma entrada analógica para digital, digite:

led = machine.PWM(machine.Pin(15))

Isso cria um objeto LED no pino GP15, mas com uma diferença: ativa a saída de PWM no pino,
canal B [7] - a segunda saída da oitava fatia, contando a partir do zero.
Você também precisará definir a frequência, um dos dois valores que você pode alterar para
controlar ou modular a largura de pulso. Adicione outra linha imediatamente abaixo da
leitura:

led.freq(1000)

Isso define uma frequência de 1000 hertz - mil ciclos por segundo. Em seguida, vá para o final
do seu programa e exclua as linhas print (voltage) e utime.sleep (2) antes de adicionar o
seguinte, lembrando-se de mantê-lo recuado por quatro espaços para que faça parte do
código aninhado dentro do loop:

led.duty_u16(potentiometer.read_u16())

ssa linha faz uma leitura bruta da entrada analógica conectada ao seu potenciômetro e, em
seguida, a usa como o segundo aspecto PWM: o duty cycle (ciclo de trabalho). O duty cycle
controla a saída do pino: um duty cycle de 0% deixa o pino desligado para todos os 1000
pulsos por segundo e efetivamente desliga o pino; um duty cycle de 100% deixa o pino ligado
para todos os 1000 pulsos por segundo e é funcionalmente equivalente a apenas ligar o pino
como uma saída digital fixa; um duty cycle de 50% tem o pino ativado para metade dos pulsos
e desativado para metade dos pulsos.
Para que você possa controlar adequadamente o brilho do LED, você precisa mapear o valor
da entrada analógica para uma faixa que a parte PWM possa entender. A melhor maneira de
fazer isso é dizer ao MicroPython que você está passando o valor do ciclo de trabalho como
um inteiro de 16 bits sem sinal, o mesmo formato de número que você recebe do pino de
entrada analógica da Pico. Isso é obtido com o uso de led.duty_u16.
Seu programa concluído ficará assim:

import machine
import utime

potentiometer = machine.ADC(26)
led = machine.PWM(machine.Pin(15))
led.freq(1000)

while True:
led.duty_u16(potentiometer.read_u16())
Clique no ícone Executar e tente girar o potenciômetro totalmente para um lado e depois
totalmente para o outro. Observe o LED: desta vez, a menos que você esteja usando um
potenciômetro logarítmico, você verá o brilho do LED mudar suavemente de completamente
desligado em uma extremidade do limite do botão do potenciômetro para totalmente aceso
na outra.
Parabéns: você não apenas dominou as entradas analógicas, mas agora pode criar o
equivalente a uma saída analógica usando PWM!

DESAFIO: PERSONALIZAÇÃO
1
Você pode combinar seus dois programas e ter o brilho do LED controlado
pela leitura de temperatura do sensor de temperatura integrado? Você
consegue se lembrar de quantas entradas analógicas a sua Pico tem? E
quanto às saídas PWM? Experimente adicionar outro sensor analógico a sua
Pico - algo como um resistor dependente de luz (LDR), sensor de gás ou
barômetro - e faça com que seu programa leia isso em vez do potenciômetro.
Capítulo 9
Registrador de dados
Transforme a Raspberry Pi Pico em um dispositivo de registro de
dados de temperatura e desconecte-o do computador para torná-lo
totalmente portátil.

Ao longo deste livro, você usou sua para acesso posterior - transformando-a
Raspberry Pi Pico conectado a Raspberry no que é conhecido como um data logger
Pi ou a outro computador por meio de sua (registrador de dados). Para isso, você só
porta micro USB. Como em todos os precisará da sua Pico e, se quiser usá-lo
microcontroladores, no entanto, não há longe da Raspberry Pi, de um carregador
razão para sua Pico ter que ser presa desta micro USB ou bateria; depois de terminar o
forma: é um sistema autônomo capítulo, você pode conectar sensores
totalmente funcional, com recursos de analógicos adicionais se quiser expandir
processamento, memória e tudo o que seu projeto.
precisa para funcionar por conta própria.
Neste capítulo, você aprenderá como usar
o sistema de arquivos para criar, escrever
e ler arquivos, permitindo que você
coloque sua Pico em qualquer lugar que
desejar e faça com que ela registre dados
O sistema de arquivos
O sistema de arquivos é onde sua Pico armazena todos os programas que você tem escrito. É
equivalente em função ao cartão microSD em sua Raspberry Pi, ou ao disco rígido ou HD em
seu laptop ou computador desktop: é uma forma de armazenamento não volátil, o que
significa que tudo o que você salvar permanece no lugar mesmo quando você desconecta o
cabo micro USB da sua Pico.
Conecte a Pico à Raspberry Pi e carregue o Thonny, se ainda não o tiver aberto. Clique no
ícone Abrir e clique em ‘Raspberry Pi Pico’ no pop-up que aparece. Você verá uma lista de
todos os programas que escreveu até agora, armazenados no sistema de arquivos da Pico.
Você não vai abrir um agora, então clique em Cancelar.
Clique na parte inferior da área do Shell para começar a trabalhar com a sua Pico no modo
interativo. Digite:

file = open("test.txt", "w")

Isso diz ao MicroPython para abrir um arquivo chamado test.txt para escrever - a parte "w" da
instrução. Você não verá nada impresso na área do Shell ao pressionar ENTER no final da
linha porque, embora tenha aberto o arquivo, ainda não fez nada com ele. Digite:

file.write("Hello, File!")
Ao pressionar ENTER no final desta linha, você verá o número 12 aparecer (Figura 9-1). Isso é
MicroPython confirmando para você que gravou 12 bytes no arquivo que você abriu. Conte o
número de caracteres na mensagem que você escreveu: incluindo as letras, vírgula, espaço e
ponto de exclamação, há doze - cada um dos quais ocupa um único byte.

Figura 9-1: O tamanho dos dados que você escreveu são impressos na área do Shell
Quando você escreve em um arquivo, você precisa fechá-lo - isso garante que os dados que
você disse ao MicroPython para escrever sejam realmente escritos no sistema de arquivos.
Se você não fechar o arquivo, os dados podem não ter sido escritos ainda - um pouco como
escrever um documento no LibreOffice Writer ou outro processador de texto e esquecer de
salvá-lo. Digite:

file.close()
Seu arquivo agora está armazenado com segurança no sistema de arquivos da Pico. Clique
no ícone Abrir na barra de ferramentas de Thonny, clique em ‘Raspberry Pi Pico’ e role pela
lista de arquivos até encontrar test.txt. Clique nele e em OK para abri-lo: você verá sua
mensagem aparecer em uma nova aba Thonny.
Você não precisa usar o ícone Abrir para ler arquivos: você pode fazer isso diretamente no
próprio MicroPython. Clique de volta na parte inferior da área do Shell e digite:

file = open("test.txt")

Você notará que desta vez não há "w": isso porque, em vez de gravar no arquivo, você o lerá.
Você pode substituir o "w" por um "r", mas o padrão do MicroPython é abrir um arquivo no
modo de leitura - por isso, basta deixar essa parte da instrução desativada.
Em seguida, digite:

file.read()
Você verá a mensagem que escreveu na impressão do arquivo na área do Shell (Figura 9-2).
Parabéns: você pode ler e gravar arquivos no sistema de arquivos da sua Pico!

Figura 9-2: Imprimindo a mensagem armazenada na área do Shell

Antes de terminar, lembre-se de fechar o arquivo - não é tão importante fechar corretamente
um arquivo depois de lê-lo quanto ao gravá-lo, mas é um bom hábito entrar de qualquer
maneira:

file.close()
Registro de temperaturas
Agora que você sabe como abrir, escrever e ler arquivos, você tem tudo o que precisa para
construir um data logger em sua Pico. Clique no ícone Novo para iniciar um novo programa
em Thonny e inicie seu programa digitando:

import machine
import utime

sensor_temp = machine.ADC(machine.ADC.CORE_TEMP)

conversion_factor = 3.3 / (65535)


reading = sensor_temp.read_u16() * conversion_factor
temperature = 27 - (reading - 0.706)/0.001721

Você pode reconhecer este código: é o mesmo que você usou no Capítulo 8 para ler o sensor
de temperatura de bordo da sua Pico. As leituras do sensor são os dados que você vai
registrar no sistema de arquivos, então você não quer simplesmente imprimi-los como fazia
antes.
Comece abrindo um arquivo para gravação adicionando a seguinte linha na parte inferior:

file = open("temps.txt", "w")

Se o arquivo ainda não existir no sistema de arquivos, será criado; em caso afirmativo, ele o
sobrescreve - esvaziando seu conteúdo para que você possa gravar novos dados.

1 AVISO
Abrir um arquivo para gravação em MicroPython excluirá tudo o que você já
armazenou nele. Sempre se certifique de ter aberto o arquivo para leitura e
salvo o conteúdo em algum lugar se quiser mantê-lo!

Agora você precisa escrever algo no arquivo - a leitura do sensor de temperatura:

file.write(str(temperature))
Em vez de escrever uma string fixa entre aspas, como você fez antes, desta vez você está
convertendo a variável de temperatura - que é um número de ponto flutuante, em outras
palavras, um com um ponto decimal nele - em uma string e, em seguida, escrevendo isso
para o arquivo.
Como antes, para garantir que os dados sejam gravados, você precisa fechar o arquivo:

file.close()
Clique no ícone Executar e salve seu programa na Raspberry Pi Pico como Datalogger.py. O
programa levará apenas alguns segundos para ser executado; quando o >>> prompt
reaparecer na parte inferior da área do Shell, clique nele e digite o seguinte para abrir e ler seu
novo arquivo:
file = open("temps.txt")
file.read()
file.close()

Você verá a leitura de temperatura que seu programa obteve aparecer no Shell (Figura 9-3).
Parabéns: seu data logger funciona!

Figura 9-3 - Seu arquivo registra a temperatura no momento em que a medição foi feita

Um registrador de dados que registra apenas uma única leitura - um datum - não é tão útil,
no entanto. Para tornar seu registrador de dados mais poderoso, você precisa modificá-lo
para que faça muitas leituras. Clique novamente em Executar e leia o arquivo novamente:

file = open("temps.txt")
file.read()
file.close()
Observe como ainda há apenas uma leitura no arquivo. Quando o programa abriu o arquivo
para gravação novamente, ele apagou automaticamente o conteúdo anterior - o que significa
que, cada vez que o programa for executado, ele apagará o arquivo e armazenará uma única
leitura.
Para consertar isso, você precisa modificar seu programa. Comece clicando e arrastando o
cursor do mouse para destacar as linhas:
reading = sensor_temp.read_u16() * conversion_factor
temperature = 27 - (reading - 0.706)/0.001721

Depois de realçar ambas as linhas - tomando cuidado para não perder nenhuma parte - solte
o botão do mouse e pressione CTRL + X no teclado para cortar as linhas; você os verá
desaparecer do programa.
Em seguida, vá até o final do seu programa e exclua tudo depois de:

file = open("temps.txt", "w")

Agora digite:

while True:
Após pressionar ENTER no final dessa linha, mantenha pressionada a tecla CTRL e pressione
a tecla V para colar as duas linhas cortadas anteriormente. Você os verá aparecer, o que evita
que você tenha que digitá-los - mas apenas a primeira linha será devidamente indentada, por
isso é aninhada como parte do loop infinito que você acabou de abrir. Coloque o cursor no
início da linha abaixo clicando e pressione a barra de espaço quatro vezes para indentar a
linha corretamente, então mova o cursor para o final da linha e pressione ENTER.
Digite a seguinte linha, certificando-se de que esteja devidamente indentada:

file.write(str(temperature))
Agora, porém, você precisará fazer algo novo. Se você fechar o arquivo como fez antes, não
poderá gravar novamente sem reabri-lo e limpar seu conteúdo. Se você não fechar o arquivo,
os dados nunca serão realmente gravados no sistema de arquivos.
A solução: esvazie o arquivo, em vez de fechá-lo. Digite:

file.flush()

Quando você está gravando em um arquivo, mas os dados não estão realmente sendo
gravados no sistema de arquivos, eles são armazenados no que é conhecido como buffer -
uma área de armazenamento temporário. Quando você fecha o arquivo, o buffer é gravado no
arquivo em um processo conhecido como flushing (esvaziar). Usar file.flush() é equivalente
a file.close(), pois libera o conteúdo do buffer no arquivo - mas ao contrário de file.close(), o
arquivo permanece aberto para você gravar mais dados nele posteriormente.
Agora você só precisa pausar seu programa entre as leituras:

utime.sleep(10)
Seu programa concluído ficará assim:

import machine
import utime

sensor_temp = machine.ADC(machine.ADC.CORE_TEMP)
conversion_factor = 3.3 / (65535)
file = open("temps.txt", "w")
while True:
reading = sensor_temp.read_u16() * conversion_factor
temperature = 27 - (reading - 0.706)/0.001721
file.write(str(temperature))
file.flush()
utime.sleep(10)
Clique no ícone Executar e conte até 60 e, em seguida, clique no ícone Parar. Agora abra e leia
seu arquivo na área de script:

file = open("temps.txt")
file.read()
file.close()
A boa notícia é que seu programa funcionou e você registrou várias leituras em um único
arquivo - cerca de seis, mais ou menos dependendo da rapidez com que contou. A má notícia
é que eles estão todos misturados em uma única linha (Figura 9-4) - dificultando a leitura.
Para corrigir esse problema, você precisa formatar os dados conforme são gravados no
arquivo. Volte para a linha file.write () em seu programa e modifique-a para que se pareça
com:

Figura 9-4: Todas as medidas estão lá, mas a formatação torna difícil a leitura
file.write(str(temperature) + "\n")
O símbolo de mais (+) informa ao MicroPython que você deseja acrescentar o que segue,
concatenando as duas strings; "\n" é uma string especial conhecida como caractere de
controle - ela funciona como o equivalente a pressionar a tecla ENTER, o que significa que
cada linha em seu registro de dados deve estar em sua própria linha separada.
Clique no ícone Executar, conte até 60 novamente e clique em Parar. Abra e leia seu arquivo:

file = open("temps.txt")
file.read()
file.close()
Você fez progresso, mas ainda não está certo: o caractere de controle \n não está agindo
como se você pressionasse ENTER, mas imprimindo como dois caracteres visíveis (Figura
9-5, verso). Isso porque file.read() está trazendo o conteúdo bruto do arquivo e não faz
nenhuma tentativa de formatá-lo para a tela.

Figura 9-5: Você está chegando perto de uma impressão fácil de ler aqui

Para corrigir o problema de formatação, você precisa envolver o arquivo lido em uma função
print():

file = open("temps.txt")
print(file.read())
file.close()

Desta vez, você verá cada leitura impressa em sua própria linha, bem formatada e fácil de ler
(Figura 9-6).
Figura 9-6: Agora você pode ler todas as temperaturas que seu data logger capturou

Parabéns: você construiu um registrador de dados que pode fazer várias leituras e
armazená-las no sistema de arquivos da Pico!

ARMAZENAMENTO DE ARQUIVO
1 O sistema de arquivos da sua Pico tem 1,375 MB de tamanho, o que significa
que pode conter 1.441.792 bytes de dados. Cada arquivo que você salva em
sua Pico, incluindo o arquivo de armazenamento do registrador de dados,
ocupa espaço. Quanto tempo leva para preencher o armazenamento vai
depender de quantos outros arquivos você tem e com que frequência o data
logger salva uma leitura: a nove bytes por leitura a cada dez segundos, você
preencherá 1,375 MB em cerca de 18,5 dias; se você fizesse uma leitura a cada
minuto, seu data logger poderia ser executado por cerca de 111 dias; se você
ler apenas uma vez por hora, seu data logger pode funcionar por mais de 18
anos!

O sistema de arquivos da Pico funciona independentemente de estar conectado à Raspberry


Pi ou a outro computador. Se você tiver um carregador de rede micro USB ou uma bateria USB
com um cabo micro USB, pode levar seu registrador de dados para qualquer cômodo da casa
e fazê-lo funcionar sozinho - mas você precisará de uma maneira de fazer seu programa
funcionar sem ter que clicar no ícone Executar no Thonny.
Para uso sem um computador conectado - conhecido como headless operation - você pode
salvar seu programa com um nome de arquivo especial: main.py. Quando o MicroPython
encontra um arquivo chamado main.py em seu sistema de arquivos, ele é executado
automaticamente sempre que é ligado ou redefinido - sem você ter que clicar em Executar.
Em Thonny, após interromper o programa se estiver em execução, clique no menu Arquivo e
em Salvar como. Clique em ‘Raspberry Pi Pico’ no pop-up que aparece e digite ‘main.py’ como
o nome do arquivo antes de clicar em Salvar. A princípio, nada parecerá acontecer: isso
porque Thonny coloca sua Pico em modo interativo, o que o impede de executar
automaticamente o programa que você acabou de salvar.
Para forçar a execução do programa, clique na parte inferior da área do Shell e mantenha
pressionada a tecla CTRL, pressione a tecla D e, em seguida, solte a tecla CTRL. Isso envia à
sua Pico um comando de soft reset, que o interromperá do modo interativo e iniciará a
execução do programa. Encontre outra coisa para fazer por cinco minutos ou mais, pressione
o ícone Parar e abra seu registro de dados:

file = open("temps.txt")
print(file.read())
file.close()

Você verá uma lista de leituras de temperatura, embora não tenha clicado no ícone Executar
- porque seu programa foi executado automaticamente quando a Pico reiniciou.
Se você tiver um carregador micro USB ou bateria USB, desconecte a Pico da Raspberry Pi,
leve-o para outra sala e conecte-o ao carregador ou bateria. Deixe-o lá por dez minutos,
depois volte e desconecte-a. Leve-a de volta à sua Raspberry Pi, conecte-a novamente e leia
seu arquivo novamente: você verá as leituras da outra sala, provando que sua Pico pode
funcionar perfeitamente bem sem a Raspberry Pi ajudando.
Parabéns: seu data logger agora está totalmente funcional e totalmente portátil, pronto para
ir com você onde quer que você precise registrar dados!

AVISO
1 O seu programa de registro de dados será executado sempre que a Pico for
ligada sem estar conectado ao Thonny. Se você não quiser que isso aconteça,
pode simplesmente abrir main.py no Thonny e excluir todo o código antes de
salvá-lo novamente. Com um main.py vazio, a sua Pico irá simplesmente
sentar e esperar por instruções novamente.

1
DESAFIO
Você pode alterar seu programa para registrar dados de um sensor externo
conectado a um dos pinos ADC da Pico? Você pode fazer seu programa
escrever um título no início do arquivo, para que seja mais fácil ver o que os
valores significam? Você pode escrever um programa que registre quantas
vezes um botão foi pressionado? Você consegue descobrir uma maneira,
como copiar e colar, de colocar seus dados no LibreOffice Calc ou em outro
programa de planilha para criar um gráfico?
Capítulo 10
Protocolos de
comunicação
digital: I2C e SPI
Explore esses dois protocolos de comunicação populares e use-os
para exibir dados em um LCD.

Até agora neste livro, vimos como e Serial Peripheral Interface (SPI). Em
trabalhar com alguns bits comuns de muitos aspectos, eles são muito
hardware, mas conforme você constrói semelhantes, pois ambos definem uma
mais projetos por conta própria, forma de conectar uma interface
provavelmente vai querer se expandir bidirecional entre dois dispositivos. Na
para usar todos os tipos de sensores, verdade, muitas peças vêm em versões
atuadores e displays. Como você se com qualquer interface, então você pode
comunicará com eles? Às vezes, você escolher a que é certa para o seu projeto.
pode descobrir que há uma biblioteca Em ambos os casos, há um dispositivo que
MicroPython que pode usar, onde alguém controla a comunicação (sua Pico) e um
já converteu as funções de baixo nível em (ou mais) que aguarda instruções do
uma interface fácil de usar. No entanto, dispositivo principal. No entanto, existem
nem sempre é esse o caso. algumas diferenças. Analisaremos os dois
Felizmente, existem algumas maneiras protocolos agora e, em seguida,
padrão de conectar dispositivos digitais ajudaremos você a escolher o correto para
de baixo nível que são implementadas no cada projeto.
MicroPython: Inter-Integrated Circuit (I2C)
NÍVEIS DE TENSÃO
1 Os pinos GPIO da sua Pico funcionam a 3,3V. Aplicar uma tensão mais alta a
eles pode danificá-los. Felizmente, esta é uma tensão comum para trabalhar
e uma grande proporção dos dispositivos que você encontra funcionam com
3,3V. No entanto, antes de conectar algum novo hardware em sua Pico,
sempre verifique se é um dispositivo de 3,3V, já que ambos os dispositivos I2C
e SPI podem funcionar a 5V às vezes e isso danificará sua Pico.

I2C
A comunicação em I2C ocorre em dois fios: um clock (geralmente marcado como SCL) e um
canal de dados (geralmente marcado como SDA).

Figura 10-1: Diagrama de pinos da Raspberry Pi Pico. As funções I2C são mostradas
em azul claro; SPI em rosa

Estes têm de ser ligados a pinos específicos na Pico. Existem algumas opções; dê uma olhada
no diagrama de pinos para as opções (Figura 10-1). Existem dois barramentos I2C (I2C0 e
I2C1) e você pode usar um ou ambos. Em nosso exemplo, usaremos I2C0 - com GP0 para SDA
e GP1 para SCL.
Para demonstrar os protocolos, usaremos um módulo SerLCD do SparkFun. Isso tem a
vantagem de ter interfaces I2C e SPI, de modo que podemos ver as diferenças entre os dois
métodos com o mesmo hardware.
Este LCD pode exibir duas linhas, cada uma com até 16 caracteres. É um dispositivo útil para
enviar bits de informação sobre nosso sistema. Vamos dar uma olhada em como usá-lo.
A montagem I2C é apenas um caso de conectar o pino SDA na Pico com o pino SDA no LCD e
o mesmo para o SCL. Devido à forma como I2C lida com a comunicação, também precisa
haver um resistor conectando SDA a 3,3 V e SCL a 3,3V. Normalmente, eles têm cerca de 4,7 k
Ω. No entanto, com o nosso dispositivo, esses resistores já estão incluídos, então não
precisamos adicionar nenhum extra.

Figura 10-2: Conexões de um módulo SerLCD para I2C

Com isso conectado (veja a Figura 10-2), exibir informações na tela é tão simples como:

import machine
sda=machine.Pin(0)
scl=machine.Pin(1)
i2c=machine.I2C(0,sda=sda, scl=scl, freq=400000)
i2c.writeto(114, '\x7C')
i2c.writeto(114, '\x2D')
i2c.writeto(114, "hello world")

Este código não faz muito. Ele se conecta ao dispositivo I2C e envia alguns dados. No entanto,
existem alguns bits que podem parecer um pouco incomuns.
O 114 nas linhas i2c.writeto() se refere ao endereço do dispositivo I2C. Você pode conectar
muitos dispositivos a um barramento I2C (mais sobre isso mais tarde), e cada vez que quiser
enviar ou receber dados, você precisará especificar o endereço do dispositivo com o qual
deseja se comunicar. Este endereço é conectado ao dispositivo (embora você possa alterá-lo
cortando um traço no PCB ou com uma bolha de solda - consulte a documentação do seu
dispositivo para obter detalhes).
Você deve encontrar o endereço do seu dispositivo na documentação, mas pode digitalizar
um barramento I2C para ver quais endereços estão em uso. Depois de configurar o
barramento I2C, você pode executar o método scan para gerar os endereços atualmente em
uso:
import machine
sda=machine.Pin(0)
scl=machine.Pin(1)
i2c=machine.I2C(0,sda=sda, scl=scl, freq=400000)
print(i2c.scan())

Os próximos bits que podem parecer um pouco estranhos são os comandos \x7C e \x2D que
são escritos. Cada dispositivo I2C requer o envio de dados em um formato específico. Não há
um padrão para isso, então você terá que consultar a documentação de qualquer dispositivo
I2C que estiver configurando. O \x no início de cada um deles diz ao MicroPython que
estamos enviando uma string hexadecimal (consulte a caixa ‘Hexadecimal’), que é uma
maneira comum de garantir que você está enviando os dados exatos que deseja. Para o nosso
LCD, 7C entra no modo de comando e 2D apaga o LCD e define o cursor para o início. Em
seguida, podemos enviar dados que são exibidos na tela:

file.close()

HEXADECIMAL
1 Hexadecimal é um sistema de numeração de base 16. Isso significa que
existem 16 dígitos: 0 – F. Portanto, o número 10 em decimal é A em
hexadecimal. 17 em decimal é 11 em hexadecimal. A vantagem disso é que
cada dígito contém dois bytes de informações. Isso o torna uma forma
compacta, mas ainda compreensível, de escrever informações digitais. Você
encontrará muitas coisas ao lidar com dispositivos que interpretam suas
instruções como valores digitais (como nosso LCD). Se você ficar confuso,
pode usar conversores hexadecimal para decimais online para alternar entre
os dois. Por exemplo: hsmag.cc/hextodec.

Claro, não há muito uso em uma tela que diz apenas Hello World, então vamos dar uma
olhada em como transformar isso em algo um pouco mais útil - um termômetro. No Capítulo
8, você aprendeu como usar o ADC para ler temperaturas usando o sensor de temperatura
interno da Pico. Agora podemos construir neste código para fazer um termômetro autônomo
que não precisa de um computador para ler a saída. Com o seu LCD ainda conectado como
antes, execute o seguinte código:

import machine
import utime

sda=machine.Pin(0)
scl=machine.Pin(1)
i2c=machine.I2C(0,sda=sda, scl=scl, freq=400000)

adc = machine.ADC(4)
conversion_factor = 3.3 / (65535)
while True:
reading = adc.read_u16() * conversion_factor
temperature = 25 - (reading - 0.706)/0.001721
i2c.writeto(114, '\x7C')
i2c.writeto(114, '\x2D')
out_string = "Temp: " + str(temperature)
i2c.writeto(114, out_string)
utime.sleep(2)

Isso deve parecer familiar. A única pequena mudança no código de temperatura anterior é
que antes de exibirmos o resultado do nosso cálculo - um número - mas o LCD precisa de
caracteres para ser exibido, então usamos a função str que converte o número em uma
sequência de caracteres. Podemos então transformar isso em uma saída um pouco mais
informativa, combinando-a com "Temp:".
Como você viu, I2C é uma maneira fácil de conectar hardware extra a sua Pico. Você
precisará garantir que tem a documentação apropriada para qualquer dispositivo que deseja
conectar que permite saber quais comandos fazem o quê, mas desde que você saiba disso,
você pode facilmente adicionar todos os tipos de módulos, dar rumos à sua Pico e criar
projetos impressionantes.

Serial Peripheral Interface (SPI)


Vimos como o I2C funciona, agora vamos dar uma olhada no SPI. Usaremos exatamente o
mesmo LCD, para que os comandos e tudo o mais sejam os mesmos, é apenas o protocolo
pelo qual enviamos os dados que é diferente.
O SPI tem quatro conexões: SCLK, MOSI, MISO e CS (às vezes rotulado como SS). SCLK é o
clock, MOSI é a linha que leva dados de sua Pico para o dispositivo periférico (consulte a
caixa ‘Terminologia SPI’) e MISO leva dados de seu dispositivo periférico para sua Pico. CS
significa Chip Select e é usado para conectar muitos dispositivos a um único barramento SPI.
Você simplesmente tem que aplicar tensão à linha CS para habilitar um periférico SPI e
puxá-lo para nível baixo para desabilitá-lo. Para confundir um pouco as coisas, este
dispositivo em particular não tem CS, mas /CS, que significa NOT CS - em outras palavras, é
o oposto de CS, então você coloca em nível baixo para habilitar o LCD e em nível alto para
desabilitá-lo. Você poderia conectar o CS a um pino GPIO e ligá-lo e desligá-lo para habilitar
e desabilitar a tela, mas como temos apenas um dispositivo, podemos simplesmente
conectá-lo ao GND para mantê-lo habilitado (Figura 10-3).
Assim, com as linhas de energia do SerLCD conectadas ao VBUS e GND, só precisamos
conectar seu SDO ao MISO do Pico (GP4 / SPI0 RX), SDI a MOSI (GP3 / SPI0 TX), SCK a SCLK
(GP2 / SPI0 SCK), e /CS para GND.
Figura 10-3: Montagem de um módulo SerLCD para SPI

TERMINOLOGIA SPI
1 O SPI requer quatro conexões: uma que leva dados do dispositivo mestre para
o dispositivo escravo, outra que leva dados na direção oposta, além de
alimentação e GND. Dois fios de dados significam que os dados podem
trafegar em ambas as direções ao mesmo tempo. Geralmente são chamados
de Master Out Slave In (MOSI) e Master In Slave Out (MISO). No entanto, você
os encontrará com nomes diferentes. Se você observar a pinagem da
Raspberry Pi Pico (Apêndice B), eles são chamados de SPI TX (transmissão) e
SPI RX (recepção). Isso ocorre porque a Pico pode ser um dispositivo mestre
ou escravo, portanto, se essas conexões são MOSI ou MISO depende da
função atual da Pico. No LCD que estamos usando, eles são identificados
como SDI (Serial Data In) e SDO (Serial Data Out).

Não há endereços no SPI, então podemos apenas aprofundar e escrever nosso código:

import machine

spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi_rx=machine.Pin(4)

spi=machine.SPI(0,baudrate=100000,sck=spi_sck, mosi=spi_tx, miso=spi_rx)


spi.write('\x7C')
spi.write('\x2D')
spi.write("hello world")
Neste caso, estamos usando SPI0 e um conjunto de pinos disponíveis para isso é GP2, GP3 e
GP4. A maioria dos tipos de comunicação serial tem uma velocidade ou taxa de transmissão,
que é basicamente a quantidade de bits de dados que ela pode enviar através do canal por
segundo. Muitas coisas afetam isso, como os recursos dos dois dispositivos sendo
conectados e a conexão entre eles (quanto tempo é e se há interferência de outros
dispositivos). Se você achar que está tendo problemas com dados mutilados, pode ser
necessário reduzi-los. Para nossa pequena tela, estamos apenas enviando um byte de dados
por caractere, então realmente não importa a rapidez com que o enviamos, mas para alguns
outros dispositivos SPI (como telas baseadas em pixels), ajustando o baud rate pode ser
importante.
Vamos dar uma olhada em como isso deixa nosso código de termômetro:

import machine
import utime

spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi_rx=machine.Pin(4)

spi=machine.SPI(0,baudrate=100000,sck=spi_sck, mosi=spi_tx, miso=spi_rx)

adc = machine.ADC(4)
conversion_factor = 3.3 / (65535)

while True:
reading = adc.read_u16() * conversion_factor
temperature = 25 - (reading - 0.706)/0.001721
spi.write('\x7C')
spi.write('\x2D')
out_string = "Temp: " + str(temperature)
spi.write(out_string)
utime.sleep(2)

Como você pode ver, há realmente muito pouca diferença no código entre I2C e SPI. Depois de
ter tudo configurado, a única mudança realmente é que com I2C você tem que especificar o
endereço ao enviar dados, enquanto com SPI você não (embora lembre-se que se você tivesse
mais de um dispositivo conectado, você precisa alternar o CS GPIO para selecionar o
dispositivo apropriado).
Então, se eles são tão semelhantes, qual protocolo você deve escolher ao construir um
projeto? Existem alguns fatores a serem considerados. O primeiro é a disponibilidade das
coisas que você deseja anexar. Às vezes, um sensor está disponível apenas como I2C ou SPI,
então você precisa usá-lo. No entanto, se você puder escolher o hardware, o maior impacto
virá quando você estiver usando vários dispositivos extras. Com I2C, você pode conectar até
128 dispositivos a um único barramento I2C; no entanto, todos eles precisam ter um endereço
separado. Esses endereços são conectados fisicamente. Às vezes, é possível alterar o
endereço com uma conexão soldável (ou cortável), mas às vezes não. Se você quiser ter
vários sensores do mesmo tipo (por exemplo, se estiver monitorando a temperatura em
muitos pontos em seu projeto), pode ser limitado pelo número de endereços I2C para seu
sensor. Nesse caso, o SPI pode ser uma escolha melhor.
Como alternativa, o SPI pode ter um número ilimitado de dispositivos conectados;
entretanto, cada um deve ter sua própria linha CS. Na Pico, existem 26 pinos GPIO. Você
precisa de três deles para o barramento SPI, o que significa que há 23 linhas disponíveis para
CS. E isso pressupõe que você não precisa de mais nada. Se os GPIOs disponíveis são
escassos, você pode querer dar uma olhada no I2C.
Na realidade, para muitos projetos, você pode usar qualquer um dos protocolos com bastante
satisfação e descobrir que a escolha de qual usar tem mais a ver com o módulo que você
encontra em sua caixa de peças do que com uma diferença técnica entre os dois.

BIT BANGING
1 Sua Pico tem dois barramentos I2C de hardware e dois barramentos SPI de
hardware. No entanto, você pode usar mais do que esses, se quiser. Ambos
I2C e SPI podem ser implementados em software em vez de hardware. Isso
significa que o núcleo de processamento principal lida com o protocolo de
comunicação em vez de um bit especializado do microcontrolador. Isso é
conhecido como ‘bit banging’. Embora possa ser útil, ele coloca mais pressão
sobre o núcleo do processador do que usar hardware especializado, e você
pode descobrir que não pode atingir taxas de transmissão altas.
A Pico tem um truque na manga para isso - PIO. Veremos isso mais de perto
mais tarde no livro (Apêndice C), mas é uma parte extra de hardware no
microcontrolador que pode ser dedicado a protocolos de entrada / saída,
como I2C e SPI. Com PIO, você pode criar barramentos I2C ou SPI extras sem
sobrecarregar o núcleo do processador principal.
Apêndice A
Especificações da
Raspberry Pi Pico

Os vários componentes e recursos de um microcontrolador são conhecidos como suas


especificações, e uma olhada nas especificações fornece as informações necessárias para
comparar dois microcontroladores.
Essas especificações podem parecer confusas à primeira vista, são altamente técnicas e
você não precisa conhecê-las para usar a Raspberry Pi Pico, mas elas estão incluídas aqui
para o leitor curioso.
O chip microcontrolador da Raspberry Pi Pico é um Raspberry Pi RP2040, que você verá
indicado por marcações gravadas na parte superior do componente se olhar de perto. O
nome do microcontrolador pode ser dividido em seções, cada uma com um significado
específico:
RP significa ‘Raspberry Pi’, simplesmente o suficiente.
2 é o número de núcleos de processador que o microcontrolador possui.
0 é o tipo de núcleo do processador, indicando que, neste caso, o RP2040 usa um núcleo
do processador chamado Cortex-M0 + da Arm, com base em Cambridge.
4 é a quantidade de memória de acesso aleatório (RAM) que o microcontrolador possui,
com base em uma função matemática especial: floor(log2 (RAM / 16)). Neste caso, '4' significa
que o chip tem 264 kilobytes (kB) de RAM.
0 é a quantidade de armazenamento não volátil (NV) que o chip possui, e é trabalhado da
mesma maneira que a RAM: floor (log2 (NV / 16)). Nesse caso, 0 significa simplesmente que
não há armazenamento não volátil integrado.

O RP2040 é o primeiro microcontrolador da Raspberry Pi; quando modelos futuros forem


lançados, esses números serão usados para que você possa ver rapidamente como seus
recursos se comparam.
Os dois núcleos do processador Cortex-M0 + da sua Pico funcionam a 48 MHz (48 milhões de
ciclos por segundo), embora isso possa ser alterado no software até 133 MHz (133 milhões de
ciclos por segundo) se o seu programa precisar de maior desempenho.
A RAM do microcontrolador é construída no mesmo chip que os próprios núcleos do
processador e assume a forma de seis bancos de memória individuais, totalizando 264kB
(264.000 bytes) de RAM estática (SRAM). A RAM é usada para armazenar seus programas e os
dados de que precisam.
O RP2040 inclui 30 pinos de entrada / saída de uso geral (GPIO) multifuncionais, 26 dos quais
são trazidos para conectores de pinos físicos em sua Pico e um dos quais é conectado a um
LED integrado. Três desses pinos GPIO são conectados a um conversor analógico-digital
(ADC), enquanto outro canal ADC é conectado a um sensor de temperatura no chip.
O RP2040 inclui dois receptores-transmissores assíncronos universais (UART), dois serial
peripheral interface (SPI) e dois barramentos inter-integrated circuit (I2C) para conexões
com dispositivos de hardware externos, como sensores, monitores, conversores
digital-analógico (DACs), e mais. O microcontrolador também inclui entrada/saída
programável (PIO), que permite ao programador definir novas funções de hardware e
barramentos no software.
Sua Pico inclui um conector micro USB, que fornece um link serial UART sobre USB para o
microcontrolador RP2040 para programação e interação, e que alimenta o chip. Manter o
botão BOOTSEL pressionado ao conectar o cabo mudará o microcontrolador para o modo
Dispositivo de armazenamento em massa USB, permitindo que você carregue um novo
firmware.
O RP2040 também inclui um clock e timer preciso no chip, o que permite controlar a hora e a
data. O clock pode armazenar o ano, mês, dia, dia da semana, hora, minuto e segundo, e
controla automaticamente o tempo decorrido enquanto houver energia.
Finalmente, RP2040 inclui single-wire debug (SWD) para fins de depuração de hardware,
trazido para três pinos na parte inferior de sua Pico.
CPU: ARM Cortex-M0 + dual-core de 32 bits a 48 MHz, configurável até 133 MHz

RAM: 264kB de SRAM em seis bancos configuráveis independentemente

Armazenamento: 2 MB de RAM flash externa

GPIO: 26 pinos

ADC: pinos ADC de 3 x 12 bits

PWM: Oito partes, duas saídas por parte para um total de 16

Clock: relógio preciso no chip e cronômetro com ano, mês, dia, dia da semana, hora,
segundo e cálculo automático do ano bissexto

Sensores: sensor de temperatura no chip conectado ao canal ADC de 12 bits

LEDs: LED on-board endereçável pelo usuário

Conectividade de barramento: 2 × UART, 2 × SPI, 2 × I2C, entrada / saída programável (PIO)

Hardware Debug: single-wire debug (SWD)

Opções de montagem: furo de passagem e pinos castelados (não preenchidos) com 4


furos de montagem

Alimentação: 5V via conector micro USB, 3,3V via pino 3V3 ou 2-5V via pino VSYS
Apêndice B
Diagrama de pinos

A Raspberry Pi Pico dispõe de 26 pinos dos 30 possíveis GPIO (entrada / saída de uso geral)
do RP2040, direcionando-os diretamente para os pinos de guia da Pico. GP0 a GP22 são
apenas digitais e GP 26–28 podem ser usados como entradas GPIO digitais ou ADC (conver-
sor analógico para digital), selecionáveis no software. A maioria dos pinos GPIO também
oferece funcionalidade secundária para protocolos de comunicação SPI, I2C ou UART. Todos
os pinos GPIO também podem ser usados com PWM (modulação por largura de pulso) - con-
sulte o Capítulo 8 para obter mais detalhes.
VBUS é a tensão de entrada micro-USB, conectada ao pino 1 da porta micro-USB. Isso é
nominalmente 5 V (ou 0 V se o USB não estiver conectado ou não estiver energizado).
VSYS é a tensão de entrada do sistema principal, que pode variar na faixa permitida de
1,8 V a 5,5 V, e que é usada pelo SMPS integrado (fonte de alimentação comutada) para gerar
3,3 V para o RP2040 e seu GPIO.
3V3_EN conecta-se ao pino de habilitação SMPS on-board e é puxado para cima (para
VSYS) por meio de um resistor de 100 kΩ. Para desabilitar 3,3V (que também desliga o
RP2040), coloque este pino em curto.
3V3 é a fonte principal de 3,3 V para RP2040 e seu IO, gerado pelo SMPS on-board. Este
pino pode ser usado para alimentar circuitos externos (a corrente de saída máxima depen-
derá da carga RP2040 e da tensão VSYS, é recomendado manter a carga neste pino menor
que 300 mA).
ADC_VREF é a tensão da fonte de alimentação (e referência) ADC, e é gerada na Pico
pela filtragem da alimentação de 3,3 V. Este pino pode ser usado com uma referência exter-
na se um melhor desempenho do ADC for necessário.
AGND é a referência de aterramento para GPIO26–29; há um plano de aterramento ana-
lógico separado funcionando sob esses sinais e terminando neste pino. Se o ADC não for
usado ou o desempenho do ADC não for crítico, este pino pode ser conectado ao GND digital.
RUN é o pino de habilitação do RP2040 e tem um resistor pull-up interno (no chip) para
3,3 V de cerca de ~ 50 kΩ. Para redefinir RP2040, coloque este pino em curto.
Apêndice C
Entradas e saídas
programáveis

Neste apêndice, examinamos o código que parece muito diferente do código com o qual
lidamos no resto do livro. Isso porque estamos tendo que lidar com as coisas em um nível
baixo. Na maioria das vezes, o MicroPython pode ocultar muitas das complexidades de
como as coisas funcionam no microcontrolador. Quando fazemos algo como:

print("hello")

... não temos que nos preocupar com a forma como o microcontrolador armazena as
letras, ou o formato em que são enviadas para o terminal serial, ou o número de ciclos de
clock que o terminal serial leva. Isso tudo é tratado em segundo plano. No entanto, quando
chegamos à entrada e saída programáveis (PIO), precisamos lidar com as coisas em um
nível muito baixo.
Faremos um tour rápido pelo PIO e apresentaremos alguns tópicos avançados para que
você possa ter uma ideia do que está acontecendo e, com sorte, entender como o PIO na Pico
oferece algumas vantagens reais sobre as opções em outros microcontroladores. No
entanto, entender toda a manipulação de dados de baixo nível necessária para criar
programas PIO leva tempo para se familiarizar totalmente, então não se preocupe se
parecer um pouco obscuro. Se você estiver interessado em lidar com essa programação de
baixo nível, então, daremos a você o conhecimento para começar e indicar a direção certa
para continuar sua jornada. Se você estiver mais interessado em trabalhar em um nível
superior e preferir deixar as disputas de nível inferior para outras pessoas, mostraremos
como usar os programas PIO.
Dados de entrada e saída de dados
Ao longo deste livro, vimos maneiras de controlar os pinos em sua Pico usando MicroPython.
Podemos ligá-los e desligá-los, receber entradas e até mesmo enviar dados usando os
controladores SPI e I2C dedicados. No entanto, e se quisermos conectar um dispositivo que
não se comunica em SPI ou I2C? E se ele tiver seu próprio protocolo especial?
Existem algumas maneiras de fazermos isso. Na maioria dos dispositivos MicroPython, você
precisa fazer um processo chamado ‘bit banging’, onde implementa o protocolo em
MicroPython. usando isso, você liga ou desliga os pinos na ordem certa para enviar dados.
Existem três desvantagens nisso. A primeira é que é lento. MicroPython faz algumas coisas
muito bem, mas não é executado tão rápido quanto o código compilado nativamente.
A segunda é que temos que conciliar isso com o resto do nosso código que está rodando no
microcontrolador.
A terceira é que alguns códigos críticos para o tempo podem ser difíceis de implementar de
forma confiável. Protocolos rápidos podem precisar que coisas aconteçam em momentos
muito precisos e com MicroPython podemos ser bastante precisos, mas se você está
tentando transferir megabits por segundo, precisa que coisas aconteçam a cada
milissegundo ou possivelmente a cada algumas centenas de nanossegundos. Isso é difícil de
conseguir com segurança no MicroPython.
A Pico tem uma solução para isso: entradas e saídas programáveis (I/O). Existem alguns
núcleos de processamento extras, realmente despojados, que podem executar programas
simples para controlar os pinos de IO. Você não pode programar esses núcleos com
MicroPython - você tem que usar uma linguagem especial apenas para eles - mas você pode
programá-los a partir de MicroPython. Vamos dar uma olhada em um exemplo:

from rp2 import PIO, StateMachine, asm_pio


from machine import Pin
import utime

@asm_pio(set_init=PIO.OUT_LOW)
def led_quarter_brightness():
set(pins, 0) [2]
set(pins, 1)

@asm_pio(set_init=PIO.OUT_LOW)
def led_half_brightness():
set(pins, 0)
set(pins, 1)

@asm_pio(set_init=PIO.OUT_HIGH)
def led_full_brightness():
set(pins, 1)

sm1 = StateMachine(1, led_quarter_brightness, freq=10000, set_base=Pin(25))


sm2 = StateMachine(2, led_half_brightness, freq=10000, set_base=Pin(25))
sm3 = StateMachine(3, led_full_brightness, freq=10000, set_base=Pin(25))
while(True):
sm1.active(1)
utime.sleep(1)
sm1.active(0)

sm2.active(1)
utime.sleep(1)
sm2.active(0)

sm3.active(1)
utime.sleep(1)
sm3.active(0)

Existem três métodos aqui que parecem um pouco estranhos, mas que definem o LED
on-board para um quarto, metade e brilho total. A razão pela qual parecem um pouco
estranhos é porque foram escritos em uma linguagem especial para o sistema PIO da Pico.
Você provavelmente pode adivinhar o que eles fazem - acendem e apagam o LED muito
rapidamente, de maneira semelhante ao como usamos o PWM. A instrução set(pins, 0)
desativa um pino GPIO e a instrução set(pins, 1) ativa o pino GPIO.
Cada um dos três métodos tem um descritor acima dele que diz ao MicroPython para tratá-lo
como um programa PIO e não um método normal. Esses descritores também podem receber
parâmetros que influenciam o comportamento dos programas. Nesses casos, usamos o
parâmetro set_init para dizer ao PIO se o pino GPIO deve ou não começar sendo baixo ou alto.
Cada um desses métodos - que na verdade são mini programas executados nas máquinas de
estado PIO - executa um loop contínuo. Assim, por exemplo, led_half_brightness irá
constantemente ligar e desligar o LED de forma que ele passe metade do tempo desligado e
a outra metade ligado. led_full_brightness fará um loop semelhante, mas como a única
instrução é ligar o LED, isso não muda nada.
O um pouco incomum aqui é led_quarter_brightness. Cada instrução PIO leva exatamente
um ciclo de clock para ser executado (a duração de um ciclo de clock pode ser alterada
configurando a frequência, como veremos mais tarde). No entanto, podemos adicionar um
número entre 1 e 31 entre colchetes após uma instrução, e isso diz à máquina de estado PIO
para pausar por esse número de ciclos de clock antes de executar a próxima instrução. Em
led_quarter_brightness, então, as duas instruções definidas levam, cada uma, um ciclo de
clock, e o atraso leva dois ciclos de clock, então o loop total leva quatro ciclos de clock. Na
primeira linha, a instrução set leva um ciclo e o delay leva dois, então o pino GPIO fica
desligado por três desses quatro ciclos. Isso torna o LED um quarto mais brilhante como se
estivesse constantemente aceso.
Depois de obter seu programa PIO, você precisa carregá-lo em uma máquina de estado. Como
temos três programas, precisamos carregá-los em três máquinas de estado (existem oito que
você pode usar, numeradas de 0 a 7). Isso é feito com uma linha como:
Os parâmetros aqui são:
O número da máquina de estado
O programa PIO para carregar
A frequência (que deve estar entre 2.000 e 125000000)
O pino GPIO que a máquina de estado manipula
Existem alguns parâmetros adicionais que você verá em outros programas que não
precisamos aqui.
Depois de criar sua máquina de estado, você pode iniciá-la e interrompê-la usando o método
ativo com 1 (para iniciar) ou 0 (para parar). Em nosso loop, percorremos as três máquinas de
estado diferentes.

Um exemplo real
O exemplo anterior foi um pouco artificial, então vamos dar uma olhada em uma maneira de
usar PIO com um exemplo real. Os LEDs WS2812B (também conhecidos como NeoPixels) são
um tipo de luz que contém três LEDs (um vermelho, um verde e um azul) e um pequeno
microcontrolador. Eles são controlados por um único fio de dados com um protocolo
dependente de tempo que é difícil de ser usado.
A fiação de sua fita de LED é simples, conforme mostrado na Figura C-1. Dependendo do
fabricante de sua fita de LED, você pode ter os fios já conectados, pode ter um soquete no qual
pode inserir os fios do conector ou pode precisar soldá-los em você mesmo.

Figura C-1 - Conectando uma fita de LED

Uma coisa que você precisa estar ciente é o potencial de consumo atual. Embora você possa
adicionar uma série quase infinita de NeoPixels ao seu Pico, há um limite para a quantidade
de energia que você pode obter do pino de 5V na Pico. Aqui, usaremos oito LEDs, o que é
perfeitamente seguro, mas se quiser usar muito mais do que isso, você precisa entender as
limitações e pode precisar adicionar uma fonte de alimentação separada. Você pode cortar
uma tira mais longa e deve haver linhas de corte entre os LEDs para mostrar onde cortar. Há
uma boa discussão sobre os vários problemas em hsmag.cc/neopixelpower.
Agora que temos os LEDs conectados, vamos dar uma olhada em como controlá-los com PIO:
import array, utime
from machine import Pin
import rp2
from rp2 import PIO, StateMachine, asm_pio

# Configure the number of WS2812 LEDs.


NUM_LEDS = 10

@asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT,
autopull=True, pull_thresh=24)
def ws2812():
T1 = 2
T2 = 5
T3 = 3
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]

# Create the StateMachine with the ws2812 program, outputting on Pin(0).


sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(0))

# Start the StateMachine, it will wait for data on its FIFO.


sm.active(1)

A maneira básica de isso funcionar é que 800.000 bits de dados são enviados por segundo
(observe que a frequência é 8000000 e cada ciclo do programa é de 10 ciclos de clock). Cada
bit de dados é um pulso - um pulso curto indicando 0 e um pulso longo indicando 1. Uma
grande diferença entre este e nosso programa anterior é que o MicroPython precisa ser capaz
de enviar dados para este programa PIO.
Existem dois estágios para os dados que chegam à máquina de estado. O primeiro é um bit
de memória denominado First In, First Out (ou FIFO). É para onde nosso programa Python
principal envia dados. O segundo é o Output Shift Register (OSR). É de onde a instrução out()
busca dados. Os dois estão ligados por instruções pull que pegam dados do FIFO e os colocam
no OSR. No entanto, uma vez que nosso programa está configurado com autopull habilitado
com um limite de 24, cada vez que lemos 24 bits do OSR, ele será recarregado do FIFO.
A instrução out (x,1) pega um bit de dados do OSR e o coloca em uma variável chamada x (há
apenas duas variáveis disponíveis no PIO: x e y).
A instrução jmp diz ao código para mover diretamente para um rótulo particular, mas pode
ter uma condição. A instrução jmp (not_x, "do_zero") diz ao código para mover para do_zero
se o valor de x for 0 (ou, em termos lógicos, se not_x for verdadeiro, e not_x for o oposto de x
- no nível de PIO, falar, 0 é falso e qualquer outro número é verdadeiro).
Há um fragmento jmp spaghetti (código cheio de desvios, de difícil leitura) que está lá
principalmente para garantir que os tempos sejam consistentes porque o loop tem que levar
exatamente o mesmo número de ciclos a cada iteração para manter o tempo do protocolo em
linha.
O único aspecto que temos ignorado aqui são os bits tipo .side(). Eles são semelhantes a set
(), mas ocorrem ao mesmo tempo que outra instrução. Isso significa que out (x, 1) ocorre
quando .side (0) está definindo o valor do pino sideset a 0.
Ufa, isso está acontecendo bastante para um programa tão pequeno. Agora que ele está ativo,
vamos ver como usá-lo. O código a seguir precisa estar de acordo com o acima em seu
programa para enviar dados a um programa PIO.

# Display a pattern on the LEDs via an array of LED RGB values.


ar = array.array("I", [0 for _ in range(NUM_LEDS)])

print("blue")
for j in range(0, 255):
for i in range(NUM_LEDS):
ar[i] = j
sm.put(ar,8)
utime.sleep_ms(10)

print("red")
for j in range(0, 255):
for i in range(NUM_LEDS):
ar[i] = j<<8
sm.put(ar,8)
utime.sleep_ms(10)

print("green")
for j in range(0, 255):
for i in range(NUM_LEDS):
ar[i] = j<<16
sm.put(ar,8)
utime.sleep_ms(10)

print("white")
for j in range(0, 255):
for i in range(NUM_LEDS):
ar[i] = (j<<16) + (j<<8) + j
sm.put(ar,8)
utime.sleep_ms(10)

Aqui, rastreamos uma matriz chamada ar que contém os dados que queremos que nossos
LEDs tenham (em breve veremos por que criamos a matriz dessa forma). Cada número na
matriz contém os dados para todas as três cores em uma única luz. O formato é um pouco
estranho, pois está em binário. Uma coisa sobre como trabalhar com PIO é que muitas vezes
você precisa trabalhar com bits individuais de dados. Cada bit de dados é 1 ou 0, e os números
podem ser construídos dessa maneira, de modo que o número 2 na base 10 (como chamamos
os números normais) é 10 em binário. 3 na base 10 é 11 em binário. O maior número em oito
bits de binário é 11111111, ou 255 na base 10.
Não vamos nos aprofundar muito no binário aqui, mas se quiser saber mais, experimente o
projeto Binary Hero aqui: hsmag.cc/ binaryhero.
Para tornar as coisas um pouco mais confusas, na verdade estamos armazenando três
números em um único número. Isso ocorre porque no MicroPython, os números inteiros são
armazenados em 32 bits, mas precisamos apenas de oito bits para cada número. Há um
pouco de espaço livre no final, pois realmente só precisamos de 24 bits, mas tudo bem.
Os primeiros oito bits são os valores azuis, os próximos oito bits são vermelhos e os oito bits
finais são verdes. O número máximo que você pode armazenar em oito bits é 255, então cada
LED tem 255 níveis de brilho. Podemos fazer isso usando o operador bit shift <<. Isso adiciona
um certo número de 0s ao final de um número, então se quisermos que nosso LED esteja no
nível 1 de brilho em vermelho, verde e azul, começamos com cada valor sendo 1 e, em
seguida, deslocamos o número apropriado de bits. Para verde, temos:
1 <<16 = 10000000000000000
Para vermelho nós temos:
1 << 8 = 100000000
E para o azul, não precisamos mudar os bits de forma alguma, então temos apenas 1. Se
somarmos todos eles, obteremos o seguinte (se adicionarmos os bits anteriores para torná-lo
um número de 24 bits):
000000010000000100000001
Os oito bits mais à direita são azuis, os próximos oito bits são vermelhos e os oito bits mais à
esquerda são verdes.
A última parte que pode parecer um pouco confusa é a linha:

ar = array.array("I", [0 for _ in range(NUM_LEDS)])

Isso cria uma matriz que tem I como o primeiro valor e, em seguida, 0 para cada LED. O
motivo de haver um I no início é que ele diz ao MicroPython que estamos usando uma série
de valores de 32 bits. No entanto, queremos apenas 24 bits disso enviados ao PIO para cada
valor, então dizemos ao comando put para remover oito bits com:

sm.put(ar,8)

Todas as instruções
A linguagem usada para máquinas de estado PIO é muito esparsa, portanto, há apenas um
pequeno número de instruções. Além dos que vimos, você pode usar:
in () - move-se entre 1 e 32 bits na máquina de estado (semelhante, mas oposto a out ()).
push () - envia dados para a memória que conecta a máquina de estado e o programa
MicroPython principal.
pull () - obtém dados do pedaço de memória que liga a máquina de estado e o programa
MicroPython principal. Não o usamos aqui porque, ao incluir autopull = True em nosso
programa, isso acontece automaticamente quando usamos out ().
mov () - move os dados entre dois locais (como as variáveis xey).
irq () - controla as interrupções. Eles são usados se você precisar acionar uma coisa
específica para ser executada no lado MicroPython de seu programa.
wait () - pausa até que algo aconteça (como um pino IO muda para um valor definido ou
uma interrupção acontece).
1 BIBLIOTECA WS2812B
Embora seja útil experimentar o programa WS2812B PIO, se você quiser
usá-lo em um projeto real, pode ser mais útil usar uma biblioteca que reúna
tudo. Há um exemplo em hsmag.cc/pico-ws2812b. Isso permite criar um
objeto que contém todos os dados de cor do LED e, em seguida, usar métodos
como set_pixel () e fill () para alterar os dados. Dê uma olhada na pasta de
exemplos desse repositório para obter mais detalhes sobre como usá-lo.

Embora haja apenas um pequeno número de instruções possíveis, é possível implementar


uma grande variedade de protocolos de comunicação. A maioria das instruções é para mover
dados de alguma forma. Se você precisar preparar os dados de alguma forma específica,
como manipular as cores que deseja que seus LEDs tenham, isso deve ser feito em seu
programa MicroPython principal, e não no programa PIO.
Você pode encontrar mais informações sobre como usá-los e a gama completa de opções
para PIO em MicroPython, em Raspberry Pi Pico no documento Pico Python SDK - e uma
referência completa de como PIO funciona no databook RP2040. Ambos estão disponíveis
em rptl.io/rp2040-get-started.
Primeiros passos com

MICROPYTHON
NA RASPBERRY PI PICO
Microcontroladores, como o RP2040 no coração da Raspberry Pi Pico, são como
computadores reduzidos ao essencial. Você não usa monitores ou teclados, mas os
programe para obter sua entrada e enviar sua saída para os pinos de entrada/saída.
Usando essas conexões programáveis, você pode acender luzes, fazer ruídos,
enviar texto para telas e muito mais. Em Primeiros Passos com MicroPython na
Raspberry Pi Pico, você aprenderá como usar a linguagem MicroPython para
iniciantes para escrever programas e conectar hardware para fazer sua Raspberry
Pi Pico interagir com o mundo ao seu redor. Usando essas habilidades, você pode
criar seus próprios projetos eletromecânicos, seja para se divertir ou para tornar sua
vida mais fácil.
O futuro da robótica está aqui - você só precisa construí-lo. Mostraremos como.

Você também pode gostar