Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Button triggering multiple LEDs

button led OnInterrupt

  • Please log in to reply
17 replies to this topic

#1 dustmouse

dustmouse

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationEdgewater, CO

Posted 15 January 2013 - 03:54 AM

I have a button that you can assign multiple output components to.  Right now I have a couple LEDs (including the onboard) that I am using to test it.  It works correctly, however there is a lag between the LEDs getting turned on, and I imagine it will only get worse as I add more LEDs (most significantly between the first and last).  

 

Is there a way to do this in code so it turns on the LEDs in a way that appears simultaneous?  Or does this require a special piece of hardware?  

 

The OnInterrupt event on my InterruptPort looks like this:

 

private void interruptPort_OnInterrupt(uint data1, uint data2, DateTime time)        {            bool isButtonUp = data2 == 1;            if (isButtonUp)                foreach(IOutputComponent outputComponent in this.OutputComponents)                    outputComponent.SetState(!outputComponent.State);        }

 

On a side note, is there any talk of Microsoft adding generic collections to the Micro Framework?

 


Check out my Netduino projects on GitHub.


#2 JerseyTechGuy

JerseyTechGuy

    Advanced Member

  • Members
  • PipPipPip
  • 870 posts

Posted 15 January 2013 - 01:12 PM

Since you are looping through and turning them on, there will be some delay due to the looping.  I don't know how your hardware is setup or what you are trying to achieve, but if you are turning them on from several GPIO pins on the Netduino and there are only 13 Digital Pins, why not just turn them all on or all off at the same time.  Will take a few more lines of code but again the max number of digital pins are 13.  If you are trying turn on many more than 13 or even close to 13, you may want to consider using a multiplexer chip so you can simply address the matrix of LEDs.

 

As far as Generic Collections, it is unlikely this will be added to keep the NETMF size down.  Basic Collections are supported like ArrayList, Hashtable, Queue and Stack.  You can also use standard arrays (ie: MyLEDS[]).



#3 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 15 January 2013 - 01:46 PM

I've never seen the IOutputComponent interface before, nor the OutputComponents collection.

 

What or these?

 

If you where to do a series of OutputPort.Write(.) you shouldn't expect any noticable latency between the toggling of individual LEDs so my guess would be that accessing the collection takes a considerable amount of time.



#4 NooM

NooM

    Advanced Member

  • Members
  • PipPipPip
  • 490 posts
  • LocationAustria

Posted 15 January 2013 - 02:39 PM

thats a impementation he made.

 

reminds me on xna .. IGameComponent

 

(where i means interface.. looping like this you do when you have some different classes that all have the same interface)



#5 dustmouse

dustmouse

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationEdgewater, CO

Posted 15 January 2013 - 02:43 PM

Since you are looping through and turning them on, there will be some delay due to the looping.  I don't know how your hardware is setup or what you are trying to achieve, but if you are turning them on from several GPIO pins on the Netduino and there are only 13 Digital Pins, why not just turn them all on or all off at the same time.  Will take a few more lines of code but again the max number of digital pins are 13.  If you are trying turn on many more than 13 or even close to 13, you may want to consider using a multiplexer chip so you can simply address the matrix of LEDs.

 

How would I accomplish turning them all on/off at once?  Would I instantiate 13 OutputPorts and set the state on all of them in the OnInterrupt event handler, or is there a Netduino class for handling that sort of thing?


Check out my Netduino projects on GitHub.


#6 dustmouse

dustmouse

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationEdgewater, CO

Posted 15 January 2013 - 02:51 PM

I've never seen the IOutputComponent interface before, nor the OutputComponents collection.

 

What or these?

 

If you where to do a series of OutputPort.Write(.) you shouldn't expect any noticable latency between the toggling of individual LEDs so my guess would be that accessing the collection takes a considerable amount of time.

 

IOutputComponent is a basic interface I put together for stuff like LEDs.  I wanted the button to set the state of an output component without knowing or caring what the component is or what it will do when the state changes. 

 

When debugging, I noticed that iterating over the collection does take a considerable amount of time, as you said.  I wonder if part of the hang up is caused by unboxing the objects in the ArrayList.  

 

The reason I used a list instead of writing a series of OutputPort.Write() statements is because I wanted to be able to dynamically add and remove output components from the button.  I don't have any practical reason for this yet, but I wanted to make the behavior as flexible and generic as possible.


Check out my Netduino projects on GitHub.


#7 JerseyTechGuy

JerseyTechGuy

    Advanced Member

  • Members
  • PipPipPip
  • 870 posts

Posted 15 January 2013 - 03:04 PM

How would I accomplish turning them all on/off at once?  Would I instantiate 13 OutputPorts and set the state on all of them in the OnInterrupt event handler, or is there a Netduino class for handling that sort of thing?

There is no special class for this, but yes you would define each of them as their own outputport.  You can call them led1, led2, led3 for instance.  Then do the led1.Write(true) or led1.Write(false).  It's a good test to see the speed difference.

 

If you share more of your code we can look to see if there is any other way to speed it up.



#8 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 15 January 2013 - 05:24 PM

IOutputComponent is a basic interface I put together for stuff like LEDs.  I wanted the button to set the state of an output component without knowing or caring what the component is or what it will do when the state changes. 

 

Ok, I thought it was something built into the framework that I didn't know about. Then I'm totally with you.

 

Here's an idea assuming that accessing the collection through an enumerator is the time consuming part:

 

In your interrupt handler, first allocate a regular array (i.e. a IOutputComponent[.]) with enough room for all items in the collection. Traverse the collection and put each IOutputComponent interface reference into the array. Loop through the array and toggle the states. It's not the least bit elegant but should create the impression of all the LEDs toggling all at once but would produce a delay before they all do so.

 

If this does not make any difference, then clearly there is something time consuming going on elsewhere, for instance in the SetState(.) method. It might not take you any further but it's a simple to make test in trying to find out where the lag comes from.

 

Ok, the Netduino is not fast compared to a MCU not running NETMF but it's not *that* slow either.



#9 dustmouse

dustmouse

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationEdgewater, CO

Posted 16 January 2013 - 01:31 AM

I should've been more specific about the type of behavior that was occurring in the .SetState() method.  When set to true, the LED would blink, and false, the LED would turn off. I tried this with just the basic on/off behavior, and I couldn't detect any kind of lag in the foreach loop.  

 

Then I put the blinking LEDs outside of the foreach loop, and just called .SetState() in series and it had the same kind of lag.  It creates a new thread each time the blinking is turned on, so that could very well be the culprit.  I have posted my code below if you want to take a look at it.

 

I don't mind that calling .SetState() is slow (if it can't be helped) so much as it causes a lag between components triggered in series.

 

public class PulseLed : Led    {        private Thread pulseThread;        #region Constructors        public PulseLed(Cpu.Pin cpuPin) : base(cpuPin)         {            base.State = false;        }        #endregion        #region Public Properties        public int PulseIntervalInMilliseconds { get; set; }        #endregion        #region IOutputComponent Members        public override void SetState(bool state)        {            base.State = state;            if (base.State)            {                if ((this.pulseThread == null || !this.pulseThread.IsAlive) &&                    this.PulseIntervalInMilliseconds > 0)                {                    this.pulseThread = new Thread(new ThreadStart(this.pulse));                    this.pulseThread.Start();                }                else                    base.outputPort.Write(true);            }             else                base.outputPort.Write(false);        }        #endregion        #region Private Methods        private void pulse()        {            bool pulseState = false;            while (base.State)            {                pulseState = !pulseState;                base.outputPort.Write(pulseState);                Thread.Sleep(this.PulseIntervalInMilliseconds / 2);            }        }        #endregion    }

 

I made a couple edits to the code.


Check out my Netduino projects on GitHub.


#10 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 16 January 2013 - 08:48 AM

It creates a new thread each time the blinking is turned on, so that could very well be the culprit

Yes, this defininately is the cause of the lag and I think you should really try to avoid doing this.

 

It would probably be much less lag (if any) if you where to create the thread in the constructor of the class implementing the IComponentOutput interface.

 

Initially you would put the thread in suspended state waiting for a signal to start/stop the blinking. You can accomplish this using an AutoResetEvent so that the SetState(.) method only signals its blinker thread to start or stop blinking. In the blinker thread you run a loop blinking the LED and each round you perform a wait on the AutoResetEvent that will either return immediately or put the thread on hold depending on weather the boolean parameter passed to the SetState(.) method is true or false.

 

Instead of using one worker thread for each instance of the IComponentOutput LED blinker class, you might consider running just one global worker thread for all the LED blinker objects. Each blinker object could register a callback with the global worker thread so that the object would perform either an ON or OFF operation on its LED depending on a parameter passed to the callback method.

 

Yes, this is a far more complicated solution and a much better way could be to use the PWM generator to do the blinking. Now, I don't know if you can do PWM at such a low frequency plus you would probably need some external hardware too, like for instance one transistor for each LED. This way you would let the PWM generator run all the time and could enable blinking on each individual LED or several/all at once depending on how many GPIO pins you are willing to spend. Such a simple circuit would be quite easy to implement on a little breadboard to go along side of your Netduino.



#11 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 16 January 2013 - 09:24 AM

Antoher solutuion that would probably appeal more to you since its software only, would be to run PWM at say 2Hz (if it can go that low) and wire the output of that to an input GPIO. Then you define an InputPort to the latter GPIO and configure an interrupt to fire on both flanks. In this single global interrupt handler you would issue a call to each registered callback (each ICompontentOutput object would register a callback in its constructor). In the callback you would call the SetState(.) method with either true or false depending on wether the interrupt handler detects a high or low flank respectively. The only external "hardware" would be a simple wire between the PWM output and the one input GPIO of your choosing.



#12 dustmouse

dustmouse

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationEdgewater, CO

Posted 16 January 2013 - 03:52 PM

It would probably be much less lag (if any) if you where to create the thread in the constructor of the class implementing the IComponentOutput interface.

 

Initially you would put the thread in suspended state waiting for a signal to start/stop the blinking. You can accomplish this using an AutoResetEvent so that the SetState(.) method only signals its blinker thread to start or stop blinking. In the blinker thread you run a loop blinking the LED and each round you perform a wait on the AutoResetEvent that will either return immediately or put the thread on hold depending on weather the boolean parameter passed to the SetState(.) method is true or false.

 

I like this idea.  I had tried to initialize the thread in the constructor but I must've implemented it wrong because it didn't work.  I'm going to follow your suggestion and implement the AutoResetEvent.  Will let you know how it goes.  Thanks! 


Check out my Netduino projects on GitHub.


#13 dustmouse

dustmouse

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationEdgewater, CO

Posted 16 January 2013 - 03:59 PM

Antoher solutuion that would probably appeal more to you since its software only...

 

Yeah, my hardware collection is pretty modest right now, so I am definitely interested in doing as much as possible in software.  If I can create the same behavior in a PWM, then I will go that route.


Check out my Netduino projects on GitHub.


#14 JerseyTechGuy

JerseyTechGuy

    Advanced Member

  • Members
  • PipPipPip
  • 870 posts

Posted 16 January 2013 - 05:29 PM

dustmouse,

 

I was playing around with a Classic Netduino this morning and created this demo that works well for flashing 8 LEDs.  I've had them all at the same rate as well as different rates.  Here's the hardware setup. (Below is the code).

 

So basically I created a Threaded demo for flashing the LEDs.  You can control the ON time, OFF time and number of times to repeat.  There is also a main thread running that flashes the onboard LED.  The threads are joined so this prevents the main thread from being suspended until all of the other threads have ended.  You can also comment out those Join lines and the threads will all run their course without waiting on each other.

 

Posted Image

 

The LED_Extension Class:

using System;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using System.Threading;using SecretLabs.NETMF.Hardware.Netduino;namespace Multithreaded_LED{    public class LED_Extension : IDisposable    {        private OutputPort _outPort;        private Thread _worker;        public LED_Extension(Cpu.Pin pin, bool onFirst)        {            _outPort = new OutputPort(pin, onFirst);        }        public void Dispose()        {            _outPort.Dispose();        }        public Thread Worker        {            get            {                return _worker;            }            set            {                _worker = value;            }        }        public void PulseLED(int onTime, int offTime, bool onFirst, uint repeat)        {            bool work = false;            _worker = new Thread(                delegate()                {                    work = doSomeWork(onTime, offTime, onFirst, repeat);                }                );            _worker.Start();        }        private bool doSomeWork(int onTime, int offTime, bool onFirst, uint repeat)        {            if (onFirst)            {                for (uint c = 0; c < repeat; c++)                {                    _outPort.Write(true);                    Thread.Sleep(onTime);                    _outPort.Write(false);                    Thread.Sleep(offTime);                }            }            else            {                for (uint c = 0; c < repeat; c++)                {                    Thread.Sleep(offTime);                    _outPort.Write(true);                    Thread.Sleep(onTime);                    Thread.Sleep(offTime);                }            }            return true;        }    }}

The core program:

 

using System;using System.Threading;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using SecretLabs.NETMF.Hardware;using SecretLabs.NETMF.Hardware.Netduino;namespace Multithreaded_LED{    public class Program    {        static Thread regularThread;        static OutputPort onboardLed;        public static void Main()        {            regularThread = new Thread(new ThreadStart(ThreadMethod));            regularThread.Start();            // Array for the 8 ports of the LEDs            LED_Extension[] leds = new LED_Extension[8];            //Set each LED pin to be an output            onboardLed = new OutputPort(Pins.ONBOARD_LED, false);            leds[0] = new LED_Extension(Pins.GPIO_PIN_D2, false);            leds[1] = new LED_Extension(Pins.GPIO_PIN_D3, false);            leds[2] = new LED_Extension(Pins.GPIO_PIN_D4, false);            leds[3] = new LED_Extension(Pins.GPIO_PIN_D5, false);            leds[4] = new LED_Extension(Pins.GPIO_PIN_D6, false);            leds[5] = new LED_Extension(Pins.GPIO_PIN_D7, false);            leds[6] = new LED_Extension(Pins.GPIO_PIN_D8, false);            leds[7] = new LED_Extension(Pins.GPIO_PIN_D9, false);            // Define the On / Off / Initial and Repeats for LEDS            leds[0].PulseLED(250, 250, true, 10);            leds[1].PulseLED(500, 500, true, 10);            leds[2].PulseLED(750, 750, true, 10);            leds[3].PulseLED(1000, 1000, true, 10);            leds[4].PulseLED(1250, 1250, true, 10);            leds[5].PulseLED(1500, 1500, true, 10);            leds[6].PulseLED(1750, 1750, true, 10);            leds[7].PulseLED(2000, 2000, true, 10);            // Join the Threads so they all end together            leds[0].Worker.Join();            leds[1].Worker.Join();            leds[2].Worker.Join();            leds[3].Worker.Join();            leds[4].Worker.Join();            leds[5].Worker.Join();            leds[6].Worker.Join();            leds[7].Worker.Join();            // Suspend the main thread            regularThread.Suspend();                    }        static void ThreadMethod()        {            int count = 0;            while (true)            {                if (count == 200)                {                    onboardLed.Write(true);                }                if (count == 400)                {                    onboardLed.Write(false);                    count = 0;                }                count++;                Thread.Sleep(10);            }        }    }}

Code Download Here



#15 dustmouse

dustmouse

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationEdgewater, CO

Posted 22 January 2013 - 03:43 AM

Hi Dave, thanks a lot for that great example.  It's a very nice implementation for syncing a bunch of blinkers.  I borrowed your use of IDisposable on your LED_Extension class and followed your conservative approach to thread creation.  

 

My final implementation (below) was slightly different because I am using a button event to turn the blinking LEDs on and off.  And because I was able to get the blinking LEDs to look closely synced by only creating the blinking thread once for each LED, I was able to keep with my foreach loop approach for turning the LEDs on/off.  

 

I also need to thank hanzibal for helping me arrive at a similar conclusion about threading.  

 

Oh, I ended up going with a ManualResetEvent because it doesn't automatically set the state to signal when it is encountered.  My Dispose() method looks a little sloppy to me and I think it can be simplified.  Anyway, here is the code (I made a couple edits to it):

 

public sealed class PulseLed : Led, IDisposable
    {
        private Thread pulseThread;
        private ManualResetEvent manualResetEvent;
        private bool isDisposed;
 
        #region Constructors
 
        public PulseLed(Cpu.Pin cpuPin) : base(cpuPin) 
        {
            this.manualResetEvent = new ManualResetEvent(true);
            this.isDisposed = false;
        }
 
        #endregion
 
        #region Public Properties
 
        public int PulseIntervalInMilliseconds { get; set; }
 
        #endregion
 
        #region IDisposable Members
 
        public void Dispose()
        {
            if (this.pulseThread != null && this.pulseThread.IsAlive)
            {
                this.manualResetEvent.Set();
                this.isDisposed = true;
                this.pulseThread.Join();
 
                if (base.State)
                    base.SetState(false);
            }
        }
 
        #endregion
 
        #region IOutputComponent Members
 
        public override bool State { get; protected set; }
 
        public override void SetState(bool state)
        {
            this.State = state;
 
            if (this.PulseIntervalInMilliseconds > 0)
            {
                if (this.State)
                {
                    if ((this.pulseThread == null || !this.pulseThread.IsAlive))
                    {
                        this.pulseThread = new Thread(new ThreadStart(this.pulse));
                        this.pulseThread.Start();
                    }
                    else
                        this.manualResetEvent.Set();
                }  
                else
                {
                    this.manualResetEvent.Reset();
 
                    if (base.State)
                        base.SetState(false);
                }
            }
            else
                base.SetState(state);
        }
 
        #endregion
 
        #region Private Methods
 
        private void pulse()
        {
            while (!this.isDisposed)
            {
                base.State = !base.State;
                base.outputPort.Write(base.State);
                Thread.Sleep(this.PulseIntervalInMilliseconds / 2);
 
                this.manualResetEvent.WaitOne();
            }
        }
 
        #endregion
    }

Check out my Netduino projects on GitHub.


#16 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 22 January 2013 - 11:16 AM

Glad you solved it!

I seemed to have confused AutoResetEvent with ManualResetEvent, sorry about that.



#17 dustmouse

dustmouse

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationEdgewater, CO

Posted 22 January 2013 - 01:34 PM

Glad you solved it!

I seemed to have confused AutoResetEvent with ManualResetEvent, sorry about that.

 

No probs, thanks again!


Check out my Netduino projects on GitHub.


#18 Dr Who

Dr Who

    Advanced Member

  • Members
  • PipPipPip
  • 261 posts
  • LocationNYC

Posted 12 July 2013 - 01:39 AM

Hello!

Dave thank you for your example. for what I've got. ah, lined up, well for a start.

 

However Chrome reacted badly. It wanted me to discard it because its the sort it thought wasn't normally downloaded. I sometimes see that with really rarely downloaded blobs.

 

And typically NAV reacts badly with obvious adware. Fortunately I don't need to download that <rude word> stuff very often.



Doctor Who
"This signature does not exist!"





Also tagged with one or more of these keywords: button, led, OnInterrupt

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.