quinta-feira, outubro 24, 2024

i2cpicousb: Um Adaptador USB para dispositivos I2C

Segundo projeto da Maratona 2024 concluído!

O i2cpicousb é uma adaptação do projeto I2C-Tiny-USB, usando uma placa com RP2040 ou RP2350 no lugar do ATtiny usado originalmente. Este adaptador permite escrever em um PC programas que interagem com dispositivos I2C conectados via USB.

O adaptador montado com um XIAO RP2040 e conectado a um relógio/memória PCF8583
Este projeto apresentou alguns desafios não esperados.

O primeiro deles foi a implementação da comunicação USB. O adaptador se identifica para o micro como um dispositivo da classe vendor e utilizada transferências de controle para trocar mensagens. A biblioteca tinyusb, usada no SDK da Raspberry Pi Pico, possui pouca documentação a respeito deste uso.

Resumindo, neste caso é preciso implementar a rotina de callback  tud_vendor_control_xfer_cb(), que é chamada nos três estágios de uma transferência de controle (SETUP, DATA e STATUS). Dentro do pacote recebido existe um código de comando (definido pelo projeto i2c-tiny-usb). 

A maior parte do processamento é feito no estágio SETUP, onde é montada a resposta que será enviada ao PC. No caso de um comando de leitura em dispositivo I2C, o adaptador deve enviar o endereço do dispositivo, conferir se foi aceito, ler a quantidade de dados especificada e passá-los para o i2c-tiny-usb enviar no estágio DATA. No caso de um comando de escrita, o adaptador deve, neste estágio, apenas enviar o endereço e conferir se foi aceito.

O estágio DATA precisa ser tratado apenas no caso do comando de escrita. É neste momento que os dados a serem escritos estão disponíveis para serem enviados ao dispositivo I2C.

O segundo desafio foi a comunicação I2C. A ideia inicial era usar o periférico I2C do microcontrolador, porém ele não oferece o controle necessário das condições de START e STOP nem suporta uma operação de escrita sem dados. A operação de escrita sem dados, embora não prevista na especificação I2C, é usada frequentemente para testar se um dispositivo com um certo endereço está conectado.

A solução foi relembrar os tempos de programação de PIC e implementar o I2C "na unha", usando GPIO.

Um ponto importante na solução é o suporte ao adaptador sob Linux, Windows e Mac (não testei este último). No Linux existe um driver que já vem incluso, para fins de teste existe o i2c-tools (que já usei com o Raspberry Pi OS). No Windows pode ser usado o driver genérico libusb, nos testes usei um módulo Python que sabe interagir com ele.

Maiores detalhes, inclusive o código completo, podem ser visto em https://github.com/dquadros/I2C-Pico-USB.

Nenhum comentário: