fbpixel
Etiquetas:

Este é um projeto simples para começar a aprender eletrónica e programação com o Arduino.

Hardware

  • Computador
  • Arduino UNO
  • Cabo USB A macho para USB B macho
  • Módulo de semáforo (ou LEDs x3 + resistências x3)
  • Botão de pressão (ou módulo de botão de pressão)
  • Prancheta
  • Cabos Dupont M
  • Botão de pressão x1

Objetivo

Vamos reproduzir o funcionamento de um semáforo vermelho. Em primeiro lugar, no modo automático, os LEDs acendem-se um após o outro. Depois, vamos adicionar um botão de chamada de peões para forçar o semáforo a ficar vermelho.

Preparação e teste do código para o Arduino

Sem ligar os LEDs, já podemos começar a trabalhar no algoritmo básico para testar a comunicação em série e a programação do Arduino. Pode seguir este tutorial para configurar e programar a placa Arduino.

int verte = 0;
int orange = 1;
int rouge = 2;


void setup() {
  Serial.begin(9600);
  Serial.println("Feux rouge initialisé");
}

void loop() {
  Serial.println("loop running");
  delay(500);
  allumer(verte);
  delay(1000);
  eteindre(verte);
  allumer(orange);
  delay(1000);
  eteindre(orange);
  allumer(rouge);
  delay(1000);
}


void allumer(int color) {
  Serial.print("allumer led ");
  switch (color) {
    case 0:
      Serial.println("verte");
      break;
    case 1:
      Serial.println("orange");
      break;
    case 2:
      Serial.println("rouge");
      break;
  }
}

void eteindre(int color) {
  Serial.print("eteindre led :");
  switch (color) {
    case 0:
      Serial.println("verte");
      break;
    case 1:
      Serial.println("orange");
      break;
    case 2:
      Serial.println("rouge");
      break;
  }
}

Esquema elétrico

O botão está ligado ao pino 2, o LED1 ao pino 9, o LED2 ao pino 10 e o LED3 ao pino 11. Tenha em atenção as resistências para não danificar os componentes. No módulo de semáforos, estas resistências não são necessárias.

arduino-feu-tricolore_bb Reproduzir o funcionamento de um semáforo

Código de gestão do LED

Assim que os LEDs estiverem ligados ao Arduino, podemos tentar ligá-los. A função utilizada para controlar um díodo é digitalWrite() com o parâmetro HIGH para o ligar e LOW para o desligar. Tudo o que tens de fazer é adicionar a função digitalWrite() à localização pretendida nas funções on e off.

O objetivo é fazer com que o LED verde se acenda, depois o LED laranja e depois o LED vermelho, após determinados intervalos de tempo.

Para facilitar a leitura, estamos a colocar as variáveis verde, laranja e vermelho num enum.

const int pinVerte = 9;
const int pinOrange = 10;
const int pinRouge = 11;

enum couleur {
  VERTE,
  ORANGE,
  ROUGE
};
int etatFeu = VERTE;

void setup() {
  Serial.begin(9600);
  pinMode(pinVerte, OUTPUT);
  pinMode(pinRouge, OUTPUT);
  pinMode(pinOrange, OUTPUT);

  Serial.println("Feu tricolore initialisé");
}

void loop() {
  Serial.println(F("Mode auto running"));
  eteindre (ROUGE);
  allumer (VERTE);
  delay (5000);
  eteindre (VERTE);
  allumer (ORANGE);
  delay (1000);
  eteindre (ORANGE);
  allumer (ROUGE);
  delay (3000);
}


void allumer(int color) {
  Serial.print("allumer led ");
  switch (color) {
    case VERTE:
      Serial.println("verte");
      digitalWrite(pinVerte, HIGH); //analogWrite(pinVerte, 250);
      break;
    case ORANGE:
      Serial.println("orange");
      digitalWrite(pinOrange, HIGH); //analogWrite(pinOrange, 250);
      break;
    case ROUGE:
      Serial.println("rouge");
      digitalWrite(pinRouge, HIGH); //analogWrite(pinRouge, 250);
      break;
    default:
      digitalWrite(pinOrange, HIGH); //analogWrite(pinOrange, 250);
      break;
  }
  etatFeu = color;
}

void eteindre(int color) {
  Serial.print("eteindre led :");
  switch (color) {
    case VERTE:
      Serial.println("verte");
      digitalWrite(pinVerte, LOW); //analogWrite(pinVerte, 0);
      break;
    case ORANGE:
      Serial.println("orange");
      digitalWrite(pinOrange, LOW); //analogWrite(pinOrange, 0);
      break;
    case ROUGE:
      Serial.println("rouge");
      digitalWrite(pinRouge, LOW); //analogWrite(pinRouge, 0);
      break;
    default:
      digitalWrite(pinVerte, LOW); //analogWrite(pinVerte, 0);
      digitalWrite(pinOrange, LOW); //analogWrite(pinOrange, 0); //
      digitalWrite(pinRouge, LOW); //analogWrite(pinRouge, 0); //
      break;
  }
}

A luminosidade do LED pode ser modulada utilizando a função analogWrite() e uma saída PWM do microcontrolador.

Código de gestão dos botões

Vamos agora testar o funcionamento do botão de pressão. O objetivo é que o semáforo mude de cor quando o botão é premido. Para o conseguir, precisamos de “ouvir” constantemente o estado do botão. Uma técnica interessante para monitorizar o estado de um sensor é utilizar uma interrupção. Voltemos então ao código deste tutorial sobre a gestão de um botão com uma interrupção.

const byte ledPin = 10;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), onEvent, FALLING);
  Serial.println(F("Système intialisé"));
}

void loop() {
  digitalWrite(ledPin, state);
}

void onEvent() {
  state = !state;
  Serial.print(F("Switch LED : "));
  if (state) {
    Serial.println(F("ON"));
  } else {
    Serial.println(F("OFF"));
  }
}

Para outras formas de gerir o botão de pressão, pode ler este tutorial.

Alterar a cor da luz utilizando o botão

Vamos combinar os dois códigos anteriores para mudar a cor do semáforo quando o botão é premido.

const int pinVerte = 9;
const int pinOrange = 10;
const int pinRouge = 11;

enum couleur {
  VERTE,
  ORANGE,
  ROUGE
};
int etatFeu = VERTE;

const byte btnPin = 2;
int state = 0;

void setup() {
  Serial.begin(9600);
  pinMode(pinVerte, OUTPUT);
  pinMode(pinRouge, OUTPUT);
  pinMode(pinOrange, OUTPUT);
  
  pinMode(btnPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(btnPin), onEvent, FALLING);
  Serial.println("Feu tricolore initialisé");
}

void loop() {
  switch (state) {
    case 0://mode automatique
      Serial.println(F("Mode auto"));
      eteindre (ROUGE);
      allumer (VERTE);
      delay (5000);
      eteindre (VERTE);
      allumer (ORANGE);
      delay (1000);
      eteindre (ORANGE);
      allumer (ROUGE);
      delay (3000);
      break;
      
    case 1:// mode manuel
      Serial.println(("Mode manuel"));
      delay (5000);
      eteindre (ROUGE);
      
      state = 0;
      break;
  }
}

void onEvent() {
  Serial.println("---> Bouton pressé");
  eteindre(3);//eteindre tout
  allumer (ROUGE);
  state=1;
}


void allumer(int color) {
  Serial.print("allumer led ");
  switch (color) {
    case VERTE:
      Serial.println("verte");
      digitalWrite(pinVerte, HIGH); //analogWrite(pinVerte, 250);
      break;
    case ORANGE:
      Serial.println("orange");
      digitalWrite(pinOrange, HIGH); //analogWrite(pinOrange, 250);
      break;
    case ROUGE:
      Serial.println("rouge");
      digitalWrite(pinRouge, HIGH); //analogWrite(pinRouge, 250);
      break;
    default:
      digitalWrite(pinOrange, HIGH); //analogWrite(pinOrange, 250);
      break;
  }
}

void eteindre(int color) {
  Serial.print("eteindre led : ");
  switch (color) {
    case VERTE:
      Serial.println("verte");
      digitalWrite(pinVerte, LOW); //analogWrite(pinVerte, 0);
      break;
    case ORANGE:
      Serial.println("orange");
      digitalWrite(pinOrange, LOW); //analogWrite(pinOrange, 0);
      break;
    case ROUGE:
      Serial.println("rouge");
      digitalWrite(pinRouge, LOW); //analogWrite(pinRouge, 0);
      break;
    default:
      Serial.println(" tout");
      digitalWrite(pinVerte, LOW); //analogWrite(pinVerte, 0);
      digitalWrite(pinOrange, LOW); //analogWrite(pinOrange, 0); //
      digitalWrite(pinRouge, LOW); //analogWrite(pinRouge, 0); //
      break;
  }
}

Se testar este código, vai aperceber-se de que o semáforo não se comporta como esperado. Conseguimos forçar a cor vermelha, mas o funcionamento automático não é retomado corretamente. Isto deve-se ao facto de a função delay() bloquear o código. Para podermos ter em conta o botão quando o premimos, temos de modificar o código para nos livrarmos da função delay().

Alteração do código

Para remover a função delay(), podemos utilizar um algoritmo com a função millis(). Vamos reproduzir a função de atraso utilizando a função millis sem bloquear o fluxo de código.

  if((millis()-previousTime)>200){
    previousTime=currentTime;
    Serial.println(F("action"));
  }

Para isso, também precisamos de decompor o funcionamento da luz vermelha em diferentes estados e integrá-los nos casos de comutação. Um estado para a mudança de cor e um estado para o atraso.

  switch (state) {
    case 0:
      eteindre (ROUGE);
      allumer (VERTE);
      state++;
      previousMillis = millis();
      break;
    case 1:
      if (millis() - previousMillis > 5000) { //delay (5000);
        state++;
      }
      break;
    case 2:
      eteindre (VERTE);
      allumer (ORANGE);
      state++;
      previousMillis = millis();
      break;
    case 3:
      if (millis() - previousMillis > 1000) { //delay (1000);
        state++;
      }
      break;
    case 4:
      eteindre (ORANGE);
      allumer (ROUGE);
      state++;
      previousMillis = millis();
      break;
    case 5:
      if (millis() - previousMillis > 3000) { //delay (3000);
        state = 0;
      }
      break;
  }

Código final completo

Uma vez efectuadas estas alterações, a pressão no botão é imediatamente tida em conta e o semáforo pode retomar o seu curso normal.

const int pinVerte = 9;
const int pinOrange = 10;
const int pinRouge = 11;

enum couleur {
  VERTE,
  ORANGE,
  ROUGE
};
int etatFeu = VERTE;
int state = 0;

const byte btnPin = 2;
int mode = 0;

unsigned long previousMillis = 0;

void setup() {
  Serial.begin(9600);
  pinMode(pinVerte, OUTPUT);
  pinMode(pinRouge, OUTPUT);
  pinMode(pinOrange, OUTPUT);

  pinMode(btnPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(btnPin), onEvent, RISING);
  Serial.println("Feu tricolore initialisé");
}

void loop() {
  switch (state) {
    case 0:
      eteindre (ROUGE);
      allumer (VERTE);
      state++;
      previousMillis = millis();
      break;
    case 1:
      if (millis() - previousMillis > 5000) { //delay (5000);
        state++;
      }
      break;
    case 2:
      eteindre (VERTE);
      allumer (ORANGE);
      state++;
      previousMillis = millis();
      break;
    case 3:
      if (millis() - previousMillis > 1000) { //delay (1000);
        state++;
      }
      break;
    case 4:
      eteindre (ORANGE);
      allumer (ROUGE);
      state++;
      previousMillis = millis();
      break;
    case 5:
      if (millis() - previousMillis > 3000) { //delay (3000);
        state = 0;
      }
      break;
  }
}

void onEvent() {
  Serial.println("---> Bouton pressé");
  if (etatFeu == VERTE) {
    Serial.println("Changement d'etat");
    state = 2;
  }
}


void allumer(int color) {
  Serial.print("allumer led ");
  switch (color) {
    case VERTE:
      Serial.println("verte");
      digitalWrite(pinVerte, HIGH); //analogWrite(pinVerte, 250);
      break;
    case ORANGE:
      Serial.println("orange");
      digitalWrite(pinOrange, HIGH); //analogWrite(pinOrange, 250);
      break;
    case ROUGE:
      Serial.println("rouge");
      digitalWrite(pinRouge, HIGH); //analogWrite(pinRouge, 250);
      break;
    default:
      digitalWrite(pinOrange, HIGH); //analogWrite(pinOrange, 250);
      break;
  }
  etatFeu = color;
}

void eteindre(int color) {
  Serial.print("eteindre led :");
  switch (color) {
    case VERTE:
      Serial.println("verte");
      digitalWrite(pinVerte, LOW); //analogWrite(pinVerte, 0);
      break;
    case ORANGE:
      Serial.println("orange");
      digitalWrite(pinOrange, LOW); //analogWrite(pinOrange, 0);
      break;
    case ROUGE:
      Serial.println("rouge");
      digitalWrite(pinRouge, LOW); //analogWrite(pinRouge, 0);
      break;
    default:
      digitalWrite(pinVerte, LOW); //analogWrite(pinVerte, 0);
      digitalWrite(pinOrange, LOW); //analogWrite(pinOrange, 0); //
      digitalWrite(pinRouge, LOW); //analogWrite(pinRouge, 0); //
      break;
  }
}

Não hesite em deixar um comentário para partilhar as suas realizações ou dar-nos a sua opinião. Também pode contactar-nos se tiver alguma dúvida.

Aplicação

  • Reproduzir uma passagem de nível com 4 semáforos sincronizados

Fonte