Guia 5 - Enviando dados da Labrador para o Arduino com I2C

De Caninos Loucos
Ir para navegação Ir para pesquisar

Guia 5 - Enviando dados da Labrador para o Arduino com I2C

Para que você possa contribuir com a Labrador, ou conduzir projetos em sala de aula, preparamos uma série de materiais que facilitarão o desenvolvimento de soluções que envolvem a programação de sistemas embarcados.

Neste quinto guia, você aprenderá a enviar dados da Labrador para o Arduino com I2C, para isso, utilize o Guia 5 disponibilizado abaixo:

Guia 5

Observações gerais

  • Pré-Requisito: "Guia 2 - Programando um LED com a Labrador"

Introdução

Durante o desenvolvimento de soluções embarcadas é comum precisarmos estabelecer a comunicação entre dois dispositivos distintos. A comunicação entre dois dispositivos só é possível quando estabelecemos um protocolo que seja capaz de viabilizar a troca de mensagens.


Um protocolo, por sua vez, pode ser tratado como uma convenção, composta por um conjunto de regras, que viabiliza a comunicação entre duas entidades distintas. Em outras palavras, um protocolo permite que criemos um conjunto de regras de comunicação para que uma "conversa" aconteça. No dia-a-dia, por exemplo, utilizamos protocolos para conversar com outras pessoas! Geralmente iniciamos uma conversa com uma saudação, por exemplo.

No universo dos microcontroladores, utilizamos um protocolo para estabelecer a comunicação entre dispositivos de baixa velocidade de transmissão, e microcontroladores, para quando os dispositivos não estão muito distantes. Este protocolo é o I2C, que significa Inter-Integrated Circuit. Este protocolo foi desenvolvido pela Philips em 1982 e tem por objetivo permitir que dois dispositivos se comuniquem de forma adequada, desde que um deles assuma o papel de dispositivo principal, e o outro possa atuar como um dispositivo agente.

Neste Guia vamos utilizar a labrador para enviar mensagens para o Arduino utilizando o protocolo I2C.

Ao final deste experimento você será capaz de:

1. Utilizar a IDE do Arduino em conjunto com a sua placa labrador 2. Estabelecer a comunicação entre a labrador (dispositivo principal) e uma placa Arduino (dispositivo agente) utilizando I2C

Observação 1

Para programar as GPIOs, enquanto a Caninos SDK estiver em modo de desenvolvimento, será necessário executar o Código 1 toda vez que você reiniciar a sua placa.

   sudo chown caninos /dev/gpiochip*
   sudo chmod g+rw /dev/gpiochip*

Código 1. Definição de permissões para o uso das GPIOs

Observação 2

Sempre mantenha a biblioteca atualizada, para isso, execute o Código 2 no terminal antes de começar a desenvolver novas soluções com sua labrador.

   pip3 install -U caninos-sdk

Código 2. Definição de permissões para o uso das GPIOs

[NOVO] Observação 3

Para utilizar o protocolo I2C será necessário autorizar as permissões de acesso, para isso, rode o Código 3.

   sudo chmod a+rw /dev/i2c-*

Código 3. Definição de permissões para o uso das GPIOs

[NOVO] Observação 4

Além disso, é necessário instalar a biblioteca listada abaixo:

pip3 install pylibi2c

Código 4. Definição de permissões para o uso das GPIOs

Componentes necessários

  • 1 Placa Labrador de 32 bits
  • 1 Placa Arduino Uno
  • 1 Hub USB para acesso a pelo menos três portas USB na Labrador
  • 3 Cabos MxF

Descrição do experimento

Conforme mencionado na introduçao deste guia, um protocolo é utilizado para garantir que as regras de comunicação sejam bem estabelecidas entre dois dispositivos diferentes. Desta forma, este experimento, diferente dos anteriores, utilizará duas placas distintas.

A Labrador assumirá o papel de placa principal, sendo capaz de enviar informações para a placa arduino. Já a placa Arduino Uno, assumirá o papel de placa agente, em que eventualmente, pode utilizar as informacões proessadas pela Labrador, para que desempenhe o seu papel enquanto um microcontrolador.

Esta comunicação utilizará duas linhas de transmissão (i) o Serial Data (SDA) e (ii) o Serial Clock (SCL). O SDA é responsavel por enviar e receber os dados de uma placa para a outra, já o SCL é utilizado para estabelecerum clock que garante a sincronia entre os sistemas.

Não nos aprofundaremos neste guia a respeito das diretrizes de uso do protocolo I2C. No entanto, destacaremos como utilizar a Caninos SDK para estabelecer a comunicação entre os dois dispositivos, bem como, construiremos juntos um exemplo para ilustrar esta comunicação.


Para isso, você deverá:

1. Estabelecer uma conexão entre as duas placas, conectando as portas SDA, SCL e GND do Arduino com as GPIOs necessárias para construção da infraestrutura de comunicação entre os dois dispositivos. 2. Escrever um código em linguagem Arduino, para que seja possível receber os dados enviados pela Laborador. 3. Escrever um código em Python, utilizando a Caninos SDK para que (i) a comunicação I2C seja estabelecida entre os dois dispositivos e (ii) seja possível enviar dados para o Arduino por I2C

Discutindo a montagem do circuito

Para lhe auxiliar no processo de montagem, utilize as portas destacadas na Figura 1. Esta figura consiste em um mapeamento de cada uma das GPIOs disponíveis na sua placa Labrador. Na hora de montar o seu circuito pelo menos duas vezes!

Figura 1

Além disso, também será necessário utilizar conexões com a placa arduino. Utilize a Figura 2, extraída do Student-Circuit (2023) como base para o mapeamento destas portas.

Figura 2. GPIOs disponíveis na placa Arduino Uno

Para estabelecer a comunicação entre os dispositivos, precisamos utilizar as portas de comunicação SDA e SCL estabelecidas para cada dispositivo. Veja a Figura 3 que ilustra esta montagem.

Figura 3. Conexões entre a Labrador e o Arduino Uno

Discutindo a montagem do programa

Do lado do Arduino...

Para programarmos o Arduino, utilizaremos a biblioteca Wire.h. Desta forma, utilize o Código 5 para importa-la em seu programa.

   #include <Wire.h>

Código 5. Importando as bibliotecas necessárias

Após isso, precisamos garantir que o preparo do Arduino, seja capaz de estabelecer as configurações mínimas para iniciar a comunicação entre os dispositivos. Note que não faremos isso manualmente, e para isso utilizamos as bibliotecas indicadas tanto para o Arduino, quanto para a Labrador.

Utilize o Código 6 para (i) definir o endereço de uso do dispositivo i2c (ii) adicionar um evento de resposta que ser "chamado" quando um dado for enviado ao Arduino (iii) iniciar a comunicação Serial.

   void setup(){
       Wire.begin(4);
       Wire.onReceive(eventoResposta);
       Serial.begin(9600);
   }

Código 6. Definindo a função de Setup no Arduino

A função onReceive() espera como parâmetro o nome de um evento. Este evento não foi criado ainda. Faremos isso logo mais, ok? Mas vale destacar que o nome eventoResposta poderia ser qualquer outro, desde que respeitasse as mesmas regras para criação do nome de uma função.

O Arduino, além da função setup(), possuí uma segunda função principal que é a função loop(). Esta função é invocada continuamente para que seja possível garantir que o Arduino utilize adequadamente o seu microcontrolador. Nesta aplicação a função loop pode ficar vazia.

Por fim, precisamos criar a função que será "invocada" para responder aos chamados da nossa placa Labrador. Esta função deve ter o mesmo nome que informamos no Código 6 e deve ter como parâmetro uma variável inteira. Veja o Código 7

   void eventoResposta(int quantidade){
       while(Wire.available()>0){
           char caractere = Wire.read();
           Serial.print(caractere);
       }
   }

Código 7. Capturando os caracteres enviados por I2C e exibindo o resultado

Neste trecho de código estamos capturando caractere por caractere que foi enviado pela comunicação I2C, e para cada um deles, armazenamos na variável local chamada caractere. Em seguida, exibimos este caractere. No final do laço de repetição, a mensagem enviada será completamente exibida.

Do lado da Labrador...

No lado da Labrador escreveremos um código em Python para estabelecer a comunicação entre os dispositivos e enviar uma mensagem importante!

Para estabelecer a comunicação entre os dispositivos é necessário importar a biblioteca da Caninos e em seguida adicionar o dispositivo que desejamos estabelecer a comunicação, utilizando I2C. Veja o Código 8.

   import caninos_sdk as k9
   labrador = k9.Labrador()


   labrador.i2c.add_device("arduino_i2c", 4)

Código 8. Preparando a Labrador para comunicação I2C

A terceira linha de código nos permite adicionar o arduino como um dispositivo I2C e estabelece o endereço de acesso como 4. Para enviar uma informação para o Arduino, utilize o trecho de Código 9.

   resposta = labrador.arduino_i2c.write("dados importantes\n")
   print (resposta)

Código 9. Enviando uma mensagem por I2C e recebendo uma mensagem I2C

O Código 9 destaca as duas funções principais implementadas para comunicação I2C. A função write() permite enviar dados para o Arduino. Esta função retorna uma resposta que pode ser exibida para indicar o sucesso do envio dos dados.

Caso tenha alguma dúvida, consulte a seção "Código do Experimento".

Código do experimento

Labrador

   #importamos as bibliotecas necessárias para utilizarmos a labrador
   import caninos_sdk as k9
   #esta biblioteca permite gerar uma pausa na labrador (um delay)
   import time


   #criamos nossa variável labrador, para uso dos recursos da placa
   labrador = k9.Labrador()


   #adicionamos o dispositivo I2C, definindo o endereço 4 de comunicação
   labrador.i2c.add_device("arduino_i2c", 4)


   #enviamos uma mensagem para o Arduino
   resposta = labrador.arduino_i2c.write("dados importantes\n")
   #imprimimos a resposta
   print (resposta)

Arduino

   //importamos a biblioteca Wire
   #include <Wire.h>


   //função chamada quando o arduino inicializa
   void setup(){
       Wire.begin(4); //definimos o endereço de comunicação
       Wire.onReceive(eventoResposta); //definimos a função de resposta (evento)
       Serial.begin(9600); //iniciamos o serial
   }
   //deixar vazio, não utilizamos neste exemplo
   void loop(){
   }
   void eventoResposta(int quantidade){ //função informada no setup
       while(Wire.available()>0){ //laço de repeetição, enquanto I2C estiver comunicando
           char caractere = Wire.read(); //lê dado recebido
           Serial.print(caractere); //imprime dado recebido
       }
   }