Processor Frquency

I am writing a basic sketch to turn a pump on for X amount of time and turn if off again after 3X time.

I tried the TimerAlarms.h route, I tried the mills rout and finally came up with something a lot simpler...so I thought.

Simply create own variable and increase it the same ways as mills increases in the back ground just now at the frequency of the processor (16MHz) and basically once the flag has reached 1 time the frequency of the processor it should be 1 second (Relay turns off) and 3 times the frequency should be 3 seconds (Flag clears) and the cycle can start again.

But it does notwork like that..The LED(Relay) flashes at a rate that is almost just a fade.

What am I missing. Surely if the processor speed is 16 000 000 Hz it will process the "Loop" function 16 000 000 times per second?

long Flag = 0; // Variable I am going to monitor to know when to switch pump on and off
const int Increment = 1; // inrement by which I will inrease the FLAG value
const int TurnON = 10; // Time to turn pump ON
long TurnOFF = 16000010; // Turn pump OFF
long ClearFlag = 48000010; // Zero Flag and start counting again
const byte ledPin = 13; // using the built in LED to simulate RELAY for Pump

void setup()
{
Serial.begin(9600); // start Serial in case we need to print debugging info
pinMode(ledPin, OUTPUT); // Declaring Pin 13 as an OUTPUT
//digitalWrite(ledPin, LOW); // Start the pump at the beginning of the program
}

void loop()
{
Flag = (Flag + Increment);
Serial.print("*****Starting the Loop again ");
Serial.println(Flag);

if (Flag = TurnON) // Test if Relay must be turned ON
{
digitalWrite(ledPin, HIGH); // If Flag = 10 turn the LED ON//
Serial.print("Pump is ON: ");
Serial.println(Flag);
}

if (Flag = TurnOFF) // Test if flag has reached TurnOff value
{
digitalWrite(ledPin, LOW); // Turn Relay OFF
Serial.print("Pump is OFF: ");
Serial.println(Flag);
}

if (Flag = ClearFlag) // Test whether Flag must be Reset
{
Flag = 0;
Serial.print("Flag Rest to: ");
Serial.println(Flag);
}
}

HermanJFourie:
Surely if the processor speed is 16 000 000 Hz it will process the "Loop" function 16 000 000 times per second?

Neglecting for the moment that totally incorrect assumption, how can you possibly believe your technique is "simpler" than using millis()?

That is why I asked the question.

Please enlighten me. what does the processor frequency then mean? How many times does it process the loop in one second?

My problem with the mills is I can not find or grasp how to get the loop to repeat. I can not reset mills to 0. It just keeps on increasing until the LONG variable type is full.

The processor's basic clock frequency is 16 MHz. Each machine instruction requires one or more clock cycles. Each line of C++ code requires one or more machine instructions. Add to that the overhead required to repeatedly call loop() from the (hidden) main() function and any interrupt-driven activity going on in the background (like updates to the millis value). Finally, there's the actually length of the loop() function itself.

So, you really can't tell how many cycles through loop you'll get every second. But, you can be sure that the update rate of the value returned by millis() will be stable and relatively accurate. You don't have to "reset" millis(). You simply increase the activation time of your even an appropriate amount into the future. See Using millis() for timing. A beginners guide

. I can not reset mills to 0. It just keeps on increasing until the LONG variable type is full

You dont reset a timer by restarting the clock, you just reset the time the timer starts.

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) 
{
    previousMillis = currentMillis; // THIS LINE RESETS THE TIMER <<<<<<<<<<<<<<<<<<<<<<<<<<<

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);

The blink without delay example(above) resets every time the timer expires.
if you want to only start the timer when a event occurs(such as a button press)
move this line into a conditional statement.

 previousMillis = currentMillis; // THIS LINE RESETS THE TIMER <<<<<<<<<<<<<<<<<<<<<<<<<<<

E.G.

if(digitalRead(button) == LOW) // LOW == button pressed
{
    previousMillis = currentMillis; // THIS LINE RESETS THE TIMER <<<<<<<<<<<<<<<<<<<<<<<<<<<
}

 unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) 
{
    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);

Appreciated..Now I understand...the mills logic. :grin:

Still fail to understand why my code does not want to work even if I set my timer flags to multiples of 16MHz. From the explanation it can only go slower, never faster. :roll_eyes: so to do the loop 16000000 times should take 1 second or a little more based on the factors mentioned?

HermanJFourie:
Still fail to understand why my code does not want to work even if I set my timer flags to multiples of 16MHz. From the explanation it can only go slower, never faster. :roll_eyes: so to do the loop 16000000 times should take 1 second or a little more based on the factors mentioned?

At the very least, part of you problem would be because this part of your code:

HermanJFourie:
if (Flag = TurnON) // Test if Relay must be turned ON
(snip)

looks very different to this code:

Hutkikz:
if(digitalRead(button) == LOW) // LOW == button pressed
(snip)

digitalWrite() is surprisingly slow - it's doing a bunch of work to convert the arduino pin number to the port and bit within that port that corresponds to the pin. I forget if it was 50-ish clock cycles of 150-ish - it was one of those. Can of course be done much faster using direct port manipulation, but still

A comparison takes several - it has to copy both things to be compared to a register, compare them, then repeat for each byte if it's a multi-byte variable... Same goes for math - and don't forget that a 32-bit integer needs to be handled in multiple steps because this is an 8-bit processor. Division is particularly slow since it's a software implementation of division (AVRs don't have hardware division)....

Even an empty loop (eg while(1){} takes IIRC 4 clock cycles per iteration.

Add all that up, and your loop is taking hundreds or thousands of clock cycles per iteration - plus there are ISRs firing in the background for millis(), which interrupt loop to run the ISR, and then return to it.

And it will take a different length of time with different versions of Arduino if the compiler is different, because it will perform different optimization, too.

Bottom line, write your loop() to run fast, but never depend on the exact time that loop() takes to run - you don't know the exact time it will take to run, and it won't even be the same amount of time every pass through loop because of the millis interrupt (which may or may not happen during a given iteration of loop) and different code path taken due to conditionals (for example, if you do something only if a condition is true, if that condition is true and it has to do something, that pass through loop will take longer).

And all those serial.print statements. 9600 baud sends just under 1 byte per millisecond. There's a 64 character buffer, with an interrupt that fires after a character finishes sending to get the next character (this takes non-zero time). But once that 64-character buffer fills up (as it will almost immediately with the code you posted), serial.print() becomes extremely slow, because it sits there waiting until there's enough space in the buffer to fit the string you're trying to print - so after a couple of runs through loop, each run is spending most of it's time sitting there waiting for serial data to send, and taking tens of milliseconds per loop.

HermanJFourie:
Appreciated..Now I understand...the mills logic. :grin:

Still fail to understand why my code does not want to work even if I set my timer flags to multiples of 16MHz. From the explanation it can only go slower, never faster. :roll_eyes: so to do the loop 16000000 times should take 1 second or a little more based on the factors mentioned?

Very basic:
You'd be right if 1+1 took only one clock cycle but it does not.

A 1 is stored somewhere in RAM, that 1 has to be reterived from ram, which takes clock cycles. What to do with that one is +. To do that instruction, which takes clock cycles, there needs to be another number, which has to be retrieved from ram. More clock cycles. Now we need someplace to do the math, a register, and there is a requirement to move that 1 into the register. More clock cycles. Then doing the addition with the other one, in the register, takes more clock cycles. Then moving the answer into RAM, takes clock cycles. After, the operation has been done, you have lost a few of the 16 Million clock ticks to a operation. Do another operation, more clock cycles are consumed.

@OP

**A:**Let us make the following few simple propositions, and based on these we try to bring modifications in your original program in order to make it work.

1. The pump will become ON (simulated by the built-in L of UNO) after 5-sec from the the execution point of the program (at the end of uploading).

2. The pump will become OFF after the exhaust of next 10-sec time. (It means that the total elapsed time from the execution point of the program is 15-sec.)

3. The pump will remain OFF for the next 15-sec. (It means that the total elapsed time from the execution point of the program is 30-sec.)

4. The ON/OFF cycle of the Pump/L will repeat (10-sec ON and 15-sec OFF).

B: The above timing slots could be generated using various techniques like the use delay() function, millis() function, TCX-based function; however, you want to generate the evnts/timeing functions of Section-A using the basic operating clock (16 MHz) of the MCU in collaboration with loop() function. It is interesting from academic point of view.

C: (1) Let us estimate the time that the MCU spends to go around the loop() function only for once.

void loop()
{

}

The above loop() space can be approximated as:

void loop()
{
   L1: goto L1;
}

OR

void loop()
{
    L1: rjmp L1    //ASM code which will not be compiled here but is shown at conceptual level
}

(2) The time required to make one pass around the loop() function is 2 cycles (0.125*10-6 sec).

(3) In 1-sec time, the MCU will make 8000000 (1/0.000000125) passes in the loop(0 function. However if we add instructions (which we have to do) withing loop() function, the counts will be much less than 8000000.

(4) Let us design program based on data of Step-C2 and test it. (tested in UNO.)

unsigned long myCounter = 0;
bool flag1 = LOW;
bool flag2 = LOW;
bool flag3 = LOW;

void setup()
{
  Serial.begin(9600);             // start Serial in case we need to print debugging info
  pinMode(13, OUTPUT);        // Declaring Pin 13 as an OUTPUT
  digitalWrite(13, LOW);      // Start the pump at the beginning of the program
}

void loop()
{
  myCounter++;
  //Serial.println(myCounter, DEC);
  if (flag3 == LOW)
  {

    if (flag2 == LOW)
    {
      if (flag1 == LOW)
      {
        if (myCounter == 5 * 500000) //take 500000 and not 8000000 for 1-sec (test purpos)
        {
          myCounter = 0;
          digitalWrite(13, HIGH);
          flag1 = HIGH;   //L is ON
          flag2 = HIGH;   //to count next 10-sec
        }
      }
    }
    else
    {
      if (myCounter == 10 * 500000) //10-sec delay for L ON
      {
        myCounter = 0;
        digitalWrite(13, LOW);
        flag2 = LOW;          //10-sec ON-period has gone
        flag3 = HIGH;         //falg3 will control 15-sec OFF-period
      }
    }
  }
  else
  {
    if (myCounter == 15 * 500000) //15-sec delay for L ON
    {
      myCounter = 0;
      digitalWrite(13, HIGH);
      flag1 = LOW;          //reset
      flag2 = LOW;          //reset
      flag3 = LOW;         //reset
    }
  }
}