Go Down

Topic: Timer help by not using delay() in a function (Read 1 time) previous topic - next topic

memphis2k

Hello all,

I am working on my home automatic system, Arduino Mega 2560 with a Arduino Net Shield and I need some assistance on getting a function to loop without the need to use the dreaded "delay()".  I can't get the function to loop and just work correctly inside the if(readString.indexOf("toggle60min") > -1).  Been at this for several hours, tried for loops, return, continue, while etc.  Remember, this should only function when I click on the timer (60 minutes).  Any suggestions?

Code: [Select]
#include <Ethernet.h>
#include <SPI.h>
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x78, 0x90 };
byte ip[] = { 192, 168, 1, 134 }; // MY IP change to your needs
byte subnet[] = { 255, 255, 255, 0 };
EthernetServer server(80);
EthernetClient client1;
String readString = String(100);

unsigned long currentTime;
unsigned long loopTime;

void setup(){

  Serial.begin(9600);
  pinMode(2, OUTPUT); //AirCon relay
  Ethernet.begin(mac, ip);
} //setup

void loop(){

  EthernetClient client = server.available();
  if (client)
  {
    while (client.connected())
    {
     if (client.available())
       {
       char c = client.read();
       if (readString.length() < 100)
          {
            readString = readString + c;
             }
       if (c == '\n')
          {
            //code for pin 2
          if(readString.indexOf("toggle2") > -1)
              {
               toggle(2);
               delay(100);
               //emailtxt();
              }
          if(readString.indexOf("get2") > -1){
               client.println("HTTP/1.1 200 OK");
               client.println("Content-Type: text/html");
               client.println();
          if(digitalRead(2) == 0){
            client.print("<IMG SRC=images/aircon_off.png>");}
            else if(digitalRead(2) == 1){
            client.print("<IMG SRC=images/aircon_on.png>");}
            }

            if(readString.indexOf("toggle60min") > -1)
            {
              currentTime = millis();
              loopTime = currentTime + 5000;
                 if(millis()%1000 != 0)
                   {
                    if(currentTime == loopTime){
                      toggle(2);
                    return;
                   } //if
          }// if

          } // read

          if(readString.indexOf("get60min") > -1){
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println();
          if(digitalRead(2) == LOW){ // not important yet
            client.print("<IMG SRC=images/timer_off.png>");}
            else if(digitalRead(2) == HIGH){
            client.print("<IMG SRC=images/timer_on.png>");}
            }

     readString="";
     client.stop();

            } // if c== '\n'
          } // if client
       } // while
     } // if connected
// int toggletimer(){
// } //toggletimer

} // void loop

int toggle(int pinnumber){
    if(digitalRead(pinnumber) == HIGH){
     Serial.print("toggle functions says ");
     Serial.print(pinnumber);
     Serial.print(" is on");
     Serial.println();
     digitalWrite(pinnumber, LOW);
     return(0);
    } //if
    if(digitalRead(pinnumber) == LOW){
     Serial.print("toggle functions says ");
     Serial.print(pinnumber);
     Serial.print(" is off");
     Serial.println();
     digitalWrite(pinnumber, HIGH);
     return(0);
    } //if
} //toggle



This code works perfect for my Garage's Arduino Uno, but I can't do anything when it's running the "While loop"

Code: [Select]
          if(readString.indexOf("toggle6") > -1)
              {
               digitalWrite(6, HIGH);
               delay(100);
               digitalWrite(6, LOW);
               Starttimer = millis();
               Currenttimer = Starttimer + 15000;
               while ( millis() <= Currenttimer) {
                    if (millis() == Currenttimer){
                         Serial.println("email sending.");
                         emailtxt();
                         Serial.println("email sent.");
                    } //if
               } //while
              } // toggle6



Arrch

It looks like inside that area, you are trying to run timing code that will do things at intervals. The problem is that if you look up through your nested ifs, that code will only run after you've received a newline character from your client.

You need to set a flag (a state variable) where you have it now, and have the timing code run outside of any other if statement except for checking if the flag is set.

memphis2k

Thanks Arrch!

Got it figured out, and for anything else, here is what I quickly came up with.

Code: [Select]

unsigned long currentTime = 0;
unsigned long loopTime = 0;
unsigned long timermillisSeconds = 0;

int timerval;
int timerState;

void setup(){

} //setup

void loop(){

  if(readString.indexOf("toggle60min") > -1)
  {
timerState = 2;
timerval = 1;
currentTime = millis();
timermillisSeconds = currentTime + 3000;
  } // read

  if (timerval != timerState) {          // the button state has changed!

  if( millis() >= timermillisSeconds)
    {
Serial.println("wait is over");
toggle(2);
timerval = 0;
timerState = 0;
    }// if
  } // if timerval & timerState

} // void loop


adis

You can use timealarm library (there is a post on the old forum http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1263305457):

Alarm.timerOnce(10, OnceOnly);       // called once after 10 seconds


Make sure you call

Alarm.delay(x)

in each loop() execution

Go Up