quinta-feira, 19 de janeiro de 2012

Projeto: Tacômetro de LEDs

O projeto está baseado no microcontrolador de oito bits 16F628 do fabricante Microchip®, mas poderia ter sido feito com um AVR ou qualquer processador pequeno.
O experimento consta de um tacômetro que medirá a rotação (rpm) de um ventilador comum. O resultado desta medição será apresentado através de uma linha de oito LEDs acoplada ao eixo de giro do ventilador aproveitando a rotação do próprio ventilador como varredura. Os números serão então projetados pelo acionamento sincronizado dos LEDs de maneira a produzir cada um dos caracteres numéricos de 0 a 9.

Display de movimento:
O display de movimento pode ser obtido a partir do acionamento preciso de cada pixel sincronizado com o movimento de rotação (caso do experimento em questão).
O movimento de rotação funciona como varredura e o acionamento dos LEDs como estrutura do pixel (On/Off).

Hardware

 O hardware é bem simples está baseado nos testes feitos no Kit com o modulo de LEDs e o conversor série-paralelo 74HC595. O circuito desenvolvido está no anexo 2.
O Microcontrolador utilizado foi o 16F628. O hardware apresenta ainda um cristal de 4MHz, um conversor série/paralelo e um sensor de infravermelho (foto-transistor) para monitoramento o pulso de medição do período de uma volta completa do ventilador.

Software

A metodologia utilizada para desenvolvimento do sistema foi a de máquina de estado. O diagrama de estados abaixo reproduz as condições de estados do sistema.


O sistema

 O funcionamento do sistema esta baseado nas interrupções impostas pelo sensor em RB3. A cada giro do ventilador um pulso será gerado e consequentemente uma interrupção no modulo CCP.

 O SETUP de algumas variáveis importantes do microcontrolador:

    set_tris_A(0x00);
   enable_interrupts(INT_CCP1);   // Habilitação de interrupção CCP1
   enable_interrupts(GLOBAL);     // Habilitação Flag de interrupções globais
   setup_ccp1(CCP_CAPTURE_FE);    // Interrupção CCP1 (modo captura) em bordadescida
   output_high(CLEAR);            // Limpa Latch (buffer de saida)
   output_low(CLOCK);             // Garante clock em nivel lógico zero
   output_low(LATCH);                   // LATCH inicial em zero
   flagPulso=0;                                      // Flag de registro de interrupção
   flagMontado=0;                // Flag de vetor montado
   indVet=1;                              // Indice do vetor
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);

 Habilitado flag de interrupções globais e interrupções de CCP1 (borda de descida), ainda como auxiliar na contagem será utilizado o TMR1 (sincronizado pelo clock interno do MPU) e “prescaler” divisor 8.Através do uso da variável “flagPulso” são capturadas duas medidas de TMR1 entre dois pulsos sucessivos o calculo do período de rotação do ventilador se dá através da seguinte equação
A partir da obtenção do período de rotação poderemos determinar a freqüência e sua rotação em rpm.
Depois de realizados os cálculos resta ao programa embutido exibir os resultados no display de movimento.

Exibição do vetor resultado:

Foram criados no arquivo  “numeros.h” os caracteres numéricos de 0 a 9 de maneira e serem utilizados no display. A montagem visual destes caracteres bem como o arquivo .h a ser utilizado na diretiva "#include" são mostrados na figura:
Cada caractere corresponde a uma matriz de 48bits (8 linhas x 6 colunas) e podem ser representados por uma seqüência de 6 bytes (representados na figura por seus valores hexadecimais).
O arquivo cabeçalho define cada um dos caracteres como uma constante matricial [1x6] de bytes, lembrando que cada byte pode representar 8 bits.

-numeros.h

const byte zero[6]= {
0x3C,0x42,0x81,0x81,0x42,0x3C
};

const byte um[6]= {
0x00,0x04,0x82,0xFF,0x80,0x00
};

const byte dois[6]= {
0x84,0xC2,0xA1,0x91,0x8A,0x84
};

const byte tres[6]= {
0x00,0x81,0x89,0x89,0x89,0xFF
};

const byte quatro[6]= {
0x18,0x14,0x12,0x11,0x11,0xFF
};

const byte cinco[6]= {
0x8F,0x89,0x89,0x89,0x89,0x70
};

const byte seis[6]= {
0x78,0x94,0x92,0x91,0x91,0x60
};

const byte sete[6]= {
0x01,0x01,0x01,0x01,0xFF,0x00
};

const byte oito[6]= {
0x76,0x89,0x89,0x89,0x89,0x76
};

const byte nove[6]= {
0x06,0x89,0x49,0x29,0x19,0x0E
};

const byte space= 0x00;

Agora que se têm disponíveis os caracteres para exibição no display, pode-se então através da rotação calculada, decompor o número em seus devidos caracteres de  milhar,centena,dezena e unidade.
Definidos os caracteres após decomposição monta-se um vetor-exibição que será transferido ao display através do latch 74HC595 (bit a bit) de saída série/paralelo.
Cada um dos bytes é então transferido ao latch até que se passem mais 3 interrupções quando um novo valor é inserido no vetor-exibição.

Testes:

Esquemático:



quarta-feira, 11 de janeiro de 2012

Automatizando impressão de etiquetas de código de barras

Quando se ouve falar de aplicações e dos níveis de controle e agilidade gerados por sistemas que utilizam códigos de barras, realmente não há como negar todas as facilidades que este tipo de implantação impacta. O que nunca é mencionado pelos distribuidores é que apenas investir na aquisição de equipamentos de código de barras nem sempre pode resolver imediatamente um problema de controle de material, é necessário um estudo prévio da aplicação, dos dados necessários e daqueles de que estão disponíveis.
Já observei implantações desorganizadas de equipamentos que simplesmente travaram processos dentro de fábricas porque não foram planejados adequadamente.

  • Imagine a situação abaixo:
O cliente solicitou que seu produto fosse entregue com identificação de código de barras onde será informando o código do produto, nota fiscal e o lote, além de imprimir data e quantidade.
A etiqueta poderia ser semelhante à seguinte:


Que passos se devem prosseguir para evitar futuras dores de cabeça?  Este “post” traz algumas experiências pessoais que julgo relevantes avaliar quando se está perante a uma necessidade semelhante visando ajudar outras pessoas a não cometerem erros de avaliação nesse momento, e principalmente ajudar o desenvolvedor a encontrar um caminho para produzir sua solução personalizada de forma rápida e segura.
Existem vários motivos para aplicação de sistemas de código de barras: Necessidade controles em geral, organização de estoque, controles de produção, controles tipo FIFO,controles de inventário, logística de transporte de algum cliente entre muitas outras.
Vários padrões de códigos de barras estão disponíveis para os mais diversos tipos de aplicação. Os lineares como code128, code39, EAN13, Interleaved 2/5 etc para menor densidade de dados e os bidimensionais como maxcode, pdd417 e micropdf quando necessária grande densidade de dados. O primeiro grupo é mais utilizado para informações numéricas e alfanuméricas simples e onde a informação seja conhecida em origem e dimensão.
Os códigos bidimensionais oferecem uma possibilidade de compactação de dados muito maior podendo carregar muitas informações em pouco espaço. O problema dos códigos bidimensionais é que precisam de leitores com scanners próprios para decodificá-los e esses normalmente tem custo mais elevado.

 Veja alguns exemplos impressos abaixo:

Observe a otimização do padrão CODE128 em relação ao CODE39. Os códigos bidimencionais (pdf) contêm uma seqüência bem maior de caracteres:
“01234567890ABDCEF Eletrobits teste padrão pdf bidimensional”

Pensando no caso de uso do início do post, é necessário saber em seu banco de dados ou em seu sistema, onde obter as informações necessárias para enviar ao sistema de impressão, isto é, tabelas de seu banco de dados que contenham as informações relevantes de seu processo e possam ser lidas por uma aplicação e enviadas às impressoras de código de barras.
Estudando previamente as etapas acima, a escolha do equipamento é relativamente simples. A produção ou adaptação de seu software estará baseada nos equipamentos disponíveis e na análise da disponibilidade de dados. Fabricantes de impressoras sempre fornecem drivers e aplicações básicas para operar seus equipamentos, porém esses programas dificilmente atendem demanda de impressão automática em larga escala. Imagine em nosso caso de uso acima que sejam necessários emitir 300 notas fiscais por dia com 10 produtos cada uma e que cada produto seja identificado. Isso gera necessidade de imprimir 3000 etiquetas. Agora imagine que seu funcionário precise digitar essas informações antes de imprimir! Certamente a tarefa, além de impossível, também é recheada de chances de erros!

 Automatizando impressões de código de barras:
Existem inúmeros fabricantes de impressoras de código de barras, Zebra, Intermec, Eltron entre muitas outras e para complicar um pouco cada uma delas tem uma linguagem de programação própria. Zebra (ZPL Zebra printer language,ZPL2),Intermec (IPL-Intermec Printer Language),  EPL etc enfim são várias as linguagens e isso pode dificultar a vida do programador quando existem equipamentos de diferentes fabricantes em uma mesma planta. Algumas impressoras mais modernas são dotadas de emuladores capazes de interpretar linguagens de outros fabricantes, mas isso não é uma regra principalmente quando os equipamentos são menores e mais modestos ou antigos.
Quem já leu um manual de programação de qualquer uma dessas linguagens sabe que são um pouco indigestos, porém é sempre bom conhecer os comandos quando o objetivo é produzir ou adaptar um software capaz e enviar comandos diretamente a essas máquinas.
Visando facilitar a vida dos desenvolvedores os software distribuídos com essas máquinas quase sempre agregam ferramentas capazes de gerarem "arquivos fonte" em formato texto que são rapidamente adaptáveis a aplicações customizadas.
Imprimindo etiqueta para em porta arquivo

Ao imprimir nossa etiqueta anterior para arquivo teremos uma “mascara” do arquivo fonte na linguagem da impressora selecionada. Observe abaixo como esses arquivos podem ser bem diferentes. O Primeiro ZPL, o segundo EPL, são a mesma etiqueta.

Arquivo ZPL:
^XA
^MCY
^XZ
^XA
^FWN^CFD,24^PW695^LH0,0
^CI0^PR3^MNY^MTT^MMT^MD15^PON^PMN^LRN
^XZ
^XA
^MCY
^XZ
^XA
^DFR:TEMP_FMT.ZPL
^LRN
^A0N,60,60^FO28,25^FDEletroBits^FS
^BY2^FO21,120^BCN,90,Y,N,N^FD>;0123456789>6ABCDEF^FS
^BY2,2.7^FO33,441^B7N,17,0,5,0,N^FH^FD0123456789ABCDEF Eletrobits teste padrão PDF bidimensional^FS
^BY2,2.5^FO24,273^B3N,N,98,Y,N^FD0123456789ABCDEF^FS
^BY2^FO595,471^BEN,106,Y,N^FD789403222022^FS
^A0N,36,36^FO536,42^FH_^FDC_A2digos de Barra^FS
^BY7^FO388,440^BFN,5,0^FH^FD0123456789ABCDEF Eletrobits teste padrão PDF bidimensional^FS
^A0N,20,20^FO20,99^FDCode-128 (Auto)^FS
^A0N,20,20^FO22,254^FDCode-39^FS
^A0N,20,20^FO34,420^FDPDF417^FS
^A0N,20,20^FO388,421^FDMicro-PDF 417^FS
^A0N,20,20^FO594,447^FDEAN-13^FS
^XZ
^XA
^XFR:TEMP_FMT.ZPL
^PQ1,0,1,Y
^XZ
^XA
^IDR:TEMP_FMT.ZPL
^XZ
Arquivo EPL:
O
Q610,1
q695
S4
D5
ZT
JF
N
A28,25,0,4,2,3,N,"EletroBits"
B21,120,0,1,2,0,90,B,"0123456789ABCDEF"
b33,441,P,813,169,s0,c0,f0,x2,y17,r90,l5,t0,o0,"0123456789ABCDEF Eletrobits teste padrão PDF bidimensional"
B24,273,0,3,2,5,98,B,"0123456789ABCDEF"
B579,471,0,E30,2,0,106,B,"789403222022"
A536,42,0,1,2,4,N,"C¢digos de Barra"
A20,99,0,1,1,2,N,"Code-128 (Auto)"
A22,254,0,1,1,2,N,"Code-39"
A34,420,0,1,1,2,N,"PDF417"
A594,447,0,1,1,2,N,"EAN-13"
P1
De posse da mascara desses arquivos basta utilizar a ferramenta de programação de sua preferência para ler os seus dados na origem e ingressá-los nos pontos determinados na mascara do arquivo texto. Feito isso basta lançar os dados para sua impressora na porta que estiver operacional.