Aula 4: Construa um semáforo

Já está sabendo tudo de LEDs e como ligá-los? Então vamos montar esse projeto maior para juntar várias coisas que aprendemos até agora. Nesse aula vamos fazer algo relativamente simples mas que abre a possibilidade de conversarmos um pouco sobre programação. A ideia é simular o funcionamento de um semáforo com Arduino. Então sem mais delongas vamos lá!

Material Necessário

O que é um chave push-button?

Na lista de materiais acima há um componente que talvez você ainda não conheça: uma chave push-button (botão).

Push button

Uma chave push-button funciona como um contato que abre e fecha, sendo assim, uma chave possui dois valores, 0 ou 1, aberto ou fechado. Conectando uma chave a uma porta do Arduino podemos ler o valor 0 ou 1 da chave e assim tomar uma ação. Por só ter dois valores possíveis, utilizaremos uma das portas digitais da placa.

Funcionamento do push button

O botão, quando pressionado, faz contato entre um lado e outro dele. Quando esse contato é fechado, essa corrente elétrica “entra” na placa e ela percebe que o botão foi pressionado. Ao escrevermos o programa, decidiremos o que fazer com essa informação.

Circuito Semáforo com Arduino (básico)

A lógica do funcionamento de um sinal varia um pouquinho dependendo de onde você mora mas de um modo geral segue sempre o mesmo padrão:

Verde  > Amarelo > Vermelho > Verde

Semáforo

Vamos começar com uma montagem simples.

Semáforo com Arduino - versão básica

O que vamos fazer nada mais é do que determinar quais leds estarão acesos e quando, bem como a pausa entre as trocas.

Código Semáforo com Arduino (básico)

// Programa: Semáforo com Arduino (básico)
// Autor: Marcio Silva

// dando um "nome" para as portas 
int vermelho = 10;
int amarelo = 9;
int verde = 8;
  
void setup() {
  // indicando para o Arduino quais portas vamos usar
  pinMode(vermelho, OUTPUT);
  pinMode(amarelo, OUTPUT);
  pinMode(verde, OUTPUT);
}
  
void loop() {
  // vamos começar do amarelo. Estranho não? 
  // você vai entender no próximo exercício!
  digitalWrite(vermelho, LOW);
  digitalWrite(amarelo, HIGH);
  digitalWrite(verde, LOW);
  
  // esperamos 2s com o sinal no amarelo
  delay(2000);
  
  // apagamos o amarelo e ligamos o vermelho
  digitalWrite(amarelo, LOW);
  digitalWrite(vermelho, HIGH);
  // Não precisa desse pois o verde já estava apagado
  // digitalWrite(verde, LOW);
  
  // esperamos 5s com o sinal fechado
  delay(5000);  
  
  // para finalizar, apagamos o vermelho e ligamos o verde
  digitalWrite(verde, HIGH);
  // não precisa desse pois o amarelo já estava apagado
  // digitalWrite(amarelo, LOW);
  digitalWrite(vermelho, LOW);
  
  // esperamos 5s com o sinal aberto
  delay(5000);
}

Circuito Semáforo com Arduino (travessia de pedestres)

Essa primeira versão é muito básica! Com certeza podemos ir mais longe. E se tivéssemos um sinal daqueles que tem um botão que o pedestre pressiona para que o sinal feche e ele possa atravessar? Como faríamos?

Agora a lógica vai mudar um pouco, já que o semáforo estará sempre aberto e só irá fechar quando o botão for pressionado. Vamos também usar o botão que estava na nossa lista (junto com a resistência de 10k ohm).

Como ficaria o circuito? Segue o esquemático abaixo.

Semáforo com Arduino - versão com travessia de pedestres

Código Semáforo com Arduino (travessia de pedestres)

Vamos aproveitar esse momento para fazer uma reestruturação no nosso código para deixá-lo mais organizado (no mundo da programação isso é chamado de refatoração).

Não é muito bom termos tanto código concentrado somente na nossa função de loop. No momento temos poucas linhas de código mas conforme formos colocando mais componentes no nosso circuito, a tendência é que fique cada vez mais difícil de entender o que está acontecendo.

Imagine que você tenha um projeto com 1000 linhas de código. Como achar onde está um eventual erro? E se for preciso alterar alguma parte? Qualquer mudança será difícil e cansativa.

As boas práticas de programação nos dizem que é melhor criarmos pequenos módulos separados com as lógicas afins. Pense como se você tivesse vários pequenos programinhas que irão trabalhar juntos orquestrados dentro da função loop(). E o bom disso é que essa mesma função que você escreveu, como estará “desacoplada” do programa como um todo, poderá ser utilizada em outras aplicações que você fizer.

Essa discussão faz parte do mundo da engenharia de software. Se gostou e quiser saber mais, procure por “separação de conceitos” e “modularidade” na internet. Não basta ser um Maker! Temos que fazer bem feito e de forma eficiente! Seus programas vão ficar muito mais robustos se você começar a pensar assim.

No nosso caso vamos criar uma função que irá conter toda a lógica da mudança do acender/apagar dos leds. Chamei ela de “semáforo” mas você pode dar o nome que quiser. Sugiro que sejam nomes bem explicativos.

Feito isso, é bem simples encaixar a lógica do nosso botão no código. Basta fazer uma verificação do estado desse botão com um “if”. Se ele for pressionado, iniciamos o código do semáforo.

// Programa: Semáforo com Arduino (travessia de pedestres) 
// Autor: Marcio Silva

// dando um "nome" para as portas 
// agora temos o botão também
int vermelho = 10;
int amarelo = 9;
int verde = 8;
int botao = 12;
 
void setup() {
  // indicando para o arduíno quais portas vamos usar
  pinMode(vermelho, OUTPUT);
  pinMode(amarelo, OUTPUT);
  pinMode(verde, OUTPUT);
 
  pinMode(botao, INPUT);
 
  // iniciamos com o verde ligado ...
  digitalWrite(verde, HIGH);
 
  // .. e o amarelo e vermelho desligados
  digitalWrite(vermelho, LOW);
  digitalWrite(amarelo, LOW);
}
 
void loop() {
  if (digitalRead(botao) == HIGH) {
      // esperamos um pouco antes de começar a lógica
      delay(2000);
      semaforo();
  }
}
 
void semaforo() {
  // amarelo logo após o botão ser pressionado!
  // se encaixa perfeitamente na nossa lógica
  // entendeu porque começamos no amarelo no exercício anterior? 🙂
  digitalWrite(vermelho, LOW);
  digitalWrite(amarelo, HIGH);
  digitalWrite(verde, LOW);
 
  // esperamos 2s com o sinal no amarelo
  delay(2000);
 
  // apagamos o amarelo e ligamos o vermelho
  digitalWrite(amarelo, LOW);
  digitalWrite(vermelho, HIGH);
  // Não precisa desse pois o verde já estava apagado
  // digitalWrite(verde, LOW);
 
  // esperamos 5s com o sinal fechado
  delay(5000);  
 
  // para finalizar, apagamos o vermelho e ligamos o verde
  digitalWrite(verde, HIGH);
  // não precisa desse pois o amarelo já estava apagado
  // digitalWrite(amarelo, LOW);
  digitalWrite(vermelho, LOW);
 
  // esperamos 5s com o sinal aberto
  delay(5000);
}

Circuito Semáforo com Arduino (cruzamento)

E para finalizar vamos simular agora o funcionamento de semáforos em um cruzamento de ruas. Teremos dois semáforos que atuarão de forma sincronizada. Depois de tudo que já fizemos, não será tão difícil assim.

Semáforo com Arduino - versão com travessia

Código Semáforo com Arduino (cruzamento)

O código é bem simples, basta apenas usarmos a lógica da nossa primeira construção duas vezes, sincronizando os dois semáforos, ou seja, em quanto um abre, o outro fecha e vice-versa.

// Programa: Semáforo com Arduino (cruzamento) 
// Autor: Marcio Silva

// dando um "nome" para as portas 
int vermelho_1 = 10;
int vermelho_2 = 11;
int amarelo_1 = 9;
int amarelo_2 = 12;
int verde_1 = 8;
int verde_2 = 13;
 
void setup() {
  // indicando para o arduíno quais portas vamos usar
  pinMode(vermelho_1, OUTPUT);
  pinMode(amarelo_1, OUTPUT);
  pinMode(verde_1, OUTPUT);
 
  pinMode(vermelho_2, OUTPUT);
  pinMode(amarelo_2, OUTPUT);
  pinMode(verde_2, OUTPUT);
}
 
void loop() {
   cruzamento();
}
 
void cruzamento() {
  // sinal 1 - amarelo
  digitalWrite(vermelho_1, LOW);
  digitalWrite(amarelo_1, HIGH);
  digitalWrite(verde_1, LOW);
 
  // sinal 2 - amarelo também
  digitalWrite(vermelho_2, LOW);
  digitalWrite(amarelo_2, HIGH);
  digitalWrite(verde_2, LOW);
 
  // esperamos 2s com o sinal no amarelo
  delay(2000);
 
  // sinal 1
  // apagmos o amarelo e ligamos o vermelho
  digitalWrite(amarelo_1, LOW);
  digitalWrite(vermelho_1, HIGH);
  // digitalWrite(verde_1, LOW);
 
  // sinal 2
  // apagmos o amarelo e ligamos o verde
  digitalWrite(amarelo_2, LOW);
  // digitalWrite(vermelho_2, LOW);
  digitalWrite(verde_2, HIGH);
 
  // esperamos 5s com o sinal fechado (1)/ aberto (2)
  delay(5000);  
 
  // sinal 1
  // apagamos o vermelho e ligamos o verde
  digitalWrite(verde_1, HIGH);
  // digitalWrite(amarelo_1, LOW);
  digitalWrite(vermelho_1, LOW);
 
  // sinal 2
  // apagamos o verde e ligamos o vermelho
  digitalWrite(verde_2, LOW);
  // digitalWrite(amarelo_2, LOW);
  digitalWrite(vermelho_2, HIGH);
 
  // esperamos 5s com o sinal aberto
  delay(5000);
}

Conseguiu pegar a lógica do programa? Você pode alterá-la conforme bem entender e fazer a sua própria lógica de semáforo!

Possíveis erros

Caso o projeto não funcione verifique alguns dos possíveis erros:

  • Verifique se os jumpers estão na mesma coluna dos terminais dos componentes, fazendo assim a conexão;
  • Verifique se os jumpers estão ligados nos pinos corretos no Arduino;
  • Verifique se o LED não está conectado invertido;
  • Verifique se o código carregou na placa através da IDE Arduino.

Desafios

Veja abaixo alguns desafios que você pode tentar!

  • Monte o circuito de uma maneira alternativa usando outros furos e posições na protoboard;
  • Mude o tempo que o LED amarelo dos veículos permanece aceso mudando o valor na programação na linha delay(3000); por exemplo: delay(6000);

O presente conteúdo é uma adaptação do post “Como criar um semáforo com Arduino“, escrito pelo Maker Hero Márcio Silva e publicado no blog da FilipeFlop em 10 de janeiro de 2020.