-Eu optei pelo arduino pelo simples fato de ter o hardware já pronto. Não havendo necessidade desenvolver e confeccionar placas de circuito impresso.
Hardware necessário:
Placa principal do ARDUÍNO UNO R3. Veja AQUI
LCD Keypad Shield Veja AQUI
Aqui tem a WIKI do LCD, com pinagem, programas de exemplo, etc.
- Este LCD Keypad Shield possui 4 chaves ligadas em uma unica porta analógica do arduino. No meu projeto não vou utiliza-las, já que vou precisar de teclas maiores que ficarão em um painel maior.
- Ligação do LCD com o arduino.
- Os pinos utilizados pelo LCD são os seguintes: 4,5,6,7,8,9 (São os pinos no arduino, não no LCD). É assim que ele vem ligado ao Arduino. O importante é o programa saber disso. Que neste caso será a seguinte instrução no começo do programa:
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); significa que estes pinos são do Arduino e estão reservados para o LCD.
- Uma mudança importante neste projeto em relação ao antigo, é a inclusão do item PEÇAS GRAVADAS. Ou seja, além do valor TOTAL digitado e o valor da contagem, aparecerá no display o número de peças já gravadas.
Exemplo do display:
T.: 1000 X1
F.: 999 G:1
Onde T.: é TOTAL de peças, X1, contará de uma-em-uma. F.: Peças que Faltam gravar e G: peças Gravadas.
Pinos utilizados no arduino:
1 -> SAÍDA - RELÊ 1 - faz a mudança do botão de PULSO para o arduino controlar. Quando o arduino estiver desligado ou ligado mas sem estar programado, o botão PULSO estará ligado diretamente na máquina laser. Como se o Arduíno não existisse. Eu fiz isso para o caso de você querer gravar sem contar peças. Assim que o botão Enter é pressionado pela primeira vez, este relê ativa e transfere o botão PULSO direto para o Arduíno. Ou seja, ao pressionar o botão PULSO, o comando vai para o pino 12 do Arduíno, e o Arduíno vai acionar o RELÊ 2, que fará o papel do botão PULSO para a máquina Laser.
2 <- ENTRADA - Botão SOBE, ligado a chave e da chave ao GND. Aciona com nivel 0.
3 <- ENTRADA - Botão ENTER, ligado a chave e da chave ao GND. Aciona com nivel 0.
4,5,6,7,8,9 Reservado ao LCD.
10 - Back Light do LCD.
11 -> SAÍDA - BUZZ, aciona a busina do alarme.
12 <- ENTRADA - Sinal de PULSO, ativa em nivel 0.
13 -> SAÍDA - RELÊ 2 - ativa a gravação.
Esquema elétrico no Proteus.
O arquivo fonte de programação do Arduino. AQUI
Um pouco sobre o programa.
- Meu forte não é programação, porém vou explicar um pouco sobre o funcionamento deste aqui.
- Como todo mundo já deve saber, uma das primeiras coisas e, as mais importantes na programação é a definição de variáveis. É por onde tudo começa.
- Eu defini as seguintes variaveis:
- q1, q2, q3 e q4, serão utilizadas para armazenar o número que se deseja contar, cada uma representa uma casa decimal. Q1 é milhar, Q2 é centena, Q3 é dezenas e Q4 unidade.
No programa fica assim:
int long q1=0;
int long q2=0;
int long q3=0;
int long q4=0;
As outras são: conta, total e m.
O principio de funcionamento é começar utilizando a variável CONTA para escolher a casa do milhar (q1), assim que o valor é escolhido o valor de CONTA vai para q1. O próximo passo é escolher a centena (q2), novamente utilizando CONTA e passando para q2, e assim sucessivamente até chegar em q4.
Exemplo: Você escolheu a quantidade de 1000 peças a serem gravadas. Então as variáveis ficariam assim:
- Primeiramente CONTA=0, utilizando a tecla SOBE o valor de CONTA foi para 1, apertando ENTER, o valor CONTA foi para q1, q1=conta;
- Segundo passo, CONTA=0, aperando ENTER, q2=conta;
No final teremos:
-q1=1
-q2=0
-q3=0
-q4=0
Valor total 1000.
Agora precisamos colocar esse valor de 1000 na variável CONTA.
Usamos a seguinte expressão:
conta=(q4*1000)+(q3*100)+(q2*10)+q1;
Agora a variável CONTA tem o valor de 1000, e assim podemos começar a contagem.
A formula é bem simples, conta=conta-1; toda vez que temos o sinal de PULSO diminuímos 1 do valor de CONTA.
Porém eu utilizo um parâmetro a mais que é possibilidade de contar até de 4 em 4.
Você vai notar que ao iniciar o programa (ligar o Arduino), o primeiro parâmetro a ser definido é o MULTIPLO, por padrão ele já vem com o valor de 1, e vai até 4. Isso significa que eu posso querer gravar até quatro peças ao mesmo tempo, ou seja, toda vez que eu apertar o botão PULSO uma vez, ele vai descontar esse valor do total.
Usando como base o valor acima que é 1000, e com múltiplo setado em 4 a conta fica assim: conta=conta-4;
Neste caso eu utilizo a variável m para armazenar este valor.
conta=conta-m;
.....
Eu gostaria de comentar um pouco sobre uma rotina interessante, que na qual custei para desenvolver, porém é bem simples, mas como eu disse no começo, programação não é meu forte.
A questão é a seguinte: O programa dentro do chip do arduino roda muito rápido, milhões de ciclos por segundo, e como o programa fica lendo cada porta de entrada do chip em cada ciclo, temos um problema de repetição da tecla repetida.
Exemplo: Temos o botão SOBE ligado ao pino 2, cada vez que apertamos o botão o nivel do sinal deste pino vai para ZERO. O programa percebe isso e aceita como a tecla pressionada, no próximo ciclo de clock e vai ler novamente este pino e se estiver em ZERO, vai entender que a tecla foi pressionada novamente, mas na verdade não foi, pois o processo é tão rápido que nem deu tempo de soltar a tecla. Mesmo que você pressione rapidamente a tecla, a contagem no display será muito rápida.
Para resolver isso eu fiz uma rotina que após a tecla ser pressionada, ele não passa adiante enquanto ela não for solta.
1ª if (digitalRead(Btnsobe)==LOW)
2ª {
3ª conta=conta+1;
4ª sobe3:
5ª ;
6ª if (digitalRead(Btnsobe)==LOW)
7ª {
8ª goto sobe3;
9ª }
Funciona assim, na primeira (1ª) linha diz o seguinte: SE a entrada digital(digitalRead), pino 2 (Btnsobe) for igual a ZERO (que é o botão SOBE pressionado), então execute o que está dentro da chave { , que é somar 1 no valor da variavel CONTA (3ª) e vá adiante.
Na 4ª linha tem um ponto de GOTO, ele vai passar direto a primeira vez.
Na 6ª linha está o segredo, ele vai verificar novamente se o botão continua pressionado, e como está pressionado e vai executar a 8ª linha que é desviar para a rotina sobe3; na 4ª linha, e vai ficar neste loop até a o botão for solto, só então ele vai continuar o programa.
MONTAGEM
- Imagem da finalização da caixa e botões.
- A chave preta rotativa do lado direito e os dois botões pequenos, não fazem parte do projeto Arduino.
Video de funcionamento.
Código arduino.
#include <LiquidCrystal.h>
// Ultima alteração em 22/08/2014
// Foi alterado o valor do delay do botão pulso de 300 para 180 ms.
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
long int q1=0 ; // Armazena o primeiro digito da contagem
long int q2=0 ;
long int q3=0 ;
long int q4=0 ;
long int total=0; // valor total de gravação
long int conta=0; //usado para contagem
int m=1; // multiplos
int t=1;
int Btnsobe=2; //botão sobe usará o pino 2
int BtnEnter=3; //Botão Enter usará o pino3
int BtnPulso=12; //Botão Pulso usará o pino 12
int buzz=13; // buzzer no pino 11
int relay1=1; //rele1
int relay2=11; //rele2 pulso
int sobe=0;
int enter=0;
int pulso=0;
int caso=0;
int pronto=0;
int gravados=0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // read the value from the sensor
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
// we add approx 50 to those values and check to see if we are close
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
// For V1.1 us this threshold
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 250) return btnUP;
if (adc_key_in < 450) return btnDOWN;
if (adc_key_in < 650) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
// For V1.0 comment the other threshold and use the one below:
/*
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 195) return btnUP;
if (adc_key_in < 380) return btnDOWN;
if (adc_key_in < 555) return btnLEFT;
if (adc_key_in < 790) return btnSELECT;
*/
return btnNONE; // when all others fail, return this...
}
void setup()
{
pinMode(Btnsobe,INPUT_PULLUP); // Habilita o pullup do pino 2, significa que está em nivel alto sempre, mudara para 0 quando o botão SOBE ligar este pino ao terra(GND).
pinMode(BtnEnter,INPUT_PULLUP); // Enter
pinMode(BtnPulso,INPUT_PULLUP); // Pulso, origem do sinal que vai ativar a máquina. É este sinal que ele vai ler para diminuir o valor da contagem.
pinMode(buzz,OUTPUT); // Saida do buzzer
pinMode(relay1,OUTPUT); // saida rele 1
pinMode(relay2,OUTPUT); // Saida rele 2 - pulso
digitalWrite(buzz,LOW);
digitalWrite(relay1,LOW);
digitalWrite(relay2,LOW);
lcd.begin(16, 2); // Inicia a biblioteca do LCD
lcd.setCursor(0,0); // Coloca o cursor na primeira linha e primeira coluna.
lcd.print("Contador Arduino"); // Imprime a mensagem CONTADOR ARDUINO
lcd.setCursor(0,1); // Coloca o cursos na SEGUNDA linha e coluna 0
//lcd.print(millis()/1000); // display seconds elapsed since power-up
lcd.print("Multiplos:");
}
void loop()
{
delay (100);
lcd.setCursor(12,1); // move to the begining of the second line
lcd_key = read_LCD_buttons(); // read the buttons
sobe=digitalRead(Btnsobe); //faz a leitura da porta digital 2 (Botão Sobe)
enter=digitalRead(BtnEnter);
pulso=digitalRead(BtnPulso);
lcd.print(m);
if (sobe==0) // Verifica se o botão SOBE foi ativado, ativa em ZERO(LOW) - obs.: Aqui tb poderia se usado if (digitalRead(Btnsobe)==LOW)
{
m=m+1; // Soma mais um à variavel M que é a contagem dos MULTIPLOS
m1: // Ponto de retorno do GOTO, usado para verificar se a tecla permanece acionada
;
if (m>5)
{
m=1; // se o valor de M for maior que 5, volta a ser 1
lcd.setCursor(12,1);
lcd.print(m);
}
if (digitalRead(Btnsobe)==LOW) // verifica se o botao continua apertado, se continuar, vai para o loop M1 logo acima.
{
goto m1;
}
}
if (digitalRead(BtnEnter)==LOW) // Defini o valor do MULTIPLO e entra na rotina para definir a quantidade de peças.
{
digitalWrite(relay1,HIGH);
lcd.clear(); //Limpa o LCD
lcd.setCursor(10,0);
lcd.print("X");
lcd.print(m);
lcd.setCursor(0,1);
lcd.print("Qtda: ");
Enter:
;
if (digitalRead(BtnEnter)==LOW) //Verifica se a tecla Enter continua acionada.
{
goto Enter;
}
conta=0;
do //rotina para definir a quantidade
{
delay (100);
if (digitalRead(Btnsobe)==LOW)
{
conta=conta+1;
sobe4:
;
if (digitalRead(Btnsobe)==LOW)
{
goto sobe4;
}
}
if (conta >9)
{
conta=0;
}
lcd.setCursor(12,1);
lcd.print(conta);
if (digitalRead(BtnEnter)==LOW)
{
q4=conta; // armazena o valor escolhido para casa de milhar na variavel Q4
enter4:
;
if (digitalRead(BtnEnter)==LOW)
{
goto enter4;
}
pronto=1;
}
} while (pronto==0);
conta=0;
pronto=0;
do //rotina para definir a quantidade
{
delay (100);
if (digitalRead(Btnsobe)==LOW)
{
conta=conta+1;
sobe3:
;
if (digitalRead(Btnsobe)==LOW)
{
goto sobe3;
}
}
if (conta >9)
{
conta=0;
}
lcd.setCursor(13,1);
lcd.print(conta);
if (digitalRead(BtnEnter)==LOW)
{
q3=conta; // armazena o valor escolhido para casa de milhar na variavel Q4
enter3:
;
if (digitalRead(BtnEnter)==LOW)
{
goto enter3;
}
pronto=1;
}
} while (pronto==0);
conta=0;
pronto=0;
do //rotina para definir a quantidade
{
delay (100);
if (digitalRead(Btnsobe)==LOW)
{
conta=conta+1;
sobe2:
;
if (digitalRead(Btnsobe)==LOW)
{
goto sobe2;
}
}
if (conta >9)
{
conta=0;
}
lcd.setCursor(14,1);
lcd.print(conta);
if (digitalRead(BtnEnter)==LOW)
{
q2=conta; // armazena o valor escolhido para casa de milhar na variavel Q4
enter2:
;
if (digitalRead(BtnEnter)==LOW)
{
goto enter2;
}
pronto=1;
}
} while (pronto==0);
conta=0;
pronto=0;
do //rotina para definir a quantidade
{
delay (100);
if (digitalRead(Btnsobe)==LOW)
{
conta=conta+1;
sobe1:
;
if (digitalRead(Btnsobe)==LOW)
{
goto sobe1;
}
}
if (conta >9)
{
conta=0;
}
lcd.setCursor(15,1);
lcd.print(conta);
if (digitalRead(BtnEnter)==LOW)
{
q1=conta; // armazena o valor escolhido para casa de milhar na variavel Q4
enter1:
;
if (digitalRead(BtnEnter)==LOW)
{
goto enter1;
}
pronto=1;
}
} while (pronto==0);
conta=(q4*1000)+(q3*100)+(q2*10)+q1; //formula da contagem
total=conta;
delay(50);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("T.: ");
lcd.print(conta);
lcd.setCursor(14,0);
lcd.print(" ");
lcd.setCursor(14,0);
lcd.print("X");
lcd.print(m);
lcd.setCursor(0,1);
lcd.print("F.: ");
do // Rotina para a contagem das peças
{
if(digitalRead(BtnPulso)==LOW) // verifica se chegou o pulso para gravação
{
delay(120); // tempo que o botão deve ficar pressionado
if(digitalRead(BtnPulso)==LOW) // O botão precisa ficar pressionado por mais tempo para ir adiante, evita ruido.
{
digitalWrite(relay2,HIGH);
delay(300);
digitalWrite(relay2,LOW);
digitalWrite(buzz,HIGH);
delay(100);
digitalWrite(buzz,LOW);
conta=conta-m; // diminui do total a ser gravado o valor do Multiplo
if ((conta-m<=0)||(conta-m>65500)) // Vai acionar o alarme quando estiver na penúltima gravação
{
digitalWrite(buzz,HIGH);
delay(250);
digitalWrite(buzz,LOW);
}
}
if ((conta<=0)||(conta>65500)) //qdo chegar a ZERO ou passar dele, encerra a contagem, FIM
{
conta=0; // deixa a contagem em ZERO
lcd.setCursor(13,0);
lcd.print("FIM");
//lcd.setCursor(4,1);
//lcd.print("0 ");
//lcd.setCursor(10,1);
//lcd.print(total);
digitalWrite(buzz,HIGH);
delay(3000);
digitalWrite(buzz,LOW);
digitalWrite(relay1,HIGH);
}
delay(250);
lcd.setCursor(4,1);
lcd.print(" ");
lcd.setCursor(4,1);
lcd.print(conta);
lcd.setCursor(10,1);
lcd.print("G:"); // G de peças já gravadas
gravados=total-conta; // coloca na variavel GRAVADOS a diferença do TOTAL, ou seja, as peças já gravadas
lcd.print(gravados); // imprime quantas peças já foram gravadas
p:
;
if(digitalRead(BtnPulso)==LOW) // verifica se o botão continua pressionado
{
goto p;
}
}
}while (conta!=0);
fim:
;
goto fim;
}
}