Manual

do

Maker

.

com

I2C com ESP8266 e MicroPython

I2C com ESP8266 e MicroPython

I2C com ESP8266 e MicroPython

O ESP8266 é uma caixinha de mágicas, sem sombra de dúvidas. Há tão pouco tempo era confundido com um "wifi para Arduino", quando na verdade ele é por sí só um processador muito mais poderoso, rodando um sistema RTOS à 80MHz! E vejam só, essa máquina ainda tem o wifi de quebra. Mas sabia que o ESP8266 só tem I2C por software? E é sobre I2C com ESP8266 e MicroPython que falaremos hoje.

O que considero um verdadeiro disperdício de recursos é a implementação de uma interface AT, como de estivesse mandando comandos para os MODEMs de conexão discada do milênio (e século)  passado(s). Com tanto poder, claro que as melhores opções estão diretamente ligadas a um console interativo, como foi o caso do pioneiro NodeMCU.  Claro que existem opções agradabilíssimas como o Sming, mas que também não é um console interativo. Porém, como já apresentei em outros artigos (incluindo a construção do firmware em seu computador pessoal), a opção que outrora promissora fez-se agora em luz! O MicroPython em versão estável já está disponível (como citei nesse outro artigo) e já que vou discorrer sobre manipulação de bits, que seja do modo mais Pytho... digo, fácil - e divertido, digo assim de passagem.

Não tem um ESP8266 ainda?

Adquira com nosso parceiro Fulltronic nesse link.

Sem o ESP8266 você não pode testar nada, claro. Se tiver o ESP-01, talvez você consiga utilizar seus 2 GPIOs para fazer o barramento I²C, mas de qualquer modo minha recomendação é que você adquira um ESP8266 para isso e entre as minhas recomendações, esse ESP8266-12, para soldar na board. É o mesmo da imagem de inicio, eu mesmo soldei, mas recomendo que deixe os pinos para cima invés de para baixo, porque o propósito dessa board não é ser conectada à protoboard, mas sim dar um acesso direto aos pinos via jumper fêmea-macho/fêmea-fêmea. E não se preocupe com a soldagem, a placa foi projetada para facilitar o processo. Para não ter nenhuma preocupação, primeiro dei um pingo de super-bonder na board e deixei o ESP8266 posicionado adequadamente. Depois foi só brincar com a solda.

Prepare sua própria imagem do MicroPython...

Esse artigo foi atualizado, especialmente nessa parte. Atualmente recomendo baixar um firmware oficial.

Prepare o SDK do ESP8266

Essa é sem dúvida  a primeira parte. Não tenha medo de fazê-lo, caso esteja usando Linux.

git clone --recursive https://github.com/pfalcon/esp-open-sdk.git

Poderia colocar uma série de comandos seguidos, mas vou explicar cada passo. Após ter feito o clone, você deverá entrar no diretório esp-open-sdk e então fazer o update. Por fim, digitar o make.

cd esp-open-sdk
git submodule update --init
make axtls
make

Parece bastante simples, mas diversas dependências surgirão e a compilação terminará com erro em cada uma delas. A única que vou citar claramente é a texinfo, que não é objetiva na mensagem de erro. O que pode acontecer é que cada maker tenha aí em seu computador um erro diferente, então não desanime, apenas leia a parte de erro ao final de cada tentativa de compilação e você chegará ao final com certeza.

Algumas dependências que tive dessa vez:

sudo apt-get install python2.7-dev help2man texinfo gperf

Você precisa agora por o compilador no path. Para isso, substitua CAMINHO pelo caminho na linha a seguir. Isto é, supondo que você baixou o esp-open-sdk em seu home, substitua CAMINHO por til ('~').

export PATH=CAMINHO/esp-open-sdk/xtensa-lx106-elf/bin:$PATH

Depois, crendo que você ainda está no mesmo nível de diretório seguindo esse tutorial, prepare o ambiente para o MicroPython agora.

git clone --recursive https://github.com/micropython/micropython.git
cd micropython
git submodule update --init
cd esp8266
make

Parece simples, mas haverão erros. Um deles está relacionado ao mpy-cross, que você resolve mudando para o nível de diretório especificado, dando um make e retornando:

cd ../../../esp-open-sdk/micropython/mpy-cross/ 
make
cd -

E execute 'make' novamente. Se você teve paciência e chegou ao final da compilação, o primeiro passo é limpar a flash do ESP8266 e depois subir o novo firmware. Lembre-se de entrar em modo flashing, seja lá qual for o ESP8266 que você está utilizando. Feito isso:

esptool.py --port /dev/ttyUSB0 erase_flash

Se você não tem o esptool, simplesmente baixe-o. Tendo finalizado o erase, reinicie o ESP8266 e entre novamente em modo flashing. Agora é hora de subir o firmware novo:

esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m 0 build/firmware-combined.bin

Reinicie o ESP8266 mais uma vez. A velocidade de conexão é 115200. Utilize seu programa preferido. Eu uso o gtkterm.

PCF8574 - Expansor de I/O

Já escrevi também sobre o PCF8574 nesse outro artigo, onde utilizei um Raspberry. Mas nele, mostrei apenas como escrever seus bits diretamente nos pinos. Sugiro a leitura para conhecer melhor o dispositivo e em seguida volte desse ponto. Já? Então sigamos.

Como você pôde ver no artigo supracitado, o PCF8574 é I²C e a seu modo o MicroPython também dá suporte a esse barramento 2-wire. O que você pode sentir de diferença em relação ao Python em uma plataforma tradicional é que alguns recursos estarão disponíveis em lugares atípicos. O I²C por exemplo, invés de ser chamado assim:

#!/usr/bin/env python
from smbus import SMBus

i2cbus = SMBus(1)

...

Você deverá chamar:

from machine import I2C
from machine import Pin

sda = Pin(12)
scl = Pin(14)

i2cbus = I2C(scl,sda)
...

Mas calma, tentarei ser detalhista tanto quanto minha própria compreensão permitir.

Primeiramente, tenhamos em mente que SDA é DAta e SCL é CLock. O clock default é 400000, que pode ser modificado passando-o como parâmetro ao I2C. De agora já podemos começar a brincadeira.

Iniciando a comunicação

A única coisa estranha nessa comunicação é que o retorno será sempre em decimal. Para iniciar a comunicação, os primeiros passos são a configuração e seguidamente um scan para ver os dispositivos encontrados:

micropython-i2c-300x229.webp

Repare que o I2C recebe como parâmetro o objeto do pino, por isso previamente deve-se instanciar SDA e SCL como pinos e passá-los como parâmetro da instância i2cbus. Se você já tem experiência com Python ou outra linguagem de alto nível, nada de estranho, com certeza.

Python buffer protocol

Um problemas que tive de cara ao tentar escrever no dispositivo foi justamente relacionado ao buffer. A definição do método diz que os parâmetros são:

I2C.writeto(addr, buf, *, stop=True)

Dos quais obrigatoriamente você deverá passar o endereço encontrado no scan e o valor a escrever. Esse valor a escrever não pode ser um int direto. Você precisará criar esse buffer solicitado e para isso deverá utilizar o bytearray() com 1 byte:

buf = bytearray(1)
buf[0] = 255
i2cbus.writeto(36,buf)

Isso manterá todos os LEDS apagados. Estou utilizando apenas 6 LEDs, então posso manipular apenas 6 bits no momento. Também estou utilizando lógica invertida, isto é, aterrando no PCF8574 invés de acender os LEDs a partir dele. Exclarecido isto, vamos ao próximo passo.

Utilizar bitwise para manipular bits

Só vamos ver o básico disso, mas é assim que se manipula LEDs. Suponhamos que você queira acender apenas o LED 3 sem manipular os demais bits, não importando se eles estão acessos ou apagados. Como fazer?  - eu pergunto, eu respondo.

Para manipular um bit específico você deve aplicar uma máscara do mesmo comprimento e manipular o valor desejado. Eu quero acender o LED 3 do barramento de 8 bits e em 8 bits eu tenho 256 valores (de 0 a 255). Você não precisará calcular o valor de 2^2, apenas empurrar o bit assim:

buf[0] = int(buf[0])&~(1<<2)

Em detalhes, isso significa que o buffer (que é um bytearray) recebe na posição 0 o valor de buf[0] com o inverso que está no terceiro bit (lembrando que começa no bit 0, por isso o bit 2 é o terceiro bit). Se não fosse lógica invertida, não seria necessário a utilização do til ('~') após o '&'. Agora o bit 2 está ligado como na imagem a seguir:

0xff&~(1<<2)

Acenda o LED da posição 0 também. Ambos acesos? Agora, como apagar apenas o LED do bit 2? Nada de contas; apenas troque o '&' por um '|' (conheço esse simbolo como 'pipe', não é um 'L').

buf[0] = int(buf[0])|(1<<2)
i2cbus.writeto(36,buf)

O valor do bit 2 é invertido, os demais bits são preservados conforme seu estado atual. E se eu quisesse acender o LED 2, 4 e 6 ao mesmo tempo? Bem, ainda é mais simples do que fazer cálculo de bits:

buf[0] = 0xff&~(1<<1|1<<3|1<<5)
i2cbus.writeto(36,buf)

Como você pode ver, a máscara foi aplicada sobre 255 e empurrados os bits 1,3 e 5, que correspondem aos LEDs 2, 4 e 6.

0xFF&~(1<<1|1<<3|1<<5)

E essa foi nossa primeira brincadeira com o ESP8266 e o MicroPython estável. Gostaram? Se quiserem mais artigos a respeito do MicroPython, comentem nas redes sociais, eu atenderei com certeza!

Inscreva-se no nosso canal Manual do Maker Brasil no YouTube.

Próximo post a caminho!

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.