Go Down

Topic: Dúvida para programar, sou iniciante (Read 647 times) previous topic - next topic

Matheus779

Boa noite amigos... alguém pode me ajudar a resolver esse exercício de programação?


       Exibir um contador no Serial Monitor atualizado a cada 1s, porém o contador só deverá ser acionado quando um botão for pressionado, se o botão for pressionado novamente o contador deverá ser pausado.

tecdiego

Tenta pelo menos fazer o código e se você não quiser, te cobro R$300,00 para lhe entregar o código pronto.
Vai postando seu código e nós vamos te ajudar com as suas dúvidas.
Mas cara, você nem tentou.

Matheus779

Tentei sim, aqui está o que eu consegui fazer por enquanto...




int count = 0;
int estadoBotao = 0;

void setup() {
  pinMode(13,INPUT);
  Serial.begin(9600);

}

void loop() {
  verificarBotao();
  contador();
}

 
void verificarBotao(){
  if(digitalRead(13) == HIGH)
  {
    estadoBotao = estadoBotao + 1;

  }
}

void contador(){

  switch(estadoBotao)
     {
      case '1':
      {
        count = count + 1;
        Serial.println(count);
        delay(1000);
        break;
      }
       
      case '2':
      {
          estadoBotao = 0;
          break;
      }
    }
 
}

binhop

Bom dia,
É difícil te ajudar sem resolver o problema, porque envolve mais a lógica de programação. Mas você já fez boa parte e vou apenas arrumar o que você desenvolveu. Tente aprender com o que eu fiz e leia os comentário no código para entender.
O código ainda não está 100% bom, porque o delay da contagem acaba atrapalhando a leitura do botão, mas como é um código básico, imagino que não tenha problema. Mas se quiser saber como contornar o problema eu posso te mostrar como, só pedir.

Code: [Select]
int count = 0;
bool estadoBotao = false; //É um booleana porque o botao ou estara ligado ou desligado (0 ou 1)

void setup() {
  pinMode(13,INPUT);
  Serial.begin(9600);

}

void loop() {
  verificarBotao();
  contador();
}

 
void verificarBotao(){
  if(digitalRead(13) == HIGH)
  {
    estadoBotao = !estadoBotao; //Basicamente eu inverti(neguei) o estado anterior, ou seja, se antes era true agora é false e vice versa (o ! nega o estado)
    delay(300); //Um pequeno delay pra dar um tempo do botao ser desacionado
  }
}

void contador(){

  if(estadoBotao == true) //Se o botao estive acionado começa/continua a contagem
      {
        count = count + 1; // Ou pode ser count++; que é a mesma coisa
        Serial.println(count);
        delay(1000);
      }
}

Matheus779

Boa tarde amigo, muito obrigado pela sua resposta, me ajudou muito, consegui entender o seu código, ainda mais com os comentários, bem explicativo, obrigado mesmo!!

Em relação ao problema com o delay do botão, como resolve?

binhop

Boa tarde,

Por nada, fico feliz em saber q eu te ajudei a aprender.
Pra resolver o delay que atrapalha o botão, a gente tem que fazer uma coisa que pode ser um pouco difícil de entender, então vou tentar deixar tudo bem claro.
O seu problema é: enquanto o código fica agarrado no delay de 1 segundo da contagem, o botão é ignorado se ele for apertado. Então, uma forma de resolver isso (e várias situações parecidas) é criar uma função delay (vou chamar de "espera") e dentro dessa função executar constantemente a sua função de verificar o botão. Assim, o botão não será ignorado mais.
Pra criar nossa função delay a gente vai usar um recurso chamado millis(). millis() é uma função que já existe no Arduino e ela retorna o tempo (em milissegundos) que o Arduino está rodando desde que foi ligado. A gente vai usar essa função pra saber se o tempo que passou desde que a nossa função "espera" foi chamada é o tempo certo para sair dela. Exemplo: é como se o millis() fosse um relógio e alguém vai te pedir pra esperar 3 segundos. Você vai olhar o relógio na hora que a pessoa pediu e vai ficar olhando no relógio se já passaram 3 segundos.

Code: [Select]
int count = 0;
bool estadoBotao = false; //É um booleana porque o botao ou estara ligado ou desligado (0 ou 1)

void setup() {
  pinMode(13,INPUT);
  Serial.begin(9600);

}

void loop() {
  verificarBotao();
  contador();
}

 
void verificarBotao(){
  if(digitalRead(13) == HIGH)
  {
    estadoBotao = !estadoBotao; //Basicamente eu inverti(neguei) o estado anterior, ou seja, se antes era true agora é false e vice versa (o ! nega o estado)
    delay(300); //Um pequeno delay pra dar um tempo do botao ser desacionado
  }
}

void contador(){

  if(estadoBotao == true) //Se o botao estive acionado começa/continua a contagem
      {
        count = count + 1; // Ou pode ser count++; que é a mesma coisa
        Serial.println(count);
        espera(1000); //Nossa funçao delay que funciona igual a função delay normal
      }
}

void espera(int periodo){ //Nossa funçao delay. 'periodo' é o parâmetro do tempo que a função deve esperar (em milissegundos)
  unsigned long tempo = millis();
  while (millis()-tempo < periodo){ //Enquanto o tempo que passou desde que entrou na funçao for menor que o periodo (tempo de espera), o código fica dentro do while e só sai quando tiver passado o tempo do "periodo"
    verificarBotao(); //Voce pode adicionar outros comandos aqui dentro do while
    delay(50); //Esse delay nao é obrigatorio, mas serve pra dar uma pequena pausa pro while e evitar que ele fique rodando a funçao verificaçao em um tempo extremamente rapido
  }
}

Espera que tenha dado para entender.

tecdiego

#6
Aug 30, 2017, 03:06 am Last Edit: Aug 30, 2017, 03:12 am by tecdiego
Boa noite amigo, vi que aprendeu muito, esse é o espírito da coisa.

Quanto ao código, teria algo a acrescentar, ao invés de usar a função delay, para "dar um tempo", pq você não usa while?
ex: 
Code: [Select]


int count = 0;

int tempoInicio = 0;  // guarda o tempo de inicio que a função contador foi chamada.

int intervalo = 1000; // tempo em milisegundos que o botão deverar ficar acionado para adicionar mais 1 ao count

int incremento = 1;   //incremento do contador

boolean estadoBotao = false;                 //É um booleana porque o botao ou estara ligado ou desligado (0 ou 1)
boolean adicionaContador = true;          // aqui vai verificar se deve adicionar +1 ao cont ou não


void setup() {
  pinMode(13,INPUT);
  Serial.begin(9600);

}

void loop() {

  contador();
}

 

void contador(){
     
     tempoIncio = millis();

     while(digitalRead(13) == HIGH)      //enquanto o botão estiver apertado
    {
       
       if (adicionaContador == true) // Verifica se adiciona ao contador, esse laço é usado para não incrementar o count sempre!
       {                                         
       
           count = count + incremento;
           Serial.println("Contador: " + count); // só imprimi na serial quando mudar o valor do count
          adicionaContador = false;
         

        } else if ((millis() - tempoInicio) >= intervalo) { // se passar mais de 1seg com o botão apertado,
                                                                              // ele altera o estado do adicionaContador

                 adicionaContador = true;                        // libera para adicionar mais um ao count

                 tempoInicio = millis();                           // guarda o inicio da função
                 intervalor -= 100;                                 // diminui em 0,1seg o tempo do intervalo
                 
                 if (intervalo < 300) {                             //aqui verifica se o intervalo é menor que 0,3seg

                     intervalo = 300;                               // não deixa ser menor que 0,3 seg
                     
                     if (incremento < 10) { // verifica se o incremento é menor que 10
 
                         incremento ++;
 
                     } // fim IF incremento
                 
 
                 } // fim IF intervalo

 
        } // fim ELSE IF
 
                         

     }// WHILE
     
     adicionaContador = true; // retorna ao estado inicial das variaveis
     incremento = 1;
     intervalo = 1000;
     
}





Tem como adicionar mais coisas, se você deixar apertado ele vai aumentado e com o passar do tempo, etc...

Desculpa a forma como escrevo os programas.
Esse eu não testei, fiz de cabeça baseado no que já existia.
Qualquer dúvida posta aqui.

Matheus779

Muito obrigado pela ajuda e explicações amigos, deu pra entender muito bem a lógica que vocês usaram, obrigado mesmo :)

binhop

#8
Sep 04, 2017, 09:06 pm Last Edit: Sep 04, 2017, 10:03 pm by binhop
Sem problemas, qualquer coisa pode contar com a gente :D .

bubulindo

Pega no exemplo Serial without delay... adiciona o código para ler o botão e parar a contagem. O maior problema é mesmo a temporização e esse exemplo tem essa parte resolvida. O resto é mais simples de resolver por ti próprio.
This... is a hobby.

leandro1301

Caros amigos, só um acréscimo no código do nosso amigo @binhop, para "não haver atraso", apenas crie uma nova variável inteiro do tipo volatio para que você possa usar o valor posterior mente:

crie a variavel:

volatile int sec = 0;

depois altere a função contador:
void contador(){

  if(estadoBotao == true) //Se o botao estive acionado começa/continua a contagem
      {
        count ++; // deixe count ++ para fazer incremento
        sec = count/10; // a cada atraso de 1ms ele vai dividir por 10 para converter em segundos.
        Serial.println(sec); // printa os segundos
        delay(100); // diminuir o delay para não haver atrasos gigantescos e acabar afetando o botão caso acionado.
      }
}

Go Up