/PWM-LED-driver

Basic LED driver using software/hardware PWM for different LED brightness levels

Primary LanguageC

A Basic LED Driver with Software PWM

This driver uses software pulse-width modulation to control the brightness of a LED. Two buttons are used to change the LED brightness level.

This driver is compiled and tested on Raspberry Pi 3 Model B running Raspbian (Linux raspberrypi 4.4.41-v7+ #942). The LED and push-buttons are connected to the Pi via a breadboard.

Pulse-width Modulation (PWM)

An easy-to-understand explanation of what PWM is can be found here

Hardware PWM

The Raspberry Pi 3 has a pulse-width modulator. A version of this driver which makes use of it can be accessed in the hw-pwm branch.

The driver in the master branch emulates PWM by alternating HIGH and LOW signals to the LED; the time between switches depends on the required brightness level.

Using the Driver

The driver's binary is compiled nativelly on the Raspberry and is included in the repository. It can be recompiled by issuing make in the source directory.

The driver should be loaded using the following command (as root):
insmod pwm-led.ko [down_button_gpio=<gpio>] [up_button_gpio=<gpio>] [led_gpio=<gpio>] [pulse_frequency=<frequency>] [led_max_level=<level>]

The module can be unloaded using this command (as root): rmmod pwm-led

Module Parameters

  • down_button_gpio, up_button_gpio and led_gpio represent the GPIOs where the components are connected. GPIO numbers are given per the BCM numbering scheme.

  • pulse_frequency represents the amount of time (in nanoseconds) for which the proportion of LOW and HIGH signals sent to the LED is calculated. E.g. with pulse width of 100 ms and requested LED brightness of 40%, 40 ms will be spent sending HIGH signal and 60 ms will be spent sending a LOW signal to the LED.
    Default value is 100 000 nanoseconds (0.1 ms).

  • led_max_level determines the number of brightness levels the driver will support. E.g., with maximum level 2 there will be 3 distinct brightness levels - 0%, 50% and 100%. With maximum level 3 there will be 4 brightness levels - 0%, ~33%, ~66% and 100%.
    Default is 5 (meaning a step of 20%).

Implementation Details

Interrupt Handler and Finite-State Machine

When one of the push-buttons is pressed, an interrupt handler processes the received IRQ and sets the proper FSM event (UP or DOWN) depending on which button was pressed. A work is scheduled to handle the actual LED level change.

In the work queued by the IRQ handler, the appropriate FSM function is called, then the FSM state is updated. The FSM function increases or decreases the current LED level or does nothing. The LED level is later translated to a brightness level (proportion of LOW and HIGH signals) in a separate work function.

LED Control Work Function

The actual lighting of the LED is performed in this work function. It uses the current LED level and pulse frequency to determine how long a LOW and a HIGH signal should last. With 100 000 ns pulse frequency and 20% requested brightness it will keep sending HIGH signal for about 20 000 ns and then keep sending LOW signal for about 80 000 ns.