Piscar com botao sempre pressionado

Boas,
adquiri recentemente um arduino uno e estou a iniciar-me neste mundo da eletronica. Gosto de aprender coisas novas mas estou aqui preso numa situação que me está a dar que fazer.
Gostaria que me indicassem como posso fazer para que um led pisque só uma vez mesmo que o botao se mantenha pressionado. Ou seja tenho um led sempre aceso e quando pressiono o botão ele fica apagado enquanto o botão estiver pressionado. Que código devo usar para que ele apague somente durante alguns ms mesmo com o botão sempre pressionado?
Já pesquisei aqui no forum mas não consigo encontrar.
Desculpem a ignorancia e desde já obrigado.
Cumprimentos.

nuno_v:
Gostaria que me indicassem como posso fazer para que um led pisque só uma vez mesmo que o botao se mantenha pressionado.
Ou seja tenho um led sempre aceso e quando pressiono o botão ele fica apagado enquanto o botão estiver pressionado.

Tens de comecar por te explicar melhor. O que pedes sao duas coisas dispares. Primeiro pedes que o led pisque, ou seja que reaja a mudanca de estado e passado algum tempo, mesmo que o botao esteja pressionado volte ao estado normal.

E depois pedes que o led mude de estado durante todo o tempo que o botao estiver pressionado.

Sao coisas diferentes. Qual pretendes mesmo?

Que e que ja tentaste fazer?

Peço desculpa, erro meu. O que pretendo é que o led apague durante 70ms mesmo que o botão continue pressionado.

O que tenho no programador é isto:

const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  
}

void loop(){
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    // turn LED on:    
    digitalWrite(ledPin, LOW);  
    delayMicroseconds(70);
    
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, HIGH); 
  }
}
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status
int jaPiscou = 0;             // variavel que identifica se o led ja piscou alguma vez

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  
}

void loop(){
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
if (buttonState == HIGH && jaPiscou == 0) {     
       
    digitalWrite(ledPin, LOW);   //apaga o led
    delayMicroseconds(70); //aguarda 70 ms
    digitalWrite(ledPin, HIGH); //acende o led 
    jaPiscou = 1; //altera o valor da variável jaPiscou para evitar que entre nesse if novamente
  } 
  else {
    // Deixa o led ligado:
    digitalWrite(ledPin, HIGH); 
    jaPiscou = 0; //quando o botão deixar de ser pressionado eu deixo a variavel jaPiscou na condição inicial que é = 0
  }
}

A ideia do código que criei acima é identificar se o led já piscou alguma vez e assim evitar que ele faça tal ação novamente, por isso adicionei o && (and) dentro do condicional, pois ele só vai ocorrer se ambas forem verdadeiras.
Veja se é isso que você quer e se o código funciona

Obrigado pela ajuda krbastos.
Acho que entendi a ideia do codigo que criou. O código funciona mas quando pressiono o botão o led apenas baixa de intensidade e assim mantém enquanto o botão está pressionado. O delayMicroseconds não está a actuar nem o led apaga completamente. O objectivo final é substituir o led por um fio que faz o corte de ignição de um motor. Pretendo que, quando pressionado, o botão corte a energia do motor durante 70 ms e mesmo que o botão fique pressionado mas de 70 ms o corte do motor não seja superior a esse tempo.
Será que com o código millis() consigo isso?
Obrigado

nuno_v:
Obrigado pela ajuda krbastos.
Acho que entendi a ideia do codigo que criou. O código funciona mas quando pressiono o botão o led apenas baixa de intensidade e assim mantém enquanto o botão está pressionado. O delayMicroseconds não está a actuar nem o led apaga completamente. O objectivo final é substituir o led por um fio que faz o corte de ignição de um motor. Pretendo que, quando pressionado, o botão corte a energia do motor durante 70 ms e mesmo que o botão fique pressionado mas de 70 ms o corte do motor não seja superior a esse tempo.
Será que com o código millis() consigo isso?
Obrigado

A falha não é do krbastos, mas sua. O krbastos, apenas pegou no seu código e fez as alterações para que funcionasse como era pedido. Penso que a principal falha, é a confusão entre milissegundos e microssegundos. Para um delay de milissegundos usa-se a função delay(). Para um delay de microssegundos usa-se a função que está a ser usada no código, isto é, delayMicroseconds().

Se pretende que "o LED" apague durante 70 milissegundos, apenas tem que substituir a linha:

    delayMicroseconds(70); //aguarda 70 ms

por:

    delay(70); //aguarda 70 ms

Em relação ao piscar/diminuir a intensidade, o que acontece é que o tempo em que o LED está apagado é tão curto, que o olho humano não é capaz de o ver nesse estado (atenção que 70 microssegundos são 70/1000000 de um segundo) e o que se nota é essa diminuição de intensidade no brilho do LED.

Fiz uma correção no código aqui pq o led não estava apagando ao ficar pressionado.
Simulei o circuito online e funcionou, mas eu coloquei um delay de 1 segundo para ver o led apagando, pq 70 ms é pouco tempo.

O código ficou assim:

const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status
int jaPiscou = 0;             // variavel que identifica se o led ja piscou alguma vez

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  
}

void loop(){
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
if (buttonState == HIGH && jaPiscou == 0) {     
       
    digitalWrite(ledPin, LOW);   //apaga o led
    delay(1000); //aguarda 1000 ms
    digitalWrite(ledPin, HIGH); //acende o led 
    jaPiscou = 1; //altera o valor da variável jaPiscou para evitar que entre nesse if novamente
  } 
  else {
    if(buttonState == LOW) {   
        // Deixa o led ligado:
        digitalWrite(ledPin, HIGH); 
        jaPiscou = 0; //quando o botão deixar de ser pressionado eu deixo a variavel jaPiscou na condição inicial que é = 0
  
    }
  }
}

O esquemático. Atenção no resistor de 10k no botton:

Obrigado krbastos, era mesmo isto que pretendia.
O esquemático eu tinha exatamente como esse mas o resistor que tenho é 3.3k. Será por isso que, quando solto o botão ele, por vezes, faz o led piscar novamente? Não acontece sempre mas por vezes pressiono o botão, o led pisca, e quando solto ele pisca novamente. Já tentei com dois botões diferentes e acontece o mesmo.
Acontece também que, mesmo se não tiver a mexer em nada, de 30 em 30 segundos o led desliga e volta a ligar. Já tentei outras programações diferentes e faz o mesmo.
Mais uma vez obrigado pela ajuda e desculpem a confusão dos mili e microssegundos, o que pretendo são milisegundos.
Obrigado.

O botao, muito provavelmente, esta a sofrer de bouncing... pesquisa por debouncing.

Pelo que percebi, bouncing é como se o arduino assumisse a alteraçao de estado do botão como um comando.
Pesquisei o código e tentei juntar ao que o krbastos criou e resolveu o problema do botão. Obrigado bubulindo.

O código ficou assim:

const int buttonPin = 2;    // the number of the pushbutton pin
const int ledPin = 8;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
int jaPiscou = 0;

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
}

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);  

  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;}      

      // only toggle the LED if the new button state is HIGH
     if (buttonState == HIGH && jaPiscou == 0) {     
       
    digitalWrite(ledPin, LOW);   //apaga o led
    delay(70); //aguarda 1000 ms
    digitalWrite(ledPin, HIGH); //acende o led 
    jaPiscou = 1; //altera o valor da variável jaPiscou para evitar que entre nesse if novamente
  } 
  else {
    if(buttonState == LOW) {   
        // Deixa o led ligado:
        digitalWrite(ledPin, HIGH); 
        jaPiscou = 0; //quando o botão deixar de ser pressionado eu deixo a variavel jaPiscou na condição inicial que é = 0
  
    }  
  }
  }
  
  // set the LED:
  digitalWrite(ledPin, ledState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

O que também já pesquisei e não encontrei nada sobre o assunto, é o facto de o arduino falhar de 30 em 30 segundos. Poderá ser por reiniciar o programa decorrido esse espaço de tempo? É possivel alterar?
Finalmente depois de todos os tutoriais, pesquisas e ajudas vossas já vou tendo alguma noção das coisas mas ainda tenho um longo caminho a percorrer. É bastante cativante este mundo da eletrónica.
Mais uma vez obrigado pela ajuda preciosa.
Cumprimentos

define falhar..

De 30 em 30 segundos o led laranja do arduino pisca duas vezes, apaga durande cerca de 1 segundo e volta a acender. E o led na breadboard apaga quando o do arduino começa a piscar e volta acender quando acende o do arduino. Fica o vídeo:

Isso, a mim, parece-me um reset. Se tive outro programa correr no Arduino acontece o mesmo? Vê-se a USB ligada ao Arduino. Como está a alimentá-lo? Através da porta USB do PC ou tem alguma fonte USB?

EDIT: Experimentei a descarregar o programa para o meu MEGA e, aparentemente, está a funcionar sem fazer este reset. Sendo assim, penso que o problema tem que estar no seu Arduino/PC/Fonte de alimentação.

EDIT2: Voltei a ver o vídeo e não estou a ver a resistência que tem a limitar a corrente do LED e também me parece que está a brilhar com muita intensidade. A maneira correcta de ligar um LED a um Arduino é esta:

se não ligar a resistência pode queimar o Arduino.

Obrigado luisilva, liguei o arduino numa outra alimentação e funciona sem falhas. Realmente só tenho resistência no botão, não sabia que era necessário no led também, vou tratar disso. Agora só falta encontrar forma de substituir o led pelo fio certo da ignição do motor, já tenho programa para o fim de semana :wink:
Vamos ver como corre.
Obrigado a todos

Atenção a essa ligação à ignição. Deve não ligar à ignição, mas deve activar o relé que liga a ignição. Também tem que prestar atenção ao facto de o Arduino não conseguir comandar directamente esse relé (não faço ideia da corrente que será necessária, mas duvido que seja menos de 20mA, que é o valor máximo que cada saída do Arduino consegue fornecer), deve usar um transístor para fazer esse comando.

A minha intenção era comprar um relé com contacto normalmente fechado que pudesse ser activado pelo arduino e abrisse o contacto quando necessário mas quendo fechado permitisse a passagem da corrente para a ignição. Penso que essa corrente seja 12V, agora só não sei se a amperagem influencia muito na escolha do relé. Deve dar para medir com o multímetro. Só no fim de semana vou ter tempo para testar.
Obrigado pelas dicas.

Em primeiro lugar a corrente não é media em Volt, mas sim, em Ampere. Essa corrente interfere na escolha do relé. Outra coisa que deve ter atenção é à tensão da bobina do relé. Como vai usar o Arduino e este tem um "conversor" de 12V para 5V, pode usar um destes dois valores (convém ter atenção à corrente que a bobina consome também). Para além disto, muito provavelmente, vai precisar também de um transístor para controlar o relé.

Finalmente consegui testar este fim de semana e funcionou sem falhas. Comprei um relé de 5v e parece estar tudo ok. Penso que não seja necessário o transístor luisilva. Só tenho mais uma dúvida, é possível adicionar um potenciómetro de forma a controlar o tempo de corte. Tenho programados 70 ms, mas gostaria de poder alterar esse tempo sem ser necessário ligar ao PC. Obrigado pela ajuda.

Sim, é possível. Basta usar o potenciómetro, ligá-lo à entrada analógica e usar o analogRead(). Esta função devolve um valor entre 0 e 1023. Pegando neste valor e multiplicando ou dividindo por alguma coisa, deve conseguir-se tirar alguma coisa que possa ser usado para controlar esse tempo. Por exemplo, se o valor 700 corresponder a esses 70ms, basta dividir o valor por 10 e conseguem-se configura valores entre 0 e 102,3ms.
Aqui está um exemplo do uso da função analogRead() e das ligações necessárias.