0

I am trying to find a way to create a 2 Hz square wave to an LED (Basically toggle between high and low at 2Hz) I have a general sense of how I think it should go, but not really sure what to do as I am new to C#, any help would be greatly appreciated!

Here's my general thought process:

While(Programruns){
      read input 
(I feel like there should be a for loop here to keep the square wave going forever until I stop it)
      if(button is pressed){
     output square wave
}
    else {
     off}
}
O. Jones
  • 103,626
  • 17
  • 118
  • 172
SWman88
  • 19
  • 1
  • 3
  • Did you forget to ask a question? – Caius Jard Sep 08 '21 at 23:26
  • @CaiusJard - _"...but `not really sure what to do` as I am new to C#, any help would be greatly appreciated!"_ –  Sep 08 '21 at 23:46
  • This is, I think, a good question from a person new to our trade. The simplest, and naive answer, involves using `Thread.Sleep(500)` in a loop. But a good answer is more involved because threads don't sleep for the exact amount of time requested. – O. Jones Sep 09 '21 at 00:31
  • Oops, I meant `Thread,Sleep(250)`. See my answer. – O. Jones Sep 09 '21 at 12:49

1 Answers1

0

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.

O. Jones
  • 103,626
  • 17
  • 118
  • 172