LusoRobótica - Robótica em Português

Sistemas específicos => Arduino / AVR => Tópico iniciado por: Sovietico em 25 de Agosto de 2013, 15:44

Título: [Dúvida] Controlo de contagem
Enviado por: Sovietico em 25 de Agosto de 2013, 15:44
Boas pessoal. Eu estou-me a iniciar no arduino e ando a montar pequenos circuitos para tentar dominar pequenas acções especificas.
Neste momento estou a tentar controlar o numero de vezes que um led pisca. Para isso tenho um botão +, um botão - e um botão start.
Ou seja, por exemplo, se carregar 2x no botão mais e depois carregar no start o led pisca 2x. Após piscar essas 2x, se carregar no botão menos queria que ele piscasse 1x apenas. Porém, ele pisca 4x e se incrementar 1x ele pisca 8x

o código que tenho é:

const int led = 8;
const int indicador = 12;
const int mais = 4;
const int menos = 2;
const int start = 7;
int smais = 0;
int smenos = 0;
int sstart = 0;
int i = 0;
int c = 0;


void setup(){
 
  pinMode(led, OUTPUT);
  pinMode(indicador, OUTPUT);
  pinMode(mais, INPUT);
  pinMode(menos, INPUT);
  pinMode(start, INPUT);
}

void loop(){

  c = 1;
 
  smais = digitalRead(mais);
  smenos = digitalRead(menos);
  sstart = digitalRead(start);
 
  if (smais == HIGH){
 
    i = i+1;
    digitalWrite(indicador, HIGH);
    delay(50);
    digitalWrite(indicador, LOW);
  }
  else if(smenos == HIGH){
 
    i= i-1;
    digitalWrite(indicador, HIGH);
    delay(50);
    digitalWrite(indicador, LOW);
  }
  else if(sstart == HIGH){
 
    while(c <= i){
      digitalWrite(led, HIGH);
      delay(500);
      digitalWrite(led, LOW);
      delay(500);
      c = c+1;
    }
 
  }
}
Título: Re: [Dúvida] Controlo de contagem
Enviado por: rglove em 25 de Agosto de 2013, 19:45
Hmm, como não tenho tempo de ver agora o código todo, li assim só por alto... Pareceu-me que não estás a considerar o ruído proveniente dos botões. Estás a fazer um delay quando o botão é pressionado, mas quando o botão é largado não estás. O ruído pode levar a que o microcontrolador apanhe mais "cliques" que o que é suposto apanhar...
Título: Re: [Dúvida] Controlo de contagem
Enviado por: LuísR.A. em 25 de Agosto de 2013, 20:35
Isso do ruido é estranho :/ em algo tao simples não me parece que aconteça.

Tens os botões em pull-down ou pull-up?
Título: Re: [Dúvida] Controlo de contagem
Enviado por: senso em 25 de Agosto de 2013, 20:38
Não é ruido, é oscilação dos contactos, pesquisem por button de-bounce.
Título: Re: [Dúvida] Controlo de contagem
Enviado por: Njay em 25 de Agosto de 2013, 20:40
O "ruído" a que o rglove se refere é o chamado "bouncing", e é um problema sim, e leva a que o software detecte mais cliques do que na realidade ocorreram. Ao carregar ou largar um botão, existe um momento na transição em que os contactos mecânicos "saltitam" e a electrónica como é rápida detecta todas essas transições.

Uma forma simples de dar a volta ao bouncing (fazer o chamado "debouncing") é esperar por uma alteração de estado dos botões, e a seguir esperar 50ms antes de ler o seu estado e considerar esse como o estado actual.
Título: Re: [Dúvida] Controlo de contagem
Enviado por: LuísR.A. em 25 de Agosto de 2013, 21:02
Pois agora reparei que o codigo não espera por premir.

Eu faria algo do género. O inserir codigo não está a funcionar não sei porque.
Primeiro espera por um dos botões ser premido. No fim de incrementar espera que nenhum dos botões esteja premido

const int led = 8;
const int indicador = 12;
const int mais = 4;
const int menos = 2;
const int start = 7;
int smais = 0;
int smenos = 0;
int sstart = 0;
int i = 0;
int c = 0;


void setup(){
 
  pinMode(led, OUTPUT);
  pinMode(indicador, OUTPUT);
  pinMode(mais, INPUT);
  pinMode(menos, INPUT);
  pinMode(start, INPUT);
}

void loop(){

  c = 1;
 
  while((smais==low)||(smenos==low)||(sstart==low)){
     smais = digitalRead(mais);
     smenos = digitalRead(menos);
     sstart = digitalRead(start);
  }
 
  if (smais == HIGH){
    i = i+1;
    digitalWrite(indicador, HIGH);
    delay(50);
    digitalWrite(indicador, LOW);
  }
  else if(smenos == HIGH){
 
    i= i-1;
    digitalWrite(indicador, HIGH);
    delay(50);
    digitalWrite(indicador, LOW);
  }
  else if(sstart == HIGH){
    while(c <= i){
      digitalWrite(led, HIGH);
      delay(500);
      digitalWrite(led, LOW);
      delay(500);
      c = c+1;
    } 
  }
 
  while((smais==high)||(smenos==high)||(sstart==high)){
     smais = digitalRead(mais);
     smenos = digitalRead(menos);
     sstart = digitalRead(start);
  }
}
Título: Re: [Dúvida] Controlo de contagem
Enviado por: rglove em 25 de Agosto de 2013, 21:56
Exato, não me estava a lembrar do termo correcto
Título: Re: [Dúvida] Controlo de contagem
Enviado por: Sovietico em 26 de Agosto de 2013, 00:08
Botões em pull up ou pull down como assim? Do lado oposto aos 5 volts tenho uma resistencia de 220ohms a ligar a terra e um cabo a ligar ao pino.

Podem me explicar o significado lógico do que está dentro do while?
Título: Re: [Dúvida] Controlo de contagem
Enviado por: LuísR.A. em 26 de Agosto de 2013, 01:06
Consegues fazer um esquema da montagem? Tipo no fritzng?

O while significa enquanto.
Enquanto o que esta dentro dos parentes se verificar nunca sai do while, fica em loop.

|| significa ou. Naquele caso tens 3 condições. Se alguma delas se verificar ele mantem-se no while. Isso faz-me lembrar que ta mal. Devia ser com &&. Depois explico e corrijo melhor
Título: Re: [Dúvida] Controlo de contagem
Enviado por: senso em 26 de Agosto de 2013, 01:24
Tem de ser OR, se não tens de carregar nos três botões para saires do while.
Título: Re: [Dúvida] Controlo de contagem
Enviado por: Sovietico em 26 de Agosto de 2013, 02:09
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fi39.tinypic.com%2F5kk3so.jpg&hash=c6aaf84f87be58c9ff1d38ffc64274f0141e26d3)
Título: Re: [Dúvida] Controlo de contagem
Enviado por: Sovietico em 26 de Agosto de 2013, 02:50
Alterei os operadores no código que postaram e já funciona ;)

Alguém me pode explicar como é que este código evita o boucing e o meu não?
Título: Re: [Dúvida] Controlo de contagem
Enviado por: samc em 26 de Agosto de 2013, 10:54
se quiseres aprender programação podes tentar escrever um código que utilize a função milis() para evitar a repetição da leitura após receberes o sinal de um botão, ou então...


...podes usar uma biblioteca externa que te faz isso e apenas precisas de a declarar:

http://playground.arduino.cc//Code/Bounce (http://playground.arduino.cc//Code/Bounce)
Título: Re: [Dúvida] Controlo de contagem
Enviado por: Sovietico em 26 de Agosto de 2013, 11:43
A programação em parte não é problema. Eu tive Algoritmia na fauldade e embora apenas ter dado VBA tenho algum racicíonio presente onde basta ver alguns exemplos para aprender.
Quanto à maneira de como o código postado previne o boucing do botão acho que já precebi ;)
Título: Re: [Dúvida] Controlo de contagem
Enviado por: LuísR.A. em 26 de Agosto de 2013, 12:13
Tem de ser OR, se não tens de carregar nos três botões para saires do while.

Não vê senso, é um enquanto, não um se.

while(ssmais==low)||(smenos==low)||(sstart==low)
isto dá enquanto qualquer um dos botões esteja low. Tinhas de premir todos ao mesmo tempo para sair. Por isso é que estava errado.

while(ssmais==low)&&(smenos==low)&&(sstart==low)
Enquanto estiverem todos a low. Bast um não estar para sair do while.

Isto tambem mes costuma apanhar sempre :/

Título: Re: [Dúvida] Controlo de contagem
Enviado por: LuísR.A. em 26 de Agosto de 2013, 12:20
Alterei os operadores no código que postaram e já funciona ;)

Alguém me pode explicar como é que este código evita o boucing e o meu não?

Não sei bem se evita o que eles diziam...acho que só um pouco.
Este principalmente evita que tu mantenhas o botão premido demasiado tempo, evita o tempo que demora o botão a voltar ao sitio. Se resalta varias vezes isto não evita.

O primeiro while, mantem o codigo em espera por um pressão de botão. Apos sair fica registado as variaveis do botões, e em principio so 1 está a high.

O segundo while mantem o codigo em espera até que todos os botões estejam a low, não premidos. Isto evita que mantenhas o dedo a incrementar, e so permite cliques e não manter clicado como um botão de volume.

PS: apesar de tambem uteis, fotos do circuito não são o melhor forma de alguem fora do assunto analisar. Convem sempre um esquema. Experimenta usar o fritzing, é facil e gratis. (a parte dos esquemas)
Pelo que vejo não tens nada que proteja o pin. Se reparares a resistencia não protege o pin. O positivo liga directamente ao pin quando ligas o botão.
Título: Re: [Dúvida] Controlo de contagem
Enviado por: beirao em 27 de Agosto de 2013, 12:17
O "ruído" a que o rglove se refere é o chamado "bouncing", e é um problema sim, e leva a que o software detecte mais cliques do que na realidade ocorreram. Ao carregar ou largar um botão, existe um momento na transição em que os contactos mecânicos "saltitam" e a electrónica como é rápida detecta todas essas transições.

Uma forma simples de dar a volta ao bouncing (fazer o chamado "debouncing") é esperar por uma alteração de estado dos botões, e a seguir esperar 50ms antes de ler o seu estado e considerar esse como o estado actual.

Ou no caso de ser a pessoa  desenhar o esquema, meter um condensadores de 100nF que evita o deboucing.
Título: Re: [Dúvida] Controlo de contagem
Enviado por: senso em 27 de Agosto de 2013, 13:13
O "ruído" a que o rglove se refere é o chamado "bouncing", e é um problema sim, e leva a que o software detecte mais cliques do que na realidade ocorreram. Ao carregar ou largar um botão, existe um momento na transição em que os contactos mecânicos "saltitam" e a electrónica como é rápida detecta todas essas transições.

Uma forma simples de dar a volta ao bouncing (fazer o chamado "debouncing") é esperar por uma alteração de estado dos botões, e a seguir esperar 50ms antes de ler o seu estado e considerar esse como o estado actual.

Ou no caso de ser a pessoa  desenhar o esquema, meter um condensadores de 100nF que evita o deboucing.

Não acho que valha a pena, ocupas mais espaço nas placas, mais componentes, por algo que pode ser muito facilmente tratado em código.

Usando um timer para gerar um contador que é incrementado a cada ms, pode-se fazer algo tão simples quanto isto:
Código: [Seleccione]
if(milis() - buttonsMilis > 10){
buttonsMilis = milis();
getBtnStatus();
}

void getBtnStatus(void){

uint8_t btnNewState = 0; //actual button state as read
static uint8_t btnLastState = 0; //previous button state read
uint8_t encNewState = 0; //actual encoder button state as read
static uint8_t encLastState = 0; //previous encoder button state read
uint8_t pressedState = 0; //Shows what are the pressed buttons after the debouncing

//read the 6 user interface buttons and debounce them (4 buttons + 2 buttons from the encoders)
btnNewState = BTNPIN & ((1<<BTN1)|(1<<BTN2)|(1<<BTN3)|(1<<BTN4));
pressedState = btnNewState & btnLastState;
btnLastState = btnNewState;
buttonState.btn1 = ((pressedState & (1<<BTN1))>>3);
buttonState.btn2 = ((pressedState & (1<<BTN2))>>2);
buttonState.btn3 = ((pressedState & (1<<BTN3))>>1);
buttonState.btn4 = (pressedState & (1<<BTN4));

//read the 4 pins that are used by the 2 rotary encoders
encNewState = ENCBTNPIN & ((1<<ENC1BTN)|(1<<ENC2BTN));
pressedState = encNewState & encLastState;
encLastState = encNewState;
buttonState.encV = ((pressedState & (1<<ENC1BTN))>>3);
buttonState.encI = (pressedState & (1<<ENC2BTN));
}
Título: Re: [Dúvida] Controlo de contagem
Enviado por: beirao em 27 de Agosto de 2013, 14:37
Sim, também. Eu tanto faço por software como por hardware. E um 100nF pode ocupar muito espaço, ou não, depende da aplicação ;)
Título: Re: [Dúvida] Controlo de contagem
Enviado por: Sovietico em 27 de Agosto de 2013, 23:57
Senso esse código ainda é um bocado hardcore para os meus conhecimentos x)
Título: Re: [Dúvida] Controlo de contagem
Enviado por: samc em 28 de Agosto de 2013, 10:38
Eu continuo a aconselhar bibliotecas... em todas as funções que são repetitivas e não fazem parte da aplicação em si mais vale utilizar as bibliotecas bem testadas por a comunidade (poupam-nos tempo e mantêm o código mais limpo e restringido ao essencial).

Já quando é para comunicar por serial também não estou com o trabalho de usar o serial.available blá bla bla. Uso a biblioteca SerialCommand.h, faz o parsing de valores, etc.