Is the eye able to see flashes at 30kHz?

I'm trying to test out a IR receiver and determine what frequency works best. I tried this code and determined that it was an IR transistor. But something was making me think... I was seeing the LED flash (I was testing it using a regular red LED) up to 37kHz. As I understand it, our eyes are not capable of seeing things flash beyond 60Hz or 100Hz due to persistence of vision. This makes me think that I am doing something wrong in my code. Here it is:

#include<TimerOne.h>

template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; }
static char const endl = '\n';

static int const inputPin = 0;
static int const outputPin = 10;

long inc = 500;
unsigned long freq = 30e3;  // 30kHz
void setup()
{
  analogReference(EXTERNAL);
  pinMode(outputPin, OUTPUT);
  Timer1.initialize(1e9/freq/2); // /2 because each interrupt is to toggle LED, doubling the frequency to call interrupt.
  Timer1.attachInterrupt(callback);
  Serial.begin(9600);
  Serial << "Freq = " << freq << "Hz - Period = " << 1e9/freq << "us" << endl;
}

int ledStatus = 0;
void callback()
{
  digitalWrite(outputPin, ledStatus = !ledStatus);
}

void loop()
{
  //delay(1000);
  if (freq > 56e3)
  {
    inc = -500;
  }
  else if (freq < 30e3)
  {
    inc = +500;
  }
  freq += inc; // increase by 0.5kHz
  
  Timer1.setPeriod(1e9/freq/2);
  analogRead(inputPin); // this extra is because I found elsewhere that the first read may not work properly
  long x = 0;
  for (int i = 0; i < 10000; ++i)
  {
    x += analogRead(inputPin);
  }
  Serial << "Freq = " << freq << "Hz - Period = " << 1e9/freq << "us" << " - " << x/10000 << endl;
}

It uses the TimerOne library I got here: Arduino Playground - HomePage

Can someone confirm that I'm doing this right or tell me if a flicker can be seen up to 37kHz?

Thanks,

Adrian

It is your persistence of vision that allows you to see it. I've run the D13 led about as fast as this thing will run it, and I still see the led lit abut half bright. A television runs your eyeballs about as fast as they can work. Remember, an analog tv is just one little tiny spot moving across the screen in a hurry.

Nothing to do with your LED flashing, but:

  analogRead(inputPin); // this extra is because I found elsewhere that the first read may not work properly

That is only true when you are taking readings from multiple analog inputs - the first reading from the second channel may still have some small left over charge in the sample and hold capacitor from the first channel. If you're only using one analog channel then there is no other channel to interfere with it.

As for the LED, if you are seeing the LED as just on all the time (not flickering) then it is toggling too fast for you to see - but you still see it because some of the time it's on. That's how PWM works. The greater the percentage of time it's on, the brighter it looks.

If you're actually seeing it flashing on and off, then yes, you must be doing something wrong. Try changing your 1e9 to 1e9UL.

You should also change 56e3 to 56e3UL.

Pete

majenko:
If you're actually seeing it flashing on and off, then yes, you must be doing something wrong. Try changing your 1e9 to 1e9UL.

No, don't do that. Its not wise to suggest (broken) advice that's wrong which you could easily have tested first:

sketch_mar18a.ino:6:22: error: invalid suffix "UL" on floating constant
sketch_mar18a.ino:15:11: error: invalid suffix "UL" on floating constant

There is no problem at all use 1e9 (a floating point constant) and casting it implicitly to long.

The flickering is probably due to timer1 interrupts and timer0 interrupts colliding every so often.

Change your 1e9 to 1000000000UL :stuck_out_tongue:

SurferTim:
It is your persistence of vision that allows you to see it. I've run the D13 led about as fast as this thing will run it, and I still see the led lit abut half bright. A television runs your eyeballs about as fast as they can work. Remember, an analog tv is just one little tiny spot moving across the screen in a hurry.

Of course it'll be half as bright, you are basically doing PWM, having it on only half the time. I'm referring to the flicker.

majenko:
Nothing to do with your LED flashing, but:

  analogRead(inputPin); // this extra is because I found elsewhere that the first read may not work properly

That is only true when you are taking readings from multiple analog inputs - the first reading from the second channel may still have some small left over charge in the sample and hold capacitor from the first channel. If you're only using one analog channel then there is no other channel to interfere with it.

Dunno, I was having some problem with another test that only used one analog input. I wasn't sure why it did it, but it did. 100us isn't going to hurt me that much anyway in this case.

majenko:
As for the LED, if you are seeing the LED as just on all the time (not flickering) then it is toggling too fast for you to see - but you still see it because some of the time it's on. That's how PWM works. The greater the percentage of time it's on, the brighter it looks.

If you're actually seeing it flashing on and off, then yes, you must be doing something wrong. Try changing your 1e9 to 1e9UL.

Thanks, I know that about PWM, but I was seeing the LED flicker at 30-37kHz. I was thinking that I shouldn't see it flicker at such a high rate and that it should be solid, but just half as bright as an always on LED.

Also, I did try replacing all of the constant doubles with constant longs with the same result.

Any other ideas?

Adrian

The simple answer is: No.

Think about mains power, which dependent on where you live runs at 50/60Hz. If you've seen LED bulbs run on mains, AC Christmas lights for example, because the cheaper types only run 50% of the time, you can notice the flicker, but only just. However the effect becomes far more noticeable when either the bulb or you are moving. This is due to persistence of image.

At 37kHz you wouldn't see anything but a dimmed light.

It's far more likely that the flicker you're seeing is due to other factors, such as code or hardware not being up to the task of switching it that fast.

adrian_h:
As I understand it, our eyes are not capable of seeing things flash beyond 60Hz or 100Hz due to persistence of vision.

Do you mean, despite persistence of vision?

I have a gadget running right now that flashes an LED (once) at 2/1000 of a second, in other words 500 Hz. It is clearly visible. You can see camera flashes that are probably 1/1000 of a second, right?

But if you mean, continual flashes at 30 KHz, not you won't see that (the flashing). After all, movies are made at around 30 Hz.

There is no problem at all use 1e9 (a floating point constant) and casting it implicitly to long.

Of course, expressing it as 1.0e9 makes it clear that it IS a floating point value, not a mistake.

Veco:
It's far more likely that the flicker you're seeing is due to other factors, such as code or hardware not being up to the task of switching it that fast.

As I said its probably some sort of strobing with timer0 interrupts.

Adding this line to setup() will disable timer0 interrupts - if this makes the flicker go away
then it proves it. Note that doing this will stop delay(), millis() and micros() from working
as they depend on timer0 interrupts.

  TIMSK0 = 0x00 ;

In normal use there is a timer0 interrupt every 1.024ms and if it coincides with timer1 interrupt
it will delay the timer1 interrupt and throw the timing out leading to unequal duty cycles
occasionally.

You need to consider that the infrared detector responds to infrared light and you need to consider
the frequency of the light being emitted by the transmitter and being detected by the receiver.

In this context, the 30 kHz ( ballpark ) flashing of the device message pulses is not relevant. The
frequency of the actual light waves doing the transmission is much higher, many gigahertz,
whatever the speed of light divided by the wavelength around 1000 nm is.

MarkT:

Veco:
It's far more likely that the flicker you're seeing is due to other factors, such as code or hardware not being up to the task of switching it that fast.

As I said its probably some sort of strobing with timer0 interrupts.

Adding this line to setup() will disable timer0 interrupts - if this makes the flicker go away
then it proves it. Note that doing this will stop delay(), millis() and micros() from working
as they depend on timer0 interrupts.

  TIMSK0 = 0x00 ;

In normal use there is a timer0 interrupt every 1.024ms and if it coincides with timer1 interrupt
it will delay the timer1 interrupt and throw the timing out leading to unequal duty cycles
occasionally.

Tried this, doesn't help. The flicker is not sporadic but continuous between 30-37kHz.

That's what I thought. In fact this should be alternating on and off at 60-74kHz. Doesn't feel right. (BTW, k is lower case for SI units)

Sorry, meant flicker not flash.

So is my code wrong? Wish I had an oscilloscope. :frowning:

adrian_h:
Doesn't feel right. (BTW, k is lower case for SI units)

Looks like you are right. I've been in the habit of capitalizing it after seeing people write mHz when they mean MHz.

So my (incorrect) rule of thumb is: capitalize things that are multipliers greater than one.

There's something wrong with your calculations. You are getting a frequency of about 36 Hz, which is visible to the eye.

Freq = 46000Hz - Period = 21739.13us - 1023
Freq = 46500Hz - Period = 21505.38us - 1023
Freq = 30000Hz - Period = 33333.33us
Freq = 30500Hz - Period = 32786.89us - 1023
Freq = 31000Hz - Period = 32258.07us - 1023
Freq = 31500Hz - Period = 31746.03us - 1023
Freq = 32000Hz - Period = 31250.00us - 1023
Freq = 32500Hz - Period = 30769.23us - 1023
Freq = 33000Hz - Period = 30303.03us - 1023

Period (say) 30000 uS.

Frequency then is:

1/30000e-6 = 33.333333333333

33 Hz.

Ugh! Thanks Nick. I was saying us but was thinking ns. :fearful: Stupid.

Write a simple sketch that only flashes the pin 13 led. Past 30 Hz you won't see flashing. By 60 Hz you should not see any difference. But to make sure you're not flattering yourself, have someone or something -else- that you can't see or hear choose the frequency and score your answers.

Humans like to think they're fast. 10011100011111!