Fast Pulsing LED ultra precise square wave

Hello everyone,
First of all thank you for the great forum of yours, it was already loads of help for me. However, I am really foreign to the whole micro controller programming and of course I also have a problem, which is as follows:

I need to make an LED Blink from 0Hz to 200Hz in 1Hz intervals (so delay and millis is not an option). Additionally I have to be able to pause the blinking for a defined time and to terminate the run after a given time. On top of this the pulse must be a perfect square with minimum delay and without shifting.

To be able to do so I was using the Timerone library but could never pause or stop the blinking since it was running in the setup not the loop.

Can you tell me if or even how i can manage to do what I need? It would be very much appreciated!

I need to make an LED Blink from 0Hz to 200Hz in 1Hz intervals (so delay and millis is not an option)

I don't understand that sentence.

Millis is always an option.

What are you trying to do? It sounds like you are over thinking the specification.

If the problem involves 14.00Hz, you'd better have a good explanation.

Hey,

This is probably an uneducated question, but why is specifically 14Hz an issue?

Sorry for the brief summary I will try to explain better what we want to do.
We are building a stimulation device for neuronal cells. The light pulses will be used to activate genetically engineered neurons which are sensitive to light. This is all a very delicate process, which is why this must be very precise.

For now we were using timerone which allows me to blink the light at a given frequency, however I can not pause or stop the blinking automatically (at least to my limited understanding). However, this pause/end is crucial to the experiment since we have to be able to exaclty reproduce the stimulation protocol.

So what is needed of the tool is:
stimulation frequency (0Hz "LED on", pulses: 1Hz, 2Hz,....,199Hz, 200Hz) in steps of 1Hz (or even more precise if possible).
Pause duration (defined time in which the LED is not pulsing)
Run time ( repetitions of the stimulation+pause duration)

Does this help?
Thank you

"exactly" and "precise" are not good terms to use; there will always be inaccuracy - so you need to specify the degree of inaccuracy you can tolerate.
i.e. if you want 50:50 duty cycle, can you tolerate 45:55, for instance?

(the 14.00Hz reference is to illegal use of this frequency and IR LEDs in urban environments)

I'd probably use pure software approach, with a phase accumulator to provide fine control, but I don't know what your limits are.

Run time ( reputations of the stimulation+pause duration)

I'll assume that should have read "repetitions"

If there is a way around it we need to avoid any inaccuracy. Meaning: as accurate as possible and as inaccurate as necessary. I think a 45:55 deviation is too much (especially for low frequencies).

as for my measurements using timerone the frequency was surprisingly accurate with no detectable shift of the wave and only a 25ns latency for switching the LED on. So this is a degree of inaccuracy which is perfectly fine and more importantly not avoidable. However, I do understand this correctly that there is no way to pause/stop, right?

And yes repetitions is what I meant :wink:

However, I do understand this correctly that there is no way to pause/stop, right?

I don't know why you make this assertion, but then, I can't see your code.

(the 45:55 figure was extreme to test the water; I wouldn't expect such poor performance at such low frequencies. OTOH, 25ns seems a bit optimistic)

not an assertion just a humble question, since you suggest to use a different approach and not timerone, which I have been using so far but failed to pause/stop as it is running in the setup not the loop.

the 25s were measured using a oscilloscope and are to my understanding quite accurate.

I'll attach you the basic code we were using to drive the LED on pin 10 for now

#include "TimerOne.h"
 
void setup()
{
  pinMode(10, OUTPUT);
  Timer1.initialize(1000);         // initialize timer1, and set a 1/2 second period
  Timer1.pwm(9, 512);                // setup pwm on pin 9, 50% duty cycle
  Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt

}
 
void callback()
{
  digitalWrite(10, digitalRead(10) ^ 1);

}
 
void loop()
{

}

I'll attach you the basic code we were using to drive the LED on pin 10 for now

OK and for now we will just look at it.

You have not got the hang of this place maybe it is because you haven't read How to use this forum
It tells you how to post code properly, how to ask a question, how to respond the the answers you get and above all it tells you to post ALL your code.

I don't see how your scheme precludes stopping and starting - you just need an enable variable acted upon by the ISR.

Apologies Grumpy_Mike I was in a hurry and could not find the right button but i fixed it now. The code however is all the code, what runs and what I would like to pause/stop.

Thank you AWOL this is great news to me! could you show me how this would look like? Apologies for my ignorance.

bool paused;
 ....
....


void callback()
{
  if (! paused)
    digitalWrite(10, digitalRead(10) ^ 1);

}

Hello. The led is attached to pin 10? What's attached to pin 9? Your code seems to be setting up a PWM on that pin.

In your original post you talk about "defined times" for pausing and terminating. How did you want to govern those times, and the pulse lenghs etc.

Paul

Hey PaulRB,

Pin 9 is not being used at the moment.
And the latter part is what I am trying to figure out. I was hoping to just use a simple delay but apparently that is not working.

I'm sorry AWOL but I don't understand how your suggestion gives a pause of a certain duration...?

By varying when and for how long "paused" is true, maybe?

blorgh:
I was hoping to just use a simple delay but apparently that is not working.

I am not asking you how you would code it but how the end user would control it during use. Don't understand what you mean about delays apparently not working, you mentioned that in your original post also, please explain.