segunda-feira, 25 de abril de 2011

Picaxe Triac





Seguindo a linha de circuitos básicos. Esta postagem trata do controle de dispositivos alimentados por tensão da rede domestica 110v ou 220v através de  um microcontrolador. Neste caso o picaxe 08M. Um triac é o componente principal da etapa de corrente alternada. Uma lâmpada é usada no exemplo mas nada impede o acionamento de outros dipositivos AC, como motores monofásicos, respeitando-se o limite de corrente no triac usado.

O circuito de força utilizado não foi concebido por mim, foi montado a partir destas informações publicadas no fórum do Arduino, onde é possível ver detalhe inclusive do layout da placa. Este circuito não controla a intensidade luminosa.


A idéia da montagem é bem simples Um potenciômetro, ligado a uma entrada analógica do picaxe, é usado para determinar o intervalo entre as piscadas de uma lâmpada incandescente comum. O desenho do circuito pode ser visto ao lado. Abaixo é mostrado o código fonte.


symbol pot_value = w1
symbol lamp_pin =  2


main: 'loop principal

READADC10 4, pot_value    ' le o valor do potenciometro ligado 
                  ' ao pino 2 e armazena em pot_value
    
high lamp_pin    'acende a lampada

pause pot_value  ' aguarda o tempo determinado pelo potenciometro

low lamp_pin     'apaga a lampada

pause pot_value  ' aguarda o tempo determinado pelo potenciometro

goto main        'fim do loop principal, retorna ao inicio


quarta-feira, 6 de abril de 2011

Arduino 8x8 leds




Existe muita coisa na internet sobre matriz de leds 8x8. Inclusive com o arduino. Mesmo assim , partindo da idéia de que quanto mais, melhor, decidi criar esta postagem que descreve a ligação de uma destas matrizes ao arduino com o auxilio de um contador  4017.
Newton C. Braga  neste artigo explica o funcionamento do contador 4017 incluindo exemplos de utilização, vale a pena.

Como o nome diz é uma matriz, naturalmente composta de linhas e colunas, cujos elementos são os leds. Numa matriz unicolor o "endereço" do led é dado por sua linha e coluna na bicolor e  na RGB é preciso determinar além da linha e coluna a cor do led. Para acendermos um determinado led(linha, coluna), julgando que o anodo está ligado ao pino linha e o catodo ao coluna, devemos ligar a linha correspondente ao positivo e a coluna ao negativo da fonte.

Nesta montagem foi usada uma matriz bicolor, entretanto o código só usa a cor vermelha. Numa outra oportunidade postarei algo que use duas cores.


Funcionamento


O 4017 tem 10 saídas. Assim que ele é ligado b0  é colocado em nível alto (+5V) e a cada pulso de clock uma das saídas subsequentes é colocada em nível alto. O ciclo se repete depois que a décima saída é colocada em nível alto, ou que o reset seja acionado, reiniciando a contagem. Aqui o 4017 é responsável pelo +5 de cada linha de led. A cada pulso de clock enviado pelo arduino ele alimenta os anodos dos diodos de uma das linhas da matriz, começando de cima.

As colunas são ligadas diretamente ao arduino que deve colocar a saída correspondente em nível baixo (0V) para acender o led cuja linha esteja sendo alimentada, com 5V, pelo 4017, conforme figura acima.
Cada caractere é armazenado em um vetor de oito bytes onde cada byte corresponde a uma linha da matriz, sempre de cima para baixo. Neste vetor '0' representa led apagado e '1' aceso.
Por exemplo, para a letra A:
  B0      0 0 1 1 1 1 1 0 0   
B1      0 1 1 1 1 1 1 1
B2      1 1 0 0 0 0 0 1 1
B3      1 1 0 0 0 0 0 1 1
B4      1 1 1 1 1 1 1 1 1
B5      1 1 0 0 0 0 0 1 1
B6      1 1 0 0 0 0 0 1 1
B7      1 1 0 0 0 0 0 1 1

Teremos o vertor: A[8] = {B00111100, B01111110, B110000011, B110000011, B111111111, B110000011, B110000011, B110000011}
 
O programa

A dinâmica do programa é a seguinte:
1.    O texto é armazenado em um vetor;

2.    O programa pega caractere por caractere compara com os caracteres disponíveis e  armazena o vetor   correspondente em uma vetor auxiliar;

3.    Cada byte, bit a bit, é armazenado em uma linha da matriz "aux" ; 

4.    A matriz aux é passada para a função que imprime no display;

5.    Para dar a idéia de deslocamento a primeira coluna da matriz aux copia a segunda, a segunda copia a terceira isso até que oitava coluna seja copiada pela sétima e receba a primeira coluna do próximo caractere ou colunas em branco enviadas pela função "apaga_coluna(n° de colunas)".  Existe, também a possibilidade de mostrar, sem deslocamento, o caractere no display atravéz do parametro modo da função escreve.
O código fonte pode ser visto abaixo.
#include <string.h>

              //  0 1 2 3 4 5 6 7
 int aux[8][8]= {0,0,0,0,0,0,0,0, //0     //poderia ter usado dois laços um para colunas outro para linhas pra fazer o mesmo
     /*  k  m */ 0,0,0,0,0,0,0,0, //1     //mas assim parece mais didatico
                 0,0,0,0,0,0,0,0,         // k linha    m columa
                 0,0,0,0,0,0,0,0,
                 0,0,0,0,0,0,0,0,
                 0,0,0,0,0,0,0,0,
                 0,0,0,0,0,0,0,0,
                 0,0,0,0,0,0,0,0};

int aux2[8][8];    // cada byte corresponde a uma linha da letra de cima para baixo        
             // linha 1          2          3           4          5          6          7          8
     byte A[8] = {B00111100, B01111110, B11000011, B11000011, B11111111, B11111111, B11000011, B11000011};            
     byte B[8] = {B11111110, B11111111, B11000111, B11111110, B11111110, B11000111, B11111111, B11111110};               
     byte C[8] = {B11111111, B11111111, B11000000, B11000000, B11000000, B11000000, B11111111, B11111111};               
     byte D[8] = {B11111100, B11111110, B11000111, B11000011, B11000011, B11000111, B11111110, B11111100};      
     byte E[8] = {B11111111, B11111111, B11000000, B11111100, B11111100, B11000000, B11111111, B11111111};                
     byte F[8] = {B11111111, B11111111, B11000000, B11111100, B11111100, B11000000, B11000000, B11000000};
     byte G[8] = {B11111111, B11111111, B11000001, B11000000, B11001111, B11000011, B11111111, B11111111};
     byte H[8] = {B11000011, B11000011, B11000011, B11111011, B11111111, B11000011, B11000011, B11000011}; 
     byte I[8] = {B11111111, B11111111, B00011000, B00011000, B00011000, B00011000, B11111111, B11111111};
     byte J[8] = {B01111111, B01111111, B00001100, B00001100, B11001100, B11001100, B11111100, B01111000};                                    
     byte K[8] = {B11000011, B11000111, B11001110, B11111100, B11111100, B11001100, B11000111, B11000011};         
     byte L[8] = {B11000000, B11000000, B11000000, B11000000, B11000000, B11000000, B11111111, B11111111};
     byte M[8] = {B11000011, B11100111, B11111111, B11011011, B11011011, B11000011, B11000011, B11000011};  
     byte N[8] = {B11000011, B11100011, B11110011, B11111011, B11011111, B11001111, B11000111, B11000011};  
     byte O[8] = {B01111110, B11111111, B11000011, B11000011, B11000011, B11000011, B11111111, B01111110};
     byte P[8] = {B11111110, B11111111, B11000011, B11111111, B11111110, B11000000, B11000000, B11000000};           
     byte Q[8] = {B01111110, B11111111, B11000011, B11000011, B11001011, B11000111, B11111110, B01111101};      
     byte R[8] = {B11111110, B11111111, B11000011, B11000010, B11111100, B11111110, B11000111, B11000111};     
     byte S[8] = {B11111111, B11111111, B11000000, B11111111, B11111111, B00000011, B11111111, B11111111};
     byte T[8] = {B11111111, B11111111, B00011000, B00011000, B00011000, B00011000, B00011000, B00011000};
     byte U[8] = {B11000011, B11000011, B11000011, B11000011, B11000011, B11000011, B11111111, B01111110};
     byte V[8] = {B11000011, B11000011, B11000011, B11000011, B11000011, B01100110, B00111100, B00011000};
     byte X[8] = {B11000011, B11100111, B01100110, B00011000, B00011000, B01100110, B11100111, B11000011};
byte ponto[8] =  {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00011000, B00011000};
byte coracao[8]= {B01100110, B11111111, B11111111, B11111111, B11111111, B01111110, B00111100, B00011000}; 
byte espaco[8] = {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000}; 


int cont = 0;

int ckPin = 13;                // clock para o contador
int displayPin[8] = {12,11,10,9,8,7,6,5};// pinos de dados
int rstPin = 3;    // reset contador

void setup()                   
{
  int i;
  
  pinMode(ckPin, OUTPUT);      
  pinMode(rstPin, OUTPUT);
  
  for(i=0;i<8;i++)
  pinMode(displayPin[i], OUTPUT);  // pinos com saida

}
char *frase ={"TECNOMELQUE.BLOGSPOT.COM  "};  // texto a ser mostrado  {"AABBCC"};
int t =0;
void loop()                     //inicio programa principal     n
{
 t =0;
 while(t < strlen(frase))
  {                            // envia letra por letra da frase para funcao escreve
  escreve(frase[t], 1, 100);  // caracte, modo 0 apenas mostra 1 desloca, tempo 
  
  apaga_coluna(2); // espaco entre letras passa quantidade de colunas
  t++;
  }
  apaga_coluna(8);
  escreve('~',0,1000);
  delay(500);
  escreve('~',0,1000);
  delay(500);
  escreve(' ',0,100);

  
 
}  //fim da funcao principal

//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

  void escreve(char letra, int modo, int tmp){
  int k;
  byte *Lt;
  
  switch(letra)   // compara a letra e armazena o vetor correspondente em Lt 
  {
  case 'A':
  Lt=A;
  break;
  
  case 'B':
  Lt=B;
  break;
  
 case 'C':
 Lt=C;
 break;

  case 'D':
 Lt=D;
  break;
  
  case 'E':
Lt=E;
  break;
  
  case 'F':
Lt=F;
  break;
  
  case 'G':
Lt=G;
  break;
  
  case 'H':
Lt=H;
  break;
  
  case 'I':
 Lt=I;
  break;
  
  case 'J':
Lt=J;
  break;
  
  case 'K':
Lt=K;
  break;

  case 'L':
 Lt=L;
  break;
  
  case 'M':
  Lt=M;
  break;
  
  case 'N':
  Lt=N;
  break;
 
  case 'O':
  Lt=O;
  break;
  
  case 'P':
  Lt=P;
  break;
  
  case 'Q':
Lt=Q;
  break;


  case 'R':
Lt=R;
  break;

  case 'S':
Lt=S;
  break;
  
  case 'T':
Lt=T;
  break;
  
  case 'U':
Lt=U;
  break;
  
  case 'V':
Lt=V;
  break;
  
 case 'X':
Lt=X;
  break;

  case '.':
  Lt=ponto;
  break;
  
  case '~':
 Lt=coracao;
  break;
  

 case ' ':
 Lt=espaco;
  break;

 }
  

 //copia o caracter para aux
 // bit por bit é armazenado na matriz aux
   for(int i=0; i<8;i++)
   {
     for(int j=0; j<8;j++)
     {
      if(modo == 0)
      aux[i][j] = bitRead(Lt[i], 7-j); 
      else
       aux2[i][j] = bitRead(Lt[i], 7-j); 
     }
   }

  if ( modo == 0)  // mostra ccaracter
 {
    imprime(tmp);
  }
  else if( modo == 1)  // modo 1 desloca caracter anterior
  {
    
  cont = 0;
   
  for (int passo =0; passo <8; passo++)
  {
    
  for(k=0; k<8; k++)  // linhas
  {
    
  for(int m=0; m < 7;  m++)   
  {
    
   aux[k][m] = aux[k][m+1];

  }
   aux[k][7] = aux2[k][cont];   // ultima coluna de aux recebe a primeira coluna de  E
  }
  
  cont ++; 

  imprime(tmp);  // mostra no display

  } //fim da contagem de passos
} // fim de escreve letra

  }
  
 
   

//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

void apaga_coluna(int qtd)
{
 int k;
  
for (int passo =0; passo <qtd; passo++)
  {
    
  for(k=0; k<8; k++)  // linhas
  {
    
  for(int m=0; m < 7;  m++)   
  {
    
   aux[k][m] = aux[k][m+1];

  }
   aux[k][7] = 0;   // ultima coluna de aux recebe a primeira coluna de  E
  }
  
  cont ++;
 
  imprime(100);  // mostra no display

 } //fim da contagem de passos

} //fim apaga coluna

//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

 void imprime(int tmp)
 {
 // int tmp = 100;

  for(int a=0; a < tmp; a++)   // tmp representa a quantidades de vezes que cada caracter é exibido
  {     
  digitalWrite(rstPin, LOW); // prepara para reset do contador
  
    for(int i =0; i<8; i++) // linhas
    {
     digitalWrite(ckPin, LOW); // como a mudança ocorre na descida do clock esta linha so faz sentido no segund ciclo
  
   for(int j=0;j<8;j++)   // colunas
  {
      if(aux[i][j] == 1) 
      {
       digitalWrite(displayPin[j], LOW);
      }
     else
     {
     digitalWrite(displayPin[j], HIGH);
     }
  }
    
  delay (0.5); // entre linhas
  
   for(int i=0;i<8;i++)                    // apaga a linha
   digitalWrite(displayPin[i], HIGH);
 
  digitalWrite(ckPin, HIGH); 
   
 }
 
  digitalWrite(rstPin, HIGH);  // reset do contador
 
 }  
 }