Menu
CoddyTech

Máquina de Estados do Semáforo

Parte da seção Temporização sem delay do Journey de Arduino da Coddy. Lição 10 de 18.

Um semáforo é uma máquina de estados: ele está sempre em um estado (verde, amarelo ou vermelho), cada estado dura um tempo determinado e cada estado sabe qual vem em seguida:

  • GREEN: verde aceso; após 2 s, vá para YELLOW
  • YELLOW: amarelo aceso; após 1 s, vá para RED
  • RED: vermelho aceso; após 2 s, vá para GREEN

Cada linha se torna um case:

case GREEN:
  setLights(HIGH, LOW, LOW);
  if (now - lightStart >= 2000) {
    light = YELLOW;
    lightStart = now;
  }
  break;

Com delay(2000), a luz também funcionaria, mas nada mais poderia ser executado. Com millis(), cada passagem por loop() leva microssegundos, então a placa tem tempo para outras tarefas: aqui, um LED de status que pisca o tempo todo para mostrar que o controlador está ativo.

challenge icon

Desafio

Médio

O LED de status no pino 13 já pisca, e o enum e lightStart estão prontos. Escreva o semáforo como um switch (light) com um case para cada luz:

  • verde 2 s, amarelo 1 s, vermelho 2 s, depois verde novamente
  • um LED por vez, com setLights()
  • sem delay(), para que o LED de status continue piscando

Pressione Run e depois Check.

Experimente você mesmo

const int greenLed = 10;
const int yellowLed = 11;
const int redLed = 12;
const int statusLed = 13;   // o LED da própria placa

enum Light { GREEN, YELLOW, RED };
Light light = GREEN;
unsigned long lightStart = 0;   // quando a luz atual acendeu

unsigned long statusPrevious = 0;
int statusState = LOW;

void setup() {
  pinMode(greenLed, OUTPUT);
  pinMode(yellowLed, OUTPUT);
  pinMode(redLed, OUTPUT);
  pinMode(statusLed, OUTPUT);
}

void setLights(int green, int yellow, int red) {
  digitalWrite(greenLed, green);
  digitalWrite(yellowLed, yellow);
  digitalWrite(redLed, red);
}

void loop() {
  unsigned long now = millis();

  // o LED de status alterna a cada 250 ms, para mostrar que o controlador está funcionando
  if (now - statusPrevious >= 250) {
    statusPrevious = now;
    if (statusState == LOW) {
      statusState = HIGH;
    } else {
      statusState = LOW;
    }
    digitalWrite(statusLed, statusState);
  }

  // o semáforo: um switch (light) com um case para cada luz
  // verde por 2 s, amarelo por 1 s, vermelho por 2 s, depois verde novamente
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Temporização sem delay

Pratique por conta própria: Playground de Arduino