O milagre da multiplicação das portas analógicas

No projeto da mesa da Mariana havia a necessidade de colocarmos sensores que permitissem que o usuário (?!?) da mesa conseguisse intervir na música e nos efeitos visuais.
Decidimos usar sensores de luminosidade (LDR-Light Dependent Resistor). São sensores baratos e eficientes, que captam a movimentação das mãos dos usuários sobre eles. Como o nome diz, eles são resistores cuja resistência à passagem da corrente varia em função da quantidade de luz que atinge a sua superfície. É encontrado em qualquer boa casa de componentes eletrônicos.



Esse é o LDR. Instalamos seis desses sensores na mesa.
Como o nosso pobre Arduino Uno não tem portas disponíveis, resolvi multiplexar também as portas analógicas, de maneira a liberar algumas delas para uso em outros circuitos.
Para isso, usei o CI CD4051, que é também fácil de encontrar e muito barato.



Abaixo o esquema do bicho:

Os pinos y0 a y7 podem ser conectados a entradas (ou saídas, ele pode também ser usado para demux, mas não é o nosso caso) analógicas ou digitais. O pino z é o pino de saída, foi conectado a alguma porta analógica do Arduino. Os pinos S0, S1 e S2 servem para selecionarmos qual porta será lida pelo pino z.
Os pinos E, Vee, gnd devem ser conectados ao terra do Arduino, e o pino Vcc ao +5V da plaquinha.

Ligando o LDR

 Como o LDR é um sensor que varia resistência e o Arduino "mede" (capta) variação de tensão, é necessário criar um circuito que transforme a variação de resistência em variação de tensão. Para isso, montou-se um  circuito divisor de tensão. Abaixo, o esquema que usaríamos se ligássemos o sensor direto no Arduíno:



Observe o circuito. Veja que o LDR é ligado em série com um outro resistor, cujo valor nem importa tanto (pode ser algo entre 220 e 10k ohms), e as extremidades dessa ligação em série são ligadas ao terra e a 5V, respectivamente. Isso significa que a queda de tensão será de 5V entre os pontos A e B.
E entre A e C? Nesse caso, a variação depende da razão entre os resistores R1 e R2.

Vac = Vab * R2 / (R1+R2)

Ex: se R1 = R2 = R temos:

Vac = Vab * R / (R+R)
Vac = 5 * 0.5 = 2.5 V

Se  R1=2R2, temos:

Vac=Vab * 2R2 / (2R2+R2)
Vac=5 * 2/3 = 3.33V

Ou seja, quanto maior o valor de R1, maior a queda de tensão Vac. Como R2 é fixo e R1 varia em função da luminosidade, teremos uma leitura tensão variando em função da luminosidade, bastando ligar o ponto C a uma porta analógica do Arduino para termos uma leitura numérica da variação de luminosidade.
A única diferença entre esse e o nosso circuito é que o sinal do ponto C dos sensores é ligado ao CI de multiplexação.

Montei então o seguinte circuito:




















O exemplo tem somente 5 sensores por facilidade no desenho da protoboard.
Para a multiplexação basta, através dos pinos s0 a s2, selecionar o sensor a ser lido em um determinado momento. A ideia é enviar ao chip usando 3 bits o número do sensor a ser lido, em seguida ler o valor da porta A5, onde está ligado o pino z do CI.

Usando esse CI vc pode multiplexar "n" portas de Arduino, ligando outros chips, como mostra a figura abaixo, onde podemos obter 64 portas analógicas sendo lidas por somente um pino analógico, usando 9 4051.



Abaixo, o código, devidamente comentado:
int r0 = 0;      //valor do pino select s0 no 4051
int r1 = 0;      //valor do pino select s1 no 4051
int r2 = 0;      //valor do pino select s2 no 4051

int sensorValue;

#define ps0 7
#define ps1 6
#define ps2 5

void setup()
{
  Serial.begin(9600);
// seta os pinos select como saída
  pinMode(ps0,OUTPUT);    
  pinMode(ps1,OUTPUT);    
  pinMode(ps2,OUTPUT);    
}

void loop()
{
  for (int i=0; i<5; i++)
  {
// pega os bits do contador e coloca nas variáveis a serem enviadas. 
    r0=bitRead(i,0);
    r1=bitRead(i,1);
    r2=bitRead(i,2);
// envia os bits para as respectivas portas select (s0 a s3 no CI)
    digitalWrite(ps0,r0);
    digitalWrite(ps1,r1);
    digitalWrite(ps2,r2);
//  em seguida, lê o valor do sensor correspondente, que vai estar disponível no pino A5    
    sensorValue=analogRead(5);
//  exibe os valores lidos, por sensor
    Serial.print(i);
    Serial.print(',');
    Serial.print(r0 | (r1 << 1) | (r2 << 2),BIN);
    Serial.print(',');
    Serial.print(sensorValue);         
    Serial.print(',');    
    delay(1000);
  }
  Serial.println("");
}

Comentários

  1. Ola boa tarde ! parabens pelo post esta sendo de muita ajuda ! mas estou em duvida na ligação de 2 ou mais CI,s vc poderia me ajudar por favor ?

    Obrigado

    ResponderExcluir
    Respostas
    1. Marco, obrigado pela visita.
      Qual é a sua dúvida? Eu montei esse esquema que está aí em cima com 16 portas (3 CD4051) e deu certim.

      Excluir
  2. Oi Mauro boa tarde, eu preciso exatamente de 16 portas e minha primeira duvida é: Eu não poderia fazer essas 16 portas usando apenas 2 CI? Eu montei um esquema na proto board usando 3 ci como na imagem mas acredito que tenha feito algo errado na programação pois não obtive resultados corretos do sensor !

    ResponderExcluir
    Respostas
    1. Sim, poderia. Vc poderia fazer o Arduino fazer o papel do 4051 que fica mais ou menos no centro da figura acima, e também duas portas analógicas do Arduino para para ler o sinal de cada um dos CIs.

      O programa, claro, seria totalmente diferente do meu exemplo, mas que daria para fazer, daria.

      Eu acho que não tenho mais nenhum chip desses, pena, senão eu montava aqui e testava.

      Excluir
  3. Minha duvida e' sobre esta frase :

    "Usando esse CI vc pode multiplexar "n" portas de Arduino, ligando outros chips, como mostra a figura abaixo, onde podemos obter 64 portas analógicas sendo lidas por somente um pino analógico, usando 9 4051."

    Neste caso de quantas portas digitais do arduino eu precisaria ?

    ResponderExcluir
    Respostas
    1. Trelin,

      Para 64 portas, 6 digitais e 1 analógica, como no diagrama aí em cima.

      Excluir
    2. Mauro, mas neste caso como eu seleciono um determinado 4051 e a porta dentro dele ?
      Você teria algum exemplo da programação no arduino ?

      Desculpa a insistencia e obrigado pela resposta.

      Excluir
  4. Mauro, seria assim ???

    // 1o seleciono qual 4051
    // ****************************
    // utilizo as saidas digitais 5,6,7
    // digamos ser o 4051 da porta 1
    int r0=bitRead(1,0);
    int r1=bitRead(1,1);
    int r2=bitRead(1,2);

    // envia os bits para as respectivas portas select (s0 a s3 no CI)
    digitalWrite(ps0,r0);
    digitalWrite(ps1,r1);
    digitalWrite(ps2,r2);


    // 2o seleciono qual porta dentro do 4051 usando os saidas digitais 2,3,4
    // **********************************************************************
    // digamos que quero ler a porta 5 do 4051
    int r0=bitRead(5,0);
    int r1=bitRead(5,1);
    int r2=bitRead(5,2);

    // envia os bits para as respectivas portas select (s0 a s3 no CI)
    digitalWrite(ps0,r0);
    digitalWrite(ps1,r1);
    digitalWrite(ps2,r2);


    // 3o ler a porta analogica no pino Z




    Renovo meu agradecimento

    ResponderExcluir
  5. Bacana! Muito bom..

    Só fiquei com a seguinte dúvida; tenho 8 entradas no A5, mas como faço pra guardar o valor de cada uma das 8 entradas do 4051 em 8 variáveis diferentes? Até a parte que mostra os valores na Serial, tranquilo, a dúvida é como guardar o valor em 8 variáveis referente a cada porta do 4051. Obrigado!

    ResponderExcluir
    Respostas
    1. Vc pode fazer algo assim:

      Depois dessa linha, vc coloca:
      sensorValue=analogRead(5);
      switch(i)
      {
      case 1:
      v1=sensorValue;
      break;
      case 2:
      v2=sensorValue;
      break;
      case 3:
      v3=sensorValue;
      break;
      case 4:
      v4=sensorValue;
      break;
      case 5:
      v5=sensorValue;
      break;
      }

      É isso. Outro jeito seria com uma variável "v" sendo um array de inteiros.

      Excluir

Postar um comentário

Postagens mais visitadas deste blog

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte III

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte I

Dividindo um programa (sketch) do Arduino em mais de um arquivo