Modern ambient light sensors are categorised as IIO (Industrial Input Output) devices in Linux along with several other sensors and actuators. This article is targeted towards application developers and does not dwell too much into hardware. Below are few links on IIO subsystem:
https://wiki.st.com/stm32mpu/wiki/How_to_use_the_IIO_user_space_interface
https://bootlin.com/blog/the-backbone-of-a-linux-industrial-i-o-driver
APDS9306 Ambient Light Sensor
Datasheet can be found here.
Driver for this light sensor is present in Linux kernel version 6.10 onward and a backport of the driver for older kernels can be found here.
Schematic and PCB design can be found here.
Assuming your Linux board is set up with this device, you should see the following sysfs entries:
Verify your device by checking the name:
root@stm32mp1:~# cat /sys/bus/iio/devices/iio:device*/name
apds9306
48003000.adc:adc@0
48003000.adc:adc@100
root@stm32mp1:~# cat /sys/bus/iio/devices/iio:device0/name
apds9306
We found our device, now we list all the important files:
root@stm32mp1:/sys/bus/iio/devices/iio:device0# tree -L 1
.
|-- events #(interrupt related)
|-- in_illuminance_raw #(raw sensor value)
|-- in_illuminance_scale #(current scale)
|-- in_illuminance_scale_available #(all available scales)
|-- in_intensity_clear_raw #(unfiltered raw value)
|-- integration_time #(intg time per sample)
|-- integration_time_available #(available intg time)
|-- name #(driver name)
|-- sampling_frequency #(in case of continuous reads, or interrupt driven implementation, after how much time, sensor should generate outputs)
|-- sampling_frequency_available #(available sampling freq)
We can obtain the values in Lux using this formula:
Lux = (raw_value + offset) * scale
offset is a fixed value which can be derived after manual testing such as if your sensor is under a darkened glass, etc. In our case, we will use zero.
root@stm32mp1:/sys/bus/iio/devices/iio:device0# scale=`cat in_illuminance_scale`
root@stm32mp1:/sys/bus/iio/devices/iio:device0# val=`cat in_illuminance_raw`
root@stm32mp1:/sys/bus/iio/devices/iio:device0# awk "BEGIN{printf (\"%f\n\", ($val + 0) * $scale)}"
388.039835
How to use Ambient Light Sensor interrupts:
A blog on how to configure and use APDS9306 IIO event interface (interrupts) can be found here.