Blinking LED at specefic hz

Hello, I am trying to be able to blink LEDs at specific hz and the program is working when using lower hz like, 10, 100 and 300 hz. The problem starts when I want up on higher hz. For example if i place 10, 100 and 300 it displays
10 in arduino = 9,98 hz on multimeter, thats fine, close...
100 = 99.77 hz also ok.
300 = 298.2 hz. It is also ok.

Problem starts here...
1000 in arduino is = 975

3000 in arduino is = 2841 hz. Thats to much drop!

also 5000 hz in arduino is = 4633 hz, also way to much drop.

What is wrong here? Cannot really find a solution...

Thanks!

#define PUSHED            LOW

#define LEDon             HIGH
#define LEDoff            LOW

#define firstFrequency     1000// Hz
#define secondFrequency    3000// Hz
#define thirdFrequency     100000// HZ

//***********************************************************************
//Switch connection
//+5V---[internal pullup resistor]---[input]---[switch]---GND(0V)
const byte startSwitch  = 2;

const byte LEDpin       = 10;  //[output pin]---[LED >|]---[220R]---GND/0V
const byte onIndicationLED = 7;

byte currentState;
byte lastStartState;
byte lastStopState;
byte frequencyCounter;

bool flashFlag          = false;

//timing stuff
unsigned long onIndicationMillis;
unsigned long switchMillis;
unsigned long xMillis;
unsigned long flashMircos;

//const unsigned long xMinutes = 10 * 60 * 1000ul;  //10 minutes
const unsigned long xMinutes   = 4 * 1000ul;        //for testing use only 4 seconds

const unsigned long timeOne   = 1000000ul / (firstFrequency  * 2);
const unsigned long timeTwo   = 1000000ul / (secondFrequency * 2);
const unsigned long timeThree = 1000000ul / (thirdFrequency  * 2);

unsigned long interval;

//***********************************************************************
void setup()
{
  pinMode(onIndicationLED, OUTPUT);
  pinMode(LEDpin, OUTPUT);
  
  pinMode(startSwitch, INPUT_PULLUP); //pushed/closed = LOW

  interval = timeOne;

} //END of setup()

//***********************************************************************
void loop()
{
  //**************************
  //onIndicationLED will toggle as long as the sketch is non blocking and the arduino is on
  //if (millis() - onIndicationMillis >= 1)
  {
    //restart timer
    //onIndicationMillis = millis();

    //toggle LED
    //digitalWrite(onIndicationLED , !digitalRead(onIndicationLED));

  }

  //**************************
  //check the switches every 50ms
  //time to check our switches ?
  if (millis() - switchMillis >= 50)
  {
    //restart timer
    switchMillis = millis();

    checkSwitches();

  }

  //**************************
  //is flashing enabled ?
  if (flashFlag == true)
  {
    //*************
    //flashing timer
    //is it time to toggle the LED ?
    if (micros() - flashMircos >= interval)
    {
      //restart timer
      flashMircos = micros();

      //toggle LED
      digitalWrite(LEDpin, !digitalRead(LEDpin));
      digitalWrite(onIndicationLED, HIGH);
    }

    //**************
    //X minute timer
    //has X minutes expired ?
    if (millis() - xMillis >= xMinutes)
    {
      //restart the timer
      xMillis = millis();

      //next frequency
      frequencyCounter++;

      //**************
      if (frequencyCounter == 1)
      {
        interval = timeTwo;
      }

      //**************
      else if (frequencyCounter == 2)
      {
        interval = timeThree;
      }

      //**************
      else if (frequencyCounter > 2)
      {
        //disable flashing
        flashFlag = false;

        //turn LED OFF
        digitalWrite(LEDpin, LEDoff);
        digitalWrite(onIndicationLED, LEDoff);
      }
    }

  } //END of if (flashFlag == true)

  //**************************

} //END of loop()



void checkSwitches()
{
  //**************************
  //Start switch
  currentState = digitalRead(startSwitch);

  //has the switch changed state ?
  if (lastStartState != currentState)
  {
    //update to the new state
    lastStartState = currentState;

    //when we 'are not' flashing, was the switch just pushed/closed ?
    if (flashFlag == false && currentState == PUSHED)
    {
      //start the x timer
      xMillis = millis();

      //initalize frequency counter
      frequencyCounter = 0;

      //select the flash frequency
      interval = timeOne;

      //start the flashing timer
      flashMircos = micros();

      //enable flashing
      flashFlag = true;
    }

    else if (flashFlag == true && currentState == PUSHED)
    {
      //disable flashing
      flashFlag = false;

      //turn LED OFF
      digitalWrite(LEDpin, LEDoff);
      digitalWrite(onIndicationLED, LEDoff);
    }
  }
}

If you want a more accurate result, you should use Timer1. You should also mind that the oscillator/crystal is sensitive to temperatures, so the clock may not be 100% accurate.

Danois90:
If you want a more accurate result, you should use Timer1. You should also mind that the oscillator/crystal is sensitive to temperatures, so the clock may not be 100% accurate.

Will check! Thanks!

What model of Arduino are you using?

    if (micros() - flashMircos >= interval)
    {      //restart timer
      flashMircos = micros();

This is going to lose microseconds if (micros() - flashMircos) is greater than 'interval' or if 'micros()' counts between the first call and the second call.

This should be more consistent:

    if (micros() - flashMircos >= interval)
    {      //restart timer
      flashMircos = flashMircos + interval;

#define thirdFrequency 100000// HZ

100000? Really, anything above 30 Hz will just appear to be 50% on.
What is the purpose of these fast blinking LEDs?

I did a program a while ago to make a "piano", but really more like an early keyboard/organ sound, with up to 13 notes from 13 buttons (using a '1284P with 32 IO available).
https://forum.arduino.cc/index.php?topic=179761.0
Take a look at how I used arrays there and capturing micros() once every pass thru loop to decide whether to turn a note high or low when it's button is pressed. Your program seems to capture & recapture the time a lot, so the base time reference is kind of drifting, if you will.

Do you really need to turn on the indicator LED thousands of times?

      //toggle LED
      digitalWrite(LEDpin, !digitalRead(LEDpin));
      digitalWrite(onIndicationLED, HIGH);

This modification of your code uses Timer1 to do the flash timing:

#define PUSHED            LOW

#define LEDon             HIGH
#define LEDoff            LOW

//***********************************************************************
//Switch connection
//+5V---[internal pullup resistor]---[input]---[switch]---GND(0V)
const byte startSwitch  = 2;

const byte onIndicationLED = 7;
const byte LEDpin       = 10;  //[output pin]---[LED >|]---[220R]---GND/0V

byte frequencyCounter;
bool flashFlag          = false;
uint8_t lastStartState;

//timing stuff
unsigned long xMillis;
uint32_t switchMillis;

const uint16_t
    c_grBlinkPeriod[] = 
    {
        16000u,         //16000 x 62.5nS = 1mS --> 1kHz
        5333u,          //5333 x 62.5nS = 333.3125uS -->3000.19Hz
        160u            //160 x 62.5nS == 10uS --> 100kHz
        
    };

const unsigned long xMinutes   = 4 * 1000ul;        //for testing use only 4 seconds

//***********************************************************************
void setup()
{
    pinMode(onIndicationLED, OUTPUT);
    pinMode(startSwitch, INPUT_PULLUP); //pushed/closed = LOW
    lastStartState = digitalRead( startSwitch );
    
    pinMode(LEDpin, OUTPUT);
    digitalWrite( LEDpin, LEDoff );

    //init WGM15 with prescaler of /1
    //pin 10 is disconnected from timer
    TCCR1A = _BV(WGM11) | _BV(WGM10);
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);      
    OCR1A = 0;
    OCR1B = 0;

} //END of setup()

//***********************************************************************
void loop()
{
    //**************************
    //check the switches every 50ms
    //time to check our switches ?
    if (millis() - switchMillis >= 50)
    {        
        switchMillis = millis();        //restart timer
        checkSwitches();
    
    }//if

    //**************************
    //is flashing enabled ?
    if (flashFlag == true)
    {
        //**************
        //X minute timer
        //has X minutes expired ?
        if (millis() - xMillis >= xMinutes)
        {
            //restart the timer
            xMillis = millis();

            //next frequency
            frequencyCounter++;
            if( frequencyCounter > 2 )
            {
                //disable flashing
                flashFlag = false;

                //turn LED OFF
                TCCR1A &= ~_BV(COM1B1);
                digitalWrite(onIndicationLED, LEDoff);                
                
            }//if
            else
            {
                TCCR1A &= ~_BV(COM1B1);
                OCR1A = c_grBlinkPeriod[frequencyCounter];
                OCR1B = c_grBlinkPeriod[frequencyCounter] >> 1;
                TCCR1A |= _BV(COM1B1);
                
            }//else
            
        }//if

    } //END of if (flashFlag == true)

} //END of loop()



void checkSwitches()
{
    //**************************
    //Start switch
    uint8_t currentState = digitalRead(startSwitch);

    //has the switch changed state ?
    if (lastStartState != currentState)
    {
        //update to the new state
        lastStartState = currentState;

        //when we 'are not' flashing, was the switch just pushed/closed ?
        if (flashFlag == false && currentState == PUSHED)
        {
            frequencyCounter = 0;
            OCR1A = c_grBlinkPeriod[frequencyCounter];
            OCR1B = c_grBlinkPeriod[frequencyCounter] >> 1;
            TCCR1A |= _BV(COM1B1);

            digitalWrite(onIndicationLED, LEDon);
            
            //start the x timer
            xMillis = millis();
            //enable flashing
            flashFlag = true;
            
        }//if
        else if (flashFlag == true && currentState == PUSHED)
        {
            //disable flashing
            flashFlag = false;
            //turn LED OFF
            TCCR1A &= ~_BV(COM1B1);
            digitalWrite(onIndicationLED, LEDoff);
            
        }//else
        
    }//if
    
}//checkSwitches

Tested on an Uno.

Blackfin:
What model of Arduino are you using?

Arduino UNO! But will use it in a standalone atmega328p circuit!

Blackfin:
This modification of your code uses Timer1 to do the flash timing:

#define PUSHED            LOW

#define LEDon             HIGH
#define LEDoff            LOW

//***********************************************************************
//Switch connection
//+5V---[internal pullup resistor]---[input]---[switch]---GND(0V)
const byte startSwitch  = 2;

const byte onIndicationLED = 7;
const byte LEDpin       = 10;  //[output pin]---[LED >|]---[220R]---GND/0V

byte frequencyCounter;
bool flashFlag          = false;
uint8_t lastStartState;

//timing stuff
unsigned long xMillis;
uint32_t switchMillis;

const uint16_t
   c_grBlinkPeriod[] =
   {
       16000u,         //16000 x 62.5nS = 1mS --> 1kHz
       5333u,          //5333 x 62.5nS = 333.3125uS -->3000.19Hz
       160u            //160 x 62.5nS == 10uS --> 100kHz
       
   };

const unsigned long xMinutes   = 4 * 1000ul;        //for testing use only 4 seconds

//***********************************************************************
void setup()
{
   pinMode(onIndicationLED, OUTPUT);
   pinMode(startSwitch, INPUT_PULLUP); //pushed/closed = LOW
   lastStartState = digitalRead( startSwitch );
   
   pinMode(LEDpin, OUTPUT);
   digitalWrite( LEDpin, LEDoff );

//init WGM15 with prescaler of /1
   //pin 10 is disconnected from timer
   TCCR1A = _BV(WGM11) | _BV(WGM10);
   TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);      
   OCR1A = 0;
   OCR1B = 0;

} //END of setup()

//***********************************************************************
void loop()
{
   //**************************
   //check the switches every 50ms
   //time to check our switches ?
   if (millis() - switchMillis >= 50)
   {        
       switchMillis = millis();        //restart timer
       checkSwitches();
   
   }//if

//**************************
   //is flashing enabled ?
   if (flashFlag == true)
   {
       //**************
       //X minute timer
       //has X minutes expired ?
       if (millis() - xMillis >= xMinutes)
       {
           //restart the timer
           xMillis = millis();

//next frequency
           frequencyCounter++;
           if( frequencyCounter > 2 )
           {
               //disable flashing
               flashFlag = false;

//turn LED OFF
               TCCR1A &= ~_BV(COM1B1);
               digitalWrite(onIndicationLED, LEDoff);                
               
           }//if
           else
           {
               TCCR1A &= ~_BV(COM1B1);
               OCR1A = c_grBlinkPeriod[frequencyCounter];
               OCR1B = c_grBlinkPeriod[frequencyCounter] >> 1;
               TCCR1A |= _BV(COM1B1);
               
           }//else
           
       }//if

} //END of if (flashFlag == true)

} //END of loop()

void checkSwitches()
{
   //**************************
   //Start switch
   uint8_t currentState = digitalRead(startSwitch);

//has the switch changed state ?
   if (lastStartState != currentState)
   {
       //update to the new state
       lastStartState = currentState;

//when we 'are not' flashing, was the switch just pushed/closed ?
       if (flashFlag == false && currentState == PUSHED)
       {
           frequencyCounter = 0;
           OCR1A = c_grBlinkPeriod[frequencyCounter];
           OCR1B = c_grBlinkPeriod[frequencyCounter] >> 1;
           TCCR1A |= _BV(COM1B1);

digitalWrite(onIndicationLED, LEDon);
           
           //start the x timer
           xMillis = millis();
           //enable flashing
           flashFlag = true;
           
       }//if
       else if (flashFlag == true && currentState == PUSHED)
       {
           //disable flashing
           flashFlag = false;
           //turn LED OFF
           TCCR1A &= ~_BV(COM1B1);
           digitalWrite(onIndicationLED, LEDoff);
           
       }//else
       
   }//if
   
}//checkSwitches




Tested on an Uno.

Big thanks! Works much better! How do I know what (u) to get the hz I want? and what is 62.5 nS?

 16000u,         //16000 x 62.5nS = 1mS --> 1kHz
        5333u,          //5333 x 62.5nS = 333.3125uS -->3000.19Hz
        160u            //160 x 62.5nS == 10uS --> 100kHz

62.5nS is the period of the 16 MHz system clock, 1/16000000.

There are 64 system clocks for each 4 microseconds, which I believe is the fastest you can time things.
(0.000004/(1/16000000))

Multiples of 4uS is the best timing control I could come up with. Might need to use 4 or 8 less than the math might indicate to account for loop() and other code doing its thing.

CrossRoads:
62.5nS is the period of the 16 MHz system clock, 1/16000000.

There are 64 system clocks for each 4 microseconds, which I believe is the fastest you can time things.
(0.000004/(1/16000000))

Multiples of 4uS is the best timing control I could come up with. Might need to use 4 or 8 less than the math might indicate to account for loop() and other code doing its thing.

Interesting! So how do I know what "u" I should put in to get the wanted hz?
for example

16000u,         //16000 x 62.5nS = 1mS --> 1kHz

How can I know that it is 16000u I need to put in to get 1khz? I might be lost there...

Period of 1000 Hz =1/1000 = .001second = 1millisecond = 1000microsecond
That's the time from rising edge to rising edge

|-----|__|-----
So you want 1/2 of that, 500uS, for each half period.

If you wanted a bunch of outputs that you have the code control without having the code create the outputs, you could use a SX1509, which has 16 PWM output. You send an I2C command to update each output with the frequency you want.

Outputs are 3.3V, buffer them with SN74ACT241N (N for DIP) if you wanted 5V outputs.

Sparkfun has a simple library to drive it with.
After the set up part, this is all you need to change the outputs:

    // Set up the SX1509's clock to use the internal 2MHz
    // oscillator. The second parameter divides the oscillator
    // clock to generate a slower LED clock. 4 divides the 2MHz
    // clock by 2 ^ (4-1) (8, ie. 250kHz). The divider parameter
    // can be anywhere between 1-7.
    io.clock(INTERNAL_CLOCK_2MHZ, 4);

    // Initialize every pin to output
    for ( byte i = 0; i < 16; i++ )
    {
      io.pinMode( i, OUTPUT );
      io.ledDriverInit( i );
      io.analogWrite( i, 127 );
    }

This code turned on every output at 50% duty cycle. I don't know if it would do the exact frequencies you are after.

CrossRoads:
Period of 1000 Hz =1/1000 = .001second = 1millisecond = 1000microsecond
That's the time from rising edge to rising edge

|-----|__|-----
So you want 1/2 of that, 500uS, for each half period.

If you wanted a bunch of outputs that you have the code control without having the code create the outputs, you could use a SX1509, which has 16 PWM output. You send an I2C command to update each output with the frequency you want.
SparkFun 16 Output I/O Expander Breakout - SX1509 - BOB-13601 - SparkFun Electronics
Outputs are 3.3V, buffer them with SN74ACT241N (N for DIP) if you wanted 5V outputs.

Sparkfun has a simple library to drive it with.
After the set up part, this is all you need to change the outputs:

    // Set up the SX1509's clock to use the internal 2MHz

// oscillator. The second parameter divides the oscillator
   // clock to generate a slower LED clock. 4 divides the 2MHz
   // clock by 2 ^ (4-1) (8, ie. 250kHz). The divider parameter
   // can be anywhere between 1-7.
   io.clock(INTERNAL_CLOCK_2MHZ, 4);

// Initialize every pin to output
   for ( byte i = 0; i < 16; i++ )
   {
     io.pinMode( i, OUTPUT );
     io.ledDriverInit( i );
     io.analogWrite( i, 127 );
   }



This code turned on every output at 50% duty cycle. I don't know if it would do the exact frequencies you are after.

Hm okey. Still not with you on how you calculating that 16000u = 1kHz
let's say I need 150HZ what do I need to do to know the "u" to get that?
I only need one output so I am happy with the atmega328p atm but thanks for the link!

void setup(){
previousTime = micros();
}
void loop(){
currentTime = micros(); // capture the current 'time'
elapsedTime = currentTime - previousTime; // how much has passed since the previous time was stored?
  if (elapsedTime >= 500){ // half a period has passed (for 1000 Hz), toggle the outout
  // reset time for the next pass
  previousTime = currentTime;
  // change output, say you are using D2:
  PIND = 0b00000100; // toggle output D2, see 14.2.2 of the 328P datasheet
  }
// do other stuff, that ideally takes < 500uS
}

All time related variables are declared as type unsigned long.

maker-20_:
Hm okey. Still not with you on how you calculating that 16000u = 1kHz

Timer 1 is set to tick up at a rate of 16MHz. Each tick of a 16MHz clock takes 62.5 nanoseconds. To find the number of Timer 1 ticks in one millisecond, take 0.001 (that is, 0.001-sec or 1mS) and divide by 62.5nS:

0.001 / 0.0000000625 == 16000.

let's say I need 150HZ what do I need to do to know the "u" to get that?

The period of a 150Hz signal is 1/150 or 0.0066667-seconds.

0.00666667 / 62.5E-09 = 106666.67.

Now, that won't work. The largest value the 16-bit timer output compare registers can hold is 65535 (0xFFFF) and 106666.67 > 65535.

To fix that you might slow the clock down by changing the prescaler to, say, /8:

At /8, the timer ticks at 2MHz or 500nS/tick.

0.00666667 / 500E-09 = 13333.3. If you run at 2MHz, you could program 13333 as you OC1A value (and 6667 or 13333/2 as your OC1B value) to give 150.00375Hz.

If you need the accuracy given by the higher clock rate then you need to start counting timer 1 overflows and using >16-bit math to know when to set the output compares.

Does that make sense?

I only need one output so I am happy with the atmega328p atm but thanks for the link!
[/quote]

It is clearer! But if I now need the for example 150 HZ and you said that I need to slower down the clock then to /8. Where do I do it and is it going up when I do a higher hz in the next one or?...
I must say, I have never used it like this before!

maker-20_:
It is clearer! But if I now need the for example 150 HZ and you said that I need to slower down the clock then to /8. Where do I do it and is it going up when I do a higher hz in the next one or?...
I must say, I have never used it like this before!

What are your complete timing requirements? You originally had 1kHz, 3kHz and 100kHz. Now you want 150Hz. Do those original ones remain? What other frequencies may you need?

Blackfin:
What are your complete timing requirements? You originally had 1kHz, 3kHz and 100kHz. Now you want 150Hz. Do those original ones remain? What other frequencies may you need?

I got it now! I am going to need many diffrent frequencies therfore I wanted to know how to calculate it so that I do not have to ask whenever I need to change... :wink: I have just tried my own freq and it displaying way better now! Thank you man!

It will be simple if you use the ezOutput library. It supports blink without delay and allow to set/change frequency. You can convert the frequency to LOW/HIGH time in a cycle and then use the blink function. for example.
led.blink(200, 200); // 200 milliseconds HIGH, 200 milliseconds LOW