# Automated keyboard and numpad backlight control with ambient light sensor

**URL:** <https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603>\
**Category:** Framework Laptop 16\
**Tags:** framework-laptop-16-amd-7040, windows\
**Created:** [May 23, 2025, 6:22am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603 "2025-05-23T06:22:40Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Positron7120](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@Positron7120](https://community.frame.work/u/Positron7120)\
**Post date:** [May 23, 2025, 6:22am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/1 "2025-05-23T06:22:40Z")

</div>

framework already has a published [GUI interface](https://github.com/FrameworkComputer/qmk_hid) for controlling the backlight of the number pad and keyboard together. How can I use that to change the backlight of both the modules based on the ambient light sensor?

I have seen that the keyboard backlight of MacBooks automatically turn on in a dark or poorly lit room I would like to have that same for my framework 16.

I have zero experience with QMK and wanted to learn more about.

My OS currently is Windows 10 Pro.

---

<div class="post-metadata">

**Author:** ![TheLPeink](https://avatars.discourse-cdn.com/v4/letter/t/e95f7d/32.png) [@TheLPeink](https://community.frame.work/u/TheLPeink)\
**Post date:** [May 23, 2025, 10:16am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/2 "2025-05-23T10:16:04Z")

</div>

This would be very nice. I have no idea about how to access the light sensor from the OS, but if you manage to read the values it could definetly be done…

A quick search got me [this](https://github.com/MicrosoftDocs/winrt-api/blob/docs//windows.devices.sensors/lightsensor_getdefault_846721868.md) from Reddit. Maybe useful!

---

<div class="post-metadata">

**Author:** ![Positron7120](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@Positron7120](https://community.frame.work/u/Positron7120)\
**Post date:** [July 11, 2025, 8:27am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/3 "2025-07-11T08:27:07Z")

</div>

But how would I implement it in the QMK code?

---

<div class="post-metadata">

**Author:** ![MJ1](https://sea1.discourse-cdn.com/flex001/user_avatar/community.frame.work/mj1/32/15519_2.png) [@MJ1](https://community.frame.work/u/MJ1)\
**Post date:** [July 11, 2025, 9:42am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/4 "2025-07-11T09:42:07Z")

</div>

> [@Positron7120](#):
>
> But how would I implement it in the QMK code?

Don’t need to. Use qmk\_hid, only not the GUI. A script can use qmk\_hid via command line. `--backlight [brightness percentage]`

---

<div class="post-metadata">

**Author:** ![Positron7120](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@Positron7120](https://community.frame.work/u/Positron7120)\
**Post date:** [July 11, 2025, 10:06am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/5 "2025-07-11T10:06:53Z")

</div>

I am quite new to this and do not what to do. Can you direct me to a resource where I can understand what I need to do?  
Thanks!

---

<div class="post-metadata">

**Author:** ![MJ1](https://sea1.discourse-cdn.com/flex001/user_avatar/community.frame.work/mj1/32/15519_2.png) [@MJ1](https://community.frame.work/u/MJ1)\
**Post date:** [July 12, 2025, 3:59am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/6 "2025-07-12T03:59:52Z")

</div>

If you’re asking about the windows scripting part, I can’t help there, I don’t use windows. I don’t know what’s good and easy.

For the qmk part, the part that is controlling the keyboard backlights, that I can help with. For example, this should be the command to set the numpad backlight to 50 percent: `qmk_hid --vid 32ac --pid 0014 via --backlight 50`

Here are the pid “product ID” codes for FWL16 keyboards

vid : pid  
32ac:0012 Framework Laptop 16 Keyboard Module - ANSI  
32ac:0013 Framework Laptop 16 RGB Macropad  
32ac:0014 Framework Laptop 16 Numpad Module  
32ac:0018 Framework Laptop 16 Keyboard Module - ISO  
32ac:0019 Framework Laptop 16 Keyboard Module - JIS

So the way you might want it to go is, the script checks the ambient light sensor, perhaps using the api that [TheLPeink](https://community.frame.work/u/TheLPeink) linked to, stores the value, checks if the value differs more than a choosen threshold from the last check, if it does, then ramp the keyboard backlights to match by sending repeated commands to change the backlights progressively.

---

<div class="post-metadata">

**Author:** ![Positron7120](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@Positron7120](https://community.frame.work/u/Positron7120)\
**Post date:** [July 12, 2025, 4:14am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/7 "2025-07-12T04:14:55Z")

</div>

Okay thank you! I will try to figure it out.

---

<div class="post-metadata">

**Author:** ![MJ1](https://sea1.discourse-cdn.com/flex001/user_avatar/community.frame.work/mj1/32/15519_2.png) [@MJ1](https://community.frame.work/u/MJ1)\
**Post date:** [July 12, 2025, 4:20am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/8 "2025-07-12T04:20:48Z")

</div>

Which keyboards do you have?

---

<div class="post-metadata">

**Author:** ![Positron7120](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@Positron7120](https://community.frame.work/u/Positron7120)\
**Post date:** [July 12, 2025, 5:34am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/9 "2025-07-12T05:34:11Z")

</div>

ANSI and the numpad and I did try a PowerShell script with a lot of help from grok, but it seems that the ambient light sensor is not accessible using the API [TheLPeink](https://community.frame.work/u/TheLPeink) linked to. Here is the script that grok gave me.

```auto
# Framework Laptop 16 Keyboard Backlight Control Script
# Controls backlight for PIDs 0012 and 0014 using ambient light sensor and display state
# Requires qmk_hid tool installed and accessible

# Configuration
$QMK_HID_PATH = "qmk_hid" # Path to qmk_hid.exe (update if not in PATH)
$BRIGHT_ENOUGH_THRESHOLD = 100 # Lux value where keys are visible without backlight
$POLL_INTERVAL = 1 # Seconds between checks
$DEVICE_PIDS = @("0012", "0014") # Framework Laptop 16 keyboard PIDs (ANSI Keyboard, Numpad)
$VID = "32ac" # Framework vendor ID

# Logging setup
$LogFile = "$PSScriptRoot\backlight_control.log"
function Write-Log {
    param($Message)
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    "$timestamp - $Message" | Out-File -FilePath $LogFile -Append
    Write-Host "$timestamp - $Message"
}

# Function to set backlight brightness for a device
function Set-BacklightBrightness {
    param (
        [string]$PID,
        [int]$Brightness
    )
    if ($Brightness -lt 0 -or $Brightness -gt 100) {
        Write-Log "Invalid brightness value: $Brightness"
        return
    }
    try {
        $command = "& $QMK_HID_PATH --vid $VID --pid $PID via --backlight $Brightness"
        Write-Log "Executing: $command"
        Invoke-Expression $command
    } catch {
        Write-Log "Error setting backlight for PID $PID : $_"
    }
}

# Function to get ambient light sensor value
function Get-AmbientLight {
    try {
        Add-Type -TypeDefinition @"
            using System;
            using System.Runtime.InteropServices;
            public class PowerManagement {
                [DllImport("user32.dll")]
                public static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, int Flags);
                [DllImport("user32.dll")]
                public static extern bool UnregisterPowerSettingNotification(IntPtr handle);
                public static readonly Guid GUID_MONITOR_POWER_ON = new Guid("02731015-4510-4526-99e6-e5a17ebd1aea");
            }
"@
        $lightSensor = [Windows.Devices.Sensors.LightSensor]::GetDefault()
        if ($null -eq $lightSensor) {
            Write-Log "No ambient light sensor found."
            return $null
        }
        $reading = $lightSensor.GetCurrentReading()
        if ($null -eq $reading) {
            Write-Log "Failed to read ambient light sensor."
            return $null
        }
        $lux = $reading.IlluminanceInLux
        Write-Log "Ambient light: $lux lux"
        return $lux
    } catch {
        Write-Log "Error reading ambient light sensor: $_"
        return $null
    }
}

# Function to check if display is off
function Test-DisplayOff {
    try {
        $monitorOn = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorPowerOn
        $isOff = $monitorOn | Where-Object { $_.MonitorPowerOn -eq $false }
        if ($isOff) {
            Write-Log "Display is off."
            return $true
        }
        Write-Log "Display is on."
        return $false
    } catch {
        Write-Log "Error checking display state: $_"
        return $false
    }
}

# Main loop
function Start-BacklightControl {
    Write-Log "Starting backlight control script."
    while ($true) {
        try {
            # Check display state
            if (Test-DisplayOff) {
                foreach ($pid in $DEVICE_PIDS) {
                    Set-BacklightBrightness -PID $pid -Brightness 0
                }
                Start-Sleep -Seconds $POLL_INTERVAL
                continue
            }

            # Read ambient light
            $lux = Get-AmbientLight
            if ($null -eq $lux) {
                Start-Sleep -Seconds $POLL_INTERVAL
                continue
            }

            # Adjust backlight
            if ($lux -gt $BRIGHT_ENOUGH_THRESHOLD) {
                $brightness = 0 # Turn off in bright conditions
            } else {
                # Map lux to brightness (0-100%)
                $brightness = [math]::Max(0, [math]::Min(100, [int]((1 - $lux / $BRIGHT_ENOUGH_THRESHOLD) * 100)))
            }
            Write-Log "Setting brightness to $brightness%"
            foreach ($pid in $DEVICE_PIDS) {
                Set-BacklightBrightness -PID $pid -Brightness $brightness
            }
        } catch {
            Write-Log "Unexpected error: $_"
        }
        Start-Sleep -Seconds $POLL_INTERVAL
    }
}

# Start the script
try {
    Start-BacklightControl
} catch {
    Write-Log "Script terminated: $_"
}

```

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex001/uploads/framework3/original/1X/64c81a89f963ddb07633887baceb642a4b056046.png) [@system](https://community.frame.work/u/system)\
**Post date:** [January 8, 2026, 5:34am UTC](https://community.frame.work/t/automated-keyboard-and-numpad-backlight-control-with-ambient-light-sensor/69603/10 "2026-01-08T05:34:21Z")

</div>

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
