Here’s an odd one for y’all. On my FW16, when I read from the ambient light device file, my kernel logs start showing:
[ 1877.126671] i2c_designware AMDI0010:00: i2c_dw_handle_tx_abort: lost arbitration
[ 1881.760340] i2c_hid_acpi i2c-FRMW0003:00: failed to set a report to device: -121
[ 1892.001761] i2c_hid_acpi i2c-FRMW0003:00: failed to set a report to device: -121
[ 1898.283896] i2c_hid_acpi i2c-FRMW0003:00: failed to set a report to device: -121
[ 1911.720061] i2c_hid_acpi i2c-FRMW0003:00: failed to set a report to device: -121
[ 1918.568412] i2c_hid_acpi i2c-FRMW0003:00: failed to set a report to device: -121
[ 1924.870413] i2c_hid_acpi i2c-FRMW0003:00: failed to set a report to device: -121
[ 1933.504369] i2c_hid_acpi i2c-FRMW0003:00: failed to set a report to device: -121
[ 1939.694706] i2c_hid_acpi i2c-FRMW0003:00: failed to set a report to device: -121
Going down the /sys/bus rabbit hole, FRMW0003 leads to the ALS, and AMDI0010 is the Synopsys DesignWare I2C adapter. The i2c_hid_acpi logs come every few seconds, i2c_designware once every few minutes.
The sensor works just fine, and I don’t think I saw this happening on my FW13.
Hi, I am on FW 16 but this has been the only program that somewhat works
However, it sets the brightness level too high. E.g. currently I am happy with 25% and it sets the brightness all the way up to 69%.
Can I ask where in the script do you control the sensitivity? Sorry for asking but I do not have much experience with bash coding.
I don’t use illuminanced but my own custom program, sorry. I actually don’t think I’ve been seeing the kernel messages recently, but I also haven’t been looking at them much so it might not be relevant.
A modification of @Michiel_Toneman’s script with the following changes:
changed backlight variable to be based on screen_brightness rather than screen_actual_brightness, as I found that when it was set to screen_actual_brightness it would lower the brightness instantly by ~10% before smoothly raising it from there to a new value. I discovered that the screen_actual_brightness value seemed to be a slightly different value to what it actually was?
slightly changed the logic on the sensitivity check, as it seemed like if [ $backlight -lt $target ] was checking if a negative value was less than sensitivity, and so of course the negative value was ALWAYS less than the sensitivity.
The major change I made was completely redoing the way it handles manual input. Previously it would handle manual input by simply offsetting the target value by the manually offset amount. I changed it to instead wait for a specified amount of time after a user manual changed the brightness, before than continuing the script as usual with no offset at all. I also added in a condition which would stop this delay immediately should the manual_sensitivity threshold be exceeded. So basically when the dsiplay brightness is changed by something other than the script, it will either wait for 20 minutes(this can be changed) or until there is a drastic lighting change.
I am running a framework 16 with the fedora plasma kde spin. I’m new to linxu and really appreciate this script @Michiel_Toneman wrote. These (mostly) small changes make it work just a little more seamlessly for me.
#!/bin/bash
# Bash script to automatically control the backlight brightness using the illumination sensor
# Written because the Gnome 45.4 auto brightness is not smooth unlike my previous MacOS laptop
# which was driving me insane.
#
# Features:
# * smooth, flicker-free ramping
# * sensitivity and delay to prevent constant adjustments
# * manual adjustment though backlight keys or software(*)
# * should work on all Framework 13 AMD and Intel laptops (**)
#
# (*) manual adjustment can be a bit glitchy at times
# (**) Intel has not yet been tested
#
# Michiel Toneman 2024, Modified by Donovan
# Released under the Apache License V2.0
# Define the appropriate devices for Intel and AMD systems
if [ -f /sys/class/backlight/intel_backlight/brightness ]
then
screen_brightness=/sys/class/backlight/intel_backlight/brightness
screen_actual_brightness=/sys/class/backlight/intel_backlight/brightness
screen_max_brightness=/sys/class/backlight/intel_backlight/max_brightness
else
screen_brightness=/sys/class/backlight/amdgpu_bl1/brightness
screen_actual_brightness=/sys/class/backlight/amdgpu_bl1/actual_brightness
screen_max_brightness=/sys/class/backlight/amdgpu_bl1/max_brightness
fi
# Set some constants
max=$(cat $screen_max_brightness)
min=0
sensitivity=$((max/10))
manual_sensitivity=$((max/5))
delay=5 # Check every 5 seconds
manual_delay=20 # wait 20 minutes before auto adjusting
debug=0 # Set to 1 for debug output
# Variables
last_target=$(cat $screen_brightness) # Start the target brightness at the current screen brightness
# Loop
while [ 1 ]
do
doupdate=0
# Get the current state of the backlight and illuminance sensor
target=$(cat /sys/bus/iio/devices/iio:device0/in_illuminance_raw)
backlight=$(cat $screen_brightness)
# If the backlight has been manually changed since the last
# change by the script, then the script will not adjust the brightness
# again until the time (in minutes) specified manual_delay has elapsed,
# OR if the difference between the new sensor reading and the sensor reading on the
# last script change exceeds the manual_sensitivity
if [ $((backlight - last_target)) -ne 0 ]
then
manual_delay_seconds=$((manual_delay*60))
for (( i=0 ; i<$manual_delay_seconds ; i+=$delay ));
do
if [ $debug -eq 1 ]
then
echo “manual delay left: $((manual_delay-$((i/60)))) minutes“
fi
# update target to match the current sensor reading
target=$(cat /sys/bus/iio/devices/iio:device0/in_illuminance_raw)
# check if the lighting has changed enough to warrant auto brightness taking effect again
if [ $last_target -gt $target ]
then
if [ $((last_target - target)) -gt $manual_sensitivity ]
then
if [ $debug -eq 1 ]
then
echo “stopping manual delay due to low target“
fi
i=$manual_delay_seconds
fi
fi
if [ $last_target -lt $target ]
then
if [ $((target - last_target)) -gt $manual_sensitivity ]
then
if [ $debug -eq 1 ]
then
echo “stopping manual delay due to high target“
fi
i=$manual_delay_seconds
fi
fi
sleep $delay
done
fi
backlight=$(cat $screen_brightness)
# so that we don't keep changing brightness all the time
if [ $backlight -gt $target ]
then
if [ $((backlight - target)) -gt $sensitivity ]
then
doupdate=1
fi
fi
if [ $backlight -lt $target ]
then
if [ $((target - backlight)) -gt $sensitivity ]
then
doupdate=1
fi
fi
# Check that we don't exceed the min and max brightness values
if [ $target -gt $max ]
then
target=$max
fi
if [ $target -lt $min ]
then
target=$min
fi
if [ $doupdate -eq 1 ]
then
# Debug logging
if [ $debug -eq 1 ]
then
echo “Starting brightness: $backlight”
echo “Brightness: $(cat $screen_brightness)“
echo “Adjusted brightness: $target”
echo “-------------------------------”
echo “Sensitivity: $sensitivity”
echo “Min: $min Max: $max”
echo
fi
# Now change the brightness smoothly in single value in/decrements per 20ms
intermediate=$backlight
while [ $intermediate -ne $target ]
do
if [ $intermediate -lt $target ]
then
((intermediate++))
else
((intermediate--))
fi
echo $intermediate > $screen_brightness
sleep 0.02
done
# Remember what the target brightness was
# If the next time round the last target brightness differs from the current backlight value
# then the assumption is that someone has manually adjusted the brightness and we can use that delta
last_target=$target
fi
sleep $delay
done
I reinstalled my laptop OS, so it is time to check with you all if there are improvements for this ambient light sensor.
@Donovan_Rainey I tried your script in a Ubuntu service the way I described previously and it didn’t work out. I guess it is discrepancies between Fedora and Ubuntu that makes it incompatible.
Thank you so much for this script, it’s incredible and just worked immediately (after disabling the crap built in one on Ubuntu). Almost wish Ubuntu/Gnome would just take this and use it instead of whatever they’re currently doing.