Neste tutorial, iremos aprender a fazer o Jogo Genius utilizando LEDs, buzzer e botões.

 
1. Introdução

No tutorial “Sirene Ambulância”, aprendemos a criar o efeito “sirene” de ambulância utilizando botões e buzzer. Agora, para emularmos o Jogo Genius (“Simon says”) de 1980, precisaremos de componentes já conhecidos como LEDs, buzzer e botões; porém o grande desafio será o programa.

Não se desespere ao ver o tamanho dele, pois escrevemos de uma forma que tudo fique mais explícito para quem está começando. Como teremos novos elementos, explicaremos parte por parte para você entender onde tudo se encaixa.

 
2. Variáveis

Neste tutorial, além do #define, usamos variáveis do tipo int.

Como o próprio nome sugere, a variável pode variar ao longo do programa e é possível utilizá-la de duas formas: globalmente ou localmente. Quando aparecem em mais de uma função ao longo do programa, usamos as variáveis globais, definidas geralmente no primeiro bloco. Já as locais são casos específicos dentro do programa todo, por exemplo, se em uma única função foi necessário criar uma variável, só precisamos declará-la apenas dentro das chaves dessa função.

As variáveis com o prefixo int indicam que os valores serão apenas números inteiros.

 
3. Funções

As funções geram uma sequência de instruções que traz algum resultado se tudo estiver certo. Como veremos abaixo, podemos ter mais de uma e podemos chamar uma dentro da outra.

Para chamarmos um função, basta escrever o nome dela acrescentando o ponto e vírgula no final, desta forma: pisca_led(int posicao); ou pisca_led();.

Algumas podem conter argumentos como pisca_led(int posicao) e outras não, como pisca_led(). O argumento é o elemento dentro dos parênteses e é fator determinante para a função executar as instruções. Quando escrevemos pisca_led(int posicao) dizemos ao programa que a função pisca_led usará a variável posicao como parâmetro. Em caso de parênteses sem argumentos a função fica em “aberto” para inserirmos os argumentos que quisermos.

No programa, temos outro detalhe acerca das funções void e int. Da mesma forma quando declaramos uma variável com o int, a função (int le_botao()) retornará como resultado um número inteiro e necessariamente traz algum resultado, por isso ao final dela precisamos escrever return + variável. O void ao contrário, é uma função que não exige um resultado, por exemplo a função pisca_led().

 
4. RandomSeed

Esse novo elemento chamado randomSeed(analogRead()) sorteia uma nova sequência aleatória toda vez que ligamos o Arduino.

O analogRead significa que o programa lê um pino qualquer analógico, pois não podemos correr o risco dele ler um dos pinos digitais selecionados, caso escrevêssemos digitalRead.

 
5. Índices e arrays

Como trabalharemos com sorteio aleatório e com mais de dois elementos, teremos que dizer ao programa onde localizar os mesmos.

A técnica mais prática seria utilizar arrays (listas), mas vamos misturar um pouco de cada coisa para uma descrição mais completa e, num próximo tutorial, executamos o programa todo baseado em arrays. Por enquanto, absorva a ideia de que dentro de uma lista temos elementos e para cada lugar ocupado temos um índice ou uma posição, que começa pelo 0. A partir da figura abaixo, podemos dizer que o LED_A está localizado no índice 0, por exemplo.

 

ARRAYS

 

6. Estrutura do programa

Como você deve ter acompanhado, precisamos descrever cada passo que o Arduino deve seguir, pois ele não tem capacidade de interpretar ou coordenar as funções por si.

O caminho que descrevemos para ele sortear uma sequência e depois o jogador seguí-la é o seguinte:

  • As luzes permanecem acesas dizendo que o jogo está pronto.
  • O jogador aperta qualquer botão para iniciar um sorteio: os LEDs piscarão 6 vezes aleatoriamente.
  • Na vez do participante, o programa comparará cada botão apertado com a sequência sorteada. Se ele errar o primeiro, o jogo já acusará erro, emitindo um som de “desaprovação” e inicia um novo sorteio. Se ele acertar cada LED, ao final emite um som de “aprovação”.

Segue a estrutura completa do programa:

  • #define e variáveis
  • O básico de todo programa é iniciar pelos elementos. No nosso caso, vamos misturar #define e variáveis, pois utilizaremos os mesmos mais de uma vez ao longo do programa, inclusive as frequências do buzzer e o tempo para acender os LEDs.

    Para não confundir os pinos com os nomes dos define, utilizamos letras (LED_A, BUTTON_A, TOM_A).

    Para a variável sorteados não especificaremos uma quantidade exata, o valor fica em aberto [QT_SEQ] para que num próximo desafio, o jogo aumente o número de vezes que os LEDs piscam.

  • void setup
  • Como nos tutoriais anteriores, é necessário dizer ao programa quais elementos serão saída (OUTPUT) e entrada (INPUT). Também definiremos o randomSeed(analogRead()). Os LEDs e o buzzer serão nossas saídas (OUTPUT) e os botões, as entradas (INPUT). Definiremos o pino analógico 0 como o “ponto de partida” para o sorteio.

  • void loop
  • Lembra das funções principais para o jogo funcionar? Elas começam aqui.

    Na linha 43, vamos fazer com que os LEDs fiquem acesos até que o jogador aperte qualquer botão. Na linha 49, quando qualquer botão for pressionado, as luzes se apagam para iniciar o sorteio.

  • Sorteio da sequência
  • A partir da linha 56, para sortear os números, precisaremos descrever um for e nele inserir as condições para acontecer: a variável jogada inicia do índice ou/ posição 0 (int jogada = 0); a mesma deve ser menor que a quantidade de vezes que os LEDs piscam (jogada < QT_SEQ); ela deve acrescentar mais uma vez dentro das outras condições (jogada ++). Em seguida dizemos ao programa que a sequência (sorteados) deverá se basear nas condições impostas [jogada] para os 3 LEDs random(3).

    Para que os LEDs pisquem conforme o sorteio, criamos uma função chamada pisca_led, que será explicada mais à frente. Logo após o sorteio precisamos chamá-la e, dentro dos parênteses inserir em qual elemento ela deve se basear para piscar (pisca_led(sorteados[jogada])).

    Definimos também um tempo para essa sequência acontecer (delay(TEMPO_ENTRE)).

  • Comparação da sequência
  • Até aqui temos o sorteio e os LEDs piscando. Precisamos comparar os botões que o jogador aperta com a sequência sorteada. Nessa parte, definimos uma variável chamada vez e ela precisa estar fora das chaves do for para podermos verificar o número de acertos no final.

    As condições para acontencer são as mesmas do for, com a diferença da variável utilizada.

    Dizemos para o programa que se cada botão que ele ler for igual ao do sorteio (le_botao() == sorteados[vez]), o LED correspondente piscará, bem como o som emitido (pisca_led(sorteados[vez])). Caso ele erre precisamos parar o for e sair dele para iniciar novo sorteio (pisca_led(sorteados[vez]); break;).

  • Resultado
  • Mas como o jogador sabe quando errou ou acertou? Vamos descrever essa sinalização agora.

    Ordenamos ao programa que, se a variável vez, ou seja a sequência do jogador, for igual a quantidade da sequência (vez == QT_SEQ), teremos um intervalo para resposta (delay(500)) e, dentro de outro for junto das suas respectivas condições (for(int i = 0; i < 3; i++)), o buzzer tocará duas vezes, com frequências diferentes (tone(BUZZER, 2000); delay(200); tone(BUZZER, 4000); delay(200);} noTone(BUZZER);), sinalizando “Acertou!”.

    Em caso de erro teremos um for parecido com a diferença das frequências (delay(500); for(int i = 0; i < 3; i++) { tone(BUZZER, 200); delay(200); tone(BUZZER, 300); delay(200); } noTone(BUZZER);).

    Ressaltamos que a variável i foi declarada somente dentro do for, pois se trata de uma variável local (será utilizada apenas nesse caso específico).

  • Função piscar LED
  • Como as funções podem ser declaradas de forma independente, deixamos as duas funções que citamos no programa (pisca_led e le_botao) por último.

    A função pisca_led se baseará na variável posicao, que representa cada posição dos LEDs dentro do array. Poderíamos definir qualquer nome, mas por questões de associação deixaremos como posicao mesmo.

    Descreveremos três blocos semelhantes, representando o comportamento cada LED. Neles ordenamos a seguinte condição: se a posição for igual a 0 (posicao == 0), acenda o LED_A, toque o Buzzer com o TOM_A, dê um intervalo (TEMPO_PISCA), apague e inicie a mesma ação com o próximo LED.

  • Função ler os botões
  • Quando definimos o le_botao precisamos designar o valor -1 para a variável result como um valor qualquer, para que o programa entenda que nenhum dos botões está pressionado. Portanto, enquanto a variável result for igual a -1 (while (result == -1)) e se o botão A estiver pressionado (if (digitalRead(BUTTON_A) == LOW)), o resultado será igual à posição 0. Fazemos esse procedimento com os outros dois botões, trocando os pelos nomes e posições. O return traz o valor inteiro da função int le_botao.

 
7. Componentes e materiais

  • Nove cabos jumper macho-macho.
  • Três LEDs.
  • Três botões.
  • Um buzzer.
  • Uma protoboard.
  • Três resistores de 220 Ohm;
  • Uma placa Arduino UNO.
  • Um cabo USB.

 

cabo-jumper

Cabos jumper

 

led

LED

 

botao acionamento

Botão

 

buzzer

Buzzer

 

protoboard

Protoboard

 

resistor

Resistor de 220 Ohm

 

placa arduino uno

Arduino UNO

 

cabo usb

Cabo USB

 

8. Montagem

Vamos conectar a parte negativa da protoboard (linha azul da placa) com o terra (GND) do Arduino através de um jumper preto. Sete cabos vermelhos ligam os polos positivos de cada LED, botão e buzzer com seu respectivo pino no Arduino. As partes negativas do LED e da protoboard serão conectadas pelos três resistores, ao invés de um cabo jumper. Quatro cabos jumper verdes ligam a parte negativa com os botões e o buzzer.

Devemos ter atenção no posicionamento dos botões, pois existe um sentido correto para encaixá-los na placa. Temos quatro extremidades do botão, porém eles trabalham em pares, como se fossem fios contínuos escondidos. O sentido correto do botão deverá ser encaixado no sentido que a energia corre na parte onde colocamos os LEDs e resistores (vertical). Precisamos conectar uma das partes do botão com a parte negativa da protoboard (cabo verde) e a outro lado do botão com o pino do Arduino (cabo vermelho).

 

sentido botao

Sentido correto botão

 

O Buzzer também possui pólos certos. O maior é o positivo e se conecta com o pino de saída escolhido.

buzzer-polos

Polos do buzzer

 

Para os LEDs definimos os pinos 5, 6 e 7; para os botões 8, 9 e 10 e para o buzzer o pino 11.

 

 

 

9. Upload

Lembre-se de conectar o Arduino à entrada USB do seu computador. Verifique se a placa e portas estão já estão configuradas na IDE. Em caso de dúvida, clique aqui e reveja como fazer.

Para efetuar o Upload, clique na seta indicada em vermelho.

 

upload

Upload do programa

 

10. Dicas

  • Caso a placa não responda, desligue-a e reconecte-a ou/e mude a porta (entrada USB) e reconfigure.
  • Caso o programa apresente algum erro, verifique linha por linha (ponto e vírgula, erros de escrita, número de porta, letras em maiúsculo e minúsculo fazem diferença).

No próximo tutorial, iremos aprender a utilizar o Monitor Serial para a comunicação do Arduino com o PC.

Produtos
Promoção!
Arduino UnoArduino Uno

Uno SMD – Arduino compatível

R$59,90 R$54,90

Ideal para iniciantes, o Uno é um Arduino compatível bem capaz, barato e com diversos shields e sensores compatíveis disponíveis. Se você está começando a aprender sobre microcontroladores e Arduinos, esta é a placa perfeita! Ela é a nossa placa principal nos nossos tutoriais de Arduino.

protoboard-830-2Out Of Stock

Protoboard transparente 830 pontos

R$24,90

Protoboard transparente com 830 pontos para prototipagem é ideal para trabalhos elétricos e eletrônicos com Arduino e microcontroladores em geral. É fácil tem muito espaço para conectar leds, cabos, resistores entre outros.

Os pólos negativos e positivos estão bem identificados para facilitar seu trabalho com vários componentes.

4 Comentários

Deixe uma resposta

Seu endereço de e-mail não será publicado. Campos obrigatórios estão marcados *

limpar formulárioPostar Comentário