Como criar um semáforo com Arduino 7

Olá amigos! Nesse post 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

Para começar vamos montar nosso circuito. Você vai precisar dos seguintes componentes:

Talvez você esteja se perguntando para que tantos resistores de 220 ohm se o semáforo só tem 3 LEDs? Para que o botão? Tenha paciência. Chegaremos lá!

 

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

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

Bem simples, não? Vamos começar com uma montagem fácil e um código bem básico usando a função delay() do Arduino.

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.

Por que você não tenta fazer antes de olhar? É um bom exercício!

Segue o código:

// dando um "nome" para as portas 
int vermelho = 10;
int amarelo = 9;
int verde = 8;

void setup() {
  // indicando para o arduíno 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);
}

Desse código simples podemos tirar um primeiro exercício. Se onde você mora a lógica não for exatamente essa, porque não tenta fazer algo igual? Talvez o amarelo acenda junto com o verde antes dos dois desligarem e acender o vermelho. Ou talvez o amarelo também acenda um pouco junto com o vermelho antes de mudar para o verde. Eu já vi essas variações.

Semáforo com Arduino, versão com botão para 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 10 kΩ).

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

Semáforo com Arduino - versão com botão para 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.

Segue o código:

// 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);
}

Semáforo com Arduino, versão 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. 

Segue o esquemático:

Semáforo com Arduino - versão 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.

Segue o código:

// 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);
}

E para concluir…

Eu não poderia deixar vocês sem um exercício para casa! Afinal é praticando que se aprende!

1) Vamos voltar com o nosso botão para o circuito, só que agora no cruzamento! Assim um sinal ficará sempre aberto e só fechará quando botão for pressionado (e o outro sincronizará com esse).

2) Essa é para quem já domina bem o Arduíno e quer um desafio um pouquinho mais complexo: Vocês já viram aqueles sinais que tem um contador de tempo? Que tal colocarmos um no nosso circuito? Essa tarefa consiste em pegar nossa primeira montagem e colocar um contador do tipo da figura abaixo:

Display de 7 segmentos: 1 dígito

Uma dica: Se você quiser diminuir a quantidade de fios no seu circuito, existe um semáforo já pronto. É só usar esse da figura que vem até com os resistores:

Módulo Semáforo

Espero que vocês tenham se divertido criando o semáforo! Ajude-nos a melhorar o Blog comentando abaixo sobre este tutorial. Conheça mais sobre esses e outros produtos Arduino.

Divirtam-se e nunca parem de criar! É praticando que aprendemos!

Faça seu comentário

Acesse sua conta e participe

7 Comentários

  1. Boa tarde Marcio, gostaria da sua ajuda com um projeto. Provavelmente o que você deixou como dever de casa.
    Preciso criar o código com dois display de tempo para travessia e botão de semaforo. Com a dinamica:

    o semáforo opera normalmente aberto para os carros e fechado para os pedestres. Portanto, o sistema deve ser iniciado nessa condição;
    quando um pedestre aperta o botão, o sistema:
    1. aguarda um tempo de espera de 100ms;
    2. mostra a luz amarela para os carros por algum tempo;
    3. fecha para os carros e, simultaneamente, abre para os pedestres;4. Displays de 7 segmentos exibem o tempo restante para travessia dos pedestres. O display dos veículos inicia a contagem a partir de 9 e o display dos pedestres a partir de 5. A cada segundo, o valor mostrado nos displays é decrementado;
    5. Ao chegar ao valor zero, o display e a luz vermelha dos pedestres começam a piscar (0,5s apagados e 0,5s acesos) indicando que o semáforo irá fechar em breve. Ao mesmo tempo, a contagem regressiva do semáforo dos veículos deve prosseguir.
    6. Quando a contagem associada aos veículos atinge zero, o semáforo fecha para os pedestres e, simultaneamente, abre para os carros (isto é, retorna ao estado inicial). Os displays são desligados.
    7. À noite, o sistema de apertar o botão é desligado e o semáforo somente pisca a luz amarela para os carros e vermelha para os pedestres, retornando ao estado original na manhã seguinte. O grupo deve utilizar um sensor tipo LDR para detectar a quantidade de luz no ambiente de modo a determinar se é dia ou noite. O sistema deve ser capaz de ignorar mudanças temporárias na luz, tais como a passagem de um pássaro sobre o sensor durante o dia, ou a incidência de um farol de carro durante a noite. Ou seja, apenas alterações de luminosidade que perdurem por pelo menos alguns segundos podem mudar o modo de operação de diurno para noturno ou vice-versa.

    Pode me ajudar?

    1. Olá Renato!

      Temos este post aqui que pode te ajudar na lógica do LDR: https://www.makerhero.com/blog/sensor-de-luz-ldr-com-rele/
      e este com a parte do contador: https://www.makerhero.com/blog/como-usar-um-display-7-segmentos-com-o-arduino/

      Abraços!
      Vinícius – Equipe MakerHero

  2. oi, bom dia, poderia me ajudar? eu fiz o Semáforo com Arduino, versão cruzamento, mais não entendi porque ele só pisca a luz verde a da esquerda, sera que fiz algo errado?

    1. Se o esquema da montagem estiver certinho pode ser o código, eu vim copiar esse aqui mas não funcionou muito bem, tive que reescrever um novo, se ainda precisar posso mandar aqui para você testar.

  3. Excelente trabalho.

  4. Muito legal. Sou leigo , mas já estou testando na placa de teste os códigos. Vou logo, logo adquirir os kit’s . SHOW

    1. Edson,

      Isso aí! Bora continuar!

      Abraços!
      Diogo – Equipe MakerHero