Skip to content

axkg/gpioals

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 

Repository files navigation

GPIO Ambient Light Sensor

This module for the Linux kernel allows measuring ambient light intensity with just a light dependent resistor (LDR) and a capacitor. A user space daemon to make use of this kernel module is available in a separate repository: alsd.

The following schematic shows how the LDR (L) and the capacitor (C) are connected to the Pi:

  +--------------+
  | Raspberry Pi |
  |              |
  |          +-+ |
  |          |G| |   +-+
  |    POWER---------|L|--+
  |          |P| |   +-+  |
  |     GPIO--------------+
  |          |I| |   | |  |
  |      GND---------|C|--+
  |          |O| |   | |
  |          +-+ |
  +--------------+

Even though I cannot find the original instructions I followed, there are a couple of similar ones available, e.g this one from Robo India. The software solution commonly proposed to measure the light the LDR is exposed to, is to poll the GPIO pin to detect when the capacitor is charged. The drawback here is not only the fact that this approach keeps the CPU busy during the measurement and context switches as well as getting the information from/to user space introduce a lot of noise.

In order to address both of these issues, this kernel module detects the charged capacitor through an interrupt and measures all timestamps directly in kernel space to reduce the jitter. Note that gpiod addresses the second part (timestamping the interrupt) but not the timestamping of switching the GPIO port direction.

Building the Module

Building the kernel module should be straight forward: Install the headers that match the kernel currently running on the Raspberry Pi (on Raspbian installing the matching raspberrypi-kernel-headers should be sufficient) and run make.

Installing the Moduile

A standard make install (either as root or via sudo) should be sufficient. Note that as with any kernel module, recompiling and reinstalling gpioals will be necessary whenever a new kernel is installed.

Loading the Module

The GPIO pin to be used can be configured via the module parameter gpioals_gpio_pin, by default pin 10 will be used.

NOTE: Starting with kernel 6.4 the GPIO pins are typically no longer mapped to offset zero. Until this module has been ported to use symbolic names, find the proper pin ID for your hardware from the kernel's table:

cat /sys/kernel/debug/gpio

Provide the integer value (not the gpio- prefix) with gpioals_gpio_pin for the GPIO pin you want to use for gpioals.

User Space Interface

Note: A simple, exemplary implementation of the user space interface in Rust is available with alsd.

When the module is loaded, udev should automatically create a /dev/gpioals character device. Currently only one process is allowed to open the device.

Writing to the Device

A user space process needs to open the device with read and write access, as currently gpioals expects user space to trigger measurements. Commands are sent as single byte writes to the device. The following commands are currently supported:

Byte Command Details
0 CANCEL Cancel any running measurements
1 ARM Set the GPIO pin to low to discharge the capacitor
2 MEASURE Switch the GPIO port back to input and wait for the interrupt and complete the measurement
3 STATISTICS Will trigger the module to printk() some internal counters for debugging

Reading Events from the Device

The device will allow reading multiples of 16 bytes only. 16 bytes is the minimum as single measurement holds two 64bit integers:

Bits Value
0-63 ktime_t timestamp when the measurement was taken
64-127 Time delta in nanoseconds from the flipping of the GPIO pin to the interrupt

Interpreting Measurements

The shorter the measured time delta is, the more light should have been detected by the LDR. The actual timing depends on the actual LDR and capacitator used. If the environment is too dark, the interrupt will not trigger within the observation time, alas no measurement will be available. So if user space is triggering measurements but not reading any measurements, one should assume that it is too dark for the "sensor" to measure.

About

Measure ambient light using a light depdendent resistor connected via GPIO

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors