LusoRobótica - Robótica em Português
Robótica => Iniciantes => Tópico iniciado por: marlon.tiedt em 04 de Dezembro de 2014, 01:37
-
Pessoal estou estudando a comunicação I2C pelo Arduino. Estou querendo fazer a comunicação com o shield MPU-6050 e estou seguindo este tutorial http://playground.arduino.cc/Main/MPU-6050 (http://playground.arduino.cc/Main/MPU-6050) para entender a comunicação I2C.
As coisas que já entendi, é que todo componente com I2C tem o seu próprio endereço e os seus próprios registradores.
Neste exemplo tem estas linhas de código:
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);/
O código Wire.write(0x6B);
indica que quero acessar o endereço 0x6B? Se sim, como o controlador sabe que o próximo byte é valor que vai ser escrito? Ou o I2C por padrão é assim, mando o endereço o componente, um registrador e depois o valor.
Como sei se é escrita ou leitura?
Outra coisa, se eu tiver um segundo parâmetro em seguida tenho que mandar o endereço e depois o valor, ou posso mandar o valor direto? Se o valor para setar for igual a 0x6B, como ele vai entender que é um valor e não para ir no endereço?
Se eu tiver no minha rede I2C um parâmetro igual a um endereço, como os slaves se comportam?
Neste código
Wire.beginTransmission(address);
Wire.write(0x03);
Wire.endTransmission();
Wire.requestFrom(address, 6);
o requestFrom(address, 6); pede 6 próximos bytes a partir do 1 endereço?
Tentei colocar todas as dúvidas direto para não ficar perguntando por partes.
[/code]
-
Bom, assim por alto:
O bus I2C em si apenas define como se faz a communicação (transmissão de dados) entre dispositivos; o que cada dispositivo faz com esses dados "é lá com ele", ou seja, está escrito na sua datasheet.
Na verdade o I2C destingue entre dispositivos mestre e dispositivos escravo, ou seja, há 2 tipos de dispositivo, sendo que apenas os do tipo mestre podem iniciar uma leitura ou escrita de dados de um dispositivo escravo (se 2 mestres pretenderem comunicar, um deles tem que se transformar em escravo temporariamente). O mestre é quem sempre controla a linha de clock (SCL), que regula o ritmo de transmissão de dados (os dados viajam na linha de dados, SDA). Quando falamos em "escrever" e "ler", é do ponto de vista do mestre, o mestre escreve ou lê dados do escravo.
Uma consequência da forma como o bus funciona é que um escravo não tem maneira de iniciar uma transmissão de dados para o mestre (excepto se se tornar num mestre!); se ele quiser enviar algo ao mestre, tem que o avisar de outra maneira (por exemplo por uma linha dedicada de "interrupção") e então o mestre é que faz a leitura dos dados do escravo.
O mestre tipicamente é um microcontrolador/processador e o escravo é um periférico/memória/sensor/etc.
O bus funciona por transmissão de "mensagens". Uma mensagem transporta um conjunto de bytes entre 2 dispositivos (sempre 1 mestre e 1 escravo), e começa com um "sinal especial" (ao nível eléctrico, chamado START CONDITION) que marca o inicio e outro sinal especial que marca o fim (STOP CONDITION). Existe ainda um bit especial de confirmação de recepção (acknowlege, ACK) depois de cada byte transmitido (quem recebe o byte confirma a recepção a quem o enviou), e uma forma de controlo de fluxo, em que o escravo pode dizer ao mestre "ei, espera aí um bocadinho, tás a falar/pedir muito depressa!", o chamado CLOCK STRETCHING (consiste no escravo "segurar" a linha de clock (SCL) a zero durante o bit de ACK, impedindo o mestre de transmitir clocks).
O 1º byte de cada mensagem é uma escrita (o mestre escreve para o escravo) que indica o endereço do escravo (7 bits) e se a operação é de leitura ou de escrita (1 bit); depois o mestre escreve ou lê dados conforme o tipo de operação escolhida no 1º byte.
Entendendo "por alto" como funciona o bus, tens que consultar a datasheet do dispositivo mestre e a do dispositivo escravo para saberes:
1) do lado do mestre, como endereçar um escravo e como efectuar escritas e leituras (no teu caso, tens a documentação da API do arduino do site do arduino)
2) do lado do escravo, que mensagens ele está preparado para receber/enviar e qual a sua composição (no caso, na datasheet desse MPU6050 (não sei o que é, não fui ver))
-
Wire.beginTransmission(MPU);
Aqui MPU deverá ser uma variável que tem o endereço do dispositivo com o qual o arduino vai comunicar.
A instrução Wire.write(x) envia valores para o dispositivo. Wire.write(0x6B) vai mandar o valor 0x68 para o dispositivo selecionado em Wire.beginTransmission(endereço); que já estará espera dele ou até de mais valores se fôr o caso.
Já a instrução Wire.requestFrom(address, x); indica ao dispositivo que tem o endereço "address" para enviar ao arduino x bytes, que serão colectados com as funções available() e read() .
Consulta a página do site do arduino que explica bem estas funções.
-
Valeu pelas dicas. Se eu fazer o código abaixo, vai escrever 0 no endereço 0x00 e 2 no endereço 0x01 ou vai escrever 0 no endereço 0x00 e depois 2 no mesmo endereço.
Wire.write(0x00);
Wire.write(0);
Wire.write(2);
Ou tenho que fazer isto, para escrever nos dois endereços:
Wire.write(0x00);
Wire.write(0);
Wire.endTransmission();
Wire.write(0x01);
Wire.write(2);
Wire.endTransmission();
-
Boa explicação Njay
-
Valeu pelas dicas. Se eu fazer o código abaixo, vai escrever 0 no endereço 0x00 e 2 no endereço 0x01 ou vai escrever 0 no endereço 0x00 e depois 2 no mesmo endereço.
Wire.write(0x00);
Wire.write(0);
Wire.write(2);
Ou tenho que fazer isto, para escrever nos dois endereços:
Wire.write(0x00);
Wire.write(0);
Wire.endTransmission();
Wire.write(0x01);
Wire.write(2);
Wire.endTransmission();
RTFM!
Os engenheiros perdem tanto tempo a escrever datasheets e depois ninguém lhes liga nenhum :(
Tens a resposta nas páginas 35 e 36 da datasheet do MPU 6050 : http://www.invensense.com/mems/gyro/documents/PS-MPU-6000A-00v3.4.pdf (http://www.invensense.com/mems/gyro/documents/PS-MPU-6000A-00v3.4.pdf)
-
Obrigado pela resposta jm_araujo.
Mas a minha dúvida é, o I2C se comporta assim ou depende do CI?
-
Tens sempre de ler as datasheets (é para isso que elas servem), cada IC implementa as partes que lhes interessa, e há alguns com umas manias bem estranhas: Recordo-me de memórias que se fizeres leituras(ou eram escritas?) sequenciais não mudavam de página de ?256bytes?, ficavam sempre na mesma, para alterar tinha-se de iniciar nova leitura.
Como já foi muito bem dito:
O bus I2C em si apenas define como se faz a communicação (transmissão de dados) entre dispositivos; o que cada dispositivo faz com esses dados "é lá com ele", ou seja, está escrito na sua datasheet.
-
Só escreve num endereço novo se fizer incrementação automática do endereço, mas tambem pode estar á espera de receber um valor de 16bits, ou 24, ou 32, ou mais bits para um só endereço e terás de fazer várias escritas para o mesmo endereço.
Se não queres ler, sacas uma biblioteca para esse chip, escreves chip.begin e chip.read e está feito, continuas é sem entender como é que funciona, mas mesmo a biblioteca i2c do arduino não é das melhores, esconde algumas coisas(ack's e nak's, o bit read/write do endereço, entre outros).
-
Só escreve num endereço novo se fizer incrementação automática do endereço, mas tambem pode estar á espera de receber um valor de 16bits, ou 24, ou 32, ou mais bits para um só endereço e terás de fazer várias escritas para o mesmo endereço.
Se não queres ler, sacas uma biblioteca para esse chip, escreves chip.begin e chip.read e está feito, continuas é sem entender como é que funciona, mas mesmo a biblioteca i2c do arduino não é das melhores, esconde algumas coisas(ack's e nak's, o bit read/write do endereço, entre outros).
Por isto estou tentando entender o padrão. Pois o Wire do Arduino esconde muita coisa mesmo. E vários post da internet, muitos são parecidos.
-
Não há nada melhor do que ler um pdf de uma memória da Philips para entender o protocolo I2C.
Entretanto já consigo ler e escrever neste tipo de ICs como nos RTCs, sensores, etc..., através da porta paralela do pc ou de um microcontrolador programado em assembler.
http://www.nxp.com/documents/data_sheet/PCF8582C_2.pdf (http://www.nxp.com/documents/data_sheet/PCF8582C_2.pdf)
-
Podemos sempre ler o que uma das pessoas que criou o protocolo tem a dizer sobre o mesmo:
http://www.siliconvalleygarage.com/i2cfaq/i2cfaq_000_index.htm (http://www.siliconvalleygarage.com/i2cfaq/i2cfaq_000_index.htm)
Tambem conhecido como free_electron no eevblog.
-
Uma das pessoas que criou o protocolo? Com o que ele diz na FAQ, não me parece:
Who put this FAQ together?
I put this FAQ together in response to my own frustration in searching for information about I2C. (...)
O I2C parece catita no papel, mas quando vamos realmente usar a coisa, as implementações de chips (principalmente mestres) por esse mundo fora estão "cheias" de bugs, dos AVR ao RaspberryPI*. Já tive que lidar com I2C em pelo menos 3 ou 4 projectos profissionais mais 1 pessoal e em absolutamente *todos* encontrei problemas com bugs do hardware e implementações de sw, que especialmente se traduzem em problemas que ocorrem esporádicamente (portanto, mesmo dos bons; uma vez passei uma bela noite no laboratório, eu, um analizador lógico e uma placa com um bus I2C). E foram só sistemas de 1 mestre, nem quero imaginar sistemas multi-mestre. Os locks de bus são os mais giros, quando há 3 ou mais dispositivos pendurados no bus; em geral é difícil ou quase impossível descobrir quem é que está a prender o bus**. A verdade é que a implementação do I2C é complexa, não passa pela cabeça de ninguém a quantidade de estados e casos possíveis que isto tem, para ser bem implementado. Admito que é um bus só uso se for "obrigado", eventualmente posso usar para aceder só a uma EEPROM ou chip simples mas mesmo assim... cuidado na escolha do hw mestre.
*O (SoC do) RaspberryPi tem um bug no clock stretching; em certas condições simplesmente ignora o pedido de stretching do escravo, resultando em locks temporários do bus e corrupção de mensagens. Sim, também já fui "mordido" por este.
**Uma dica: num sistema complexo, deixem no PCB maneira de poder desligar qualquer um dos dispositivos escravo do bus, ponham 2 jumpers/resistências de 0 Ohm em série com as linhas à entrada do dispositivo. Desta forma podem isolar o dispositivo do bus se tiverem problemas.
-
Felizmente nunca tive que usar I2C :) Mas tenho encontrado testemunhos com o Njay dos problemas daquilo. Acho estranho principalmente porque ja devia ser um protocolo "maduro".
Tenho a impressão que a maior parte das erratas relacionadas com I2C, sao devido a novas expansões (plus plus plus...) ao protocolo original.
'E quando as leio que penso para mim "espero nunca vir a precisar disto!" ???
-
Provavelmente estou a confundir com outro nome, sorry.
Até me sinto melhor ao saber que não é só comigo que sempre que há alguma coisa a falar i2c que há sempre algum problema inesperado, a ultima guerra foi com um PCA9685.
-
Como nunca mexi com I2C, estas informações são muito valiosas.
Estou querendo mexer com acelerômetros e giroscópios, e encontrei o MPU-6050. Mas o que me desanimou foi o I2C. Já vi acelerômetros com saidas digitais, que eu acho mais tranquilo de trabalhar, pois cada elemento tem uma saída analógica.
Porém não achei nenhum giroscópio com saída analógica, será que existe? E claro, outros componentes como magnétron e medidor de pressão e altitude, tudo usa I2C.
E minha singela opinião, ler 3 saídas analógicas é mais rápido do que ler 6 bytes.
-
Se for com um Arduino não, porque a ADC corre a pouco mais de 10Khz, e depois introduzes ruidos, problemas a desenhar filtros analógicos, bla bla bla.
Esses sensores são muito, muito usados, tens milhentas bibliotecas, quem não conhece, aqui fica uma boa base de dados de código comprovado e testado:
http://www.i2cdevlib.com/ (http://www.i2cdevlib.com/)
-
Não senso, não é só de ti que o I2C não gosta :)
Não Kamm., não tem nada a ver com extensões ao I2C, são simplesmente bugs de implementação da funcionalidade básica.
-
A ultima coisa estranha foi mesmo o PCA ser um Plus(ou plus + ou lá o nome do i2c rápido esta semana) que devia funcionar a 1Mhz, mas acima de 400Khz e passa-se quando tento mudar o prescaler do clock, o sinal tem uma forma bonita, tem os devidos pull-ups e pistas curtas, mas nem me preocupei muito com aquilo, a 400Khz funciona rápido o suficiente.
-
Na DiffTrike (http://myownhybrid.wordpress.com/) temos um RasPI ligado a 2 isoladores galvânicos I2C que ligam a 2 AVR (que controlam as pontes-H de potência), por um cabo "em Y" que terá cerca de 50cm entre o PI e cada AVR, e I2C a bombar a 500 kbps (a 3V3). Temos uma "checksum", mas nunca vimos nenhum erro. Agora bomba, mas não sem antes termos partido a cabeça com o bug no I2C do PI.
O isolador I2C foi crucial para detectar o bug do PI, porque pela forma como funcionam estes isoladores; o sinal "low" tem uma tensão ligeiramente diferente para o mestre e para o escravo, o que permitiu perceber quem é que estava a fazer o quê.
O cabo não foi escolhido à toa, é um cabo de rede, que escolhi por causa de ter vários pares entrançados; cada sinal (SDA, SCL) tem o seu próprio par, em que o GND é ligado nas 2 pontas. Por ser entrançado reduz a inductância do cabo (e logo distorções, emissões de EMI e susceptiilidade a EMI) e o crosstalk (por serem pares separados e viajarem com o seu próprio GND). A alimentação para o isolador I2C também viaja pelo cabo, no seu próprio par entrançado o que também ajuda a reduzir a inductância e logo problemas de alimentação (quando se tenta puchar corrente muito depressa através duma inductância, ela opõe-se fazendo baixar a tensão, e vice-versa).