Cluster i2c com Arduino

i2c com Arduino
i2c com Arduino
i2c com Arduino

i2c com Arduino

Iniciando meus testes com intercomunicação, na noite passada fiz a prova com i2C com Arduino. Hoje reproduzi o teste com o hardware da LightComm (nossos agradecimentos à empresa pela colaboração com o software livre!). Esses testes não fazem parte de nenhuma especificação de projeto, além de ser o básico da comunicação i2C, por isso o estou descrevendo aqui.

Dependendo da quantidade de pinos necessários para seu projeto, pode ser muito viável a utilização do Arduino Mega, que possui mais de 50 portas – e pode ser válido mesmo que não se pretenda utilizar todas. Porém, um projeto menor ainda pode utilizar mais do que as portas de um Arduino Uno, então para esse problema pode-se fazer um pseudo-cluster utilizando dois ou mais Atmega328P e i2C. E existem duas maneiras de fazer isso, ambas tendo suas aplicações:

– Ligando Arduino Uno em paralelo
Nesse caso, seu projeto pode ter sofrido um esgotamento dos recursos ou o processamento está sendo demasiado grande para o módulo. Nesse caso, cria-se uma rede i2C emparelhando os dispositivos e ampliando assim o número de portas e dividindo a carga (através da distribuição entre os pinos de ambos).

– Montar uma placa modular
Montar uma board que seja capaz de receber 2 ou mais chips Atmega328P não é trabalhoso nem custoso e esse recurso permite um ‘upgrade’ do seu dispositivo em caso de necessidade de clusterização do módulo, apenas adicionando outro chip à board.

para esse teste será necessário possuir 2 módulos Arduino. O farei com 2 Arduino Uno.

O que é i2C
O i2C (i-squared cee) é uma forma de comunicação serial entre dispositivos de baixa velocidade com motherboard, sistemas embarcardos, telefones celulares e afins.
Em muito mais detalhes, você pode ler a respeito nesse artigo da wikipedia.
A comunicação i2C utiliza duas linhas abertas – Serial Data (SDA) e Serial Clock (SCL). Utiliza-se comumente voltagens de 3.3V ou 5V, mas é possível a utlização com outras tensões.

Há um limite de 112 nós por barramento, qnos modos e 10/100 (kbit/s, não se empolgue). Versões mais recentes do i2C podem chegar a 3.4Mbit/s e até 10bits de endereçamento.

Apesar de realmente se tratar de uma ‘rede’, a capacitancia de 400 pF restringe a distância de comunicação para poucos metros – mas o suficiente para interconexões, mantendo o foco em divisão de processamento ou distribuição de recursos.

Interconexão dos dispositivos
É simples demais:
– ligue o pino analógico 4 do Arduino A ao pino analógico 4 do Arduino B.
– ligue o pino analógico 5 do Arduino A ao pino analógico 5 do Arduino B.

No meu teste ambos estão conectados ao meu notebook, portanto compartilham de um ground em comum. Porém se as alimentações forem destintas, não se esqueça de compartilhar um aterramento para que não haja flutuações, pois nesse caso a comunicação falhará.

O código
A comunicação é feita entre Master e Slaves. No exemplo, apenas 1 slave. Utilizei a biblioteca padrão Wire. Para o Master utilizei o código do post sobre a ethernet 28J60, apenas incluindo a parte de código para wire, dentro de uma função chamada writeI2C. Quando é feita uma atualização no browser, a informação é enviada também pelo barramento i2C para o Arduino Slave, que está utilizando o código padrão dos exemplos de wire – o slave_receiver:

// M A S T E R - wire + web server
 #include "etherShield.h"
 #include "ETHER_28J60.h"
 #include <Wire.h> int outputPin = 2;
 //***** config para leitura do LM35 *****//
 int LED = 5;
 int pin_reader = 0;
 int freq;
 float temp1;
 String msg = " ";
 char buf[50];
 
//********* parametros de rede **********//
 static uint8_t mac[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x24};
 static uint8_t ip[4] = {10, 0, 0, 252}; static uint16_t port = 80;
 //***** ID dos sensores char id[] = {'A','B','C','D'};
 //***** criando objeto da ethernet ******// ETHER_28J60 e;
 void writeI2C(String str,byte pos){ byte buf = 'S';
 // (S)tart int strSize = str.length();
 Wire.beginTransmission(4); //device remoto
 Wire.write(pos);
 Wire.write('-');
 for (int s=0;s<strSize;s++){
    buf = str.charAt(s);
    Wire.write(buf);
 }
 Wire.endTransmission();
 }
 void setup() {
 e.setup(mac, ip, port);
 pinMode(pin_reader,INPUT);
 pinMode(LED,OUTPUT);
 Wire.begin(); //Para o master o endereco eh opcional
 } void loop() {
 if (e.serviceRequest()) {
     e.print("<H1>LightMon 1.0</H1><br/><table>");  
     e.print("<tr><th>Input</th><th>Value</th></tr>");
 for (int i = 0; i < 4; i++) {
     freq = analogRead(i);
     temp1 = (5.0*freq*100.0)/1024.0;
     msg = dtostrf(temp1,3,2,buf);
     e.print("<tr><td>");
      e.print(i);
      e.print("</td><td>");
      e.print(buf);
      e.print("</td></tr>");
      writeI2C(msg,byte(id[i]));
 }
 e.print("</table>");
 e.respond();
 } delay(100);
 float sensor0; 
 freq = analogRead(5);
 sensor0 = (5.0*freq*100.0)/1024.0;
 if (sensor0 > 28.0 && sensor0 < 30.0){
 analogWrite(LED,30); 
}
 else if (sensor0 > 30.0){ 
analogWrite(LED,255); 
} else{ analogWrite(LED,5); } 
}
//(identação apodrecida quando colei o codigo aqui...)

O slave é o padrão da lib da IDE, mas para que não seja necessário abrir o código na interface de desenvolvimento do Arduino enquanto você Lẽ este post, eis o código do Slave:

// Wire Slave Receiver
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Receives data as an I2C/TWI slave device
// Refer to the "Wire Master Writer" example for use with this

// Created 29 March 2006

// This example code is in the public domain.
#include <Wire.h>

void setup()
{
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
}

void loop()
{
delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
while(1 < Wire.available()) // loop through all but the last
{
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}

Compile os programas e suba-os nos dispositivos; tenha-os conectados devidamente como descrito anteriormente. Agora, abra o monitor serial no dispositivo SLAVE. Abra no browser a URL do Master e veja a informação que é apresentada ser também exibida no serial do Slave!

Você encontra outras referências com I2C, através desse link.

Um video sem grandes informações:

2 Comentários


  1. Esse é um exemplo de comunicação ou realmente eles dividem processamento ? Ampliar IO ok mas aumentar capacidade de processamento sem dividir código entre eles não é possível certo ?

Deixe uma resposta