Primeiro projeto, semáforo ; Arduino Uno

Estou com extrema dificuldade em fazer um simples semáforo... basicamente é um sinal de trânsito rodando em looping, ai eu queria colocar um botão para quando a luz dos pedestres for vermelha ou quando a luz do semáforo B ser verde esse botão gerar outro laço para fazer os pedestres andarem ...

Porém, eu já tem tentei "while" (ele para o looping e fica esperando eu apertar o botão OU faz o laço a mais que queria colocar ficar rodando sem parar -não sei se é problema no botão ,físico ). Já tentei também o "if" , mas tenho que colocar um ponto para ser testado e também não dá muito certo...

Enfim, alguém sabe algum comando que faça o arduino esperar pelo apertar de botão por um determinado tempo e ao mesmo tempo fazer o laço principal rodar mesmo se o botão não for apertado?

entenderam? To traumatizado, huauhauhauhauhauhauhauhahua

meu código semi feito... não está completo, tenho até outras 5 tentativas também...

 int vermelho=13;
 int amarelo=12;
 int verde=11;
 int vermelho2=10;
 int amarelo2=9;
 int verde2=8;
 int vermelhopedestre=7;
 int verdepedestre=6;
 int botao=2;
 unsigned long tempoderecarga;
void setup(){
pinMode(vermelho,OUTPUT);
pinMode(amarelo,OUTPUT); 
pinMode(verde,OUTPUT);
pinMode(vermelho2,OUTPUT);
pinMode(amarelo2,OUTPUT);
pinMode(verde2,OUTPUT);
pinMode(vermelhopedestre,OUTPUT);
pinMode(verdepedestre,OUTPUT);
pinMode(botao,INPUT); 
  
}

void semafaroA(){ //o semafaro A fica vermelho nesse ciclo

 //while (true) {
 //   if (digitalRead(botao) == true) {
 //     pedidopedestre();
  //    break;
 //   } //else semafaroA(); 
//  }
  delay(19900); //tempo obrigatorio considerando o tempo do outro semafaro igual a 59 segundos 59/3=19,900
 
digitalWrite(verde2,LOW);
digitalWrite(amarelo2,HIGH);
delay(10000);
digitalWrite(amarelo2,LOW);
digitalWrite(vermelho2,HIGH); 
piscarapido();//sinal dos pedestres piscando
digitalWrite(verdepedestre,HIGH);
digitalWrite(vermelho,LOW);
digitalWrite(verde,HIGH);
delay(59700); //obrigatoria verde liberado por 43, tempo que escolhi fazendo o calculo aproximado do tempo total

semafaroB();
}
void semafaroB(){ //o semafaro B fica vermelho nesse cilo
  digitalWrite(verde,LOW);
  digitalWrite(amarelo,HIGH);
  delay(7000);
  piscarapido();
  digitalWrite(amarelo,LOW);
  digitalWrite(vermelho2,LOW);
  
}

void piscarapido(){ //sinal do pedestre pisca rapido 3 vezes idem obrigatório do texte 
//istoconsome 3 segundos para ser executado
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,HIGH);
delay (500);
digitalWrite(vermelhopedestre,LOW);
digitalWrite(verdepedestre,LOW);
delay(500);
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,HIGH);
delay (500);
digitalWrite(vermelhopedestre,LOW);
digitalWrite(verdepedestre,LOW);
delay(500);
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,HIGH);
delay (500);
digitalWrite(vermelhopedestre,LOW);
digitalWrite(verdepedestre,LOW);
delay(500);

}

void pedidopedestre(){
  piscarapido();
  piscarapido();
  piscarapido();
  piscarapido();
  piscarapido();
  
}

void loop(){
digitalWrite(vermelho,HIGH);
digitalWrite(verde2,HIGH);
digitalWrite(vermelhopedestre,HIGH);
  delay(1000);
  int j = digitalRead(botao);
  delay(1000);
  int x=digitalRead(botao);

  
  /*verifica se o botao foi pressionado e se faz mais de 5 seg desde a ultima vez*/
 while(true){ if (j == HIGH && x==HIGH ) {
    
    delay(1000);
    pedidopedestre();
    break;

} 
else{semafaroA();}

}

 semafaroA();
}

Pelo que eu entendi você quer adquirir uma variavel do pedestre para modificar o semafaro em qualquer estagio, isso?

Priorize o variavel do pedestre e verefique todas as outras variaveis antes de rodar a do pedestre.

Sendo que se, o pedestre apertar o botão e mudar a variavel para HIGH ele terá que esperar o ciclo do semafaro completar, para depois deixar todos os semafaros vermelhos e ligar as luzes de pedestres no verde.

Quando o ciclo do pedestre acabar tera que setar a variavel pedestre em LOW e começar o loop novamente.

Acho que sua lógica de fluxo deveria ser um pouco diferente, por exemplo em vez de delay usar a função millis() e checar o botão a cada ciclo (procura nos exemplos, blink without delay).

Acho que deveria ser tipo:
Checa botão -> checa timer -> botão pressionado? S:seta variavel. -> timer atingido? S:(variavel setada? N: proxima cor, S:vai para semaforo de pedestres) -> volta ao inicio.

Entenda que checa botao e checa timer devem rodar a cada clock do uControlador, por isso é importante não usar a função delay. Durante a rotina do semaforo de pedestres pode ter delay normal

Consegui! Agora de manhã na minha 7 tentativa huauhauhauhauhahua

eu coloquei uma função testar se o botão está ligado ... dei delays e vários testes do mesmo e funcionou! ^^

código final do sinal de trânsito, tudo funcionando corretamente =(

int vermelho=13;
 int amarelo=12;
 int verde=11;
 int vermelho2=10;
 int amarelo2=9;
 int verde2=8;
 int vermelhopedestre=7;
 int verdepedestre=6;
 int botao=2;
 unsigned long tempoderecarga;
void setup(){
pinMode(vermelho,OUTPUT);
pinMode(amarelo,OUTPUT); 
pinMode(verde,OUTPUT);
pinMode(vermelho2,OUTPUT);
pinMode(amarelo2,OUTPUT);
pinMode(verde2,OUTPUT);
pinMode(vermelhopedestre,OUTPUT);
pinMode(verdepedestre,OUTPUT);
pinMode(botao,INPUT); 
  
}

void semafaroA(){ //o semafaro A fica vermelho nesse ciclo

 //while (true) {
 //   if (digitalRead(botao) == true) {
 //     pedidopedestre();
  //    break;
 //   } //else semafaroA(); 
//  }
//  delay(19900); //tempo obrigatorio considerando o tempo do outro semafaro igual a 59 segundos 59/3=19,900 ;OBS: retirei esse delay e coloquei lá no loop, inicio do programa.
 
digitalWrite(verde2,LOW);
digitalWrite(amarelo2,HIGH);
delay(10000);
digitalWrite(amarelo2,LOW);
digitalWrite(vermelho2,HIGH); 
piscarapido();//sinal dos pedestres piscando
digitalWrite(verdepedestre,HIGH);
digitalWrite(vermelho,LOW);
digitalWrite(verde,HIGH);

delay(59700); //obrigatoria verde liberado por 43, tempo que escolhi fazendo o calculo aproximado do tempo total

semafaroB();
}
void semafaroB(){ //o semafaro B fica vermelho nesse cilo
  digitalWrite(verde,LOW);
  digitalWrite(amarelo,HIGH);
  delay(7000);
  piscarapido();
  digitalWrite(amarelo,LOW);
  digitalWrite(vermelho2,LOW);
  
}

void piscarapido(){ //sinal do pedestre pisca rapido 3 vezes idem obrigatório do texte 
//istoconsome 3 segundos para ser executado
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,HIGH);
delay (500);
digitalWrite(vermelhopedestre,LOW);
digitalWrite(verdepedestre,LOW);
delay(500);
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,HIGH);
delay (500);
digitalWrite(vermelhopedestre,LOW);
digitalWrite(verdepedestre,LOW);
delay(500);
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,HIGH);
delay (500);
digitalWrite(vermelhopedestre,LOW);
digitalWrite(verdepedestre,LOW);
delay(500);

}

void pedidopedestre(){ 
  
piscarapido(); // anunciando que o pedido foi feito, mas ainda não liberando a passagem dos pedestres
digitalWrite(vermelhopedestre,HIGH);
  digitalWrite(verde2,LOW);
  delay(500);
  digitalWrite(verde2,HIGH);
  delay(500);
  digitalWrite(verde2,LOW);
  delay(500);
  digitalWrite(verde2,HIGH);
  delay(500);
  digitalWrite(verde2,LOW);
  delay(500);
  digitalWrite(verde2,HIGH);
  delay(500);
  digitalWrite(verde2,LOW);
  digitalWrite(amarelo2,HIGH);
 delay(10000);
 digitalWrite(amarelo2,LOW);
 digitalWrite(vermelho2,HIGH);
 delay(2000); //regra de passagem pedido no exercício entre vermelho e verde
 digitalWrite(vermelho,LOW);
 digitalWrite(verde,HIGH);
 digitalWrite(vermelhopedestre,LOW);
 digitalWrite(verdepedestre,HIGH);
 delay(59700);
  
  
  digitalWrite(verde,LOW);
  digitalWrite(amarelo,HIGH);
  piscarapido();
  digitalWrite(vermelhopedestre,HIGH); //estado inicial do loop ..teoricamente não necessário, mas coloquei aqui.
  delay(7000);
  digitalWrite(amarelo,LOW);
  digitalWrite(vermelho,HIGH); //estado inical do loop
  delay(2000);
  digitalWrite(vermelho2,LOW); 
  digitalWrite(verde2,HIGH); //Estado inicial do loop
 
  
}
//$$$$$$$$$$$$$$$$$$$$
void verificadorbotao(){
 
  while (true) {
    if (digitalRead(botao) == true) {
      pedidopedestre();
      break;
    } else {break;}
  
}
 
  
}
//$$$$$$$$$$$$$$$$$$$
void loop(){
digitalWrite(vermelho,HIGH);
digitalWrite(verde2,HIGH);
digitalWrite(vermelhopedestre,HIGH);
//$$$$$$$$$$$$$$
//verificando se o botão foi pressionado... enquanto isso as luzes do inicio do loop estão ligadas
//e necessario ficar apertando no mínimo 2 segundos para detectar se o botão foi apertado, depois disso ele vai para funcao pendidopedestre
delay(2000);
verificadorbotao();
delay(2000);
verificadorbotao();
delay(2000);
verificadorbotao();
delay(2000);
verificadorbotao();
delay(2000);
verificadorbotao();
delay(2000);
verificadorbotao();
delay(2000);
verificadorbotao();
delay(2000);
verificadorbotao();
delay(2000);
delay(1900);
//esses delays acumulam 19,900 que é o tempo do verde de um dos semafaros

//$$$$$$$$$$$$
 semafaroA();
}

Obrigado pelas respostas, vou procurar outras formas também de fazer, assim que me recuperar do trauma huahuauhauhauh

:sweat_smile:

Fazendo um pequeno UP no tópico...
segundo um professor esse "Break" que usei não poderia , pois isso "quebra lógica", para min se existe esse comando no programa deveria ser usando uhauhauhahua em fim ...

uma forma de contornar esse problema de vários teste é fazer um comando "for" e dentro dele colocar "if" de verificação, ficou assim:

int soma;
for(soma=0;soma<=100;soma++){
delay(199);
if (digitalRead(botao)==1){soma=101; pedidopedestre(); }
if (digitalRead(botao2)==1){soma=101; foradeoperacao();}
}
isso substituiu todas essa linhas aqui abaixo:

delay(2000);
verificadorbotao();
verificadorbotao2;
delay(2000);
verificadorbotao();
verificadorbotao2();
delay(2000);
verificadorbotao();
verificadorbotao2;
delay(2000);
verificadorbotao();
verificadorbotao2();
delay(2000);
verificadorbotao();
verificadorbotao2();
delay(2000);
verificadorbotao();
verificadorbotao2();
delay(2000);
verificadorbotao();
verificadorbotao2();
delay(2000);
verificadorbotao2();
verificadorbotao();
delay(2000);
verificadorbotao2();
verificadorbotao();
delay(1900);

Além dessa os períodos que tinha delays maiores de 2s eu substitui por períodos "for" e dentro "if". Isso garantiu que a qualquer momento do programa eu possa pará-lo no momento que quero que o botao 2 funcione e também o periodo que o botao1 funcione.

int vermelho=13;
 int amarelo=12;
 int verde=11;
 int vermelho2=10;
 int amarelo2=9;
 int verde2=8;
 int vermelhopedestre=7;
 int verdepedestre=6;
 int botao=2;
 int botao2=3; //botao de parada durante os sinais vermelho e verde ao mesmo tempo,ou seja, nos períodos longos. 
 unsigned long tempoderecarga;
void setup(){
pinMode(vermelho,OUTPUT);
pinMode(amarelo,OUTPUT); 
pinMode(verde,OUTPUT);
pinMode(vermelho2,OUTPUT);
pinMode(amarelo2,OUTPUT);
pinMode(verde2,OUTPUT);
pinMode(vermelhopedestre,OUTPUT);
pinMode(verdepedestre,OUTPUT);
pinMode(botao,INPUT); 
pinMode(botao2,INPUT);  
}

void semafaroA(){ //o semafaro A fica vermelho nesse ciclo


//  delay(19900); //tempo obrigatorio considerando o tempo do outro semafaro igual a 59 segundos 59/3=19,900 ;OBS: retirei esse delay e coloquei lá no loop, inicio do programa.
 
digitalWrite(verde2,LOW);
digitalWrite(amarelo2,HIGH);
//aqui existira um delay de 10s , mas substitui por uma verificação de 10s 
//verificacao10s();
int soma;
for(soma=0;soma<=100;soma++){
 delay(100); 
if (digitalRead(botao2)==1){soma=101; foradeoperacao();}
}

digitalWrite(amarelo2,LOW);
digitalWrite(vermelho2,HIGH); 
piscarapido();//sinal dos pedestres piscando
digitalWrite(verdepedestre,HIGH);
digitalWrite(vermelho,LOW);
digitalWrite(verde,HIGH);

//delay de 59,7s abaixo; //obrigatoria verde liberado por 43, tempo que escolhi fazendo o calculo aproximado do tempo total; coloquei aproximadamente 60s de verificação para substituir logo abaixo
for(soma=0;soma<=597;soma++){
 delay(100); 
if (digitalRead(botao2)==1){soma=598; foradeoperacao();}
}

}
void semafaroB(){ //o semaforo B fica vermelho nesse cilo
  digitalWrite(verde,LOW);
  digitalWrite(amarelo,HIGH);
    int soma;
    for(soma=0;soma<=70;soma++){
  delay(100); 
  if (digitalRead(botao2)==1){soma=101; foradeoperacao();}
  }
  piscarapido();
  digitalWrite(amarelo,LOW);
  digitalWrite(vermelho2,LOW);
  
}

void piscarapido(){ //sinal do pedestre pisca rapido 3 vezes item obrigatório do teste 
//isto consome 3 segundos para ser executado
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,HIGH);
delay (500);
digitalWrite(vermelhopedestre,LOW);
digitalWrite(verdepedestre,LOW);
delay(500);
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,HIGH);
delay (500);
digitalWrite(vermelhopedestre,LOW);
digitalWrite(verdepedestre,LOW);
delay(500);
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,HIGH);
delay (500);
digitalWrite(vermelhopedestre,LOW);
digitalWrite(verdepedestre,LOW);
delay(500);

}

void pedidopedestre(){ 
  
piscarapido(); // anunciando que o pedido foi feito, mas ainda não liberando a passagem dos pedestres
digitalWrite(vermelhopedestre,HIGH);
  digitalWrite(verde2,LOW);
  delay(500);
  digitalWrite(verde2,HIGH);
  delay(500);
  digitalWrite(verde2,LOW);
  delay(500);
  digitalWrite(verde2,HIGH);
  delay(500);
  digitalWrite(verde2,LOW);
  delay(500);
  digitalWrite(verde2,HIGH);
  delay(500);
  digitalWrite(verde2,LOW);
  digitalWrite(amarelo2,HIGH);
 //abaixo um delay de 10s
int soma;
for(soma=0;soma<=100;soma++){
 delay(100); 
if (digitalRead(botao2)==1){soma=101; foradeoperacao();}
}
 
 digitalWrite(amarelo2,LOW);
 digitalWrite(vermelho2,HIGH);
 delay(2000); //regra de passagem pedido no exercício entre vermelho e verde
 digitalWrite(vermelho,LOW);
 digitalWrite(verde,HIGH);
 digitalWrite(vermelhopedestre,LOW);
 digitalWrite(verdepedestre,HIGH);
 //abaixo um delay "for" de 59,700s;
  for(soma=0;soma<=597;soma++){
 delay(100); 
if (digitalRead(botao2)==1){soma=598; foradeoperacao();}
}
  
  
  digitalWrite(verde,LOW);
  digitalWrite(amarelo,HIGH);
  piscarapido();
  //espera de 7s abaixo
  digitalWrite(vermelhopedestre,HIGH); //estado inicial do loop ..teoricamente não necessário, mas coloquei aqui
  for(soma=0;soma<=70;soma++){
  delay(100); 
  if (digitalRead(botao2)==1){soma=101; foradeoperacao();}
  }
  digitalWrite(amarelo,LOW);
  digitalWrite(vermelho,HIGH); //estado inical do loop
  delay(2000);
  digitalWrite(vermelho2,LOW); 
  digitalWrite(verde2,HIGH); //Estado inicial do loop
 
  
}

void foradeoperacao(){
  digitalWrite(vermelho,LOW);
  digitalWrite(amarelo,LOW);
  digitalWrite(verde,LOW);
  digitalWrite(vermelho2,LOW);
  digitalWrite(amarelo2,LOW);
  digitalWrite(verde2,LOW);
  digitalWrite(vermelhopedestre,LOW);
  digitalWrite(verdepedestre,LOW);
  delay(60);
  
  digitalWrite(amarelo,HIGH);
  digitalWrite(amarelo2,HIGH);
  digitalWrite(vermelhopedestre,HIGH);
  digitalWrite(verdepedestre,HIGH);
  delay(500);
    digitalWrite(amarelo,LOW);
  digitalWrite(amarelo2,LOW);
  digitalWrite(vermelhopedestre,LOW);
  digitalWrite(verdepedestre,LOW);
  delay(500);
if (digitalRead(botao2)==0){ foradeoperacao();}
else{delay(5000); 
digitalWrite(vermelho,HIGH);
digitalWrite(verde2,HIGH);
digitalWrite(vermelhopedestre,HIGH);
int soma;
for(soma=0;soma<=100;soma++){
 delay(199);
if (digitalRead(botao)==1){soma=101;  pedidopedestre(); } 
if (digitalRead(botao2)==1){soma=101; foradeoperacao();}
}
semafaroA();} 
}

void loop(){
  
  //estado inicial de todo o loop, para evitar problemas de troca, o loop inicial marca todas as variaveis possíveis
digitalWrite(verde,LOW);
digitalWrite(vermelho,HIGH);
digitalWrite(amarelo,LOW);
digitalWrite(verde2,HIGH);
digitalWrite(amarelo2,LOW);
digitalWrite(vermelho2,LOW);
digitalWrite(vermelhopedestre,HIGH);
digitalWrite(verdepedestre,LOW);
//abaixo verifica se o botão UM ou DOIS estão ligados e de acordo manda o código para respectiva funcao; no total esse "for" tem 19,90s só que está quebrado em tempos de 0,199s em 100 partes
int soma;
for(soma=0;soma<=100;soma++){
 delay(199);
if (digitalRead(botao)==1){soma=101;  pedidopedestre(); } 
if (digitalRead(botao2)==1){soma=101; foradeoperacao();}
}
//esses delays acumulam 19,900 que é o tempo do verde de um dos semafaros
 semafaroA();
}

Encontrei um erro no código, mas é de tempos de acendimento do semáforo , note também que escrevi semáforo errado hehehe mas também vou corrigir mais tarde ^^ Eu estava errando escrever if por confundi os estados iniciais... portanto o código também ficava rodando direito quando eu não queria... além dos botões físicos dar problema e eu ter que apertar e tentar fazer ele voltar a funcionar normalmente ...enfim, traumas ^^ obrigado pelas dicas de novo ^^

Em regra usar delays é má pratica de programaçao por tanto o teu programa apesar de te parecer funcionar a meu ver nao esta correcto e foge há boa pratica de programaçao.
Em resumo imagina que a funçao delay nao existe , e tenta refazer o teu programa.Todo o teu programa esta baseado em delays e assumes que toda a operaçao do semaforo esta num seguimento temporal inalteravel.Isto nao é verdade num semaforo!
Por exemplo tens a funçao piscarapido() que deve demorar cerca de 3 segundos como dizes mas e se alguem tocar num dos botoes?
Obviamente o teu programa nao contempla isso e vais perder esse pedido no botao.Entao isso quer dizer que o operador desse semaforo tem de tentar advinhar e ir carregando a espera de ter sorte em nao cair em nenhum desses delays ....
A chave para fazeres o teu programa bem esta nas seguintes pesquisas:
Blink without delay
Interrupts

for(soma=0;soma<=597;soma++){
 delay(100); 
if (digitalRead(botao2)==1){soma=598; foradeoperacao();}
}

}

Eu sou um gajo do contra, portanto e se eu carregar so no botao que referes nesta funçao(pinMode(botao,INPUT); e nao no teu botao2?
Fico a tentar advinhar o que raio o semaforo anda a fazer, ou considero o que esta avariado e aventuro-me a atravessar de qualquer das formas?
Bons estudos