Postagem em destaque

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

Este post é o primeiro de uma série de seis que escrevi tratando de controle de potência e PID (controle proporcional, integral e derivativo...

domingo, 25 de agosto de 2013

Reportagem na Veja Online

Sexta feira passada foi publicada uma matéria na Veja Online para a qual dei uma entrevista. No fim só sobrou uma frase e o meu rostinho bonito, mas o cara captou o espírito da coisa. O que importa é que o recado Arduínico foi dado: http://veja.abril.com.br/noticia/vida-digital/hardware-aberto-incentiva-amadores-e-especialistas-a-criar-dispositivos-eletronicos#Texto.

Automação no Parque, 24/08/2013 - Projeto Rover 5

Nesse sabadão lidamos com dois projetos: um carrinho de esteiras, o Rover 5, muito popular nos EUA para diversão com o Arduino. O outro fiu um tacômetro baseado em dois encoders, visando determinar a velocidade e a direção de giro de um disco. Nesse projeto a único resultado que obtivemos foi queimar os dois encoders, graças à minha teimosia em ligar LED sem resistor. Semana que vem tem mais...

Já no outro projeto tivemos bastante sucesso.


Esse é o Rover 5. Fabricado pela Dagu, é vendido em muitas lojas on-line dos EUA. Você o acha por aqui, também, mas prá variar custa uma grana.

Tem duas versões: uma com dois motores CC e a outra com quatro. Cada motor tem seu próprio encoder, o que deve possibilitar um controle muito preciso de posicionamento. Esse que estamos hackeando tem quatro motores. É de um ex-aluno da FATESF o Ângelo, que vai comandá-lo a partir de um celular.

Ele comprou o jipinho nos EUA. Quando chegou aqui descobriu que um dos eixos estava completamente empenado, o que fazia com que a esteira simplesmente saísse fora quando os motores eram acionados. Nada complicado prá um sujeito que trabalha na Embraer.

Nesse sábado a ideia ela simplesmente acionar os motores através do driver, já ele só havia sido testado ligando-se os motores direto na bateria.

O Ângelo comprou esse driver de acionamento de motores aqui:


Ele funciona com até quatro motores CC, cada um com seu encoder. As conexões estão descritas no diagrama acima. Basicamente,à esquerda são ligados os pinos do Arduino que comandam os motores, respectivamente:

- Pino terra (GND)

- Pino PWM: ligado a um pino PWM do Arduino, controla a velocidade do motor.

- Pino Direction: controla a direção de giro, sinal do Arduino HIGH roda numa direção, LOW na outra. Uma coisa interessante no carrinho é que os motores são montados em oposição em termos de giro. Isso significa que se vc aplicar HIGH num motor da parte dianteira do carrinho e ele girar prum lado, ao aplicar o mesmo HIGH a um motor da parte traseira (ou na parte oposta, já que ele é simétrico, então vc tem que escolher a frente) ele vai girar na direção contrária. Nada que não possa ser corrigido por software.

- Pino Current: é conectado a um sensor de corrente, com sensibilidade de 1V/A, até o máximo de 5V. isso significa que vc pode legá-lo diretamente a um pino analógico do Arduino e monitorar a corrente, de modo a ver se tem algo errado. Esses motores não devem operar acima de 1,5A, ou menos até.

À direita são conectados os encoders, suas entradas e alimentação (pinos que vem dos encoders) na parte externa da placa e as saídas na parte interna. São dois encoders, que juntos permitem que a gente determine não só a velocidade e consequentemente a distância mas também a direção de giro. Como fazer isso? Fica para um próximo post. Por agora, a tarefa é acionar os motores na mesma direção, controlando a velocidade.

No mais, tem a conexão para a fonte de alimentação dos motores. Já que o Arduino não consegue prover a corrente necessária, é preciso ter uma outra fonte para isso. Essa pode ser seis pilhas AA, ligadas em série de maneira a prover 9Vcc. Tem também uma conexão para alimentação da parte eletrônica da placa, que vc pode "pegar" da saída Vcc do Arduino. E por fim, as conexões para os quatro motores.

Os camaradas já trouxeram o carrinho com s conexões elétricas prontas entre motores, encoders, driver e Arduino, então foi fazer um "pograminha" de teste e botar prá rodar.

À esquerda, o  driver conectado.











E abaixo, o carrinho montado. Dá prá ver as seis baterias dos motores e uma de 9V para alimentação do Arduino.


/*************************************************************
Automação no Parque - 25/08/2013
Controle do Dagu Rover 5
assismauro@hotmail.com
**************************************************************/

#define FRENTE 1
#define RE 0

// O array abaixo define o controle dos  motores
// Indica onde está ligado cada pino do Arduino
// correspondente a um motor (0,1,2,3)
//                  CUR DIR PWM FWD MSK 
int motor[4][4] = {{A0, 4,  5,  HIGH}, // motor 0
                   {A1, 7,  6,  HIGH}, // motor 1
                   {A2, 10, 11, LOW},  // motor 2
                   {A3, 8,  9,  LOW}}; // motor 3
/*    
Diagrama do posicionamento dos motores no carrinho   

      Frente
      _____
    0|     |1
     |     |
     |     |
    2|_____|3

Pino     Função
--------------------------------------------------
CUR      Sensor de corrente
DIR      Direção
PWM      Velocidade
FWD MASK indica qual o sinal que o motor deve receber para acionar o motor prá frente.
*/

// Essa rotina é a que conta os sinais enviados pelo encoder.
// A saída de um dos encoders está ligada ao pino 2 do Arduino,
// fazendo que count seja incrementado. Quanto mais veloz, mais 
// "counts" por unidade de tempo.
volatile unsigned int count = 0;
void encoderInt()
{
  count++;
}

// Set os modos dos pinos que serão usados
void setPinsMode()
{
  for(int i=0;i<4;i++)
  {
    for (int j=1;j<3;j++)
    {
      pinMode(motor[i][j],OUTPUT);
      pinMode(motor[i][j],OUTPUT);
    }
  }
}

// Comanda cada motor individualmente. Recebe como parâmetro o número do motor,
// a direção e a velocidade
void setMotor(int no, int dir, int speed)
{
  // Aqui ocorre a inversão do sinal de direção de acordo com a posição do motor
  if (dir)
    digitalWrite(motor[no][1], motor[no][3]);
  else
    digitalWrite(motor[no][1], !motor[no][3]);
  analogWrite(motor[no][2], speed);
}

// Aqui se aciona o carrinho "como um todo" (argh!).
// Tem dois dir e duas speed, porque comanda-se individualmente
// cada lado do rover, de maneira a fazer curvas, por exemplo.
void rover(int dirEsq, int dirDir, int speedEsq, int speedDir)
{
  setMotor(0,dirDir,speedDir);
  setMotor(1,dirEsq,speedEsq);
  setMotor(2,dirDir,speedDir);
  setMotor(3,dirEsq,speedEsq);
}

//Para o rover (dãããã...)
void roverParado()
{
  rover(FRENTE,FRENTE,0,0);
}

void setup()
{
  Serial.begin(9600); 
  setPinsMode();
// Conecta a interupção do encoder
  attachInterrupt(0,encoderInt,RISING);
}

void loop()
{
  // Move o rover à frente, com velocidade 50 (vai até 255)
  rover(FRENTE,FRENTE,50,50);
  // Mostra a contagem do encoder a cada segundo, ou seja, indica a velocidade.
  // Depois vai-se calibrá-lo para m/min.
  delay(1000);
  Serial.println(count);
  count=0;
}


Por fim, vídeo do resultado. Sabadão tem mais com o jipinho.



quinta-feira, 22 de agosto de 2013

Porque existem displays de anodo comum?



Eu sempre me perguntei porque a maioria dos displays com os quais trabalhei são anodo comum e não catodo comum. Para quem não sabe, anodo é o terminal positivo e catodo o negativo. Na minha cabeça fazia mais sentido o catodo comum, quer dizer, o terra comum . Assim, quando eu quisesse ligar um segmento, era só mandar 5V para o pino correspondente e o bicho acenderia. No caso do anodo comum é o contrário, ou seja, +5V para desligar o LED.


Não que isso faça alguma diferença, tanto faz ligar com +5V ou 0V, mas não é esquisito?

Acima, um esquema de display com anodo comum.

Bom, aí resolvi investigar e descobri porque usa-se o anodo comum: é que os CIs de controle, para serem pequenos, tem capacidade de fornecer apenas alguns miliamperes de corrente por pino. Porém esses mesmos CIs tem a capacidade de "aterrar" 20+ mA por pino, ou seja, se o display for anodo comum exige-se menos do CI, e pode-se usar uma corrente por segmento maior => maior brilho.

Sacou?

sexta-feira, 2 de agosto de 2013

Mais sobre displays de LED com 74HC595 - Parte II

Na parte inicial deste artigo, vimos a parte de hardware de uma montagem com 12 displays de LED conectados ao Arduino via três CIs 74HC595.

Agora vamos discutir os fontes da aplicação:

#include "Arduino.h"
/*****************************************************************
 Controle de "n" displays de LED 3x8 tipo Para Light A-573H 
 http://automatobr.blogspot.com.br
******************************************************************/

// Este programa funcionará com qualquer número de dígitos
#define nDigits 12 // número de dígitos a serem usados
#define nCIs    3  // número de CIs 595 existentes no
                   // circuito, no mínimo 2.

// pinos para comunicação com o CI 74HC595
#define latchPin 8
#define clockPin 12
#define dataPin  11 

/* máscara de bits para os dígitos, conforme diagrama abaixo:
     A 
    --- 
  F|   |B
   | G | 
    ---
  E|   |C
   | D | 
    --- *d
*/
byte digits[] = 
//  dGFEDCBA - segmentos
  {B00111111, // 0
   B00000110, // 1
   B01011011, // 2
   B01001111, // 3
   B01100110, // 4
   B01101101, // 5
   B01111101, // 6
   B00000111, // 7
   B01111111, // 8
   B01101111, // 9
   B10000000, // dot
   B00000000}; // blank  

// valor apresentado no display
uint64_t displayValue = 0;

// rotina que envia um byte para o 595 de maneira serial, 
// um bit de cada vez

void shiftOut(byte dataOut) 
{
  boolean pinState; 
// prepara o envio
  digitalWrite(dataPin, LOW); 
  digitalWrite(clockPin, LOW);
  for (int i=0; i<=7; i++) 
  { 
    digitalWrite(clockPin, LOW); 
// se o bit "i" está ligado, envia para o pino de dados um byte com 
// só o primeiro bit ligado (HIGH), se não, envia 0 (LOW)
    if ( dataOut & (1 << i) ) 
      pinState = HIGH;
    else 
      pinState = LOW;
// envia o bit
    digitalWrite(dataPin, pinState);
// informa ao chip que terminou o envio
    digitalWrite(clockPin, HIGH); 
    digitalWrite(dataPin, LOW);
  }
  digitalWrite(clockPin, LOW); 
}

// "desenha" um determinado dígito (digit) no display 
// (display). O número 1 é o menos significativo
// (primeiro da direita) e assim por diante.
void displayDigit(int display, int digit)
{
// primeiro montamos o endereço do display, quer dizer, 
// vamos indicar qual display será
// habilitado e mostrará o dígito.
  int data1, data2;
  if(display <= 8)
  {
    data1 = B00000001 << (8-display);
    data2 = B00000000;
  }
  else
  {
    data1 = B00000000;
    data2 = B00000001 << (16-display);
  } 
  // prepara o envio
  digitalWrite(latchPin, LOW);
  // envia o dígito para o CI 3
  shiftOut(digits[digit]);
  // envia o endereço (máscara de bits) indicando 
  // o display a ser ativado
  shiftOut(data1);
  // se tiver mais de 1 CI de endereçamento, envia 
  // a outra parte do endereço
  if (nCIs > 2)
    shiftOut(data2);
  // termina o envio
  digitalWrite(latchPin, HIGH);
}

// exibe um número inteiro
void display(uint64_t number)
{
    for (int i = 1;i <= nDigits && number != 0;i++) 
    {
      // pega o i-ésimo dígito
      int digit = number % 10LL;
      // envia para exibição
      displayDigit(i,digit);
      // trunca o número, eliminando o último 
      // dígito exibido
      number /= 10LL;
    }
}

void setup()
{
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin,  OUTPUT);  
  // "inverte" a máscara de bits, porque os displays são 
  // anodo comum => o bit "1" desliga o LED.
  // Se os seus displays forem catodo comum, 
  // delete as próximas duas linhas.
  for(int i=0; i < sizeof(digits)/sizeof(digits[0]);i++)
    digits[i]=~digits[i];
}

void loop()
{
  displayValue=188459823945LL;
  while(displayValue < 9999999999999LL)
  {
    display(displayValue);
    displayValue++;
  }
}

O fonte está todo comentado acima.

As constantes nDigits e nCIs servem para vc adaptar o programa ao seu circuito, informando quantos CIs 595 vc tem e o número de dígitos que vc usou. Para usar mais ou menos CIs (e dígitos, consequentemente) vc deve adaptar o circuito que publiquei, não é difícil. Se forem, por exemplo, seis displays, vc pode usar 2 CIs, um para controlar os segmentos e outro para multiplexar (selecionar) os displays. Nesse caso a diferença é que vc não terá o CI 1 e consequentemente nenhuma de suas conexões e o pino de dados do CI 2 (pino 14) será conectado ao Arduino (pino 11). Mas nada impede que vc controle menos displays com algum CI sobrando, ou seja, os números são "quase" independentes ou seja: para controlar 10 displays vc é obrigado a ter no mínimo 3 CIs, já para controlar 4 displays apenas 2 são necessários, mas se vc tiver ligado 3 o programa funcionará.

Uma curiosidade desse sketch é que eu usei o tipo de dado uint64_t, que é um inteiro 64 bits suportado pelo Arduino. Usando-se esse tipo de dados podemos manipular um decimal até 20 dígitos.

É isso. Vou fazer ainda mais um post com outras brincadeiras com esse mesmo circuito.

Obrigado pela força do Euclides e do César, nosso "associado remoto".


Mais sobre displays de LED com 74HC595 - Parte I




Outro dia apareceu no nosso Sabugosa (apelido do Hacker Clube de São José dos Campos) um monte de displays de oito segmentos e três dígitos, desses daí ao lado.


Aqui no blog existe uma série de posts com projetos envolvendo o chip 74HC595. Aqui vai mais um. O resultado você pode ver no vídeo abaixo.



Clique para ver o datasheet.


Na figura à esquerda, o esquema  visual do display. O dígito mais à esquerda é o 1, os segmentos são identificados por letras de A a G e o ponto decimal é o DP (Dot Point). Essa identificação aparece em 100% dos displays que vi até hoje.



Essa outra figura é o esquema elétrico do display O display é de anodo comum, ou seja, o terminal positivo é conectado em comum para cada display (pinos 8,9,10).

Isso significa que, para ligar um determinado segmento, temos que conectar o pino do segmento correspondente ao terra. Para desligar o segmento, é só alimentar o pino correspondente com a mesma tensão do anodo, 5V no caso de nosso circuito. Isso vai contra o senso comum. que é 5V liga, 0V desliga, mas é assim mesmo.

Temos então um pino que é o anodo de todos os segmentos de um determinado display. O catodo é comum aos segmentos iguais dos diferentes displays, e os segmentos são conectados aos pinos 7,6,3 etc. Observe que eles são interconectados nos três displays, quer dizer, se eu conecto +5V ao pino 8 e 0V aos pinos 6 e 3 vai aparecer o número 1 nos três displays.

Como faço então para mostrar números diferentes nos displays? É só alternar o número a ser mostrado com o display ligado. Supondo que temos que mostrar o número 1,2,3 temos que fazer assim:

1) Habilito o display 1 (5V pino 10).
2) Desenho o número 3 (0V em 7,6,3,2,4)
3) Desligo o display 1 (0V em 10)
4) Ligo o display 2 (5V pino 9)
5) Desenho o número 2 (0V em 7,6,2,1,4)
6) Desligo o display 2 (0V pino 9)
7) Ligo o display 3 (5V pino 8)
8) Desenho o número 1 (5V pinos 6,3)
9) Volto ao passo 1.

E para que é feito dessa forma? Porque não ter um pino para cada segmento? R: Para diminuir o número de conexões necessárias ao acionamento do display. Se fosse um para cada seriam 25 pinos a serem comandados, um para cada segmento mais um anodo comum. No display que usamos temos apenas 11 conexões.

Na minha montagem, para diminuir ainda mais o número de pontos eu conectei todos os segmentos iguais dos quatro displays que usei. Assim se ativamos todos os displays e mostramos um 4, o que aparece é o que vc vê aí do lado.
Temos então 8 segmentos mais 1 pino para cada chip a comandar, o que dá "apenas" 20 pinos para comandar 12 displays, muito menos que os exatos 100 que seriam necessários caso fossem ligados a todos os pinos (96 LEDs mais 1 catodo comum para cada conjunto de 3 displays).


De toda forma, 20 pinos digitais é o limite máximo do Arduino Uno (14 digitais "verdadeiros" mais os 6 analógicos que podem ser usados como digitais), ou seja, se ligarmos o display direto no Arduino não dá para usar o Arduino prá mais nada. Temos que diminuir mais ainda o número de portas necessárias. Aí entra o 74HC595.

Em 2012 eu fiz alguns posts sobre o uso desse chip para controlar LEDs RGB. Lá eu descrevo detalhadamente o funcionamento dele: Parte I, Parte II. Tem também outros posts sobre a conexão de displays de oito segmentos isolados, então não vou repetir a descrição do bicho. Vou apenas dizer que ele é um conversor serial-paralelo, ou seja, com apenas 3 pinos eu comando oito pinos de saída. Além disso eles podem ser interconectados, o que faz com que eu possa controlar, teoricamente, "n" pinos com apenas três pinos do Arduino.

No nosso caso, usamos 3 chips 595: um deles comanda os segmentos e os outros dois selecionam cada um dos displays. Observem que a gente poderia então ter mais quatro displays sendo comandados pelos mesmos três chips, já que estou usando apenas 12 dos 16 possíveis na saída de dois 595. Não coloquei mais porque simplesmente não coube na protoboard e eu não tinha outra.

Abaixo, um vídeo do sistema funcionando, só que com 100 ms entre cada exibição de display:


Dá para ver "em câmera lenta" os dígitos sendo exibidos. Observe que, como é um contador, o primeiro dígito (à direta, claro) vai mudando.

Quando a gente acelera (retira o delay), tem-se o resultado do primeiro vídeo.

Não vou postar o esquema (Fritzing) do circuito por razão óbvia: a preguiça de desenhar esse "aranzel", como se diz em minha terra. Mas dá para explicar como fiz. Identifique os CIs na figura logo abaixo.

Os dois 595 à esquerda (chamarei de 1 e 2) são responsáveis pela seleção do display corrente, e o do direita, o 3, comanda os segmentos.





Para conectar os CIs entre si são ligados os pinos 11 e 12 de cada CI entre si. O pino 9 do CI 1 é ligado ao pino 14 do CI 2. Essa conexão é a que será usada pelo CI 1 para "exportar" os dados para o CI 2. Da mesma forma, conectamos o CI 2 ao 3.

Abaixo um esquema com dois 595 conectados. O nome dessa conexão em inglês e "daisy chain (seriam "margaridas encadeadas"???), em português se usa "cascata".




Os pinos de saída do chip são conectados aos displays, da seguinte forma:

Vamos chamar os displays de 1 a 4 do menos significativo ao mais significativo, ou seja, da direita para a esquerda.

O esquema de ligação dos CIs está descrito na tabela abaixo:
   
       
           CI
                        Pino                  Display                  Pino            CI       Pino Arduino        Pino Função
1 1 4 9 Seleciona display 2
1 2 4 8 Seleciona display 3
1 3 3 10 Seleciona display 4
1 4 3 9 Seleciona display 5
1 5 3 8 Seleciona display 6
1 6 2 10 Seleciona display 7
1 7 2 9 Seleciona display 8
1 8 GND GND
1 9 2 14   Daisy chain
1 10 Vcc Vcc
1 11 2 11  12   Clock
1 12 2 12  8   Latch
1 13 GND GND
1 14 11  Data
1 15 4 10 Seleciona display 1
1 16 Vcc
2 1 1 10 Seleciona display 10
2 2 1 9 Seleciona display 11
2 3 1 8 Seleciona display 12
2 4 Não usado
2 5 Não usado
2 6 Não usado
2 7 Não usado
2 8 GND GND
2 9 3 14   Daisy chain
2 10 Vcc Vcc
2 11 3 11   Clock
2 12 3 12   Latch
2 13 GND GND
2 14 1 9   Data
2 15 2 8 Seleciona display 9
2 16 Vcc Vcc
3 1 1 6 Segmento B
3 2 1 3 Segmento C
3 3 1 2 Segmento D
3 4 1 1 Segmento E
3 5 1 5 Segmento F
3 6 1 4 Segmento G
3 7 1 11 dot
3 8 GND GND
3 9 2 14   Daisy chain
3 10 Vcc Vcc
3 11 2 11   Clock
3 12 2 12   Latch
3 13 GND GND
3 14 Data
3 15 1 7 Segmento A
3 16 Vcc Vcc









Observe que tem pinos que são conectados a mais de um ponto simultãneamente, ex: os pinos 9, 11 e 12 do CI 1 estão também conectados ao Arduino.

Além dessas conexões é necessário ligar os segmentos correspondentes da seguinte forma: conecte os pinos 7,6,3,2,1,5,4,11 dos quatro chips aos seus correspondentes, ou seja o pino 7 do display 1 ao pino 7 do display 2, o pino 7 do display 2 ao pino 7 do display 3, o pino 6 do display 1 ao pino 6 do display 2 e assim por diante. Uma sugestão: faça PRIMEIRO essa conexão entre os displays, acho que deve ser mais fácil assim.

No próximo post, o software.