Pages: [1]   Go Down
Author Topic: Using millis for time delay for (push ON/OFF button)  (Read 521 times)
0 Members and 1 Guest are viewing this topic.
Hyderabad, India.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

so guys i finally managed to hack the ac remote and control AC via PIR sensor.

but for this i am using the delay() function and the problem is even though there is movement because of the delay() the arduino wont implement it, even if there is movement when AC is turned on it switches off after the preset time from the first movement but not the last movement detected because delay is triggered after the first movement!

the code is

Code:
void loop()
{
 val = digitalRead(sensor);                             //reads value from PIR proximity sensor
  potval = analogRead(pot);                           //reads potentiometer value
  timedelay = map(potval, 0, 1023, 20, 600);  //scales potentiometer value for delay
  timedelay=timedelay*1000;
  Serial.println(potval);
  Serial.println(timedelay);
 if(val == 1)                                                 // when proximity is detected
{
  ac();                                                         //activates ON/OFF button
  delay(timedelay);
  ac();                                                             
  }
  delay(1000); 
}

void ac()                                                     // for ON/OFF
{
 
  digitalWrite(led, HIGH);   
  delay(500);
  digitalWrite(led, LOW);
}


i cant implement the else if loop for using millis function as it triggers the ac() function each and every loop because of the ac() function in the else loop....

the code for led version using millis function for time delay is


Code:
void loop()
{
  val = digitalRead(sensor);                                //pir sensor
  potval = analogRead(pot);                                //pot value for time delay
  timedelay = map(potval, 0, 1023, 20, 600);

  if(val == 1)                                                     // if pir sensor triggered
  {
    digitalWrite(led, HIGH);
    time = millis()/1000;
  }
  timep=millis()/1000;
  if( abs(timep-time) <= timedelay)
  {
    digitalWrite(led, HIGH);
  }
  else
  {
    digitalWrite(led, LOW);
  }
 
  Serial.println(timedelay);
  delay(100);
}


please help me out as there is only single button to control the switching of the AC and tell me how i can implement it using millis
« Last Edit: June 06, 2013, 03:34:57 pm by kiriti » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How would YOU perform the required actions, using a pencil, paper, and a watch? The millis() function takes the place of the watch. The pencil and paper are replaced by variables in the code.

Logged

Hyderabad, India.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i would do that using the else if loop for a led which works perfectly fine for led


if( abs(timep-time) <= timedelay)   
  {
    digitalWrite(led, HIGH); 
  }
  else
  {
    digitalWrite(led, LOW);
  }

but if i use the same structure for my ac remote


if( abs(timep-time) <= timedelay)   
  {
    ac();                                               //executes repeatedly until the set time
  }
  else
  {
    ac();                                              //executes repeatedly when it is idle
  }



when these are being executed repeatedly the whole purpose is not satisfied as the AC keeps Switching ON and OFF every cycle irrespective of the value of the sensor
Logged

Hyderabad, India.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the hurdle is that while the led has 2 different commands to turn it ON and OFF

the ac remote has just a single command for ON and OFF
Logged

Australia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 99
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the ac remote has just a single command for ON and OFF

So *you* need to keep track of whether it is on or off, and only switch it if it's different to what you want it to be.

Also you shouldn't need the abs() calls as the type of your "timep" and "time" variables will be "unsigned long" already.
« Last Edit: June 06, 2013, 08:55:08 pm by crimony » Logged

Hyderabad, India.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Also you shouldn't need the abs() calls as the type of your "timep" and "time" variables will be "unsigned long" already.

yea crimony, but the millis button will overflow back to 0 after 50 days, that time the "timep-time" would go negative and the condition without abs "(timep-time) <= timedelay" would be satisfied for 50 more days smiley-razz

thats why i included the abs function, or is it not necessary or am i overlooking something?


and thanks crimony and Pauls, will post the final code in few mins smiley-grin
Logged

London
Offline Offline
Edison Member
*
Karma: 46
Posts: 1368
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i would do that using the else if loop for a led which works perfectly fine for led

That's not what PaulS asked you to do.
Write down the steps you would take if you were doing it with a stopwatch.

1) wait for button to be pressed
2) start stopwatch
3) do something
4) wait until the stopwatch shows the delay time
You continue....
When you've done that, perhaps you will understand what you're trying to do and how to do it.

Also note that
Code:
if(millis() - starttime >=delaytime)
avoids any problems with rollover.
Logged

Australia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 99
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yea crimony, but the millis button will overflow back to 0 after 50 days, that time the "timep-time" would go negative and the condition without abs "(timep-time) <= timedelay" would be satisfied for 50 more days smiley-razz

thats why i included the abs function, or is it not necessary or am i overlooking something?

Your code uses time in seconds, so you can't use the standard transparent technique for managing millis() rollover, which would be something like this (not tested, likely to contain some errors):

Code:
unsigned long timedelay;
unsigned long time;
unsigned long timep;
bool ac_on = false;

void loop()
{
  val = digitalRead(sensor);                                //pir sensor
  potval = analogRead(pot);                                //pot value for time delay
  timedelay = 1000 * map(potval, 0, 1023, 20, 600); // delay in milliseconds

  if(val == 1)                                                     // if pir sensor triggered
  {
    digitalWrite(led, HIGH);
    if (!ac_on)                                              // only toggle the AC if it's not on yet.
    {
      ac();
      ac_on = true;
    }
    time = millis();
  }
  timep = millis();
  if( ac_on && timep - time > timedelay)                   // time delay exceeded
  {
    digitalWrite(led, LOW);
    ac();
    ac_on = false;
  }
 
  Serial.println(timedelay);
  delay(100);
}


This code assumes the AC starts *OFF*. If it's not, then the logic will be reversed. You really should have a mechanism for detecting whether the AC is on or off, it would make your solution much more robust.
« Last Edit: June 06, 2013, 10:06:41 pm by crimony » Logged

Hyderabad, India.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

henry it means that i had to use the else if loop right?


my final working code:)
Code:
void loop(){
  val = digitalRead(sensor);
  potval = analogRead(pot);
  timedelay = map(potval, 0, 1023, 20, 600);
  Serial.println(potval);
  Serial.println(timedelay);
 
  if(val == 1)
  {
    time = millis()/1000;
  }
  timep=millis()/1000;
  if( timep-time <= timedelay)
  {
    acon();
  }
  else
  {
    acoff();
  }
  delay(1000); 
}

void acon(){
  if(state == 0)
  {
    digitalWrite(led, HIGH);   
    delay(500);
    digitalWrite(led, LOW);
    state = 1;
    Serial.println("AC ON");
  }
}

void acoff(){
  if(state == 1)
  {
    digitalWrite(led, HIGH);   
    delay(500);
    digitalWrite(led, LOW);
    state = 0;
    Serial.println("AC OFF");
  }
}


crimony i did it the same way as your code, but using int and not boolean


if by mechanism you mean external feedback to see weather AC is on, i dont think it is required as the AC remote sends different signals for ON and OFF so even though ac is initially ON, the functions wont get reversed smiley-grin

i tried overriding with external remote, works good without inverting the states of the AC
Logged

Pages: [1]   Go Up
Jump to: