[TRACKING] "auto-brightness" aka ambient light sensor in Linux? Details?

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 was trying to set up the same thing today via GitHub - mikhail-m1/illuminanced: Ambient Light Sensor Daemon for Linux and I am not able to set it up. Basically sensors responds with the correct value but it does not change the brightness.
Have you managed to solve it?

Hi, I am on FW 16 but this has been the only program that somewhat works :smiley:
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.

Also, I found out that the your script on the pastebin has these shenanigans set on: newline - Bash script – "/bin/bash^M: bad interpreter: No such file or directory" - Stack Overflow
So maybe could you re-run sed -i -e 's/\r$//' scriptname.sh on it and update?

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.

I have also tried a script that got posted somewhere above and and I have seen zero issues with it…

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

1 Like

I got it working, however, I’m still trying to understand and tweak the set points.

For my different office and late night couch setups, it’s responding okay-ish for now.

Though, the developer itself is not really sure how it all works.