Arduino: Como ligar botões de uma forma “profissional
Por Samuel Carreira para o Pplware
Uma das formas mais comuns de controlar o Arduino é utilizar interruptores ou botões de pressão. Neste pequeno tutorial, vou explicar como utilizar botões de uma forma fácil, “profissional” e recorrendo a poucas linhas de código.
No âmbito deste tutorial, vão ainda introduzidos os seguintes conceitos básicos:
- PWM
- Constante INPUT_PULLUP
- “Bounce” de um botão
- Instalação automática de uma biblioteca externa no Arduino
- Utilização da biblioteca Bounce
Para introduzir este tutorial, imaginemos uma situação prática em que pretendemos controlar o brilho de um LED através de dois botões (um botão para aumentar o brilho e outro para o diminuir). Os botões devem controlar o aumento de uma forma precisa (aumentar o valor do brilho em incrementos de uma unidade) e possibilitar um aumento mais rápido do valor caso se mantenha o botão premido.
Parte I - Hardware
Para se variar o brilho do LED é necessário utilizar uma porta com saída PWM. O que acontece de uma forma simples numa saída PWM é que o LED é ligado e desligado muito rapidamente (até aproximadamente 490 vezes por segundo). Variando o os valores deste pulso é possível “obter a sensação” que o LED não está com o brilho máximo (mais informações sobre PWM aqui).
O pino escolhido para ligar o LED poderá ser qualquer um dos pinos do Arduino que suportem PWM, como por exemplo, o número 11. Visto que na saída dos pinos do Arduino a corrente máxima é de 40 mA a 5 V, deverá utilizar-se uma resistência ligada em série com o LED para o proteger (tipicamente utiliza-se uma resistência de 220 Ohms).
A ligação dos dois botões poderá ser realizada em qualquer uma das portas digitais do Arduino (neste caso vamos escolher os pinos 7 e 8). Na maioria dos tutoriais são utilizadas resistências de proteção em conjunto com os botões (chamadas de resistências pull-down), no entanto, para simplificar as ligações e o número de componentes usados, vamos utilizar as resistências internas do Arduino (chamadas de resistências de pull-up), e por isso a ligação será realizada diretamente entre a massa (ground ou GND) e o botão.
As nossas ligações ficariam assim:
Ou o esquema eléctrico:
NOTA: no esquema é utiliza um botão de pressão simples de dois terminais, os botões de 4 terminais que devem ser ligados da seguinte forma
Parte II - Software
Algo que pode passar despercebido ao principiante na eletrónica é que os interruptores mecânicos não funcionam de uma forma totalmente “limpa”. De uma forma simples, quando se pressiona um botão, os contactos metálicos não fecham o circuito imediatamente devido às condições microscópicas das superfícies de contacto e ocorre um ligeiro oscilar (Bounce) entre estados durante breves microssegundos entre. A figura abaixo esquematiza este pormenor ao representar a variação de estado de um botão ao longo do tempo:
Como os microcontroladores são muito rápidos a processar os sinais, conseguem detetar esta oscilação no estado do botão e em determinadas aplicações tal facto pode ser problemático. Existem diversas formas de contornar este problema. A mais comum é utilizar algumas linhas de código que recorrem à função millis() do Arduino ( http://arduino.cc/en/Tutorial/Debounce ). No entanto, vamos aprender a utilizar a biblioteca Bounce que foi escrita para este efeito e que adiciona algumas funcionalidades interessantes de uma forma muito simples e sem ser necessário escrever muitas linhas de código.
Instalar a biblioteca automaticamente
1- Fazer download da biblioteca (comprimida em zip) aqui
2- Na IDE do Arduino, navegar até ao menu Sketch -> Importar Biblioteca… -> Adicionar Biblioteca… e escolher o ficheiro descarregado anteriormente
NOTA: caso deseje instalar a biblioteca manualmente poderá utilizar as instruções disponíveis aqui
Análise do código
O código inicia com a chamada da biblioteca e a definição dos pinos de ligação. Definir os pinos utilizados é uma boa prática que simplifica a alteração das ligações eléctricas sem ser necessário rever todo o código escrito.
#include <bounce.h> // biblioteca utilizada // definição dos pinos de ligação #define LED_PIN 11 #define AUMENTAR_PIN 8 #define DIMINUIR_PIN 7 </bounce.h> |
É criada uma variável do tipo byte (valores entre 0 e 255) que irá armazenar o valor do brilho do LED.
byte brilho = 0; // valor do brilho do LED entre 0 e 255 |
Os dois botões utilizados são declarados como objetos da seguinte forma Bounce(byte pin, unsigned long debounce_interval) sendo que o intervalo de debouce é definido em milissegundos (5 milissegundos é um valor tipicamente utilizado).
#define DEBOUNCE_TIME 5 // tempo em ms Bounce aumentar = Bounce(AUMENTAR_PIN, DEBOUNCE_TIME); Bounce diminuir = Bounce(DIMINUIR_PIN, DEBOUNCE_TIME); |
O pino do LED é definido como pino de saída e os pinos dos botões são definidos como entrada com o argumento INPUT_PULLUP que possibilita o uso das resistências internas de pull-up. Esta definição inverte o comportamento do pino no sentido que um valor HIGH ou ligado significa que o sensor está desligado e vice-versa.
De forma a monitorizar o valor da variável que define o brilho do LED é iniciada uma comunicação série que pode ser controlada através do Monitor Série integrado na IDE Arduino (Menu Ferramentas -> Monitor Série).
void setup() { pinMode(LED_PIN, OUTPUT) pinMode(AUMENTAR_PIN, INPUT_PULLUP); pinMode(DIMINUIR_PIN, INPUT_PULLUP); Serial.begin(9600); Serial.println("Tutorial Botao"); } |
O código da função principal do programa começa com a escrita do valor da variável brilho (um valor de 0 corresponde a sempre desligado e um valor de 255 corresponde a sempre ligado). O estado dos botões é detetado através da função update, caso este valor seja verdadeiro (o que corresponde a uma mudança de estado do botão), é verificado se o botão encontra-se premido (devido à utilização da resistência interna de pull-up corresponde a um estado inverso, ou seja, 0 ou LOW).
A função rebounce força o sinal do estado do botão a alterar mesmo que o estado físico não altere. Neste caso é utilizado para repetir o estado do botão a cada 250 milissegundos enquanto o botão estiver a ser premido (útil para alterar rapidamente o valor). O valor da variável brilho pode ser lido no monitor série de forma a se comprovar o correto funcionamento do programa (a função Serial.println(valor) escreve o valor da variável seguido de uma quebra de linha ou “parágrafo”).
void loop() { analogWrite(LED_PIN, brilho); if (aumentar.update() ) { if (aumentar.read() == LOW ) { aumentar.rebounce(250); if (brilho < 255) brilho ++; Serial.print("Aumentar o brilho do LED: "); Serial.println(brilho); } } if (diminuir.update() ) { if (diminuir.read()== LOW ) { diminuir.rebounce(250); if (brilho > 0) brilho --; Serial.print("Diminuir o brilho do LED: "); Serial.println(brilho); } } } |
Aconselhamos a uma revisão cuidada do código e das ligações elétricas antes de fazer o upload do código. Uma configuração errada dos pinos de entrada pode danificar permanente o Arduino. Caso o upload seja realizado com sucesso poderão utilizar o Monitor Série (atalho: CTRL+SHIFT+M) para observar a alteração do valor da variável que controla o brilho e comprovar o correto funcionamento do programa.
Video de Demonstração
Referências
Esquemas desenhados no Fritzing: ver aqui
Este artigo tem mais de um ano
Parabéns gostei!
Muito bem!!!
Com estes kist do Arduino tão baratos no ebay e com um leque de possibilidade infinitas, estes tutoriais são muito bem vindos!
Eu estou a fazer com base no Arduino, uma estação meteorológica online, sem necessidade um ter um PC ligado a enviar para a net, e com recolha dos dados do tempo por “wireless”, com uns sensores económicos a funcionar a 433MHz.
Por pouco mais de 60€, fico com uma estação meteorológica, a enviar os dados (temp, chuva, vento, direcção, humidade, …) em tempo real, para site próprio e Wheatherunderground!!!
Continuem a ensinar e dar ideias ao pessoal!
Rui Peixoto, podes partilhar que componentes usas? Por acaso também estava a analisar a possibilidade de fazer algo semelhante. O que tinha em mente, para a temperatura e humidade seria um dht11 e para luminosidade um ldr. Para chuva sei que há módulos dedicados. Mas para o vento, que utilizas?
Eu usei um Arduino UNO rev3 (http://www.dx.com/p/120464), um BMP085 que me dá a pressão atmosférica e a temperatura interior (http://www.dx.com/p/147261) e um receptor wireless 433MHZ (http://www.dx.com/p/149252). Comprei tudo no dx.com se procurares pelo ebay, ainda se encontra tudo mais barato.
Em adição e para envio directo para a net, tenho uma Ethernet Shield W5100.
Depois, andei a ver o que sairia mais barato para os receptores externos (pluviómetro, termómetro, higrómetro e anemómetro e cata vento) e acabei por comprar uma estação meteorológica completa do Lidl (Auriol h13726) igual a isto: http://www.celestron.com/astronomy/celestron-deluxe-weather-station.html
Sensores de UV e Radiação solar ainda não tenho, só depois de ter isto tudo a 100%.
O que me está a dar mais trabalho, é que não quero ter um PC ligado todo o dia. Há em vários sites o código pronto e liga o arduino por USB a um PC com o software Cumulos que trata os dados dos sensores e envia para a net. Eu estou a evitar este passo e enviar os dados directamente para a net e fazer aí o tratamento dos dados…
Bom dia.
Acho muito interessante a sua ideia. Estava a pensar se estiver interessado poderíamos criar uma rede a nível nacional de estações metereológicas caseiras com arduino.
Ola poderia me ajudar tenho um Arduino idêntico ao seu
posso usar uma bateria de lipo de 7.5V de 500miliamper para alimentalo
ou corro risco de queimalo
poderia me ajudar por favor
O arduino tem um regulador de tensão integrado por isso não há problema em o alimentar com 7.5 V. A desvantagem é apenas uma eficiencia energetica reduzida
O bounce podia muito bem ter sido eliminado na fonte, com um circuito RC em cada interruptor, era escusado induzir iowaits via software.
é bem verdade, mas isso faz com que tenhamos que gastar mais dois componentes por botão, e se tivermos muitos, ou se o custo final do equipamento for baixo, a melhor solução é usar o micro…apesar de isso poder criar problemas de performance, dependendo da aplicação/micro.
cmps
Exato, felizmente na eletrónica há muitas formas de fazer a mesma coisa. Podia-se utilizar uma resistência de pull down no interruptor (como é tradicionalmente realizado nos tutoriais http://arduino.cc/en/tutorial/button ) no entanto, no esquema apresentado acima evitou-se o uso de componentes extra, só o botão e o microcontrolador.
Na minha experiência até ao momento, o uso do software para eliminar o bounce, não tem tido influências perceptíveis na performance.
boas…a questão da performance, vai depender muito do hardware e da especificidade do projecto.
Se tiveres a correr uma aplicação em tempo real que precise de ter sempre cpu para realizar tarefas, ai pode acontecer, porque enquanto corres código de debounce não podes correr código da aplicação.
Mesmo que os inputs usem irq’s existe sempre o problema de correres código de debounce.
Embora que usando DMA possas minorar ou resolver por completo o problema, pois aceleras um pouco todas as tarefas que programas-te para usufruirem do DMA, e por sua vez libertas espaço para outras coisas…
cmps
Bom tutorial, so uma coisa,
“variando o os valores deste pulso é possível “obter a sensação” que o LED não está com o brilho máximo”
O led não esta mesmo com o brilho ao máximo, pois o pwm esta a limitar a corrente que o led recebe, logo se não tem corrente “máxima” então o led não brilha ao máximo.
Não é uma questão de percepção, é mesmo assim.
Por outro lado se o PWM for muito lendo, então sim, o led chega a receber a corrente máxima, mas a velocidade tipica do pwm não costuma ser tão baixa.
Ai que este “know how” anda perdido. Quando fazer uns posts Ikari-Pt?
No PWM limita-se a potência média do circuito (na fórmula do cálculo da potência é necessário multiplicar por o DutyCycle T=1/F). Numa onda quadrada monofásica a corrente e a tensão são MÁXIMAS no seu pico.
Repara que estamos a falar do comportamento de um díodo (LED) e não de uma carga indutiva ou resistiva não linear (como uma lâmpada incandescente).
Mais info sobre o efeito visual aqui: http://en.wikipedia.org/wiki/Flicker_fusion_threshold
Desculpa mas não concordo. O tutorial está mesmo correto.
O PWM, como a sigla pretende indicar, é a modulação por largura de pulso. Isso significa que o LED apenas tem dois estados: 0 e 1, ou se preferires, corrente máxima e zero.
Com 0 a corrente é zero. Com 1 a corrente é máxima.
O que vai dar mais ou menos brilho é o tempo que o LED permanece ligado durante a pulsação.
O teu raciocínio estaria completamente correto se tivesses dito que em termos de média de corrente nunca seria máxima. Isso estaria certo porque com o PWM o valor médio é sempre mais baixo que se estivesse sempre ligado. O valor médio pode ser calculado com recurso às áreas dos retangulos. Para dificultar a coisa até podiamos usar um integral…
pixar…o que o colega disse , ou deixou subentendido não está errado por aquilo que percebi…
A corrente demora tempo a circular, de tal forma que quando dizes que o led quando está on a currente é maxima…isso também não é uma verdade absoluta…pois a currente demora tempo a subir…
por esses motivos, e por outros podemos ficar com a sensação que o led não esta no seu valor maximo de corrente…porque este efeito visual depende de muitos aspectos…
Para termos uma noção de brilho maximo, teremos que atingir determinados valores de corrente por intervalo de tempo…
Claro que o pwm resolve esta situação, e o duty cycle é porporcional á quantidade de corrente, mas esta não está disponivel no imediato…e o led também tem o seu tempo de resposta como tudo na vida…
Por outras palavras…teremos que ter um duty cylce maior para surtir os efeitos teoricos(esquecendo a velocidade de propagação da corrente/defeitos do conductor/calor-resistência/lentidão do led em responder).
cmps
Boas. A questão do tempo de resposta do LED não é significativa neste projecto. Neste caso a frequência é de 490Hz, muito abaixo do que um LED consegue fazer tendo em conta os seus tempos de subida e descida.
Dependendo da qualidade do LED, facilmente funcionam na casa dos 30kHz (os mais rascas).
O projecto em cima põe em prática o que está aqui explicado.
http://www.newtoncbraga.com.br/index.php/eletronica/57-artigos-e-projetos/6006-art1318
Uma pequena informação extra:
As resistências pull-up ou pull-down não servem como protecção, mas sim para evitar falsos positivos ou negativos.
Se não estiverem ligadas por defeito a um dos extremos (HIGH ou LOW) alguns dispositivos mais sensíveis podem apanhar electricidade estática do ar o que pode alterar os valores lidos pelo Arduino.
Se esperam receber um sinal HIGH quando carregam no botão, assumem que quando não se carrega vão receber um sinal LOW. Para o garantir ligam uma resistência ao GND para que essa faça o serviço de pull-down.
Escrevi este artigo quando aprendi sobre isso:
http://thylux.blogspot.pt/2011/03/curious-case-of-pull-up-push-down.html
a principal aplicação é mesmo como protecção dos integrados…cada vez mais on integrados usam-nas internamente, ou então disponiblizam saidas em open colector, precisamente para a malta distraida,ou atarefada, não se “divertir” a queimar as saidas…
Mas também são muito utilizadas para esse fim…
cmps
O youtube foi a baixo.
Print tirado por mim:
http://oi41.tinypic.com/v6olro.jpg
Posso só dizer que esta demonstração do hardware está errada
Deveria levar uma resistência entre o pino do botão que liga ao Arduino e os 0V
Podes confiar na montagem que está tudo correto. Se leres o artigo bem encontras as explicações.
Alguém sabe de um tutorial onde possa controlar à volta de 50 leds com um arduino?
Como já foi mencionado, há muita forma de fazer a mesma coisa.
A maneira mais amadora é utilizares a enorme quantidade de portas de um Arduino Mega (há alguns modelos baratos no OLX).
A forma mais “profissional” é utilizares shift registers (exemplo http://arduino.cc/en/Tutorial/ShiftOut )
Para além disso podes ainda achar interessante o uso de matrizes de leds. Para 49 leds só precisas de usar 14 pinos do arduino. Tens é de trabalhar mais para conseguir acender 1 de cada vez.
Exemplo:
http://thylux.blogspot.pt/2010/10/poor-mans-led-matrix.html
http://www.instructables.com/id/LED-Dot-Matrix-Display/
Prezado, boa noite.
Quanto tento usar a biblioteca em questão, recebo erro na compilação: “expected unqualified-id before ‘<' token" referente a linha
Saberia me ajudar? Baixei a biblioteca e instalei como instruído.
Grato
ola
se vc estiver tentando ativar alguma shild
ante3s de compilar desencaixe ela pois quando a uma shild conectada no Arduino não aceita compilação
Bom dia , sera que alguem poderia me ajudar a introduzir um codigo no steeperdo motor de passo do arduino para que quando eu apertar um botao o motor gira 360 graus e pare.Nao sei criar o codigo e se alguem puder me enviar o mesmo eu agradeco,
PS o acionamento do motor deve ser ao toque do botao,sem mante-lo pressionado.
Grato sergio costa
Boa tarde gostaria de saber se existe uma forma de ligar o arduino automatico tipo eu programo ele pra livar tal dia e tal hora e ele liga sozinho tem como fazer isso ….eu pensei em uzar o agendador de tarefas do Windows mas ai nao deu certo…
Boa tarde, gostei muito do post. Estou querendo adicionar botão profissional para controlar o tempo de funcionamento de um relê, tem com vocês me ajudarem?
boas
sou novo neste mundo do arduino, ainda ando a recolher informação para perceber como funciona a programação e precisava de uma ajuda.
montei este esquema e funciona cinco estrelas mas tentei add mais um led e um botao para acender e apagar esse novo led mas sem sucesso o programa só me faz a função aqui mostrada.
alguém me podia dar uma ajuda
Viva, sem o código será dificil perceber o problema…
o código ficou assim :$
#include // biblioteca utilizada
// definição dos pinos de ligação
#define LED_PIN 11
#define AUMENTAR_PIN 8
#define DIMINUIR_PIN 7
#define led 12
#define botao 6
byte brilho = 0; // valor do brilho do LED entre 0 e 255
#define DEBOUNCE_TIME 5 // tempo em ms
Bounce aumentar = Bounce(AUMENTAR_PIN, DEBOUNCE_TIME);
Bounce diminuir = Bounce(DIMINUIR_PIN, DEBOUNCE_TIME);
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(AUMENTAR_PIN, INPUT_PULLUP);
pinMode(DIMINUIR_PIN, INPUT_PULLUP);
pinMode(led,OUTPUT);
pinMode(botao,INPUT);
digitalWrite(botao,HIGH);
// digitalWrite(led, HIGH);
Serial.begin(9600);
Serial.println(“Tutorial Botao v.1.0.0”);
}
void loop() {
analogWrite(LED_PIN, brilho);
if (aumentar.update() ) {
if (aumentar.read() == LOW ) {
aumentar.rebounce(20);
if (brilho 0)
brilho –;
Serial.print(“Diminuir o brilho do LED: “);
Serial.println(brilho);
}
}
}
void ledd() {
int valor = digitalRead(botao);
if (valor == HIGH) {
while (digitalRead(botao) == HIGH){
delay(100);
}
brilho = !brilho;
digitalWrite(led, brilho);
}
}
vi o código por alto e estão aqui vários erros de iniciante
pinMode(botao,INPUT); // o botão assim estará ligado da forma “tradicional” com uma resistência, se o ligaste da forma que está aqui no esquema e com esse código arriscas-te a queimar esse I/O pin do arduino. o artigo explica isso
parei a análise do código aqui:
if (brilho 0)
brilho –;
!!! estão aí erros “básicos” de programação. O meu conselho é começares a “brincar” com código ainda mais simples para treinares a programação porque uma letra a mais faz diferença (tens uma função chamada ledd (que está “perdida” no meio do código)
Daqui a um tempo quando estiveres mais à vontade já vais conseguir mexer neste código (que é de nível básico, mas ainda exige os mínimos de conhecimentos)
Boa tarde. Gostei da ideia, mas a página pra download do sketch não está mais disponível?
Ver aqui
https://pastebin.com/TXkEb68B
boa noite amigo como faço para baixar a biblioteca não está indo o link.Poderia me ajudar?
Realmente. A biblioteca .zip não está funcionando
To procurando informações e gostei do conteúdo, passando pelo seu blog para conhecer mais seu trabalho, muito obrigado por compartilhar.