How to automatically control the display brightness of your Raspberry Pi photo frame

Changing the display brightness via software is really difficult to do from a Raspberry Pi. It works with some selected displays, but for the large majority, it doesn’t. But there is a workaround.

With a digital picture frame, you may want to automatically dim the screen a little bit in the evening so that it doesn’t shine too bright in the room.

Fortunately, this functionality is now available in the latest release of the PictureFrame image viewer.

Tested with: Raspberry Pi OS March 2021 version, Raspberry Pi 2, 3, and 4, Pi3D 2.43, PictureFrame 2021.03.20, 1080p and 4K displays.

How it works

In my Raspberry Pi digital picture frame setup tutorial, I mention the Pi3D PictureFrame image viewer, which produces those wonderful crossfading image transitions.

It turns out that the same image algorithms can be used to reduce the brightness of an image.

The brightness can be controlled via MQTT or Home Assistant, which means that you can remote control it from mobile devices or simply through a time-controlled Python script.

In this article, I will show you how to do it either way.

Remote control via MQTT

The new parameter to control the brightness variable is unsurprisingly called “brightness”.

The payload value can range from “0.0” (nothing to see here) to “1.0” (full brightness).

So, if your device ID is called “picframe”, and you wanted to dim your screen to 80%, you would send a message like

mosquitto_pub -h localhost -t picframe/brightness -m "0.8"

If you want to know how this works with Apple devices, check here, for Android, here.

Control the brightness automatically with sunrise/sunset

Rather than manually changing the screen’s brightness, in most cases, an automation will be fine for most of the cases.

This is easy to do with a Python script.

First install the astral package.

 sudo pip install astral

Create a new file and paste this code. Save as “brightness_automation.py”.

#!/usr/bin/python3
import logging
import time
import traceback
from datetime import datetime
import paho.mqtt.client as mqtt
from astral import LocationInfo
from astral.sun import sun
from pytz import timezone

logging.basicConfig(filename="log.txt",format="%(asctime)s-%(levelname)s-%(message)s",level=logging.DEBUG)

MQTT_HOST="localhost" #enter your MQTT server here
MQTT_PORT=1883
#MQTT_USER=""
#MQTT_PASWD=""

completed=False
connected=False

def on_connect(client, userdata, flags, rc):
    print("Connected. %d." % (rc))
    global connected
    connected=True
    update_brightness()
    
def update_brightness():
    
    city = LocationInfo(name="Bad Soden am Taunus", region="Germany", timezone="Europe/Berlin", latitude=50.1420634310433, longitude=8.496851921081545) #enter your location info here
    c_data = sun(city.observer, tzinfo=city.timezone)

    dawn=str(c_data["dawn"])
    sunrise=str(c_data["sunrise"])
    sunset=str(c_data["sunset"])
    dusk=str(c_data["dusk"])
    current_local_time=datetime.now(tz=timezone(city.timezone))

    print("Current Time: ",current_local_time)
    print("Dawn: " + dawn)
    print("Sunrise: " + sunrise)
    print("Sunset: " + sunset)
    print("Dusk: " + dusk)

    dawn=datetime.fromisoformat(dawn)
    sunrise=datetime.fromisoformat(sunrise)
    sunset=datetime.fromisoformat(sunset)
    dusk=datetime.fromisoformat(dusk)

    bright_val=1.0

    if current_local_time>=dawn and current_local_time<sunrise: #this is where you adjust your brightness settings depending on sunrise and sunset
        bright_val=0.9
    elif current_local_time>=sunrise and current_local_time<sunset:
        bright_val=1.0
    elif current_local_time>=sunset and current_local_time<dusk:
        bright_val=0.9
    else:
        bright_val=0.8

    print("Brightness: ",bright_val)
    # publish screen brightness value
    client.publish("picframe/brightness", bright_val, qos=0, retain=True)
    global completed
    completed=True

if __name__ == "__main__":
    try:
        # MQTT Broker
        client = mqtt.Client()
        client.on_connect=on_connect
        client.username_pw_set(username=MQTT_USER,password=MQTT_PASWD)
        client.connect(host=MQTT_HOST,port=MQTT_PORT,keepalive=60)
        client.loop_start()
        while completed!=True:
            time.sleep(0.01)
            if not connected:
                print(".",end="")
    except:
        traceback.print_exc()
        logging.error("Error",exc_info=True)

Adjust the values in your script as it works best with your screen and the room environment.

To start it automatically at boot and keep it running in the background, create a service with systemd.

Enter

sudo nano /etc/systemd/system/brightness_control.service

Paste the following text into the editor window

[Unit]
Description=Control display brightness automatically
After=multi-user.target

[Service]
Type=idle
User=root
ExecStart=/usr/bin/python3 /home/pi/brightness_automation.py
Restart=always
RestartSec=300

[Install]
WantedBy=multi-user.target

Save and close.

Now change the file permissions with

sudo chmod 644 /etc/systemd/system/brightness_control.service

and update the services with

sudo systemctl daemon-reload
sudo systemctl enable brightness_control.service

Reboot.

Conclusion

Being able to soft-control your screen’s brightness through the Pi3D image viewer allows you to hide any monitor controls that you would otherwise need access to.

You could obviously also attach a brightness sensor, but I didn’t want to drill a hole in the frame. But if someone has a great idea how to do this without showing a fat sensor on the front of the frame, please contact me.

Thank You, Paddy, for a great addition to the PictureFrame script.

Was this article helpful?


Thank you for your support and motivation.


Scroll to Top