The Inter-Integrated Circuit (I2C) bus is a chip-level serial communications mechanism that operates over just two wires. Alguns desenvolvedores pronunciam o nome do ônibus eye-two-see, outros eye-squared-see, mas ambos se referem à mesma coisa. Concebido pela Philips no início dos anos 80, o I2C foi estabelecido para padronizar as comunicações entre os chips da empresa, mas desde então tornou-se um padrão de facto suportado por muitos dispositivos de microcontroladores de Arduino boards para o Raspberry Pi e, claro, PIMS.,o próprio barramento físico compreende dois fios. Uma linha I2C transmite dados, a outra os sinais do relógio que sincronizam a conversa entre dispositivos. A linha de dados é chamada ‘SDA’, a linha de relógio ‘SCL’.tipicamente, ambos SDA e SCL são conectados a uma linha de energia de 3,3 ou 5V através de uma única resistência “pull-up”, uma em cada linha. Isto é necessário porque as conexões SDA e SCL dos dispositivos são linhas de “dreno aberto”: eles podem forçar a tensão na linha para 0V, ou “baixo”, mas não pode elevá-lo para 3,3 V, ou “alto”., Altas e baixas são as representações elétricas dos 1s e 0s que são os componentes fundamentais da informação digital. A adição destas duas resistências — e o barramento precisa apenas de duas, não importa quantos dispositivos estejam conectados a ele-garante que a tensão sobe de volta para 3,3 V sem um curto-circuito.
I2C insiste que os dispositivos têm linhas de drenagem abertas para garantir que nenhum componente-ferindo altas correntes são capazes de fluir quando dois dispositivos tentam sinalizar simultaneamente.
na maioria dos casos, você será esperado para adicionar essas resistências você mesmo, mas alguns dispositivos, tipicamente aqueles que operam a 3.,3V, incluem-los, a fim de ser compatível com dispositivos de fornecimento de 5V. Lembre-se, você só precisa de um par de pull-up resistências por autocarro, de modo que pode ser necessário para remover pull-up resistores ligados a outros dispositivos no barramento. Embora o PIM tenha resistências internas de pull-up próprias, estas são muito fracas para serem úteis para o I2C e por isso são automaticamente desativadas quando seus pinos são configurados para lidar com sinais de I2C.
Controladores E Periféricos
O barramento I2C separa os dispositivos em “controladores” e “periféricos”., Apenas um dispositivo pode enviar pulsos de tempo na linha SCL de cada vez, e esse é o escolhido para ser o controlador. Todos os outros sincronizam seus horários com o controlador, e são, portanto, considerados periféricos. O controlador — tipicamente o imp-e seus periféricos podem todos transmitir e receber dados, mas apenas o controlador pode dizer a um periférico quando transmitir dados de volta.
endereçamento
para que um dispositivo I2C comunique com outro numa base de um para um, ambos os dispositivos precisam ser identificáveis de forma única. Esta identidade é o endereço I2C do dispositivo., Endereços I2C são normalmente números de 7 bits, então um barramento pode incluir até 127 dispositivos ao todo. Um byte compreende oito bits; o bit extra é usado para indicar se o sinal está sendo enviado pelo controlador para o periférico — um ‘write’ — ou na outra direção — um ‘read’. Este oitavo bit é na verdade o bit zero no endereço byte enviado para o ônibus. O endereço de 7 bits é colocado em bits de um a sete do byte de endereço.
de acordo com este formato, a API imp toma um endereço I2C como um valor de 8 bits., Os fornecedores de dispositivos geralmente dão os endereços de seus produtos como um número de 7 bits, então é necessário converter o endereço de sete bits para oito. This is a achieved with Squirrel’s<<
operator, which moves a number’s individual bit values to the left. Este processo é o equivalente à multiplicação por dois. Em Código, este processo se parece com este:
local sevenBitAddress = 0x39;local eightBitAddress = sevenBitAddress << 1;
Esquilo automaticamente define bit zero para o valor correto definido por I2C: 0 para uma operação de Escrita, 1 para uma leitura., Agora você está pronto para usar um dos métodos I2C do imp para escrever dados para o barramento:
i2c.write(eightBitAddress, dataInStringForm);
o endereço de 7 bits do dispositivo com o qual você quer que o seu imp comunique será fornecido pelo fabricante do componente e listado na ficha do dispositivo. Pode não ser fixo, mas selecionado a partir de uma gama de endereços de acordo com a tensão aplicada a outro dos dispositivos pinos., Por exemplo, um TAOS TSL2561 sensor de luz tem três endereços: 0x29
0x49
ou 0x39
, dependendo se o seu ENDEREÇO de pin é fixada em 0V, 3.3 V ou ‘flutuante’ entre os dois. Dizemos que o valor está flutuando porque não foi ativamente selecionado para operar em uma tensão específica; pode ser qualquer coisa de 0 a 3.3 V inclusive.
sinalização
O controlador de barramento I2C usa o endereço de 7 bits de um periférico para identificar o componente com o qual ele quer falar., Na verdade, a sinalização é mais complexa do que isso, mas felizmente todos os detalhes são tratados pelo imp de modo que você só precisa fornecer o endereço como um valor de 8 bits.
Se você está escrevendo para o periférico, você também precisa fornecer os dados para escrever, que muitas vezes inclui valores de registro que instruem o periférico o que fazer com os dados. A documentação da API imp refere-se a estes registos como ‘sub-endereços’:
i2c.write(eightBitAddress, dataString);
write() requer dados em forma de cadeia de caracteres. Consequentemente, você pode precisar converter o valor armazenado em outros tipos de variável em forma de cadeia de caracteres.,
ler informações de um dispositivo pode exigir um comando para dizer ao dispositivo quais os dados a obter. Dizer ao imp para ler os dados do barramento I2C também envolve fornecer um terceiro parâmetro, o número de bytes que você espera receber:
i2c.read(eightBitAddress, controlDataString, numberOfBytesToRead);
por trás destas operações são os sinais elétricos do I2C, aplicados à linha SDA sincronizados com os pulsos de tempo aplicados à linha SCL. A escrita para o barramento envolve um marcador inicial: largando SDA para 0V enquanto SCL é 3.3 V. mudar a tensão SDA quando a tensão SCL é alta define marcadores de início e paragem., Se a tensão SDA não mudar enquanto SCL é alta, dispositivos I2C sabem que os dados, ao invés de marcadores, estão sendo enviados.
SDA agora vai alto ou baixo para enviar cada bit do byte de endereço: o endereço do dispositivo de 7 bits seguido pelo bit de leitura/escrita. Os bits do byte são enviados para fora-a maior parte bit — o ‘bit mais significativo’ — primeiro, com o SDA indo alto se o valor do bit é 1 ou baixo se for zero. O periférico alvo irá agora puxar o SDA para baixo para sinal de aviso de recepção dos dados, e então sai oito bits de informação de controle ou dados, seguido por mais dados, se necessário., Há uma pausa de reconhecimento ‘ ack ‘ de pulso único na SDA entre cada oito bits enviados, cronometrado para um nono pulso SCL. Se o periférico não acusar a recepção desta forma, o controlador irá detectar que o SDA permaneceu elevado e irá assinalar um erro.,
Quando os dados fluem do periférico para o controlador, este também reconhece a recepção de oito bits, puxando SDA para baixo no nono pulso SCL, a menos que este seja o byte final de um lote, caso em que o controlador não puxa SDA para baixo — ele faz um sinal “nak”, ou “sem aviso de recepção” — a fim de deixar o periférico saber que ele terminou.quando terminarmos, o SDA vai alto como um marcador de paragem.,
O início da transmissão é indicado por SDA caindo de alta a baixa tensão (o retângulo à esquerda),
parar pelo reverso (o retângulo direito). SCL deve ser alto quando isso ocorre
Timing
a velocidade padrão do relógio para comunicações I2C é de 100kHz — 100.000 pulsos SCL por segundo. É possível ir mais rápido, até 400kHz. Alguns dispositivos podem não ser capazes de suportar esta velocidade; Verifique a ficha de dados que acompanha o dispositivo que deseja ligar ao seu imp., No entanto, muitos dispositivos lentos usam uma técnica chamada ‘clock stretching’ para forçar dispositivos mais rápidos a trabalhar para sua velocidade. O imp suporta dispositivos que fazem uso desta técnica. Essencialmente, eles mantêm o SCL baixo enquanto eles estão obtendo os dados que você quer que eles enviem para o imp. O imp detecta isso, libera a linha SCL e espera até o SCL subir novamente antes de continuar.
no entanto, poderá ter de baixar a velocidade I2C se as características eléctricas da sua instalação abrandarem a velocidade de transição entre 0V e 3.3 V, denominada “tempo de subida”., Isto é muitas vezes causado por fios longos, que aumentam a capacitância do circuito. Para que os dispositivos detectem com sucesso a transmissão de cada bit, o bus precisa correr mais lentamente. Corrupção de dados ou resultados inesperados são as pistas que você deve olhar para fora. Reduzir a velocidade do barramento I2C até que os dados estejam sendo lidos com sucesso.
a API imp fornece actualmente quatro valores de clock pré-definidos: 10, 50 100 e 400kHz., Eles são selecionados por passar uma constante para I2C método de configuração como um parâmetro:
i2c.configure(speedConstant);
, onde o valor de speedConstant é um dos
- CLOCK_SPEED_10_KHZ
- CLOCK_SPEED_50_KHz
- CLOCK_SPEED_100_KHZ
- CLOCK_SPEED_400_KHZ
a criação de Um imp Para I2C
O i2c objeto em linhas de código de exemplo dado acima não é fornecida diretamente pelo imp, mas escolhido por você, de acordo com o que escolheu imp pinos do que você vai usar para I2C comunicações., Cada tipo de imp tem vários ônibus I2C, todos disponibilizados no arranque. Confira o PIN mux para o tipo de imp que você está usando para ver quais objetos I2C estão disponíveis para você. Vamos assumir que estás a usar um imp001. Os dois barramentos I2C do imp001 estão em pinos 1 e 2, e pinos 8 e 9, respectivamente, instanciados como propriedades i2c12 e i2c89 do objeto de hardware quando o PIM começa. Os pinos 1 e 8 são atribuídos à SCL, 2 e 9 à SDA.,
é comum referenciar a sua escolha com uma variável global:
código de exemplo
o seguinte código funciona com o TAOS TSL2561 visible and infrared light sensor, um dispositivo de 3.3 V que utiliza o I2C para comunicar com o seu microcontrolador hospedeiro. A ficha do chip pode ser baixada do site da Adafruit. A Adafruit vende o chip num tabuleiro de fuga de baixo custo, que inclui resistências adequadas no pino de energia, VCC. Isto significa que está pronto para se conectar diretamente aos pinos I2C de um imp.,
Adafruit do TSL2561 breakout board
Note que, Após este artigo foi escrito, Adafruit atualizado seu TSL2561 placa do sensor. A nova versão funciona com o código atual.
Aqui está o código, para o agente e, em seguida, o dispositivo:
o que o código faz
o código do agente responde a um pedido HTTP recebido, notificando o dispositivo que ele requer uma leitura. Por simplicidade, a leitura é simplesmente exibida no log.
o código do dispositivo lê o sensor e calcula um valor de lux de acordo com a matemática definida na ficha técnica TSL2561., A primeira parte do programa estabelece constantes para os registradores e configurações chave do TSL2561, incluindo suas opções de endereço I2C. Outras constantes são usadas no processo de conversão de luminosidade.
a Fiação até o imp
No início do programa ponto, o código de aliases um dos imp s I2C pin definido como uma variável global, configura a velocidade do barramento para 100 khz e, em seguida, desloca o TSL2561 do I2C endereço de um bit para a esquerda, então ele está pronto para ser usado com o imp I2C funções. Em seguida, configura o sensor., Só para verificar se funcionou, lemos o registro de controle: o valor de retorno deve ser 3 Se o TSL2561 acabou de começar, ou 51 se o dispositivo já foi ligado.
em seguida, o código define a resolução ADC do sensor através do registro de tempo do TSL2561, e, em seguida, define o ganho de sinal para alto.finalmente, dizemos ao imp como responder a"sense"
notificações do agente. Isto chama uma função que lê os dois sensores de luz do TSL2561, valores digitais para os quais são armazenados nos quatro registros ADC de 8 bits do chip., Os dois primeiros dão uma leitura óptica e infravermelha combinada de 16 bits, o segundo par um valor IR apenas de 16 bits. As funções readSensorAdc0 () e readSensorAdc1 () convertem os valores individuais do registo em números de 16 bits multiplicando o byte mais significativo por 256 e adicionando o valor do byte menos significativo. The multiplication is performed by the shifting the eight-bit number’s bits left eight places with Squirrel’s << operator.,
o código então fornece ambas as leituras para uma terceira função para calcular uma luminosidade final, valor ‘lux’.
Leitura Adicional
- I2C erros-como depurar I2C ler e escrever problemas