zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.48k stars 6.42k forks source link

RFC: Improvements to `drivers/sensors` for light sensors #13455

Open microbuilder opened 5 years ago

microbuilder commented 5 years ago

RFC: Improvements to drivers/sensors for light sensors

Introduction

This RFC details a number of issues and potential improvements to the handling of 'light' in the current sensor API.

An explanation of radiometric versus photometric units is presented, as well as some options to make the current system more practical in real-world applications.

Problem Description

The current solution for 'describing' light-related sensor data is fundamentally flawed at the unit level (lux for IR, etc.), and has some unnecessary limitations in terms of what type(s) of light-related data can be stored or conveyed with the current API.

Proposed Changes

Detailed RFC

At present, sensor.h has the following photometric value types defined for light sensors:

/** Illuminance in visible spectrum, in lux. */
SENSOR_CHAN_LIGHT,
/** Illuminance in infra-red spectrum, in lux. */
SENSOR_CHAN_IR,
/** Illuminance in red spectrum, in lux. */
SENSOR_CHAN_RED,
/** Illuminance in green spectrum, in lux. */
SENSOR_CHAN_GREEN,
/** Illuminance in blue spectrum, in lux. */
SENSOR_CHAN_BLUE,

There are a number of problems and limitations with the current approach, which are detailed below.

Key Technical Concepts

Before detailing the problems with the current sensor API, an explanation of radiometric versus photometric units may be useful.

Radiometric vs. Photometric Units

Radiometric Units

Electromagentic radiation is characterised by radiometric units, which describe the physical properties of light (the number of photons, photon energy, or radiant flux). These units have no relation to human vision. Infrared radiation, for example, is not visible to the human eye (>780 nm) but it definitely exists as a radiometric phenomenon and can be accurately measured, described and analysed for scientifically significant purposes.

Photometric Units

To characterise light relative to the human eye, we need to use photometric units such as luminous intensity, which represents the light intensity of a source as perceived by the human eye, measured in candela (cd).

Since photometric measurements are limited to what the human eye can perceive, these measurements are restricted to the visible spectrum of 380 nm to 780 nm wavelengths.

One of the most common photometric units is luminous flux, which is measured in lumens (lm). It's even more common derivative is illuminance (used in this RFC and the current API), which is the luminous flux incident per a specific area. Illuminance is measured in lux (which is equal to lm/m^2).

It should be noted that all photometric units are based on a theoretical model of human vision, and thus are not entirely accurate (compared to radiometric units). Anything dealing with 'lux' or photometric units will always, by definition, be an approximation, even if it's a reasonably good one!

Photometric Units and Radiometric Equivalents

The two unit families have the following relationships:

Photometric Unit Dimension Radiometric Unit Dimension
Luminous Flux lm Radiant Flux W
Luminous Intensity lm/sr=cd Radiant Intensity W/sr
Illuminance lm/m^2=lux Irradiance W/m^2
Luminance cd/m^2 Radiance W/(sr m^2)

Key Problems

Some of the key limitations of the current approach to capturing light samples are listed below:

  1. Lux is a photometric unit. Photometric units are used to represent light as perceived by the human eye. Radiometric units would be preferable since they are based on an actual physical model, not a theoretical estimation, and you can easily convert from radiometric to photometric units. (The radiometric equivalent of illuminance or lux is irradiance, which is measured in W/m^2.)
  2. Lux, by definition, has no meaning in the IR, RED, GREEN, or BLUE spectra since it can't be isolated to these narrow wavelengths, but is a calculation based on a curve representing a model of 'normal' human vision. Lux should be it's own inferred value type, based on raw radiometric data capture and the response of the photodiodes used.
  3. IR, Red, Green and Blue are common components of the light spectrum, but there is currently no way to account for other (visible or non-visible) wavelengths which are scientifically important, such as UV, or narrow bandwidths that can be captured by speciality light sensors or photodiodes. Ideally, it should be possible to return a radiometric sample that indicates the wavelength(s) of the light sample, and it's relative strength, without an arbitrary limitation to the IR/R/G/B ranges.

    Real World Example: Spectrometer

An easy to understand example of the limitations of the current API is trying to design a spectrometer.

A spectrometer works by capturing a number of samples at fixed wavelengths or wavelength ranges, with all of the spectral data in that range making up one dataset (capture in a single 'fetch' event).

A spectrometer might measure light in the human-visible-range, for example (380-780nm), and in 10nm intervals, meaning that each 'fetch' operation consists of 40 samples, each associated with either a fixed wavelength (ex. 420 nm, 430 nm, etc.) or a range of values (385-395 nm).

At present, there is no obvious mechanism to support either of these requirements:

Proposed Changes/Solutions

  1. Converting between radiometric and photometric units is done via the luminous efficiency function, of which several versions exist (CIE 1931, CIE 1988, etc.). Since lux is a commonly used value type, conversion from irradiance to illuminance should be provided via an appropriate function, taking radiometric data as an input and lux as an output. Radiometric units should be preferred, with support added for converting between the two unit families.
  2. A new SENSOR_CHAN_LUX channel should be added, or the current ambiguously-named SENSOR_CHAN_LIGHT channel should be renamed to clearly identify this as a photometric unit (lux) describing an estimation of human vision related to the capture light sample(s).
  3. Changes should be made to enable multiple instances of a channel per fetch operation, and the addition of meta-data to distinguish each of these channel instances.

Concerns

These modifications would obviously be a significant breaking change to the current sensor API, and require changes to any drivers using the current API.

Memory usage is also a critical concern, particularly when you need to maintain a large number of data samples in memory.

Unresolved Questions

Related Issues

1387: Lack of a performant sensor API

microbuilder commented 5 years ago

An initial attempt to address some of the weaknesses and errors in the current light sensor API is visible in PR https://github.com/zephyrproject-rtos/zephyr/pull/14245

adamfowleruk commented 3 years ago

I'm interested in this given the need to support the detection of being indoor or outdoor for a digital contact tracing application. Current sensor we are looking at are in this family: Broadcom APDS-9250 - Has components for IR,R,G,B.

teburd commented 11 months ago

Proposal for better sensor channel specifiers #63830 would perhaps atleast address the issue of the type of data (LIGHT) subtype (R/G/B/IR/UV/CUSTOM) and channel index in the sensor (N) to deal with light spectrometer sensors for example.