Counter info

Hello,

My name is Mircea and I'm new on this forum. Dunno if anyone asked this before so I'm sorry if someone did.

I want to blink a LED (not in the traditionally way with delays in a matter of seconds/tens of seconds or using millis() function) but using a counter. The foolowing program code is working but I have a question for you:

int led = 13;
int counter;

void setup() 
{                
  pinMode(led, OUTPUT);    
  counter=0;
}


void loop() 
{
  if(counter%2==0)
      digitalWrite(led, HIGH);   
   else
      digitalWrite(led, LOW);   
      
 delay(1000);
 counter++;
}

Q: If i want to modify the delay at 10 ms for example, what value should i choose in if(counter%?==0)? (in order the LED to be on for 1 second and off for the other second) Cand someone please explain me how this "%" works?

PS: I know maybe my question is dumb, I admit that I don't know so much about programming but I'm eager to learn so please, take me easy and ignore my newbie knowledge in Arduino programming.

% calculates the remainder when one integer is divided by another so

  if(counter%2==0)

This means 'if the remainder when counter is divided by 2 is zero'

By the way, you are, of course, blinking the LED using delay(), despite what you say.

Q: If i want to modify the delay at 10 ms for example, what value should i choose in if(counter%?==0)?

the 2 is right , it is the counter you should adapt.

If the delay is 10 ms the values 0..99 => LED ON 100..199 => LED OFF 200.299 => LED ON etc

so if you divide the counter by 100 you will get teh sequence 0 1 2 3 4 etc

put into code makes this:

if ((counter /100) %2 == 0)

Why mess around with a counter when you are using delay() anyway ?

byte led = 13;
boolean ledOnOff = true;

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

void loop() 
{
  digitalWrite(led, ledOnOff);
  delay(1000);
  ledOnOff = !ledOnOff;
}

@UKHeliBob: You're right, I still use delay, I was reffering that I don't want to use delays so big because I want to do other actions in parallel and as I read, the arduino pratically pauses the whole actions during the delay().

@robtillaart: Thank you, it works perfectly. I tryed to make the LED stay ON for 2 seconds, and OFF for other 2 seconds, i tought that changing the "2" with "4" in "if(counter/100%4==0) would do it but it seems not, can you advice me on this matter too? I'd really apreciate it.

LE: I got it now. In if((counter/x)%y==0) x - is the interval at which the led should be on/off and y- even/odd frame.

Then use the concepts demonstrated in the Blink Without Delay example.

if(read_led1 == HIGH && read_led2 == HIGH)
{
  
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);
}
delay(10);

After both led1 & led2 are ON in the same time I want to have a delay of 3 seconds using a counter (not millis() or delay(x) ) and after 3 seconds to turn all 3 of them off.

I've tryed to implement "if(counter/300%2==0)" after the first "if" but it doesn't work. I want somehow the counter to start counting those 3 seconds after both led1 & led2 are ON at the same time.

I would really apreciate if someone could help me.

Without a counter of some sorts… How will you determine that a second has gone by?

Bbo

SparksInside: I would really apreciate if someone could help me.

We're trying to, but you're saying you want to implement a delay without using millis() or delay() and then turning around and using delay(). Perhaps you can see why we are confused.

We may be able to help you more if you can say why you don't want to use millis() to write non blocking code. If you don't fully understand how it works then say so, in a PM if you want, and someone will walk you through it. If there is another reason then I would be interested to hear it.

Ok, maybe I should give you more details.
So, I’m in the 4th year at Electric Engineering and Computer Science and my bachelor degree examination is coming in 3 months and I was planning to make a project which consists of a double leaf bascule bridge system - fully automated, using sensors/micro-servo motors and audio and visual warnings.
Basically, I use 2x Sharp proximity sensors placed one in the left side of the bridge and the other one in the right side.

For example:

  • if the left sensor detects movement (that means a cargo-boat is aproaching the bridge)
  • then wait 5 seconds, start the audio ( one mini-speaker set at a specific frequency) and visual warnings on the bridge (2 red LEDs blinking)
  • after 5 more seconds lower the tollbooths,
  • after 5 more seconds lift the bridge leafs and then wait in this position untill the right sensor detects movement
  • when the right sensor detects movemet, that means the cargo-boat passed under the bridge and reached the safe distance from the bridge
  • wait 5 more seconds to be sure, then lower the bridge
  • wait 5 seconds, lift up the tollbooths and shut off the audio and visual warnings (and maybe turn on a green LED)

This is my idea for the project, I bought all components but I’m newbie at programming.Despite that, I want to make it on my own, not paying someone to do it for me (because it’s common practice here in Romania). I’m eager and want to make it on my own, keeping intact my ego and proudness.

Getting back at my problem, I don’t know if I can use delays between actions (for ex: blinking 2 led’s at 700ms) because I’m doing other actions in the same time, or at least it seems that in “IF”-s statements the delays are summing themselves and i need for ex: 2 secs delay for LEDs, 5 secs delay for the bridge, 10 secs for tolbooths…etc. Maybe I’m wrong, that’s why I came here to learn from more experienced people.

For ex, when the left sensor detects movement it turns ON led_l (used as marker - for the examiners to know that the left sensor detected movement) and the LED stays on. After that when the right sensor detects movement (that means the cargo-boat passed under the bridge), another LED (led_r) turns ON for visual confirmation. After this I want both marker LEDs to stay on in the same time for 3 seconds (regardless if the sensors are detecting movement or not in this 3 second interval) and after that to turn them OFF, lower the bridge, lifting the tolbooths and turning off the audio warning and tolboots warning red-LEDs.

Here is my problem, I don’t know how to do that without using a big delay of 3 seconds because I think it would interact with the other delays (if i use delays).
I wanted to use counters, and at the end of the loop to put a small delay of 10 ms but I can’t manage to make it work no matter how hard I sweat…

As you can see in the code below, for “red LED’s warning of tolbooths” i used the millis() function but i cannot use the millis() function for turning off the marker LEDs of the sensors because I don’t know how much it takes to a cargo-boat to pass from left sensor to right sensor, it could vary from one type of boat to another (30 secs - 2 minutes)…and the examiners might take this into consideration. [ And as i know, the millis() function start counting when the program start running, so, in this case can’t help me much, only in “red LED’s warning of tolbooths” case). ] ← here is my problem.

const int ledPin13 =  13;      // the number of the LED pin
const int ledPin12 =  12;
int ledState13 = LOW;            // ledState used to set the LED
int ledState12 = LOW;
long previousMillis = 0;         // will store last time LED was updated
long previousMillis2 = 0;  
long interval = 700;            
long interval2 = 5000;

//sharp proximity sensor

const int LED_L = 10;      // warning led
const int LED_R = 11;      // warning led
const int Lstate = 2;      // pin 2 - read sensor
const int Rstate = 4;      // pin 4 - read sensor
int var_Lstate = 0;       // reset to zero the variable used to read the state of the OUT pin of the sensor
int var_Rstate = 0;
int read_LED_L = 0;
int read_LED_R = 0;


void setup() 
{
 
  pinMode(ledPin13, OUTPUT);     // set the digital pin as output:
  pinMode(ledPin12, OUTPUT);     // set the digital pin as output:
  
  
  
  //senzor
  
  pinMode (LED_L, OUTPUT);   // left warning led
  pinMode (LED_R, OUTPUT);   // right warning led
  pinMode (Lstate, INPUT);  // sets pin 2 as digital input 
  pinMode (Rstate, INPUT);  // pin 4
  
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  var_Lstate = digitalRead(Lstate);    // reads the status of the left sensor
  var_Rstate = digitalRead(Rstate);    // reads the status of the right sensor
  read_LED_L = digitalRead(10);
  read_LED_R = digitalRead(11);

  
  unsigned long currentMillis = millis();      // check to see if it's time to blink the LED; that is, if the 
                                               // difference between the current time and last time you blinked 
                                               // the LED is bigger than the interval at which you want to 
                                               // blink the LED.
                                               
     if(var_Lstate == LOW)
       digitalWrite (LED_L, HIGH);      // turn on the LED - LEFT
     else
       if(var_Rstate == LOW)
         digitalWrite (LED_R, HIGH);    // turn on the LED - RIGHT
         
         // if sensor L or R is detecting movement (regardless the duration)  start audio and light warning
         if(read_LED_L == HIGH || read_LED_R == HIGH)
             {
               if(currentMillis - previousMillis > interval) 
                {
                        previousMillis = currentMillis;           // save the last time you blinked the LED 
                        if (ledState13 == LOW)                    // if the LED is off turn it on and vice-versa:
                          {
                            ledState13 = HIGH;
                            ledState12 = LOW;
                            tone(8, 2200, 250);
                          }
                          else
                          {
                            ledState13 = LOW;
                            ledState12 = HIGH;
                            tone(8, 1800, 250);
                          }
                    
                   digitalWrite(ledPin13, ledState13);      // set the LED with the ledState of the variable:
                   digitalWrite(ledPin12, ledState12);
                
                
                // TOLBOOTS's MOTORS function for LOWERING - in progress..
                // BRIDGE MOTORS function for lifting it - in progress..
                }
                
              }
              
              
              
              // turning the sensor's LEDs OFF if they're ON on the same time, after a while - HERE IS MY PROBLEM..
      unsigned long currentMillis2 = millis();
               
            
          if(read_LED_L == HIGH && read_LED_R == HIGH)
              {
                
               
                
                
                if(currentMillis2 - previousMillis2 > interval2) 
                {
                        previousMillis2 = currentMillis2;  
                
                 ledState12 = LOW;
                ledState13 = LOW;
                digitalWrite(ledPin13, ledState13);      // set the LED with the ledState of the variable:
                digitalWrite(ledPin12, ledState12);
                noTone(8);  
                
                digitalWrite(LED_L, LOW);
                digitalWrite(LED_R, LOW);
                
                }
                
                
                  
                // BRIDGE MOTORS function for LOWERING - in progress..
                // TOLBOOTS's MOTORS function for LIFT UP - in progress..
              }
            
             
             
             
}

For the micro-servo motors (for both bridge and tollbooths - the difference between bridge and tollboots is only in the matter of choosing the degrees), I tought at:

// bridge
int pos = 20;
void loop
{
while(pos < 81)    
  {
    pos++;        // it goes from 20 -> 80 degrees
    myservo.write(pos);
    delay(70);     // delay between steps of the micro-servo motor
  }
  
  pos2=pos;

 
while(pos2>20)      // it's actually 80
  {
    pos2--;            // lower to 20 degrees
    myservo.write(pos2);
    delay(70);
  }
  
  pos=pos2;

}

I haven’t got the time yet but i wan’t to try the counter here to see if I can replace the delay, if not, maybe the visible delay won’t be so noticed.

Today I tought at using SWITCH-CASE statement and re-do the whole code, maybe in this case I can use delays (implemented in cases…or don’t know… I could really use a more experienced people opinions/advices or help.

I’m sorry for my english if I made some huge mistakes but hopefully after this whole roman-novel of a post someone could help me. :slight_smile:

Delays using millis() is your friend

Don't start an action that will take time to complete, stopping any other code from executing. Instead, start the action that will take time to complete and check periodically whether it is time to take action. Meanwhile, do other things like reading sensors.

Look at the BlinkWithoutDeay example or look at this

//turn on LED on pin 13 if button on pin 8 is pressed
//the button is wired to take the pin LOW when pressed
//It is normally held HIGH by INPUT_PULLUP in its pinMode

byte ledPin = 13;
byte buttonPin = 8;
long timeToStayOn = 4000;
long timeStarted;
byte buttonState;

void setup() 
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() 
{
  buttonState = digitalRead(buttonPin);
  if (buttonState == LOW)
  {
    timeStarted = millis();
    digitalWrite(ledPin, HIGH);
  }
  if (( millis() - timeStarted) > timeToStayOn)
  {
    digitalWrite(ledPin, LOW);       
  }
}

All it does is turn an LED for 4 seconds when a button is pressed, but the crucial thing is that it could do other things inside loop() and still turn the LED off after 4 seconds.

I used this function already once for the tollbooth red LEDs warning. I tryed to used it once more for turning OFF LEDs of the tollbooth and markers with your notations:

long timeToStayOn = 4000;
long timeStarted;

void loop()
{
if(read_LED_L == HIGH && read_LED_R == HIGH)
              {
                  timeStarted = millis();
                    if (( millis() - timeStarted) > timeToStayOn)
                        {
                            ledState12 = LOW;
                            ledState13 = LOW;
                            digitalWrite(ledPin13, ledState13);      // set the LED with the ledState of the variable:
                            digitalWrite(ledPin12, ledState12);
                            noTone(8);  
                            digitalWrite(LED_L, LOW);
                            digitalWrite(LED_R, LOW);
                            
                        }
              }  
}

And guess what, it doesn't work corectly. If both LEDs markers are on, nothing happens....the audio and visual warnings are still running...

                  timeStarted = millis();
                    if (( millis() - timeStarted) > timeToStayOn)

Think about this. If you write down the current time and immediately check the time within microseconds, how can 4 seconds ever pass?

if(read_LED_L == HIGH && read_LED_R == HIGH)
              {
                 
              
                        if (( millis() - timeStarted) > timeToStayOn) 
                            {
                                 timeStarted = millis();
                                //previousMillis2 = currentMillis2;  
                                ledState12 = LOW;
                                ledState13 = LOW;
                                digitalWrite(ledPin13, ledState13);      // set the LED with the ledState of the variable:
                                digitalWrite(ledPin12, ledState12);
                                noTone(8);  
                                digitalWrite(LED_L, LOW);
                                digitalWrite(LED_R, LOW);
                                
                            }

              }

It still doesn't work properly. If "LED_R" & "LED_L" are both ON in the same time during the first 4 seconds after I upload the program, it works, BUT if LED_R is ON during the first 4 seconds, and LED_L is switched ON in the 5th second (or vice-versa), it just reset the whole thing and wait for the other LED to be ON in the next 4 seconds in order to switch OFF the rest of the LEDs.

And as I said, I don't know how much it takes to a cargo-boat to pass from left sensor to right sensor, it could vary from one type of boat to another (30 secs - 2 minutes).

What can I do?

I can upload a video if you need it.

What can I do?

Post your whole code as it is now with an explanation of what it should do.

For instance, where are read_LED_L and read_LED_R coming from ?

You need explain what you're expecting that block of code to do, rather than just say it's not working. You've declared LED_R and LED_L as output pins, presumably to drive an LED, so why are you reading it as if it's an input?

I've explained earlier what the project consists of and what are my expectations:

Once again: My idea for the project: A double leaf bascule bridge system - fully automated, using sensors/micro-servo motors and audio and visual warnings. A GIF to get an idea: http://upload.wikimedia.org/wikipedia/commons/6/60/MovableBridge_draw.gif

What I want it to do: For example, following the next steps:

  • if the left sensor (placed on the left of the bridge at a distance let's say...20cm) detects movement (that means a cargo-boat is aproaching the bridge)
  • then turn ON the left marker LED (LED_L - left sensor) [ and leave it ON]
  • then start the audio ( one mini-speaker set at a specific frequency) and visual warnings on the bridge (2 red LEDs blinking)
  • after 5 more seconds lower the tollbooths,
  • after 5 more seconds lift the bridge leafs and then wait in this position untill the right sensor detects movement
  • when the right sensor detects movement, that means the cargo-boat passed under the bridge and reached the safe distance from the bridge
  • then turn ON the right marker LED (LED_R - left sensor) [ in this moment both LED_R & LED_L are ON ]
  • wait 5 more seconds to be sure, then lower the bridge
  • wait 5 seconds, lift up the tollbooths and shut off the audio and visual warnings (and maybe turn on a green LED as a "safe way to proceed on the bridge" - for the cars)

This is an example of "From left to right passing boat" but from right to left is the same principle.

[ I've used the LED markers to say that.... if(both markers == HIGH) -> turn OFF all warnings - that's why I'm using the LEDs as input and output]

In the code below are some comments also to understand better what it's going on:

const int ledPin13 =  13;      // the number of the LED pin of tollbooth
const int ledPin12 =  12;      // the number of the LED pin of tollbooth
int ledState13 = LOW;            // ledState used to set the LED - for tollbooth
int ledState12 = LOW;            // ledState used to set the LED - for tollbooth
long previousMillis = 0;         // will store last time LED was updated
long interval = 700;            // interval for millis() function used for tolbooth's LED warning (blink 2 leds one OFF/one ON)





//sharp proximity sensor

const int LED_L = 10;      // warning led
const int LED_R = 11;      // warning led
const int Lstate = 2;      // pin 2 - read sensor
const int Rstate = 4;      // pin 4 - read sensor
int var_Lstate = 0;       // reset to zero the variable used to read the state of the OUT pin of the sensor
int var_Rstate = 0;      
int read_LED_L = 0;        // variable for reading the left marker LED of the left sensor
int read_LED_R = 0;        // variable for reading the right marker LED of the right sensor

long timeToStayOn = 4000;
long timeStarted;

void setup() 
{
   Serial.begin(9600);
  pinMode(ledPin13, OUTPUT);     // set the digital pin as output:
  pinMode(ledPin12, OUTPUT);     // set the digital pin as output:
  
  
  
  //senzor
  
  pinMode (LED_L, OUTPUT);   // left warning led of the left sensor
  pinMode (LED_R, OUTPUT);   // right warning led of the right sensor
  pinMode (Lstate, INPUT);  // sets pin 2 as digital input 
  pinMode (Rstate, INPUT);  // pin 4
  
}

void loop()
{
  

  var_Lstate = digitalRead(Lstate);    // reads the status of the left sensor
  var_Rstate = digitalRead(Rstate);    // reads the status of the right sensor
  read_LED_L = digitalRead(10);        // reads the status of the left marker of the left sensor
  read_LED_R = digitalRead(11);        // reads the status of the right marker of the right sensor

  
  unsigned long currentMillis = millis();      // MILLIS USE FOR TOLBOOTH LEDs
                                                // check to see if it's time to blink the LED; that is, if the 
                                               // difference between the current time and last time you blinked 
                                               // the LED is bigger than the interval at which you want to 
                                               // blink the LED.
                                               




     if(var_Lstate == LOW)              // if the left sensor detected movement
       digitalWrite (LED_L, HIGH);      // turn ON the left led of the left sensor 
     else
       if(var_Rstate == LOW)            // if the right sensor detected movement
         digitalWrite (LED_R, HIGH);    // turn ON the right led of the right sensor
         
         // LED_L and LED_R are used as markers to see when the sensors are active, after a sensor is activated (even for a bit, the LED stays ON)
         
         // if one of the markers readings are HIGH, starts the audio (via speakers) and visual (via other leds)  warnings.
         
         if(read_LED_L == HIGH || read_LED_R == HIGH)
             {
               if(currentMillis - previousMillis > interval) 
                {
                        previousMillis = currentMillis;           // save the last time you blinked the LED 
                        if (ledState13 == LOW)                    // if the LED is off turn it on and vice-versa:
                          {
                            ledState13 = HIGH;
                            ledState12 = LOW;
                            tone(8, 2200, 250);
                          }
                          else
                          {
                            ledState13 = LOW;
                            ledState12 = HIGH;
                            tone(8, 1800, 250);
                          }
                    
                   digitalWrite(ledPin13, ledState13);      // set the LED with the ledState of the variable:
                   digitalWrite(ledPin12, ledState12);
                
                
                // TOLLBOOTS's MOTORS code for LOWERING - in progress..
                // BRIDGE MOTORS code for lifting it - in progress..
                }
                
              }
              
              
              
              
              
              // turning the sensor's LEDs OFF (aka the markers: LED_R & LED_L) if they're ON on the same time, after a while - HERE IS MY PROBLEM..
      
              // it doesn't work properly
              // If "LED_R" & "LED_L" are both ON in the same time during the first 4 seconds after I upload the program, it works, 
              //BUT
              //if LED_R is ON during the first 4 seconds, and LED_L is switched ON in the 5th second (or vice-versa), 
              //it just reset the whole thing and wait for the other LED to be ON in the next 4 seconds in order to switch OFF the rest of the LEDs.
            
          if(read_LED_L == HIGH && read_LED_R == HIGH)
              {
                 
              
                        if (( millis() - timeStarted) > timeToStayOn) 
                            {
                                 timeStarted = millis();
                                //previousMillis2 = currentMillis2;  
                                ledState12 = LOW;
                                ledState13 = LOW;
                                digitalWrite(ledPin13, ledState13);      // set the LED with the ledState of the variable:
                                digitalWrite(ledPin12, ledState12);
                                noTone(8);  
                                digitalWrite(LED_L, LOW);
                                digitalWrite(LED_R, LOW);
                                
                            }

              }
                  
                // BRIDGE MOTORS function for LOWERING - in progress..
                // TOLBOOTS's MOTORS function for LIFT UP - in progress..
              
            
           
             
             
}

I've added a video, below, of how it's working now.I've explained in the video, how it should work and what's not working as it should.

Video: http://www.filebox.com/hle6w03lsiu8

What you're looking for should be doable with a state machine broken up as such:

SparksInside: - if the left sensor (placed on the left of the bridge at a distance let's say...20cm) detects movement (that means a cargo-boat is aproaching the bridge) - then turn ON the left marker LED (LED_L - left sensor) [ and leave it ON]

Start in an IDLE state. The only thing that needs to take place during the IDLE state is a reading of the left sensor. When tripped, you record the current time, turn the LED_L on, and move to the next state

  • then wait 5 seconds, start the audio ( one mini-speaker set at a specific frequency) and visual warnings on the bridge (2 red LEDs blinking)

In this state, you keep checking if it's been 5 seconds since you last recorded the time. When that is reached, record the currentTime again (for the next state), start the audio, and set some sort of flag that tells the LEDs to blink. The blink code should be done outside of the state logic, something like this:

void loop()
{

 if ( blink flag is set and the blink interval is reached)
 {
    blink the LED
  }

  switch (state)
  {
    case 1: ...
    case 2: ...
    case 3: ...
    ...
  }
}
  • after 5 more seconds lower the tollbooths,

Same thing as last state, check for the elapsed 5 seconds. Once you hit it, record the new time, lower the tollbooth and move to the next state.

  • after 5 more seconds lift the bridge leafs and then wait in this position untill the right sensor detects movement

Again, check for the elapsed 5 seconds. Once you reach it, lift the bridge and move into the next state.

  • when the right sensor detects movement, that means the cargo-boat passed under the bridge and reached the safe distance from the bridge
  • then turn ON the right marker LED (LED_R - left sensor) [ in this moment both LED_R & LED_L are ON ]

In this state, you are just checking for the the right sensor to be tripped. When that happens, turn on the LED_R, record the current time and move to the next state.

  • wait 5 more seconds to be sure, then lower the bridge

After 5 elapsed seconds, lower bridge, record time and move into the next state.

  • wait 5 seconds, lift up the tollbooths and shut off the audio and visual warnings (and maybe turn on a green LED as a "safe way to proceed on the bridge" - for the cars)

After 5 elapsed seconds, finish up and move back to the idle state.

Start small. Write the code for the first state. Test and make sure it works. Write the code for the second state. Test and make sure it works, etc.

You could probably break up all the states into their own function to make it easier to read. You would just need to make the state variable and the record time variables global. This is a simple shell for a state machine:

int state = 0; // start in state 0 (idle)

void loop()
{
  switch (state)
  {
    case 0: 
      stateZero();
      break;
    case 1: 
      stateOne();
      break;
    case 2: 
      stateTwo();
      break;
  }
}

Okay, thank you.

I will start all over again and use SWITCH-CASE statement.

I'll come back after this weekend with the code and if I'll stumble upon other problems.