24 abril 2014

Painel de led com módulo Max7219 e matriz 8x8

Ok, não vai ser "aquele" painel de leds, afinal estou trabalhando apenas com dois módulos Max7219, mas vamos aproveitar a facilidade de ligação (apenas 3 pinos de dados) dessa matriz de leds 8x8 com o Arduino, e montar um painel com scroll (rolagem) de texto, muito fácil de ser expandido.

Ligação Arduino e módulo matriz de leds 8x8
 Para quem ainda não conhece o Módulo Matriz de leds 8x8 com Max7219, recomendo a leitura deste artigo. Lá eu falo um pouco mais sobre o componente e como utilizá-lo para realizar um scroll em um único módulo, com todo o array de caracteres definido no programa. Na montagem do painel deste post aqui, vou utilizar uma biblioteca para controlar os dois módulos.

Na foto abaixo eu retirei a matriz de leds para mostrar as conexões : do lado esquerdo (JP1), os pinos Vcc, GND, DIN, CS e CLK, que serão ligados ao Arduino. Do lado direito (JP2), as conexões Vcc, GND, DOUT, CS e CLK, que serão utilizadas na ligação ao segundo módulo.


Detalhe conectores do Módulo Max7219

O circuito abaixo mostra que a ligação dos dois módulos não tem nenhum grande segredo : os 5 pinos de saída (lado direito - JP2) do primeiro módulo são conectados diretamente aos 5 pinos de entrada do segundo módulo, e apenas o primeiro módulo é ligado diretamente ao Arduino :

  • Pino 5v do Arduino ligado ao Vcc
  • Pino GND do Arduino ligado ao GND
  • Porta 4 do Arduino ligada ao DIN
  • Porta 5 do Arduino ligada ao CS
  • Porta 6 do Arduino ligada ao CLK

Painel de Leds Arduino e Módulo matriz de leds Max7219





Para o programa, vamos utilizar a biblioteca MD_MAX72xx, que pode ser encontrada neste link. Descompacte o arquivo e coloque a pasta MD_MAX72xx dentro da pasta LIBRARIES da IDE do seu Arduino, não esquecendo de reiniciar a IDE para que a nova biblioteca seja reconhecida.

O programa está configurado para usar 2 módulos Max7219. Alterando o valor de MAX_DEVICES, adequamos o programa ao número de módulos conectados.

As variáveis DATA_PIN, CS_PIN e CLK_PIN definem os pinos do Arduino que serão utilizados para conexão. SCROLL_DELAY define a velocidade com que os caracteres serão mostrados, e CHAR_SPACING define o número de colunas que serão usadas como intervalo entre um caracter e outro. Por fim, o comando

mx.control(MD_MAX72XX::INTENSITY, 4);

determina o nível de luminosidade do display.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Programa : Painel de leds com modulo Max7219  
// Adaptacoes e comentarios : Arduino e Cia  

// Carrega a biblioteca MD_MAX72xx  
#include <MD_MAX72xx.h>  
  
// Numero de modulos utilizados  
#define     MAX_DEVICES     2  
  
// Ligacoes ao Arduino  
#define     DATA_PIN     4  
#define     CS_PIN       5  
#define     CLK_PIN      6  
   
MD_MAX72XX mx = MD_MAX72XX(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);  
  
// Velocidade do scroll  
#define SCROLL_DELAY     2000  
// Colunas entre cada caracter  
#define     CHAR_SPACING     1  
  
#define     BUF_SIZE     75  
char curMessage[BUF_SIZE];  
char newMessage[BUF_SIZE];  
  
// int scrollDelay;  
  
uint8_t scrollDataSource(uint8_t dev, MD_MAX72XX::transformType_t t)  
{  
  static char          *p = curMessage;  
  static uint8_t     state = 0;  
  static uint8_t     curLen, showLen;  
  static uint8_t     cBuf[8];  
  uint8_t colData;  
  
  switch(state)  
  {  
  case 0:  
    showLen = mx.getChar(*p++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);  
    curLen = 0;  
    state++;  
    if (*p == '\0')  
    {  
     p = curMessage;  
    }  
  case 1:       
    colData = cBuf[curLen++];  
    if (curLen == showLen)  
    {  
     showLen = CHAR_SPACING;  
     curLen = 0;  
     state = 2;  
    }  
    break;  
  case 2:  
    colData = 0;  
    curLen++;  
    if (curLen == showLen)  
     state = 0;  
    break;  
    default:  
    state = 0;  
  }  
  return(colData);  
}  
  
void scrollText(void)  
{  
  static uint32_t     prevTime = 0;  
  if (millis()-prevTime >= SCROLL_DELAY)  
  {  
    mx.transform(MD_MAX72XX::TSR);       
    prevTime = millis();  
  }  
}  
  
void setup()  
{  
  mx.begin();  
  mx.setShiftDataInCallback(scrollDataSource);  
  // Define o nivel de luminosidade  
  mx.control(MD_MAX72XX::INTENSITY, 4);  
  // Mensagem a ser exibida   
  strcpy(curMessage, " Arduino e Cia ");  
  newMessage[0] = '\0';  
}  
   
void loop()   
{  
  scrollText();  
}  

Abaixo, vídeo do projeto em funcionamento :





16 abril 2014

Controle de motor CC com o L293D - Ponte H

Para quem tem um circuito integrado L293D e gostaria de entender um pouco mais sobre esse componente, hoje vou mostrar como usar o CI para controle de motor CC.

O L293D é um CI fácil de encontrar, barato e que possibilita o controle de 2 motores ao mesmo tempo, pois contém, internamente, dois circuitos denominados PONTE H.

CI L293D ponte h Arduino
Imagem : 4tronix.co.uk


Ponte H é um conceito bem simples, em que um motor é controlado por 4 chaves e uma fonte de alimentação :

Motor CC Ponte H

Observando a figura abaixo, vemos que, acionando as chaves S1 e S4, o sentido da corrente será da esquerda para a direita, e o motor será acionado. Desligando S1 e S4 e ligando S2 e S3, o sentido da corrente é invertido, e consequentemente o motor passa a girar no sentido contrário.

Motor CC Ponte H - Funcionamento

Internamente, o L293D utiliza transistores e diodos para realizar este chaveamento. Podemos construir nossa própria ponte H utilizando esses componentes, mas sem dúvida o tamanho compacto do CI representa uma grande vantagem na montagem de circuitos de controle de motor.

Segundo o datasheet do L293D, o componente suporta correntes de saída de 600mA por canal, isso é, você pode ligar até 2 motores de 600mA cada. A voltagem suportada é de 4.5 à 36 volts. Isso nos permite controlar diversos tipos de motores respeitando-se, é claro, a corrente máxima suportada pelo chip. Por questões de segurança, recomenda-se utilizar motores com menos de 600 mA, apesar do CI suportar picos de 1.2A. Também é recomendado utilizar um dissipador de calor caso o CI comece a esquentar.

Para controle do CI, aplicamos uma tensão variável ao pino 1, que irá determinar a velocidade do motor, e aos pinos 2 e 7 (INPUT 1 e INPUT 2), alternamos os estados LOW (baixo) e HIGH (alto) para utilizar os conceitos de ponte H e determinar o sentido de rotação. Na ilustração abaixo, mostro a pinagem do L293D, e destacado em vermelho os pinos que utilizaremos para montagem do circuito deste post :

Pinagem L293D


Como estou utilizando um motor de 5v, os pinos 8 (Vs) e 16 (Vss) estão ligados aos 5v do Arduino. Se você for utilizar uma fonte externa, conecte o positivo ao pino 8 (Vs), tomando o cuidado de verificar se o CI não está esquentando. Nesse caso, utilize algum tipo de dissipador de calor.


Circuito Motor CC e L293D Arduino

Optei por uma versão resumida do programa de controle, sem o uso de botões, chaves ou potenciômetros, para mostrar a utilização da porta 3 do Arduino para controle de velocidade (ligado ao pino 1 - ENABLE 1do CI),  e das portas 2 (INPUT 1  - pino 2 do CI), e 7 (INPUT 2  - pino 7 do CI) para controlar o sentido de rotação simplesmente alterando o nível ALTO e BAIXO (1 ou 0) das portas.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Programa : Controle de motor CC com o L293D  
// Autor : Arduino e Cia  
   
int PinoVelocidade = 3; //Ligado ao pino 1 do L293D  
int Entrada1 = 2; //Ligado ao pino 2 do L293D  
int Entrada2 = 7; //Ligado ao pino 7 do L293D  
   
void setup()  
{  
  //Define os pinos como saida  
  pinMode(PinoVelocidade, OUTPUT);  
  pinMode(Entrada1, OUTPUT);  
  pinMode(Entrada2, OUTPUT);  
}  
   
void loop()  
{  
  //Define a velocidade de rotacao  
  int velocidade = 500;  
  analogWrite(PinoVelocidade, velocidade);   

  //Aciona o motor  
  digitalWrite(Entrada1, LOW);  
  digitalWrite(Entrada2, HIGH);  
  delay(3000);  

  //Chama a rotina de parada do motor  
  para_motor();  

  //Aciona o motor no sentido inverso  
  digitalWrite(Entrada1, HIGH);  
  digitalWrite(Entrada2, LOW);  
  delay(3000);  
  para_motor();  
}  
    
void para_motor()  
{  
  digitalWrite(Entrada1, LOW);  
  digitalWrite(Entrada2, LOW);  
  delay(3000);  
}  

Pequenas alterações no circuito e no programa permitem que você utilize os mais variados tipos de chaves, sensores e dispositivos para controlar o seu motor CC.

Abaixo, vídeo mostrando o funcionamento do circuito e programa apresentados neste post :



08 abril 2014

Sensor de estacionamento / ré com Arduino e sensor ultrasônico HC-SR04

No post de hoje vamos utilizar o Arduino juntamente com o sensor ultrasônico HC-SR04 para montar um sensor de estacionamento (ou sensor de ré), que emite um "bip" conforme o sensor se aproxima de um obstáculo. Quanto mais próximo o obstáculo, maior a frequência do bip.

Como (geralmente) uma imagem vale mais do que mil palavras, vamos dar uma olhada no sensor instalado em um trator, devidamente "emprestado" do sobrinho :-)



O circuito é composto apenas pelo Arduino, um sensor ultrasônico HC-SR04 e um buzzer, com uma resistência de 330 ohms para limitar a corrente.

Circuito Sensor de estacionamento com sensor ultrasonico HC-SR04
 
No programa, utilizei a biblioteca NEWTONE, que pode ser baixada nesse link e que eu já abordei nesse post.

O motivo de usar essa biblioteca é que a função TONE, normalmente usada para produzir sons com Arduino, apresenta conflito com a biblioteca Ultrasonic, também utilizada nesse projeto.

O som do bip pode ser alterado conforme a necessidade, alterando o valor das variáveis frequencia e tempo, setadas no começo do programa.

O pino Trigger do sensor vai ligado ao pino 13 do Arduino, e o pino Echo do sensor vai ligado ao pino 10 do Arduino. A alimentação do sensor é de 5 volts. O buzzer vai na porta 2 do Arduino.

A variável cmMsec armazena o valor da distância entre o sensor e o obstáculo. Uma série de comandos IF verificam o valor de cmMsec e atualizam a variável atraso, que é utilizada no final do programa para determinar a frequência de acionamento do bip.

Os valores lidos pelo sensor também podem ser acompanhados pelo serial monitor e, com algumas alterações no programa, exibidos em um display.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Programa : Sensor de estacionamento com HC-SR04  
// Autor : Arduino e Cia  
   
#include <Ultrasonic.h>   //Carrega a biblioteca Ultrasonic  
#include <NewTone.h>    //Carrega a biblioteca Newtone  
   
//Dados do buzzer  
#define tempo 500   
int frequencia = 2000;   
int Pinofalante = 2;   
    
int atraso = 1000;  
   
//Define o pino do Arduino a ser utilizado com o pino Trigger do sensor  
#define PINO_TRIGGER 13   
//Define o pino do Arduino a ser utilizado com o pino Echo do sensor  
#define PINO_ECHO   10   
   
//Inicializa o sensor ultrasonico  
Ultrasonic ultrasonic(PINO_TRIGGER, PINO_ECHO);   
   
void setup()  
{  
  pinMode(Pinofalante,OUTPUT); //Pino do buzzer   
  Serial.begin(9600); //Inicializa a serial  
}  
   
void loop()  
{  
  float cmMsec, inMsec;  
    
  //Le os dados do sensor, com o tempo de retorno do sinal  
  long microsec = ultrasonic.timing();   
   
  //Calcula a distancia em centimetros  
  cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM);   
    
  //Ajusta o atraso de acordo com a distancia  
  if (cmMsec > 80)  
  {  
    atraso = 2000;  
  }  
  else if (cmMsec >50 && cmMsec<80)  
  {  
    atraso = 1500;  
  }  
  else if (cmMsec >30 && cmMsec<50)  
  {  
    atraso = 1200;  
  }  
  else if (cmMsec > 10 && cmMsec < 30)  
  {  
    atraso = 700;  
  }  
  else if (cmMsec < 10)  
  {  
    atraso = 300;  
  }  
     
  //Apresenta os dados, em centimetros, na Serial  
  Serial.print("Cent: ");  
  Serial.print(cmMsec);  
  Serial.print(" atraso : ");  
  Serial.println(atraso);  
  //Emite o bip  
  NewTone(Pinofalante, frequencia, tempo);   
   
  delay(atraso);  
} 

Podem ser adicionados outros comandos IF para melhorar a "precisão" do sensor, ou até mesmo ser utilizada outra solução para calcular o valor do delay. Uma sugestão seria a utilização da função map, por exemplo.

Por enquanto é isso. Já posso devolver o trator para o dono. :-)

01 abril 2014

Controlando motor de passo 28BYJ-48 utilizando CustomStepper

Além da tradicional biblioteca Stepper do Arduino, uma outra biblioteca bastante utilizada para controle de motores de passo, e que vamos utilizar com o motor de passo 28BYJ-48 e driver ULN2003, é a CustomStepper, que tem funções como rotacionar o motor determinado número de vezes, rotacionar apenas em um ângulo específico, ou rotacionar até que um novo comando seja enviado ao motor.

Motor de passo 28BYJ-48 e driver ULN2003


Atenção : Para mais informações sobre o funcionamento do 28BYJ-48, assim como a utilização do mesmo com a biblioteca Stepper, consulte o artigo Ligando Motor de passo 28BYJ-48 e ULN2003.

O download da biblioteca CustomStepper pode ser feito nesse link, e a instalação segue o procedimento da maioria das bibliotecas do Arduino : descompacte o arquivo zip e colque a pasta CustomStepper na pasta LIBRARIES da IDE do seu Arduino. Não esqueça de reiniciar a IDE para que a biblioteca seja carregada.

Vamos demonstrar as funções desta biblioteca utilizando dois programas diferentes. Primeiramente, monte o circuito abaixo, que utiliza o motor de passo 28BYJ-48 e o driver ULN2003 juntamente com o Arduino Uno :

motor de passo customstepper Arduino


O primeiro exemplo é o controle do número de rotações do motor. Carregue o programa abaixo, que rotaciona o motor 3 vezes no sentido horário, aguarda 2 segundos e rotaciona 2 vezes no sentido anti-horário :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Programa : Controle motor de passo 28BYJ-48 - Rotacoes  
// Autor : Arduino e Cia  
   
#include <CustomStepper.h>  
   
//Define os parametros de ligacao do motor de passo  
CustomStepper stepper(8, 9, 10, 11, (byte[]){8, B1000, B1100, B0100, 
B0110, B0010, B0011, B0001, B1001}, 4075.7728395, 12, CW);  

boolean rotate1 = false;  
boolean rotatedeg = false;  
boolean crotate = false;  
   
void setup()  
{  
  //Define a velocidade do motor  
  stepper.setRPM(12);  
  //Define o numero de passos por rotacao  
  stepper.setSPR(4075.7728395);  
}  
   
void loop()  
{  
  if (stepper.isDone() && rotate1 == false)  
  {  
    delay(2000);  
    //Define o sentido de rotacao (CW = Horario)  
    stepper.setDirection(CW);  
    //Define o numero de rotacoes  
    stepper.rotate(3);  
    rotate1 = true;  
  }  
    
  if (stepper.isDone() && rotate1 == true)  
  {  
    delay(2000);  
    //Define o sentido de rotacao (CCW = Anti-horario)  
    stepper.setDirection(CCW);  
    //Define o numero de rotacoes  
    stepper.rotate(2);  
    rotate1 = false;  
  }  

  //Comando obrigatorio para funcionamento da biblioteca  
  stepper.run();  
}  

O segundo exemplo é o controle do motor de passo pelo ângulo de rotação. A cada 2 segundos, o motor rotaciona 90 graus :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Programa : Controle motor de passo 28BYJ-48 - Angulo  
// Autor : Arduino e Cia  
   
#include <CustomStepper.h>  
   
//Define os parametros iniciais de ligacao do motor de passo  
CustomStepper stepper(8, 9, 10, 11, (byte[]){8, B1000, B1100, B0100, 
B0110, B0010, B0011, B0001, B1001}, 4075.7728395, 12, CW);  
   
void setup()  
{  
  //Define a velocidade do motor  
  stepper.setRPM(12);  
  //Define o numero de passos por rotacao  
  stepper.setSPR(4075.7728395);  
}  
   
void loop()  
{  
 if (stepper.isDone())  
 {  
   //Intervalo entre acionamentos  
   delay(2000);  
   //Define o sentido de rotacao (CW = Horario)  
   stepper.setDirection(CW);  
   //Define o angulo de rotacao  
   stepper.rotateDegrees(90);  
  }  

  stepper.run();  
}  

Você pode adaptar esse programa para outros motores de passo, observando a sintaxe do comando CustomStepper no inicio do programa :

CustomStepper stepper(8, 9, 10, 11, (byte[]){8, B1000, B1100, B0100, B0110, B0010, B0011, B0001, B1001}, 4075.7728395, 12, CW)

onde :

8, 9, 10 e 11 : são as portas utilizadas para ligação ao motor/driver

byte[]){8, B1000, B1100, B0100, B0110, B0010, B0011, B0001, B1001} : Refere-se à sequência de ativação das bobinas do motor. O número 8 corresponde ao número de passos, que no caso do 28BYJ-48 segue a tabela abaixo:

Sequencia de ativação - 28BYJ-48


4075.7728395 = Numero de passos necessários para uma rotação completa do motor. O valor refere-se ao motor de passo 28BYJ-48, e deve ser ajustado para outros tipos de motores.

12 = Velocidade de rotação

CW = O último parâmetro é o sentido de rotação, que pode ser CW = Horário, CCW = Anti-horário, ou STOP = Parado

Como vimos, a utilização da biblioteca CustomStepper é bem simples e se mostra uma boa alternativa para controle de motores de passo.