COMUNICAÇÃO I2C COM VARIOS ATMEGA8

Bom dia a todos,

Tenho um projeto em que precisam ser monitorados vários potenciômetros (um total de 44) utilizando o atmega8. Pensei em utilizar da comunicação i2c, colocando um atmega como mestre e outros 11 como escravos (eu sei, são muitos, mas tem que ser com atmega8 :~ ). Mas preciso de ajuda com a codificação deles, uma vez que quero que os escravos passem os dados dos potenciômetros identificados para o mestre e este por sua vez passe para o computador via serial. Alguém poderia me ajudar??

Obrigado.

Opa... Eu tinha esse site Expanding Arduino ports guardado para a prosperidade.

Vamos ver se outros colegas apresentam outras opções =)

A primeira pergunta que faço é que distancia estarao os dispositivos?
Pergunto isto porque o barramento I2C nao pode exceder uns centimetros (nao tenho agora o valor certo, depende da capacitancia, velocidade de transmissao)
Com 44 dispositivos parece-me que vais necessitar de muitos mais metros nao?
Eu talvez opta-se por RS485 ...

Mortis, é mais ou menos isso que eu quero. Só não entendi bem onde eu aplico tal código, afinal tem o mestre e escravo. Também não entendi o endereçamento. Contudo, isso me esclareceu bastante.

Hugo,

São 44 potenciometros, mas apenas 12 atmega (1 mestre e 11 escravos (6 adc - 1 sda - 1 scl = 4 adc disponiveis, 4x 11 = 44)). A distancia não ira interferir, o design é pequeno.

A minha dúvida principal é a codificação. Irei usar um atmega mestre ligado na serial via rx/tx e em 11 escravos via sda/scl (TWI/I2C). Quero saber qual o código que devo colocar nos escravos para que mandem os dados identificados (o dado do potenciometro 1 como POT1, por exemplo) e que o mestre entenda que este dado passado é do potenciometro 1 e passe para o pc, para que eu veja.

Se fosse apenas um atmega, seria isso: http://arduino.cc/en/Tutorial/AnalogReadSerial
o problema é que são 11 para apenas uma porta db9.

Obrigado por terem respondido.

Perdoe-me, mas tens de usar 1 atmega8 e poder usar alguns ADC (conversor analogo para digital) ou tens realmente de usar todos esses atmega8?

Aqui tem um exemplo usando I2c com dois arduinos (leia-se atmega ^^), parece-se exatamente o que queres =)

+1 Online Casino Sites In India 2022 | Best Online Casinos To Play At

Tem mais no google se procurarmos por arduino i2c :wink:

A distancia não ira interferir, o design é pequeno.

Com tantos dispositivos :roll_eyes:
Nao sei se poderas considerar isto como alternativa, mas talvez possas usar um multiplexer analogico de 8 para 1. O ic chama-se
74HC4051
Basicamente com ele consegues ler 8 entradas analogicas(nao em simultaneo claro) usando apenas 1 entrada no AVR.Necessitas de 3 linhas extra para fazer a seleçao do MUX da entrada que queres ler.

O que ainda ninguém referiu é que os pinos I2C no ATmega 8, 168 e 328 ficam no porto A... que coincidentemente é o porto do ADC.
Então vais ter 44/4 = 11 chips ATmega.

Isto é, a meu ver, um pouco ridículo. Importas-te de explicar a aplicação que pretendes fazer para darmos uma ideia sobre como melhor resolver isto?

A ideia do Hugo com um MUX parece-me a melhor. E ainda melhor seria um AD externo com vários muxes. Meia dúzia de chips e ficava tudo medido. Mas tu é que sabes.

Que precisão pretendes? 10? 8? 12? bits.

4 chips destes:

E tinhas a festa feita. O problema seria mesmo o facto de ser SPI e não I2C, ou seja, ocupar-te-ia 7 pinos em vez dos 2 que o I2C ocupa. No entanto, teria a vantagem de ser mais rápido. :slight_smile:

Acho que a tua dúvida se prende com algo chamado de protocolo de comunicação. Basicamente tens de definir um protocolo para passar os dados dum lado para o outro. Isso é o que não falta neste fórum. Tudo o que envolve comunicação entre ambas as partes envolve um protocolo.

Mortis, esses textos me ajudaram muito. Obrigado. 8)
É, realmente são muitos CIs, mas tem que ser assim. Não entendi bem a ideia do RS485. :relaxed:

Hugo e bubulindo, mux são digitais, preciso de leitura analógica. ADCs são uma ideia valida, mas transformarei uma entrada analogica em 8 saidas digitais, que ocuparia praticamente um atmega8 inteiro.

preciso que seja i2c, nao SPI. Velocidade não importa muito (o projeto anda com low speed).

Bubulindo,

O que, basicamente, quero fazer é monitorar os potenciometros (que podem ter o valores alterados simultaneamente ou nao) via computador (excel ou sei la qual programa). Para isso eu posso usar as entradas db9, db25 e usb. Usb é inviavel pra mim no momento. db25 é paralela, nao tem o porque usa-la. sobra a db9. Os dados dos pots serao coletados pelos atmegas. mas serao 11 atmegas para apenas uma db9. se eu usasse um mux aqui daria certo se os dados não fossem simultaneos. Entao eu pensei em usar um microcontrolador central para receber esses dados e enviar para o pc. Mas o problema é que eu preciso que os dados vao identificados, para que eu saiba qual pot foi alterado e qual nao foi. Entendeu?

o mux que o hugo referiu é analógico. escolhres um canal com pinos digitais, mas o valor passado é analógico.

não percebi isso da entrada analógica e 8 saídas...

isto é para um trabalho de escola?

identifgicar os dados é feito vcom um protocolo.

como garantes que as medidas entre atmegas são simultaneas?

Colega lê isto do Nick Gammon

Certamente no final iras entender melhor sobre o que este MUX analogico faz.
A minha sugestao do RS485 é devido a nao acreditar que iras conseguir ligar 12 dispositivos com I2C.Se conseguires irei ficar surpreso pois o I2C nao e feito para trabalhar da forma que tu o queres implementar.Ele foi desenvolvido para comunicar com perifericos na mesma PCB e nao suporta grandes distancias...
Como vais evitar a distancia dos cabos com 12 dispositivos?A nao ser montes tudo na mesma PCB ou breadboard ...
Estas a prever que distancia?

O microcontrolador do Arduino implementa internamente os resistores pull-up requeridos pelo protocolo I2C (normalmente de 1,5 Kohms); no entanto, é interessante colocar 2 resistores de 10 Kohms; o comprimento máximo dos cabos que levam os sinais I2C para as placas periféricas é de 1 metro, em função da capacitância (embora existam chips reforçadores de sinal I2C, como o Philips P82B715, que permite uma distância de até 50 metros).

Retirado daqui:

Bubulindo,

tenho alguns projetos da universidade que mexe com atmega. Mas esse é um projeto paralelo. Hmm, mux analogico seria interessante, mas ainda sim, eu prefiro mexer com hardware complexo do que com um firmware tenso por causa do mux.

Hugo,

São todos CIs na mesma PCB, faz parte do mesmo circuito. A distancia maxima entre um atmega e outro mais distante é de o comprimento de 3 atmegas, isso se eu nao usar shields, porque se usar, a distancia fica menor ainda.

Ok com essa distancia nao ha problema entao. :grin:

prefiro mexer com hardware complexo do que com um firmware tenso por causa do mux.

Talvez estejas a fugir a soluçao que te é mais facil.Repara, este MUX tem 8 entradas analogicas e uma saida.Essa saida ligas numa entrada analogica a tua escolha e depois para comutares a entrada so necessitas de ligar ou desligar os pinos de controlo.Super facil ...
Como sao 3 pinos de controlo o numero de combinaçoes possiveis serao 2 ^3 que dá 8 posiçoes

#define ANALOGICA A0

unsigned int POSentradaADC = 0;
unsigned int valoresADC[7];//Vector que ira armazenar os 8 valores analogicos para depois fazeres o que desejares
uint8_t i = 0;

void setup()
{
DDRB = 0x1F; //seta os 5 bits menos significativos do porto B como outputs 0b00011111
 /*O portB tem como pinos no Atmeha328 a seguinte ordem:
 bit0 do PortoB ----->Pino 8 no arduino
 bit1 do PortoB ----->Pino 9 no arduino
 bit2 do PortoB ----->Pino 10 no arduino
 bit3 do PortoB ----->Pino 11 no arduino
 bit4 do PortoB ----->Pino 12 no arduino*/
PORTB = 0;
}
void loop()
{
  leEntradasNoADC();
  delay(500);
}

void leEntradasNoADC()
{
 if(POSentradaADC>=9)POSentradaADC = 0;//Reseta pois ja atingiu as 8 posiçoes
 PORTB = POSentradaADC;//Escreve o valor no MUX escolhendo assim a entrada a ser lida
 valoresADC[i++] = analogRead(ANALOGICA);//Le o valor e armazena 
 POSentradaADC++;//Incrementa o valor e consequentemente muda o MUX
 
}

Ja tou com os olhos cheios de sono mas algo assim ou perto disso deve resultar.

Hugo, mux não dá certo. Enquanto ele está lendo um pot, ele tá ignorando os outros 7. O delay do ciclo de leitura pode cortar a leitura do atmega e me dar um valor errado.

Enfim, só preciso de uma iluminação sobre o código que seria para 11 atmega escravos e 1 mestre. seria algo assim?

para o mestre:

//Código para o ATmega8 Mestre

#include <wire.h>

void setup()
 {
	 Serial.begin(9600);
	 Wire.begin();
	 byte pot[11][4];	 
     int i = 0;
     int j = 0;
  }

int main(void)
{
   
    while(1)
    {
      for(j=0; j<11; j++)
       for(i=0; i<4; i++)
        {
         Wire.requestFrom(j+1,1);  
	     while(Wire.available())  
         {
		  pot[j][i] = Wire.read();  
		  Serial.print(pot[j][i]);      
		  }
         }
     }
 }

para o escravo

#include <Wire.h>

void setup()
{
  Wire.begin(1);                //endereço dos escravos vai de 1 a 11
  Wire.onRequest(requestEvent);
  
  int const pot1 = A0;
  int const pot2 = A1;
  int const pot3 = A2;
  int const pot4 = A3;
  int vpot[4] = 0;
  int i = 0;
  
}

void loop()
{
 vpot[0] = analogRead(pot1)/4; //precisão ADC de 10 bits
 vpot[1] = analogRead(pot2)/4; // mas I2C é 8 bits
 vpot[2] = analogRead(pot3)/4;
 vpot[3] = analogRead(pot4)/4;
 }


void requestEvent()
{
  Wire.write(vpot[i]); 
  if (i<3)
   i++;
  else if (i==3)
   i=0;                  
}

seria isso??

E julgas que o ATMEGA tem 5 ADCs?

Não. Tem um ADC e um mux analógico, logo não vais ler 5 canais ao mesmo tempo a não ser que invistas em hardwar especifico.

Se preferes hardware complicado, porque é que não contemplas ADCs externos?

Nunca vais conseguir fazer aquisição de 44 canais ao mesmo tempo, logo acho melhor começares a pensar nas tolerâncias que são aceitáveis.

Os potenciómetros serão usados por humanos?

Hugo, mux não dá certo.

Se tu o dizes entao prepara-te para abrir os cordoes à bolsa (€) pois vai ficar caro implementares isso :grin:
Nao entendo o teu ponto de vista.Como o Bubulindo te disse o proprio AVR implementa internamente um MUX para assim escolher a entrada … e toda a gente o usa e funciona.
Claro que será impossivel obteres samples todas ao mesmo tempo de todos os potenciometros, mas tambem fará assim tanta diferença leres um após outro? O sistema é assim tao complexo para ter essa necessidade?

É cada vez mais difícil sem saber o objetivo...

Se usar um mux, terás dentro de um loop a chamada pelo método exemplificado pelo Hugo:

void leEntradasNoADC()
{
 if(POSentradaADC>=9)POSentradaADC = 0;//Reseta pois ja atingiu as 8 posiçoes
 PORTB = POSentradaADC;//Escreve o valor no MUX escolhendo assim a entrada a ser lida
 valoresADC[i++] = analogRead(ANALOGICA);//Le o valor e armazena 
 POSentradaADC++;//Incrementa o valor e consequentemente muda o MUX
}

se usar a porta analógica do arduino, terás a mesma lógica no loop (o método analogRead):

val = analogRead(analogPin);    // read the input pin

Ou seja, a leitura em qualquer um dos casos será sequencial (uma após a outra, nunca ao mesmo tempo), e ainda tens a questão do tempo de leitura da porta e da precisão da leitura (considerou essas variáveis em relação ao que objetivas?). E mais a questão do desempenho do I2C.

Aqui falam um pouco sobre a velocidade de leitura das portas analógicas do arduino Arduino Forum.

Vejo pelos fóruns muitas pessoas usando usando ICs específicos por causa da precisão e ou velocidade de leitura dos atmegas usados no arduino.

E isso porque tenho a visão muitíssimo limitada, se comparar com a dos colegas Bubulindo, Hugo e outros feras do fórum.

Sim, Bubulindo, eu sei que há mux internos no MCU. mas se colocarmos mux nas entradas, vai ficar 8 portas em mux em outro mux... o tempo de resposta assim é exponencial.

Mortis, a velocidade de leitura das analogs é suficiente pra mim, só não posso abusar do tempo, pois a margem de erro que calculei.

Não, os pots irão acompanhar movimentos de máquinas. Mas são várias máquinas e elas tem movimentos independentes, que podem mover-se simultaneamente.

Aqui é R$, o que deixa o projeto mais caro ainda, mas custo já é risco calculado.

O código que eu citei serviria?

Ok... já que é assim, porque não teres ADs externos?
Estou farto de colocar esta questão e tu continuas sem responder...

Como calculaste o tempo que demora o envio das tramas?

Se você já considerou tudo o que foi sugerido, por mim, assunto encerrado ^^

Passando os olhos no teu código não vejo nada de errado (mas não confio tanto na minha visão rs), faz o upload e vê como o sistema se comporta 8)

Bubulindo, obrigado pela ajuda, está dispensado (não precisa mais ficar farto, ora).

Mortis, muito obrigado pela sua ajuda, respondeu o que eu queria saber.