Main Site Documentation

Dimming a LED in the background


#1

Dimming a LED with PWM is quite easy.
But if you need to dim several LEDs at the same time or within different periods, you maybe want to dim them in the backround.

I’ve written a small class which dims a LED in an own thread.
So the main thread doesn’t care about it.

My test environment is a low current LED with a 560 Ohm resistor connected to P9 of the extender module (picture is below).

How to use it:


PWM_Dimmer pwmDimmer = new PWM_Dimmer(GT.Socket.GetSocket(8, true, m_Extender, "P"), GT.Socket.Pin.Nine, m_Extender, 2000 /* Hz */);
pwmDimmer.Start(0 /* % */, 100 /* % */, 3 /* seconds */);

I’m using the gadgeteer abstraction layer here for addressing the PWM pin.
The Start() functions dims the LED from 0% to 100% within 3 seconds.
Of course all values between 0% and 100% are possible, even in reverse order.
The function returns immediately.
But you can use the event OnEnd() which is called after the given timespan.

Please notice: due to the missing logarithm function in Math the dimming is only linear.

Here is the code:


  public class PWM_Dimmer
  {

    #region Constants

    public const int UPDATE_FREQ = 25;  // Hz

    #endregion

    #region Types

    public delegate void DOnStart();
    public delegate void DOnEnd();

    #endregion

    #region Attributes

    private readonly PWMOutput m_PWM;
    private readonly uint m_Period;
    private uint m_StartDuty;
    private uint m_EndDuty;
    private int m_DimmTime_s;
    private Thread m_Thread = null;

    #endregion

    #region Events

    public event DOnStart OnStart;
    public event DOnEnd OnEnd;

    #endregion

    #region Methods

    #region public public PWM_Dimmer(GT.Socket socket, GT.Socket.Pin pin, GTM.Module module, int freqHz)
    public PWM_Dimmer(GT.Socket socket, GT.Socket.Pin pin, GTM.Module module, int freqHz)
    {
      m_PWM = new PWMOutput(socket, pin, module);
      m_Period = (uint)((1F / (float)freqHz) * 1000000000F);
    }
    #endregion

    #region public void Start(uint startDuty, uint endDuty, int dimm_time_s)
    public void Start(uint startDuty, uint endDuty, int dimm_time_s)
    {
      if ((startDuty > 100) || (endDuty > 100) || (startDuty == endDuty) || (dimm_time_s <= 0) || (null != m_Thread))
        throw new ArgumentException();

      m_StartDuty = startDuty;
      m_EndDuty = endDuty;
      m_DimmTime_s = dimm_time_s;
      m_Thread = new Thread(ThreadStarted);
      m_Thread.Start();
    }
    #endregion

    #region private void ThreadStarted()
    private void ThreadStarted()
    {
      int sleep_time = 1000 / UPDATE_FREQ;
      int numSteps = ((m_DimmTime_s * 1000 + sleep_time - 1) / sleep_time);
      float percent_inc = 100F / (float)numSteps;
      uint curr_highTime = 0;

      if (null != OnStart)
        OnStart();

      if (m_StartDuty > m_EndDuty)
        percent_inc *= -1;

      float percent = m_StartDuty;
      for (int x = 0; x <= numSteps; ++x, percent += percent_inc)
      {
        float highTime = (float)m_Period * percent / 100;
        if (highTime < 0)
          highTime = 0;
        else if (highTime > m_Period)
          highTime = m_Period;
        if (curr_highTime != (uint)highTime)
        {
          curr_highTime = (uint)highTime;
          if (0 == curr_highTime)
            m_PWM.Active = false;
          else
          {
            m_PWM.Active = true;
            m_PWM.SetPulse(m_Period, curr_highTime);
          }
        }
        Thread.Sleep(sleep_time);
      }

      m_Thread = null;

      if (null != OnEnd)
        OnEnd();
    }
    #endregion

    #endregion

  }


#2

Thanks for sharing. I love this extender module. It is pretty useful little board!