o que esta errado aqui?

pessoal vejam esse programa

#define botao 11
#define led 13

void setup() {
pinMode(botao, INPUT);
pinMode(led, OUTPUT);
}

void loop()
{
long tmp = millis();
while(digitalRead(botao));
{
if((millis() - tmp) >= 3000)
digitalWrite(led, HIGH);
else
digitalWrite(led, LOW);
}
}

do jeito que esta ao pressionar o botao por 3s ou mais era pra ascender o led, porém ele só da uma piscada rápida e apaga.
se eu tirar o bloco else, ele ascende normalmente, porém não consigo apagá-lo que é o que eu pretendo, ascender ao pressionar o botao por 3s e apagar ao pressionar de outra forma?

alguem consegue ver o erro?

obrigado

o millis retorna unsigned long. Isso dá-te problemas mais tarde.

O teu problema é na programação.

#define botao 11
#define led 13

void setup() {
 pinMode(botao, INPUT);
 pinMode(led, OUTPUT);
}

void loop()
{
    long tmp = millis();
    while(digitalRead(botao)); // ESTE ; FAZ COM QUE O CÓDIGO FIQUE AQUI PARADO ENQUANTO O TEU DEDO ESTIVER NO BOTÃO.
{
    if((millis() - tmp) >= 3000)
digitalWrite(led, HIGH);
else
digitalWrite(led, LOW);
}
}

O resto do código também não me parece que faça o que pretendes...

Este deve funcionar um pouco melhor... experimenta.

if (botão == PRESSIONADO) {
    tmp = millis(); 
    light = ON; 
}

if (millis() - tmp >= 3000) {
    tmp = 0; 
    light = OFF;
}

não entendi esse programa que postastes,,

Tu pediste um programa que após uma tecla ser pressionada, ligasse uma luz durante 3 segundos.

O primeiro if desse programa, vê quando a tecla é pressionada e liga a luz.

O segundo if do programa desliga a luz quando passarem 3 segundos após teres tirado o dedo do botão. Pode não ser exactamente o que pretendes, mas a lógica está lá e só falta adicionares as outras condições, se tiveres, para fazer o que pretendes.

Talvez eu tenha percebido mal o que pretendes, queres confirmar o que pretendes fazer ou vais tentar perceber o código que deixei?

na verdade o que pretendo é o seguinte, ao pressionar o botao por 3 segundos o led ascende e fica asceso até que o botao seja pressionado novamente por 1 segundo.

esse bloco de programa que vc postou vem depois do loop ou depois do millis que eu havia colocado?

obrigado pela atenção...

unsigned long botao_agora = 0, botao_antes = 0; 

loop() {

if (botao == pressionado && led == OFF) {
   botão_antes = millis();
   while ((botao == pressionado) && ((botão_agora = millis())-botao_antes < 3000)); 
   led = ON; 
   botao_antes = 0;
   botao_agora = 0;
   }
if (botao == pressionado && led == ON) {
   botão_antes = millis();
   while ((botao == pressionado) && ((botão_agora = millis())-botao_antes < 1000)); 
   led = OFF; 
   botao_antes = 0;
   botao_agora = 0;
   }

Isto?

Eu não gosto muito desta implementação por causa do while bloquear a execução do programa por 3 segundos... logo a maneira de evitar isso seria criar outra variável para lidar com essa hipótese. Mas deixo isso para tu pensares. :slight_smile:

desculpe me pela demora em responder, mas é que a faculdade consome o tempo todo,,,,

decidi mudar um pouquinho o programa usando switch case,,,

desta forma ficou assim..

#define botao 8
#define led 13

typedef enum {
BOTAO_OFF,
BOTAO_ON} t_estados;

t_estados estado;

int time;

void setup() {
pinMode(botao, INPUT);
pinMode(led, OUTPUT);

digitalWrite(led, LOW);
estado = BOTAO_OFF;}

void loop()
{
switch (estado)
{
case BOTAO_OFF:
if(digitalRead(botao) != 0)
{
time= millis();
estado = BOTAO_ON;
}
break;
case BOTAO_ON:
if(digitalRead(botao) == 0)
{
time= millis() - time;
if(time >= 3000)
digitalWrite(led, HIGH);
else if(time <= 1000)
digitalWrite(led, LOW);
estado = BOTAO_OFF;
}
break;
default:
break;
}
}

porém ainda tenho o problema do led apenas dar uma piscada quando deveria permanecer aceso, se eu tiro a linha da condição <= 1000 ai funciona normal, aí nao consigo apagar o led por não ter este comando no programa,, por que será??

obrigado

o que é que a condicão time < 1000 tem a ver com pressionares um botão para apagar o led?

unsigned char led_state = 0; 
unsigned long time=0;


loop() {

//iniciar a temporizacão
if (botao == PRESSIONADO && led_state == 0) {
    time = millis();
} //sabemos quando o botão foi pressionado. 

//mudar o estado do LED
if (botao == PRESSIONADO && (millis() - time >=3000) {
    led_state = HIGH; 
}

//mudar o estado do LED para desligado. 
if (botao != PRESSIONADO && led_state == HIGH) {
   led_state = LOW;
}

//fazer update do pino baseado na variável led_state. 
digitalWrite(LED, led_state);
}

é que na verdade o led só vai ser apagado com uma nova mudança de estado do botão, e não simplesmente ao soltá-lo, tipo pressiona e solta para acender(3000) e pressiona e solta para apagar(1000)..

Mas o programa que eu postei acima funcionou, o que faltava era colocar um resistor de pull-up no pino do botao até o GND,

Obrigado pela colaboração,,

:slight_smile:
Reparei agora que o time é calculado antes do if. Não vi bem isso da outra vez.

Bubulindo agora ta tudo certo funcionando como deve.

Preciso agora converter esse programa para usar com pic porque aqui os pics sao mais
baratos que os atmegas,

por onde começar? Alguma sugestão? Existe alguma ide para pic em c++ igual a do arduino?

Obrigado pela atenção

Abraço

Não faco ideia... fiquei traumatizado ao usar PICs e nunca mais quis sequer ouvir falar delas.

Bom diante da minha situação, resolvi usar o attiny85 no meu projeto, ele conta com 5 i/o's e da pra programar pelo próprio arduino..

Resolvi completamente meu problema agora,,

muito obrigado a todos pela ajuda... Obrigado bubulindo pela atenção

abraços