10sec delay without using delay() function

I wrote the whole code with delay() but getting to the sensor part is not working as expected because of the delay () shortccoming that was i resulted to the code am using. If i know how to fix it i wouldnt have been here. If something is done once or twice you learn it from it. I have read about many example like interupts switch case blink without delay also some timer lib. Is like am asked to solve 2+2 and i have no idea. If i was been put through and solved for me . Do you think next time i wont solve 3+3 on my own .of course i will on my own Gpop1 u are always appreciated thanks for your help. Thanks i will chk the ladder logic. Thanks mas3

Hi.

The problem is that you are now incorporating a lot of new techniques, while still busy learning another one. I'm not telling you those techniques aren't to be used ever again. But try to keep the learning manageable by doing one thing at a time. I like gpop1's suggestion of the "master timer" and a counter. That will be quite transparant for you to use. So study that.

I've got to go now but don't give up and re-read some of the suggestions. You will also learn when your attempts fail, but of course a success now and then will be more fun.

One key concept is that with millis(), your functions have to return immediately if there is nothing to do. So "for"s and "while"s must be written as "if"s.

thanks for your contribution everybody God bless. gonna figure it out

both mas3 and aarg are posting great comments. I know it seems unhelpful as either of them could knock out this code in a few minutes and it would work. The problem is that you would not understand the code. hell ive seen some of there codes and It takes me ages to figure out how they do things. Just like ladder logic every programmer has a style and it takes a while to understand how the program works in there style.

Example codes are generally designed to do one thing and repeat it for ever so it uses commands based on that concept. While and for are used because it cleaver code and looks smart. The trouble is there designed to do one thing which makes adding extra code a pain.

1/ start with a plan
2/ keep the code as simple as possible even if it means using 3 times more code
3/ stay in the main loop
4/ write it from top to bottom that’s the way the processor reads it
5/ after you have a working code that you understand then you can rewrite it using better commands

your whole project can be made in the main loop just using the “if” command.

a/ how do you want the lights to start when the arduino is turned on.//this is where you can set the globals at a setpoint like timer_2=20; that way you enter the program with 20 already on the counter so a if timer_2<10 then its already false. Or tell it in setup that timer_2=20;

b/ when should the light change pattern // this is where you start (reset to 0) the timer then use that timer to control the pattern. set a flag so what ever started the light sequence does not affect it if it changes.

c/ what do you do once the lights are changed//something needs to hold this state (unsigned int timer_1 will roll over at some point)

d/ when do I want to reset or reverse the lights// timer or event

e/ when do I reset or hold the timers to get back to b.// also reset the flag so its ready to go again

olaoludavid:
Basically, i wanted a delay before the LDR (photocell) sensor sense a car.

A delay from when? It’s no use saying “a delay of 5 seconds”, you need to say “a delay of 5 seconds between event A and event B”. I mean - you know what you mean, but you have to specify it.

In any case, what you want to do is best handled by a state machine.

First, you need to identify the states that your machine can be in. Then you identify the events that trigger a change from one state to another, and what needs to be done on entry to that other state in order to set things up correctly: for instance, putting the current millis into a varibale somewhere.

I like to use a C++ enum for the states. That way, you can know for sure that you have handled all possible values in your switch statement.

Code looks like this, and you can see that this is a generally useful pattern to follow.

enum State {
  INIT = 0,
  LED_OFF = 1,
  CAR_SENSED = 2,
  LED_ON = 3
};

State currentState = INIT;  // always start in INIT mode
int sensorPin = A0;         // select the input pin for the ldr
int LDRLED  = 5;            // select the input pin for the ldr
unsigned long sensingTimeout;

void transitionTo(State newState); // forward declaration.

void setup() {
  transitionTo(LED_OFF);
}


void loop() {
  switch (currentState) {
    case LED_OFF:
      if (isCarOnSensor()) {
        transitionTo(CAR_SENSED);
      }
      break;

    case CAR_SENSED:
      if (!isCarOnSensor()) {
        transitionTo(LED_OFF);
      }
      else if (isSensingTimeoutElapsed()) {
        transitionTo(LED_ON);
      }
      break;

    case LED_ON:
      if (!isCarOnSensor()) {
        transitionTo(LED_OFF);
      }
      break;
  }

}

void transitionTo(State newState) {
  switch (newState) {
    case LED_OFF:
      if (currentState == LED_ON)  {
        digitalWrite(LDRLED, LOW);
      }
      break;

    case CAR_SENSED:
      sensingTimeout = millis();
      break;

    case LED_ON:
      digitalWrite(LDRLED, HIGH);
      break;
  }

  currentState = newState;
}


boolean isCarOnSensor() {
  return analogRead(sensorPin) < 300;
}

boolean isSensingTimeoutElapsed() {
  return millis() - sensingTimeout > 3000;
}

DELETED

gpop1 you've really done a great job. I appreciate. I got all what you said boss but I can't just fix the mess. I learn from what is been solved as I don't have the basis of programming. Base on ICS I can do the job. PaulMurrayCbr I wanted to delay the LDR so that every car passing will not be sensed until the car is waiting at the sensor spot for the X seconds. Thanks for your contribution. As I have said early am an electronics engineer with little database and qbasics knowledge which not even relevant because sketch is C language. Am new to Arduino, the only concept of timing or delay I know for now is the delay () function. I have the complex code writing and working using delay () but because of the sensor that's why am looking for away out. Right now am tensed up. If I know what to do I wouldn't have posted my issue. I really thanks everyone for there contributions. Vaclav as you've said '' Hopefully you have learn one thing from this useless ( from simple delay to convoluted "situations" ) and contributors time wasting exchange - when you ask for help you should at lest have the courtesy / gumption to follow the instructions.'' yes Of course I have learnt a lot but pleass don't have to be insulting. The project matters to me a lot thanks

DELETED

how do traffic lights work where you are located? red-red/amber-green-amber-red or red-green-amber-red ?

I presume the traffic light will be red then the car will stop over a sensor. after 10 seconds the traffic lights will go green then after a pause will cycle back to red. (this is why in calafornia motorbikes can turn left on red as they carnt always trip the sensor)

is this meant to be a intersection or pedestrian crossing light?

Remember as a engineer nothing you say makes sense...lol.

Vaclav thanks for you time again You gave me another idea today using while. gpop1 thank you very much. We use red-red/amber-green-amber-red . The 10secs is testing i can change it anytime. I am dealing with with car overflow not sensing car to change the light land lady light to green. All the great suggestions are pretty good if i know what i have to do but what do you expect from a newbie in proggramming world. Thanks very much. In all honesty i cant really learn when am in a tight conner. I solved the problem today with hardware still under testing. It worked as expected you know i told you am a guru in using chips just new in programming .i will share the details tommorrow how it was solved with hardware. IN ALL HONESTY I HAVE BEEN A LOT TO LEARN. EVERY SUGGETION GIVEN TO ME MUST BE STUDIED. PLEASE NO EFFORTS HAS BEEN WASTED. I can't just get it each time i try. After i wrap up the probject i have list of functions to learn. Thanks amillion times everyone . AM NOT STILL GIVING UP ON THE CODE I WILL FIND A WAY OF FIXING IT .

take a break and play with this and see if you can understand this real basic code. Its written in long hand to make it easy to follow. Its USA style traffic lights but im sure you can change that. This is real bad code if you think about it. If your boss said he didn’t like the amber light being on that long you have to recode a lot of lines to change it but its easy to read for a beginner and hopefully will lead you on to better ways of coding it.
I kinda tested it using serial monitor I think it works as designed.

unsigned long previousMillis = 0;//used in one second counter
int sensorPin = A0;            // select the input pin for the ldr
unsigned int sensorValue = 0;  // variable to store the value coming from the ldr
int LDRLED  = 5;            // select the input pin for the ldr
int timer_1 = 0;//used for debounce on sensor
int timer_2 = 0;//used to control light sequence
byte t1_red = 3;//pin number for light
byte t1_amber = 4;//pin number for light
byte t1_green = 5;//pin number for light
byte t2_red = 6;//pin number for light
byte t2_amber = 7;//pin number for light
byte t2_green = 8;//pin number for light
byte flag = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(t1_red, OUTPUT);//set pins as outputs
  pinMode(t1_amber, OUTPUT);
  pinMode(t1_green, OUTPUT);
  pinMode(t2_red, OUTPUT);
  pinMode(t2_amber, OUTPUT);
  pinMode(t2_green, OUTPUT);

  digitalWrite(t1_green, HIGH);//set lights to default for when starting
  digitalWrite(t1_amber, LOW);
  digitalWrite(t1_red, LOW);
  digitalWrite(t2_green, LOW);
  digitalWrite(t2_amber, LOW);
  digitalWrite(t2_red, HIGH);

  Serial.begin(9600);
}

void loop() {

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > 1000L) {
    timer_1++;
    timer_2++;
    previousMillis = currentMillis;
  }
  //every second both timers are increased by one

  sensorValue = analogRead(sensorPin);
  if (sensorValue < 300) { //lower than 300 equals something sensed
    if (timer_1 >= 10 && flag == 0) {
      flag = 1; //flag=1 means cycle lights
      timer_2 = 0;//set timer ready to cycle lights
    }
  }//watch the switch before a else command or it will link to the wrong if
  else// sensor now reads over 300
  {
    timer_1 = 0;
  }

  if (flag == 1) {//once this starts it will stay running until flag is reset to 0
    if (timer_2 >= 1 && timer_2 <= 3) {//basic over 1 second or over and under 4 seconds
      digitalWrite(t1_green, LOW);
      digitalWrite(t1_amber, HIGH);
      Serial.println (" t1-green off  t1-amber on ");

    }
    if (timer_2 >= 4 && timer_2 <= 5) {
      digitalWrite(t1_amber, LOW);
      digitalWrite(t1_red, HIGH);
      Serial.println (" t1-amber off  t1-red on ");
    }
    if (timer_2 >= 6 && timer_2 <= 18) {
      digitalWrite(t2_red, LOW);
      digitalWrite(t2_green, HIGH);
      Serial.println (" t2-red off  t2-green on ");
    }
    if (timer_2 >= 19 && timer_2 <= 20) {
      digitalWrite(t2_green, LOW);
      digitalWrite(t2_amber, HIGH);
      Serial.println (" t2-green off  t2-amber on ");
    }

    if (timer_2 >= 21 && timer_2 <= 23) {
      digitalWrite(t2_amber, LOW);
      digitalWrite(t2_red, HIGH);
      Serial.println (" t2-amber off  t2-red on ");
    }
    if (timer_2 >= 25 && timer_2 <= 26) {
      digitalWrite(t1_red, LOW);
      digitalWrite(t1_green, HIGH);
      Serial.println (" t1-red off  t1-green on ");
      flag = 0;//reset flag to exit light cycle
      timer_1 = 0;//reset timer so if a car is broke down on sensor it doesnt loop until 10 seconds
    }
  }

  Serial.print (" flag ");
  Serial.print (flag);
  Serial.print (" timer ");
  Serial.println (timer_2);

}

@olaoludavid:

Forgive this Vaclav guy, he doesn't know any better than to post crap like that, while blaming any other forum member for being either rude or stupid. Just skip those posts, i do so unless i see some reason to actually read them (your reaction to his posts was one of those reasons).

So now back to things that do matter.

You want to delay the LDR, so you can see a car that is over it. For that to happen, you need to see it at least twice within a certain time. Now you are starting a timer once you see the LDR go below a threshold. The timer looks for a certain time to be passed since you last looked at the "master clock". For that you need to record a moment in time so you have something to compare it with. This is where that happens:

     if (currentMillis - previousMillis >= interval_1) {//10 second timer

Just before you did this check, you've updated currentMillis. But when was your last update of previousMillis ?

It gets a bit worse. Once you're below the LDR-threshold, you start the timer test. If that test fails (which will probably not happen), you are resetting previousMillis. This means that, unless you have a really slow iteration time going on, the test will never pass.

As a figure of speak, you are counting from 1 to 3. So you are adding one to whatever you already have. Then you go and check if you're at 3 already, and if you're not, you reset to 1. You'll never reach 3 this way.

You seem to have about all the steps you need for this, but they are in the wrong place in your code.

You can help yourself a bit. Use another variable, that will tell you if the timer has been activated / the threshold has been reached. If the threshold hasn't been reached before, but is now, you need to reset the timer by updating previousMillis, and you need to to this only at that specific moment. You should not need to update previousMillis while the timer is running. So only after you're done with the timer you're free to update it (but why would you do so if you're not using the timer..).

Once the timer has lapsed, and the traffic light has changed, you can reset the "timer activated" variable.

I've often told people to keep track of all you are and have been doing. That's what this is all about.

I was overwhelmed when i saw gpop1 and MAS3 response. Thank you, thank you for not giving up on me thanks . I have decided to learn the concept currentMillis ,previousMillis and interval how they were been used as i cant escape them in my day to day in writing sketch.

@MAS3 i love the way u broke currentMillis ,previousMillis down thank . my concept is different from the normal way of traffic light . The delay is used in order not the LDR sense every car passing except the car that stop in front of the sensor for x secs before performing a task. i have started studying currentMillis and previousMillis . The sketch written by gpop1 really help me too. i have checked “blink without delay” many times but just understanding it, i had no clue before.

@gpop1 thanks for always been there. I got the sketch yesterday and i have been studying it. Truly speaking it was a great job you did. Thanks. I added pedestrian cross to it and is working fine. i did some alteration to the sketch so as to work as expected.
i have some questions

  • why did you “byte t1_red = 2;//pin number for light” why not “int t1_red = 2;//pin number for light”

  • can you please explain this “timer_1++;” and its function. i know ++ is increment. i want to understand and not cramming
    i understood the rest part of the code at least.

2 things to do more on it
1 make the pedestrian light blink with interval
2 the sensor should be delayed before sensing for example sensor 1 delay = 10secs if car A is at the sensor for 3sec and left the timer will be reset .if car B is there for more than 10secs then change traffic light 1 to from green to amber delay 4sec then red light on while Traffic light 2 is NOT interrupted
here is the modified code below

unsigned long previousMillis = 0;//used in one second counter
int sensorPin = A0;            // select the input pin for the ldr
unsigned int sensorValue = 0;  // variable to store the value coming from the ldr
int LDRLED  = 10;            // select the input pin for the ldr
int timer_1 = 0;//used for debounce on sensor
int timer_2 = 0;//used to control light sequence
byte t1_red = 2;//pin number for light
byte t1_amber = 3;//pin number for light
byte t1_green = 4;//pin number for light
byte t2_red = 6;//pin number for light
byte t2_amber = 7;//pin number for light
byte t2_green = 8;//pin number for light
byte t1_blue = 5;//pin number for pedestrian
byte t2_blue = 9;//pin number for pedestrian


byte flag = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(t1_red, OUTPUT);//set pins as outputs
  pinMode(t1_amber, OUTPUT);
  pinMode(t1_green, OUTPUT);
  pinMode(t2_red, OUTPUT);
  pinMode(t2_amber, OUTPUT);
  pinMode(t2_green, OUTPUT);
  pinMode(t1_blue, OUTPUT);
  pinMode(t2_blue, OUTPUT);
  pinMode(LDRLED, OUTPUT);

  digitalWrite(t1_green, HIGH);//set lights to default for when starting
  digitalWrite(t1_amber, LOW);
  digitalWrite(t1_red, LOW);
  digitalWrite(t1_blue, LOW);
  digitalWrite(t2_green, LOW);
  digitalWrite(t2_amber, LOW);
  digitalWrite(t2_red, HIGH);
  digitalWrite(t2_blue, HIGH);

  Serial.begin(9600);
}

void loop() {

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > 1000L) {
    timer_1++;
    timer_2++;
    previousMillis = currentMillis;
  }
  //every second both timers are increased by one

  sensorValue = analogRead(sensorPin);
  if (sensorValue < 300) { //lower than 300 equals something sensed
    if (timer_1 >= 10 && flag == 0) {

      digitalWrite(LDRLED, LOW);

      flag = 1; //flag=1 means cycle lights

      timer_2 = 0;//set timer ready to cycle lights

    }
  }//watch the switch before a else command or it will link to the wrong if
  else// sensor now reads over 300
  {
    digitalWrite(LDRLED, HIGH);
    digitalWrite(t1_green, LOW);
    digitalWrite(t1_amber, HIGH);
    digitalWrite(t1_red, HIGH);

    flag = 0;//reset flag to exit light cycle
    timer_1 = 0;

  }

  if (flag == 1) {//once this starts it will stay running until flag is reset to 0
    if (timer_2 >= 1 && timer_2 <= 3) {//basic over 1 second or over and under 4 seconds
      digitalWrite(t1_green, LOW);
      digitalWrite(t1_amber, HIGH);
      digitalWrite(t2_blue, LOW);
      Serial.println (" t1-green off  t1-amber on ");

    }
    if (timer_2 >= 4 && timer_2 <= 5) {
      digitalWrite(t1_amber, LOW);
      digitalWrite(t1_red, HIGH);
      Serial.println (" t1-amber off  t1-red on ");

    }
    if (timer_2 >= 6 && timer_2 <= 18) {
      digitalWrite(t2_red, LOW);
      digitalWrite(t2_green, HIGH);
      digitalWrite(t1_blue, HIGH);

      Serial.println (" t2-red off  t2-green on ");
    }
    if (timer_2 >= 19 && timer_2 <= 20) {
      digitalWrite(t2_green, LOW);
      digitalWrite(t2_amber, HIGH);
      digitalWrite(t1_blue, LOW);

      Serial.println (" t2-green off  t2-amber on ");
    }

    if (timer_2 >= 21 && timer_2 <= 23) {
      digitalWrite(t2_amber, LOW);
      digitalWrite(t2_red, HIGH);
      Serial.println (" t2-amber off  t2-red on ");
    }
    if (timer_2 >= 25 && timer_2 <= 26) {
      digitalWrite(t1_red, LOW);
      digitalWrite(t1_green, HIGH);
      digitalWrite(t2_blue, HIGH);
      Serial.println (" t1-red off  t1-green on ");
      //flag = 0;//reset flag to exit light cycle
      //timer_1 = 0;//reset timer so if a car is broke down on sensor it doesn't loop until 10 seconds
    }
  }

  Serial.print (" flag ");
  Serial.print (flag);
  Serial.print (" timer ");
  Serial.println (timer_2);

}

thanks and God bless

  • why did you "byte t1_red = 2;//pin number for light" why not "int t1_red = 2;//pin number for light"

computers work in binary which is 1 or 0. Basic numbers to a computer are counted in base 2 so

so 00000111 = 7 in decimal.

a byte is 8 bits long (you can use 7 bits as the first is reserved for minus unless changed in the code to a unsigned)

so 10000111 = -7 in decimal

the largest pin number on the uno is 13? so I only need a byte to hold that number.

a int is 2 bytes which means its seen as 16 bits long which is a waste of space as the largest pin number doesn't need that many bits.

google byte, int, long and it will explain it better than me.

  • can you please explain this "timer_1++;" and its function. i know ++ is increment. i want to understand and not cramming

its short hand for timer_1=timer_1 + 1

timer_1 does not change unless its told to do so. If timer_1 was 20 and the next line of code said timer_1++ then timer would become 21 and stay there until told to change.

I suggest that you look on line for a pdf called "basic C for arduino" that's what I used when I first started.

hello sir gpop1 how has been your day thanks for your support . I got the explanation above well understood. i have downloaded the PDF thanks. The hardware is still working well with my previous code am gonna share it soon.

I handed you a tool to do the 10 seconds delay for the car sensor. Use an extra variable. If you want 2 seconds for an extra function, then you should use another variable for that.

As has been told before: make a list of things you need to do. Use a large piece of paper for that. Make sure you leave plenty of space between the items you start with. While you're constructing this list, you'll probably think of some more items to add to that list. After that, take every item and make another list of how to solve that.

If you do this thorough enough, you'll end up with a list that is almost your sketch, but easy to convert to a sketch anyway.

for example sensor 1 delay = 10secs if car A is at the sensor for 3sec and left the timer will be reset

If i understand correct, you want 3 things here: A delay of 10 seconds. After that a delay of 3 seconds.

So you need to keep track of what counter is active.. You can do that using a single variable. If that one is 0, no counter is active. If it is 1, the 10 second timer is active. And if it is 3.. well, you'll get where this is going by now. The variable isn't restricted (well actually it is, depending on how you declare it, but let's forget that for now).

@MAS3 thanks for the time taken to explain things to me. I appreciate. The counter sounds very good idea of solving it. If 0 nothing is gonna happen. If 1 10 seconds is active, if 2 3secs is active and soon. I will look for an example to study that

I said before all I know for now is using delay() function. However I have open mind to learn more as delay() is going no where.

I have written and planed the project before coding. I have the specification of design. I have the algorithm and flow chart.

I will put up a diagram illustrating what the sensor and traffic should do for clearer understanding. Thanks for all contributions

now that you are beginning to understand the counter its not such a big step to understand millis timing. Its basically the same thing just better. At some point you start a timer, end a timer, reset/block a timer or use the timer.

The down side of a counter especially in seconds is that you can not use the first second. In your sketch that's probably not important if the first count is one second long or one hundredth of a second long but in future sketchs that going to be a problem which is why people push for you to learn the best way to code rather than the easiest. But I do believe we all have to start somewhere and until you can see something working you can just get over frustrated which just leads to going no where. Sometime in the future you will look back at this post and smile and judge if i really helped you or just made matters worse by showing you the wrong way.