29 de set. de 2013

Interface PPM - Usando rádio controle de modelismo

 

E ai pessoal, tudo certo?  estou voltando aos post’s e gostaria de apresentar a vocês um projeto bacana para quem pretende conciliar duas áreas distintas porém que trazem muitas alegrias a quem lhes concede tempo e empenho, são elas a eletrônica embarcada e o modelismo!

 

foto

 

Que tal desenvolvermos um software para agregarmos funções aos nossos modelos? ou quem sabe incrementarmos aquele robô em desenvolvimento para que possamos obter distâncias maiores além de podermos utilizar vários rádios disponíveis no mercado a preço atraentes… bora lá!!!

Bom para tanto precisamos entender como funciona o sistema de rádio controle destes utilizados no modelismo, não importando qual área de modelismo se aplica, tanto auto, aero ou helimodelismo utilizam a mesma técnica de controle que se dá através de controle PPM.

Controle PPM

PPM (Pulse Position Modulation) é a técnica de controle de servos e outros dispositivos utilizados em modelismo que consiste da modulação por posicionamento de pulso, esta técnica já foi vista anteriormente no blog quando abordamos o  controle de servomotores e mostramos como gerar os pulsos para controlarmos os dispositivos atuadores (servos).

 

servo-pwm_w400

 

A abordagem desta vez será inversa, ou seja, iremos aprender a ler um pulso proveniente de um receptor de aeromodelismo a fim de criarmos nossos próprios atuadores, que podem ser chaves digitais On-Off, saídas de tensão proporcionais aos valores dos Sticks do rádio, sistemas de iluminação, automáticos para trens de pouso, sequenciadores de portas, enfim, o que sua imaginação lhe proporcionar!

 

Rádios e Receptores

Atualmente os sistemas de radio controle para modelismo sofreram uma merecida atualização no que diz respeito ao meio de comunicação entre rádio e receptor, várias técnicas já foram utilizadas, sendo elas AM(Amplitude Modulada), FM (Frequência Modulada) muito comum até então e por fim a mais utilizada atualmente, a 2.4GHz que utiliza um protocolo baseado em salto de frequência, mais isso no momento não é o foco do nosso projeto, iremos nos concentrar apenas no sinal PPM já processado pelo receptor.

 

SPM18800-GAL01

 

Neste exemplo vamos utilizar um receptor DSMX2 da marca Orange, que possui uma taxa de repetição de frames a cada 22ms, cada frame varia então de 1ms a 2ms correspondentes a posição do Stick do rádio, a alimentação do receptor é de 5V sendo alimentado pela própria placa PK2Lab.

 

70170

 

 

Processamento do sinal PPM

Para efetuarmos a análise do sinal PPM pelo microcontrolador podemos efetuar a medição do tempo em que o sinal permanece em nível alto, para isto vamos utilizar o recurso CAPTURE do modulo CCP1 do PIC 16F887.

 

Sinal captura com Stick centrado

 

Bom, temos agora que começar configurando o TMR1 do PIC16F887 para incremento a cada 1us,  e a borda de interrupção do módulo CCP1 para captura na borda de subida, assim que este evento for detectado, zeramos os contadores de 16 bits do TMR1 e alteramos a borda de captura para detectar o momento exato em que esse sinal volta a nível baixo, quando isso ocorrer os registradores do TMR1 irão conter o valor exato correspondente diretamente ao tempo em que o sinal permaneceu alto, esse tempo é um espelho do posicionamento do stick do controle.

Vale observar que a mudança de sensibilidade de borda do módulo CCP1 gera o disparo errôneo desta interrupção, portanto, temos que tomar a precaução de manter desabilitada essa interrupção durante esta mudança de borda.

 

Programa

 

/******************************************************************************

                      JL Audio Manutenção Eletrônica

Data: 09/2013
Autor: Jean Carlos
Projeto: Decodificador de sinais PPM
Microprocessador: PIC16F887
Clock do processador: 8MHz
Estação de desenvolvimento: PK2Lab
Compilador: MikroC PRO V4.60.0.0
Versão atual:  1.0
Descrição:

              Este projeto consiste em decodificar os sinais PPM
              provenientes da saída de um receptor de rádio controle


*******************************************************************************/
// Configuração do LCD da placa PK2Lab V.1.1

sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;

sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;


//Variáveis Globais

char txt[7];
unsigned int Tempo_L, Tempo_H, Pulso;

//Interrupções

void interrupt()
{
if(CCP1IF_bit && CCP1CON.B0)  // Captura por CCP1 e borda como subida...
{
  CCP1IF_bit  = 0;            // Limpa a flag para nova captura
  CCP1IE_bit  = 0;            // Desabilita interrupção por periféricos(CCP1)
  CCP1CON     = 4;          // Configura a borda de captura para DESCIDA.
  CCP1IE_bit  = 1;            // Habilita interrupção por periféricos(CCP1)
  TMR1H       = 0;             // Zera registradores do TMR1 para contagem de tempo
  TMR1L       = 0;
  TMR1ON_bit  = 1;          // Habilita contagem de tempo.
}

else if(CCP1IF_bit)
      {
       CCP1IF_bit  = 0;       // Limpa a flag para nova captura
       TMR1ON_bit  = 0;     // Desabilita contagem de tempo.
       CCP1IE_bit  = 0;       // Desabilita interrupção por periféricos(CCP1)
       CCP1CON     = 5;     // Configura a borda de captura para SUBIDA.
       CCP1IE_bit  = 1;       // Habilita interrupção por periféricos(CCP1)
       Tempo_H     = CCPR1H; 

       Tempo_L     = CCPR1L;  // Carrega valores de tempo   capturado           
      }

}

//Rotina Principal

void main()
{
TRISD  = 0b00000000;
TRISE  = 0b00000000;
TRISC  = 0b00000100;         // Entrada CCP1
PORTC  = 0b00000000;
ANSEL  = 0b00000000;       // Entradas digitais.
ANSELH = 0b00000000;      // Entradas digitais.
INTCON = 0b11000000;       // Liga interruptores GIE e PEIE
TMR1IE_bit = 0;                 // Desabilita interrpções de TMR1
CCP1IE_Bit = 1;                 // Habilita interrupções por CAPTURA(CCP1)
CCP1CON    = 5;                // CCP1 para CAPTURA borda de SUBIDA.

T1CKPS1_bit = 0;               // Prescaller TMR1 2:1
T1CKPS0_bit = 1;
TMR1CS_bit  = 0;               // Clock selecionado -> OSC/4
TMR1ON_bit  = 0;               // Timer -> 1 = Habilita contagem


Lcd_Init();
Lcd_Cmd(_Lcd_Cursor_Off);
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"***  PK2Lab  ***");
Lcd_Out(2,1,"Pulso us:       ");
Delay_ms(100);

while(1)
{
Delay_ms(100);                               // Intervalo entre leituras.
Pulso = (Tempo_H<<8)+ Tempo_L;   // Obtenção do pulso PPM
IntToStr(Pulso, txt);                         // Converte texto para impressão
Lcd_Out(2,11,txt);                           // Mostra Pulso em us no display

if(Pulso > 1600) PORTE.B1 = 1;
    else          PORTE.B1 = 0;

if(Pulso > 1100) PORTD.B0 = 1;
    else          PORTD.B0 = 0;

if(Pulso > 1200) PORTD.B1 = 1;
    else          PORTD.B1 = 0;

if(Pulso > 1300) PORTD.B2 = 1;
    else          PORTD.B2 = 0;
   
if(Pulso > 1400) PORTD.B3 = 1;
    else          PORTD.B3 = 0;

if(Pulso > 1500) PORTD.B4 = 1;
    else          PORTD.B4 = 0;

if(Pulso > 1600) PORTD.B5 = 1;
    else          PORTD.B5 = 0;

if(Pulso > 1700) PORTD.B6 = 1;
    else          PORTD.B6 = 0;

if(Pulso > 1800) PORTD.B7 = 1;
    else          PORTD.B7 = 0;
   
   
}//while(1)
}//main

/******************************************************************************

 

Vídeo do projeto

19 de jan. de 2013

Acelerômetro Digital via I²C

Olá pessoal… depois do jejum de post’s resolvi postar algo um pouco mais complexo para me redimir um pouco… se bem que acredito que a leitura será interessante e muito agradável pois se trata de uma tecnologia atual e que já faz parte do nosso cotidiano, vamos implementar o uso de um acelerômetro digital com comunicação via I²C.

Acelerômetro

O acelerômetro consiste em um dispositivo micro eletromecânico (MEMS) que utiliza-se de nanotecnologia para construção de sensores que medem a grandeza de aceleração em objetos.

Acelerometro_GLB

Para conseguir efetuar a leitura desta grandeza, este componente possui em seu interior uma massa móvel contendo várias placas que interagem com placas fixas ao ci, formando desta maneira um sistema capacitivo que altera o valor da capacitância conforme o movimento da massa móvel, ou seja, a cada movimento no componente temos uma informação disponível relacionada a um dos eixos.

Zoom de 1500x em um MEMS da ST

mems II

A empresa ST Microeletronics desenvolve a muitos anos essa tecnologia e hoje conta com seus MEMS instalados em muitos equipamentos, desde pequenos brinquedos e controle de video games até os telefones de ultima geração.

Para este post, vamos utilizar o LIS3LV02DL que possui muitos recursos embutidos além de medir aceleração em três eixos e possuir comunicação via barramento I²C que é um dos mais utilizados para comunicação entre microcontroladores e seus periféricos, além de ter duas escalas de medição, uma medindo até 2 g e outra medindo até 6 g, sendo 1.0025 g o equivalente a uma aceleração de 9.8310 m/s².

Este componente é fornecido pela ST Microeletronics em uma placa de avaliação comercializada pelo código STEVAL-MKI009V1.

image_steval-mki009v1

DSC01323

Abaixo podemos observar a foto do acelerômetro LIS331, utilizado no iPhone 3GS comparado a uma moeda.

LIS331

Os acelerômetros podem apresentar duas formas de interfaceamento, sendo, digital ou analógico, nos analógicos as saídas correspondentes aos eixos informam a grandeza variando o nível de tensão DC no pino correspondente ao seu eixo, já no caso dos acelerômetros digitais, esses valores são transferidos via comunicação serial, podendo ser utilizado I²C ou SPI.

mems3

Este componente ainda conta com uma interrupção por movimentos, sendo possível efetuar o ajuste do nível de sensibilidade.

Curiosidade!!!

Alguns computadores antigos da Apple, contam com uma função que detecta uma possível queda de nível, fazendo com que a agulha do HD fosse para a posição de descanso a fim de não danificar o disco antes do impacto acontecer, pois bem, como é possível efetuar a detecção de queda livre?

R. Como todos sabemos, todos os corpos na terra sofrem a ação da gravidade, portanto o acelerômetro sempre estará sofrendo esta força, quando em queda livre de maneira linear, esta força tende a se anular pois o corpo acelera em relação ao eixo da terra e é neste momento que se pode detectar a queda livre ou free fall.

free fall


Interfaceamento 

Para interfacear o acelerômetro, temos que atentar para o fato da tensão de alimentação do mesmo que é de 3.3V ser diferente da tensão de alimentação da placa, para isto vamos utilizar um regulador externo de 3.3V além de dois resistores de pull up, este é um diferencial da placa PK2Lab, pois foi construída com o intuito de trabalhar com periféricos I²C com tensões de 3.3V ou 5V de forma simples e direta.
 
Vale lembrar que os microcontroladores PIC quando alimentados com uma tensão de 5V, entendem como nível lógico alto uma tensão superior a 2V, portanto podemos conectar os pinos TX e RX do acelerômetro nos pinos do microcontrolador que os níveis lógicos serão entendidos.
 
Comunicação I²C
 
A comunicação foi estabelecida pelo protocolo I²C na frequência de 100Khz  a 3.3V sendo respeitado a tabela de tempos conforme datasheet.
 
Para efetuarmos as leituras referentes aos eixos, primeiro precisamos configurar o acelerômetro para informar como desejamos receber os dados, para isto devemos seguir a seguinte sequência.
 

# Inicializar o barramento

# Informar o comando de escrita para o LIS3LV02DL

# Escrever o conteúdo do registrador CTRL_REG1 (Já vem indexado)

# Escrever o conteúdo do registrador CTRL_REG2

 

Após este procedimento podemos efetuar as leituras propriamente ditas seguindo a sequência abaixo.

# Inicializar o barramento

# Informar o comando de escrita para o LIS3LV02DL

# Informar qual o endereço desejamos ler inicialmente

# Reinicializar o barramento novamente

# Informar o comando de leitura para o LIS3LV02DL

# Efetuar a leitura de forma sequencialmente dos eixos

Por fim, como a leitura do acelerômetro se dá em 12 bits, precisamos concatenar esses dois bytes para obtermos a informação desejada para enfim apresentarmos os resultados no display LCD  e via porta serial.

 
Alguns registradores internos ao Acelerômetro
  • WHO_AM_I
    Endereço padrão deste CI no barramento I²C…
  • CTRL_REG1
    Configurações para habilitação de leitura dos eixos, self test…
  • CTRL_REG2
    Seleção de escala, interrupções…
  • CTRL_REG3
    Ajuste de clock e filtros passa alta…

 


Software

O software para este exemplo mede a aceleração dos 3 eixos em 12 bits apresentando os valores lidos no display LCD, e envia os dados periodicamente via porta serial para o terminal serial do PC a 9600bps.

/******************************************************************************

                      JL Audio Manutenção Eletrônica

Data: 23/04/2011
Autor: Jean Carlos
Projeto: MEMS ST - Acelerômetro  ( LIS3LV02DL )
Microprocessador: PIC18F4550
Clock do processador: 8MHz
Estação de desenvolvimento: PK2Lab V1.1
Versão atual:  V 1.0
Descrição:

          Este projeto demonstra o uso de um MEMS(Sistema Micro eletromecânico)
          da ST, modelo LIS3LV02DL que se trata de um acelerômetro digital
          de 3 eixos (2G e 6G)


*******************************************************************************/
//Variáveis Globais

unsigned char XL,XH,YL,YH,ZL,ZH;
unsigned int X,Y,J;
char txt[7];


//****************************************************************
//Rotinas Auxiliares

void Le_Acelerometro()
      {
      I2C_Start();
      I2C_Wr(0x3A);     // Endereço do acelerômetro para escrita.
      I2C_Wr(0xA8);     // Endereço do registrador Eixo X Lower (0x28), ainda foi setado o sétimo bit do registrador para indicar a indexação automática do endereço.
      I2C_Repeated_Start();
      I2C_Wr(0x3B);     // Endereço do acelerômetro para leitura.
      XL = I2C_Rd(1);
      XH = I2C_Rd(1);
      YL = I2C_Rd(1);
      YH = I2C_Rd(1);   // Carrega as informações referentes aos eixos
      ZL = I2C_Rd(1);
      ZH = I2C_Rd(0);
      I2C_Stop();
      }
     
     
void Envia_Serial()
     {
     Usart_Write(X);
     Usart_Write(Y);
     Usart_Write(J);
     }
    
//****************************************************************
//Rotina Principal

void main()                               // Início do programa principal
{
TRISA = 0b00000000;
PORTA = 0b00000000;
TRISB = 0b00000000;
PORTB = 0b00000000;
TRISC = 0b00000000;
PORTC = 0b00000000;
TRISD = 0b00000000;
PORTD = 0b00000000;
TRISE = 0b00000000;
PORTE = 0b00000000;
ADCON1 = 0X0F;          // Entradas digitais.

Lcd_Config(&PORTB,2,3,1,7,6,5,4);  // Configuração PK2Lab V.1.1
Lcd_Cmd(Lcd_Cursor_Off);
Lcd_Cmd(Lcd_Clear);
Lcd_Out(1,1,"***  PK2Lab  ***");
Lcd_Out(2,1,"  Acelerometro  ");
Delay_ms(3000);
Lcd_Cmd(Lcd_Clear);
Lcd_Out(1,1,"X:");
Lcd_Out(2,1,"Y:");
Lcd_Out(2,9,"Z:");

Usart_Init(9600);  // Inicia comunicação RS232
I2C_Init(100000);  // Inicia comunicação I2C


   I2C_Start();                          // Inicia comunicação I2C
   I2C_Wr(0x3A);                     // Endereço do LIS3LV02DL para escrita
   I2C_Wr(0xA0);                     // Primeira palavra de endereço inicia pelo registrador CTRL_REG1 (0x20) , escrita contínua…
   I2C_Wr(0xC7);                     // 11000111 ---> CTRL_REG1  C7
   I2C_Wr(0x04);                      // 00000100 ---> CTRL_REG2  04
   I2C_Stop();

 

while(1)
{
Le_Acelerometro();          // Efetua a leitura de aceleração dos 3 eixos
Delay_ms(100);

X = (XH);                         // Concatena as partes altas e baixas dos registradores.
X = (X<<8) + XL;

Y = (YH);
Y = (Y<<8) + YL;

J = (ZH);           // Foi usado J no lugar de Z pois Z o compilador usa como Zero
J = (J<<8) + ZL;

intToStr(X,txt);                
Lcd_Out(1,3,txt);
intToStr(Y,txt);
Lcd_Out(2,3,txt);
intToStr(J,txt);
Lcd_Out(2,11,txt);

Envia_serial();                // Envia os dados pela porta serial a 9600bps

}//while(1)
}//main


Vídeos do projeto

Neste vídeo podemos observar o projeto em funcionamento.

Neste outro vídeo, vemos o acelerômetro controlando um equipamento de iluminação profissional (Moving Head) onde controlamos PAN e TILT através da leitura dos eixos X e Y respectivamente.

 

Gostaria de agradecer imensamente ao Eng. André Braz, representante da empresa ST Microelectronics no Brasil, que gentilmente cedeu algumas peças destas incríveis máquinas assim como muita informação técnica! Valeu André!!!

Bom pessoal, por hoje é isto, grande abraço a todos e bons projetos!

16 de dez. de 2012

PK2Lab - Como adquirir sua placa.

E ai galera, mais um ano que finda, com muitas coisas boas para serem comemoradas e muitas histórias a serem contadas, para mim particularmente foi uma ano de conquistas e abertura de novos horizontes espero que todos possam compartilhar do mesmo sentimento!

Apresento a vocês o novo site da minha empresa JL Audio Manutenção Eletrônica, através do qual serão comercializados os produtos por mim desenvolvidos, entre eles a placa PK2Lab e o Curso de microcontroladores PIC.

 

Site

 

Todo o processo de compra pode ser efetuado pelo próprio site, onde é possível ainda simular o valor de frete.

Para compras em maior quantidade, empresas  ou instituições de ensino, enviar  e-mail para contato@jlaudioeletronica com o assunto PK2Lab, para ter acesso a descontos especiais.

Para facilitar o acesso do hardware ao aluno ou hobbysta, o valor da placa pode ser parcelado em até 18 vezes no cartão de crédito, tornando a tecnologia acessível a todos.

Tire seus projetos da tela do PC… crie realmente aplicações reais em tempo real !

É isso ai, grande abraço a todos, um feliz Natal e um próspero Ano Novo!

Em 2013 teremos vários projetos bacanas envolvendo muitos periféricos interessantes… até breve!

Jean Carlos

PK2Lab Team! @2012

 

27 de out. de 2012

Expansão de I/O - 74HC595

Pessoal, continuando com os posts relacionados aos CI’s de expansão de I/O, apresento a vocês o CI 74HC595, tal como o CI 74LS164, consiste em um conversor serial paralelo de 8 bits (Shift Register) porém com características que ao meu ver o tornam muito mais interessante que o 74164.

74595

Uma das características que o tornam tão especial é o fato de possuir dois registradores para manuseio dos dados, sendo:

  • Shift Register
    Armazena as informações transferidas serialmente como registrador temporário, a cada pulso de clock no pino SRCLK este registrador é carregado bit a bit conforme o nível lógico disponível no pino SER (Entrada Serial).
  • Storage Register
    Este registrador é carregado com as informações disponíveis no registrador  Shift Register quando o pino RCLK é pulsado com um nível lógico alto (Latch), ou seja, podemos manusear o envio dos bits um a um e ao término habilitamos o latch. Isto nos trás uma vantagem enorme na simplificação do hardware, pois no caso do uso do 74164 teríamos que providenciar um mecanismo eletrônico que durante a atualização dos dados apagasse o display para evitar que a serialização fosse percebida.

Além desses dois registradores, o 74595 possui um pino que habilita a operação do mesmo (OE), sendo que quando garantimos um nível alto neste pino temos todas as saídas configuradas como tri-state, ou seja, não drena e nem fornece corrente alguma ao circuito, portando fica configurada como alta impedância.

Outra característica importante é que este CI é capaz de trabalhar com cargas de +- 6ma sendo suficiente para por exemplo, alimentarmos pequenos leds para uso em painéis de IHMs diretamente pelos I/Os do CI.

Lógica de operação:

Diagrama temporal

Aqui podemos observar o funcionamento deste CI passo a passo!


Exemplo de uso

Para exemplificar o uso deste componente, vamos criar uma aplicação junto a PK2Lab, que consiste num contador de 0 à 99 com o uso de dois displays de sete segmentos conectados aos shift registers 74595 em cascata (Daisy Chain), assim podemos criar posteriormente projetos maiores como por exemplo um relógio com horas, minutos e segundos… tendo apenas como limite a sua imaginação!

Esquema:

Esquema

Podemos observar que além dos pinos de alimentação, são utilizados apenas 3 pinos de I/O para controlar os dois displays, e mesmo aumentando a quantidade de CIs, continuamos utilizando apenas 3 pinos, esta é a grande vantagem de se utilizar a comunicação serial para transferência de dados.

DSC01053

Poderíamos ainda ter utilizado os pinos de Reset e Operational Enable para controlar mais algumas funcionalidades, porém no exemplo não foram implementadas ficando estas a cargo do leitor caso queira implementar.


Software

A parte de software deste exemplo já foi explorado anteriormente nos outros posts, apenas temos o acréscimo de um pino de latch que fará com que os dados previamente setados no Shift Register sejam transferidos para os pinos do CI acionando os segmentos dos displays.

Uma prática interessante que podemos adotar ao construir software é o cuidado utilizado ao criar nomes de variáveis dentro de funções, por exemplo, podemos criar uma função chamada Display() e utiliza-lá em muitos projetos com grande facilidade, basta apenas que as variáveis internas desta função utilizem características próprias da função de origem, neste exemplo podemos observar que foi criada a função SN74HC595() e todas as variáveis internas desta função começam com SN74HC595_ seguido do nome da variável propriamente dito, a primeira vista temos a impressão de que o programa fica carregado, porém, facilita muito o inter-relacionamento das variáveis como um todo.

Outro ponto interessante é a chamada recorrente de funções, na linha abaixo podemos ver que chamamos a função display() duas vezes dentro da função SN74HC595().

SN74HC595(Display(Unidade), Display(Dezena));

Com esta única linha de comando montamos os dois bytes referentes aos dígitos de dezena e unidade e enviamos serialmente essas informações.

/******************************************************************************

                      JL Audio Manutenção Eletrônica

Data: 10/2012
Autor: Jean Carlos
Projeto: Registrador de deslocamento SN74HC595
Microprocessador: PIC18F4520
Clock do processador: 8MHz
Estação de desenvolvimento: PK2Lab V 1.1
Compilador: MikroC PRO V 4.60.0.0
Versão atual: 1.0
Descrição:

          Demonstração do uso de shift register para expansão de I/O


*******************************************************************************/
// Inicializações do programa

// Configuração do LCD da placa PK2Lab V.1.1

sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;

sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;

//******************************************************************************
// Variáveis Globais

short Contador = 0;       // Variável para contagem de 0 a 99.
short Dezena   = 0, Unidade = 0;

#define Latch      PORTC.B0
#define Clock      PORTC.B1
#define Ser_Out  PORTC.B2

//******************************************************************************
// Rotinas Auxiliares
//******************************************************************************
// Driver de display de 7 segmentos, número a ser impresso é passado como
// argumento da função.

unsigned char Display(unsigned char no)
{
    unsigned char Pattern;
    unsigned char SEGMENT[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,
                                                0x7D,0x07,0x7F,0x6F};

    Pattern = SEGMENT[no];             // Segmento a retornar
    return (Pattern);
}

void SN74HC595(char SN74HC595_Display1, char SN74HC595_Display2)
{
short SN74HC595_Aux;                 // Variável local de controle do laço for
for(SN74HC595_Aux = 0; SN74HC595_Aux < 8; SN74HC595_Aux ++)
    {
     if( SN74HC595_Display1 & 0b10000000)  Ser_Out = 1;// Máscara o sétimo bit
     else Ser_Out = 0;                      // e verifica se é zero ou um.
     SN74HC595_Display1 = SN74HC595_Display1 << 1; // Rotaciona o próximo bit
     Clock = 1;                                // Pulsa o clock para envio do bit
     Delay_us(1);
     Clock = 0;
    }
Ser_Out = 0;                               // Mantém a linha de dados em nivel baixo
 
  for(SN74HC595_Aux = 0; SN74HC595_Aux < 8; SN74HC595_Aux ++)
    {
     if( SN74HC595_Display2 & 0b10000000)  Ser_Out = 1;// Máscara o sétimo bit
     else Ser_Out = 0;                   // e verifica se é zero ou um.
     SN74HC595_Display2 = SN74HC595_Display2 << 1; // Rotaciona o próximo bit
     Clock = 1;                             // Pulsa o clock para envio do bit
     Delay_us(1);
     Clock = 0;
    }
Ser_Out = 0;                             // Mantém a linha de dados em nivel baixo
 
Latch = 1;
Delay_us(1);
Latch = 0;
}

 

//******************************************************************************
//Rotina Principal

void main()
{
TRISA    = 0b00000000;
PORTA  = 0b00000000;
TRISB    = 0b00000000;
PORTB  = 0b00000000;
TRISC    = 0b00000000;
PORTC  = 0b00000000;
TRISD    = 0b00000000;
PORTD  = 0b00000000;
TRISE    = 0b00000000;
PORTE  = 0b00000000;
ADCON1 = 0X0F;            // Entradas digitais.
OSCCON.B5 = 1;            // Ajusta oscilador interno para 8MHz
OSCCON.B4 = 1;            // Ajusta oscilador interno para 8MHz

Lcd_Init();
Lcd_Cmd(_Lcd_Cursor_Off);
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"***  PK2Lab  ***");
Lcd_Out(2,1,"Shift  SN74HC595");
Sound_Init(&PORTE,0);
Sound_Play(1000,200);
Delay_ms(100);
Sound_Play(1000,200);

while(1)
{
Dezena  = Contador / 10;
Unidade = Contador % 10;
SN74HC595(Display(Unidade), Display(Dezena));
Delay_ms(200);
Contador ++;
if(Contador == 100)
   {
   Contador = 0;
   Sound_Play(1000,200);
   Delay_ms(100);
   Sound_Play(1000,200);
   Delay_ms(100);
   Sound_Play(1000,200);
   while(1){};          // Trava o programa até ser pressionado o reset
   }
  
}//while(1)
}//main


Download do código

Abaixo podemos observar os sinais de controle que foram capturados no analisador lógico, o primeiro sinal é referente ao pino de DADOS, o segundo é o clock e por fim temos o pino de habilitação de transferência(Latch) que é onde efetivamente carregamos os novos valores nos displays.

Analisando as informações podemos ver o número “00” no display, onde os dois pulsos baixos iniciais correspondem aos segmentos “g”  e “.” (ponto decimal) apagados e os outros segmentos acesos.

Analisador

Protótipo montado

Montagem

 

Vídeo do projeto

Bom pessoal, é isso, grande abraço a todos e ótimos projetos!!!

12 de set. de 2012

Expansão de I/O - 74HC164

 

Dando prosseguimento ao último post, venho apresentar um componente bem conhecido dos entusiastas da eletrônica digital, trata-se do circuito integrado SN74HC164, um conversor de dados serial para paralelo de 8 bits também conhecido por registrador de deslocamento ou apenas shift register, sendo este componente facilmente encontrado no mercado brasileiro.

ic164(1)

SN74HC164

Este Ci possui um pino para entrada de dados, sendo esta entrada disponibilizada por meio de uma porta AND (entradas A e B), o que facilita o controle de entrada dos dados.

Lógica

Além dos pinos de entrada de dados, A e B, podemos encontrar um pino para entrada do sinal de clock, podendo operar até 25MHz com a alimentação de 5V, um pino de /CLR que recebe a função de limpar todas as saídas do shift register além dos 8 pinos de saída, pinos estes que podem fornecer uma corrente máxima de 25mA o que já é suficiente para acender de forma eficiente um LED, porém devemos atentar para o fato da corrente máxima admissível entre VDD e VSS que é de 50mA não seja ultrapassada.

Lógica de operação:

TimeChart

Como podemos observar, este CI não possui um pino para controle de ativação das saídas, ou seja, assim que enviarmos o conteúdo dos bits serialmente, estas informações aparecerão nos pinos de saída de forma indesejável, podendo causar danos ao hardware ou mão funcionamento do mesmo. Uma alternativa ao SN74HC164 é o circuito integrado CD4094 que abordaremos em um próximo post.


Exemplo de Uso

Neste exemplo vamos utilizar o SN74HC164 para adicionar 8 LEDs à placa PK2Lab utilizando apenas 2 pinos do microcontrolador, neste caso não será utilizado o pino de reset e o mesmo deverá ser conectado ao VCC, este recurso seria interessante no caso de controlarmos displays de 7 segmentos onde teríamos a possibilidade de efetuar o apagamento de todos os dígitos simultaneamente ao aplicarmos um nível lógico baixo no pino 9.

Esquema

Caso seja necessário aumentar a quantidade de saídas podemos interligar mais de um shift register em cascata, basta interligarmos o pino 13 (MSB) ao pino de entrada de dados do próximo SN74HC164, assim sucessivamente.

Esquema 2

Um exemplo de utilização em cascata deste componente pode ser visto na placa DE-DP011, comercializada pela Sure Electronics, que consiste de um conjunto de cinco shift registers serializados para a apresentação de 40 Leds.

Sure Foto

Abaixo podemos observar o funcionamento desta placa em uma IHM, fornecendo indicação visual sobre distância e tensão de bateria.

Esquema DE-DP011

Para nosso exemplo utilizaremos apenas um CI e 8 Leds para simular um PORT auxiliar, para isto vamos usar o primeiro esquema apresentado neste post.

Foto_1


Software

O Software desenvolvido para este exemplo consiste basicamente de uma função que irá transmitir os dados a serem exibidos no “PORTAux” e uma rotina principal que incrementa uma variável contador a cada 100ms, mostrando o valor de forma binária nos Leds conectados ao SN74HC164.

Para a utilização de mais de um CI cascateado, basta efetuar a chamada da função na mesma proporção de CIs utilizados.

/******************************************************************************

                      JL Audio Manutenção Eletrônica

Data: 09/2012
Autor: Jean Carlos
Projeto: Registrador de deslocamento SN74HC164
Microprocessador: PIC18F4520
Clock do processador: 8MHz
Estação de desenvolvimento: PK2Lab V 1.1
Compilador: MikroC PRO V 4.60.0.0
Versão atual: 1.0
Descrição:

          Demonstração do uso de shift register para expansão de saídas


*******************************************************************************/
// Inicializações do programa

// Configuração do LCD da placa PK2Lab V.1.1

sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;

sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;

//******************************************************************************
// Variáveis Globais

unsigned short contador = 0; // Variavel para contagem de 0 a 255.
char txt[4];                 // Variavel para conversão de dados.

//******************************************************************************
// Rotinas Auxiliares

#define Clear    PORTC.B0
#define Clock    PORTC.B1
#define Ser_Out  PORTC.B2

void SN74HC164(char SN74HC164_Value)
{
short SN74HC164_Aux;                 // Variável local de controle do laço for
for(SN74HC164_Aux = 0; SN74HC164_Aux < 8; SN74HC164_Aux ++)
    {
     if( SN74HC164_Value & 0b10000000)  Ser_Out = 1;  // Máscara o sétimo bit…
     else Ser_Out = 0;                      // e verifica se é zero ou um.
     SN74HC164_Value = SN74HC164_Value << 1;        // Rotaciona o próximo bit
     Clock = 1;                                 // Pulsa o clock para envio do bit
     Delay_us(1);
     Clock = 0;
    }
Ser_Out = 0;                                 // Mantém a linha de dados em nível baixo
}

//******************************************************************************
//Rotina Principal

void main()
{
TRISA = 0b00000000;
PORTA = 0b00000000;
TRISB = 0b00000000;
PORTB = 0b00000000;
TRISC = 0b00000000;
PORTC = 0b00000000;
TRISD = 0b00000000;
PORTD = 0b00000000;
TRISE = 0b00000000;
PORTE = 0b00000000;
ADCON1 = 0X0F;            // Entradas digitais.
OSCCON.B5 = 1;            // Ajusta oscilador interno para 8MHz
OSCCON.B4 = 1;            // Ajusta oscilador interno para 8MHz

Lcd_Init();
Lcd_Cmd(_Lcd_Cursor_Off);
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"***  PK2Lab  ***");
Lcd_Out(2,1,"Shift  SN74HC164");
Delay_ms(1000);
Lcd_Out(2,1,"Contador:       ");


while(1)
{
ByteToStr(Contador, txt);   // Converte o byte numa string para impressão no LCD
Lcd_Out(2, 11, txt);
SN74HC164(Contador);      // Envia os dados para o SN74HC164
Delay_ms(100);                 // Delay entre incrementos
Contador ++;                     // Incremento da variável em uma unidade
}//while(1)
}//main

//**********************************************************************************************

Abaixo podemos observar os níveis lógicos capturados através do analisador lógico da própria PK2Lab. O pino de dados está conectado ao CH1 e o pino de clock está conectado ao CH2. Nesta captura podemos observar o valor do contador igual a 1.

Logic Analiser

Na tela abaixo podemos verificar a captura do contador igual a 128, podemos notar que o formato de envio dos dados é enviando primeiro o bit menos significativo (LSB).

Logic Analiser_128

Bom pessoal, segue o vídeo do projeto em funcionamento, qualquer dúvida ou sugestão deixem um comentário pois será muito bem vindo!

Código do projeto

2 de ago. de 2012

Expansão de I/O - 74HC165

Quando precisamos utilizar um grande número de pinos de I/O em um microcontrolador e não os dispomos, podemos fazer uso de vários recursos, dentre eles a técnica de multiplexação de pinos ou a utilização de registradores de deslocamento.

A última técnica foi utilizada neste projeto com o intuito de demonstrar como conectar cinco teclas e um encoder rotativo (potenciômetro sem fim) ao microcontrolador utilizando apenas 3 pinos de I/O.

74HC165

74HC165

O circuito integrado 74HC165, consiste de um conversor paralelo serial de 8 bits que pode funcionar em uma frequência máxima de operação de 10MHz, possui dois pinos de clock, sendo um deles atribuído para inibição do mesmo possui ainda, um pino responsável pelo carregamento  das informações contidas em suas entradas para um latch interno que é transferido posteriormente de forma serial a cada pulso de clock.

Portanto, para transferirmos a informação contida em suas entradas, precisamos primeiramente carregar estas informações e  depois aplicar 8 pulsos de clock.

Neste exemplo conectamos um encoder rotativo com push-botton e mais 4 chaves tact, onde a cada 1ms obtemos seus estados que ficam armazenados na variável Teclas_8bits.

Encoder

O esquema abaixo utiliza um CI 74HC165 conectado ao hardware escolhido.

Esquema

Podemos efetuar a conexão de mais de um CI 74HC165 para obtermos um maior número de I/Os disponíveis, no exemplo abaixo podem se ver a utilização de dois CIs contendo o total de 16 chaves tacts.

2x74hc165


Software

O software responsável pela leitura do 74HC165 consiste basicamente de um loop for para deslocar os bits e armazenar os valores na variável que irá conter os estados das entradas, neste processo efetuamos o uso de lógica digital para trabalhar os bits da variável, isto é feito dentro da rotina SN74165_8bits().

unsigned char SN74165_8bits()
{
char count;
char bitval;
char teclas_8bits = 0;
Clock = 1;
Load = 0;
Load = 1;
Clock = 0;
for(count=0; count<8; count++)
   {
    bitval = Ser_in;
    teclas_8bits |= (bitval << (7-count));
    Clock = 1;
    Clock = 0;
   }
return(teclas_8bits);
}

Na linha abaixo podemos observar a aplicação de diversos recursos disponibilizados pelo compilador, para que seja possível maximizar a eficiência do código gerado, sendo a utilização de agrupamentos de operadores e a análise de mais de uma condição na mesma linha de comando.

teclas_8bits |= (bitval << (7-count));


Análise dos sinais de controle

Utilizando a ferramenta de Analisador Lógico disponível na placa PK2Lab podemos observar o funcionamento do código e obter os tempos de clock e load aplicados no CI.

Captura 1


Nesta tela acima podemos observar os sinais Load no canal 1, o sinal Clock no canal 2 e a resposta do CI 74HC165 através do sinal Ser_in no canal 3, neste caso os bits dos dois últimos pinos estão em nível alto.

Captura 2

Nesta tela podemos ver o primeiro e último pino em nível alto.

Na aba de trigger, o ajuste [ Ch1=\ ] indica  que o sinal começará a ser capturado quando o pino Load, passar do nível alto para o nível baixo, ou seja, o sinal de trigger ou disparo é sensível a borda de descida.


DSC00948

Código do projeto

17 de jul. de 2012

Relógio LCD com números grandes

Durante o desenvolvimento do projeto de um robô de sumô para a disciplina de projeto integrado II do curso de Engenharia de Controle e Automação, me deparei com a necessidade de mostrar informações numa tela de LCD caractere de 20X4, porém uma grande limitação destes displays facilmente encontrados a venda no comércio é o tamanho efetivo do caractere.

Pensando nisto busquei um artigo que havia me deparado na internet, em que o programador utilizava mais de um caractere para a construção dos dígitos a serem exibidos. O artigo em questão pode ser visto aqui.

Utilizando a técnica descrita anteriormente, aqui mesmo neste blog  foram criados alguns caracteres especiais que formam os dez algarismos utilizados para a criação deste relógio que apresento hoje a vocês.

Caracteres Especiais

A junção de quatro destes caracteres especiais formam um numeral decimal que ocupa o lugar de seis caracteres do display com exceção dos dois últimos caracteres que formam os pontos para divisão dos dígitos do relógio.

Para a base de tempo utilizamos o RTC PCF8583 contido na placa PK2Lab, que nos retorna de forma serial as informações referentes a hora, minutos e segundos e ainda gera um sinal de clock de 1Hz  para a atualização dos dados no display a cada segundo.

O microcontrolador escolhido para este exemplo é o PIC18F4520, por ser o microcontrolador escolhido pela Microchip como substituto natural ao PIC16F877 sendo a pinagem totalmente compatível com os microcontroladores da linha 16F, portanto os pinos de comunicação I2C também seguem esta regra, consequentemente a placa tem que estar com os jumpers na posição 16F e não na posição 18F como usual.

1

Os pinos de enables dos leds devem estar dasabilitados para não influenciarem na comunicação serial I2C.

O programa foi desenvolvido utilizando a ferramenta MikroC PRO e foi baseado no código exemplo do RTC que acompanha a placa, apenas foram feitas algumas modificações para a inserção do código que gera os caracteres maiores no LCD.

Para este projeto foi utilizado o oscilador interno de 8MHz do microcontrolador, é importante observar que por default o microcontrolador opera com uma frequência de 1MHz e é necessário que sejam setados dois bits do registrador OSCCON para configurar a frequência de 8MHz.

OSCCON.B5 = 1;            // Ajusta oscilador interno para 8MHz
OSCCON.B4 = 1;            // Ajusta oscilador interno para 8MHz

Foram criadas algumas funções para conversão e exibição dos números no LCD.

void Caracter_Especial()         

Cria os caracteres especiais na CGRAM do display LCD

void Converte_Numeros(char numero,char lin, char col)

Efetua a conversão dos numeros do RTC para os digitos grandes

void Display_Time()

Mostra os digitos na tela do display LCD

void ZERO(char linha, char coluna)

Prepara os caracteres especias para exibição dos digitos grandes

void PONTOS(char linha, char coluna)

Prepara os caracteres especiais para exibição dos pontos


O resultado pode ser visto abaixo:

DSC00926

 

 

Código do projeto