You want a loop with a sleep operation in it.
You didn't tell us how you turn on and off that LED, so I will assume you have a method called SetLED(val)
. A val
of 0 turns the LED off, and 1 turns it on. And, let's have a method called ButtonPressed()
that comes back true
when the button is pressed.
To get a 2Hz square wave you want to flip val
every 250 milliseconds. This code will do that for you.
var ledState = 1;
while (ButtonPressed()) {
SetLED(ledState);
Thread.Sleep(250); //milliseconds
ledState = 1 - ledState; //flip the value
}
SetLED(0); // turn the LED off when done.
That will basically work. But there's a complication: C# and its various underlying operating systems are not hard real-time systems. Therefore Thread.Sleep()
sometimes wakes up a bit late. These late wakeups can accumulate and make your square wave a little jittery and, cumulatively, less than 2Hz. You can't do much about the jitter.
But you can avoid the frequency degradation by looking at the time-of-day clock and computing how long to sleep in each loop.
The expression DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond
gets you the present time in milliseconds (since some long-ago epoch).
So you can compute the number of milliseconds for the next sleep in your code. That corrects for .Sleep()
oversleeping.
var ledState = 1;
long nextTickTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
while (ButtonPressed()) {
SetLED(ledState);
nextTickTime += 250;
long nowTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
int sleepInterval = nextTickTime - nowTime;
if (sleepInterval > 0)
Thread.Sleep(sleepInterval);
ledState = 1 - ledState; //flip the value
}
SetLED(0); // turn the LED off when done.
That's a fairly robust blinker. You can also raise the priority of the thread while the loop is running, but that's a question and answer for another day.