====== Synchronizing the Backlight with the X11 Screensaver ======
This program will turn the backlight ON or OFF according to the ON/OFF state of the display as reported by [[https://www.x.org/releases/X11R7.7/doc/xextproto/dpms.html|DPMS]] (run ''xset q'' from a terminal to see the DPMS report).
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace std::chrono;
#define PIN 34 // CPi-A/B/F/S
// #define PIN 44 // CPi-C
void log_info(const char *const message)
{
printf("%s\n", message);
syslog(LOG_INFO, "%s", message);
}
void log_err(const char *const message)
{
printf("%s\n", message);
syslog(LOG_ERR, "%s", message);
}
void backlight_on()
{
auto instance = pigpio_start(NULL, NULL);
if (instance != 0)
{
log_err("pigpio_start did not return success");
return;
}
auto result = set_mode(instance, PIN, PI_OUTPUT);
if (instance != 0)
{
log_err("set_mode did not return success");
return;
}
result = gpio_write(instance, PIN, 1);
if (instance != 0)
{
log_err("gpio_write did not return success");
return;
}
pigpio_stop(instance);
}
void backlight_off()
{
auto instance = pigpio_start(NULL, NULL);
if (instance != 0)
{
log_err("pigpio_start did not return success");
return;
}
auto result = set_mode(instance, PIN, PI_OUTPUT);
if (instance != 0)
{
log_err("set_mode did not return success");
return;
}
result = gpio_write(instance, PIN, 0);
if (instance != 0)
{
log_err("gpio_write did not return success");
return;
}
pigpio_stop(instance);
}
void set_backlight(CARD16 state)
{
switch (state)
{
case DPMSModeOn:
log_info("Turning backlight on");
backlight_on();
break;
case DPMSModeOff:
log_info("Turning backlight off");
backlight_off();
break;
default:
log_info("Invalid state");
break;
}
}
int main(int argc, char *argv[])
{
openlog("backlight_service", LOG_NDELAY, LOG_USER);
log_info("Starting");
Display *dpy;
dpy = XOpenDisplay(NULL);
if (dpy == NULL)
{
log_err("Unable to open display");
exit(EXIT_FAILURE);
}
BOOL onoff;
CARD16 last_state;
CARD16 state;
// Initialize last_state
if (!DPMSInfo(dpy, &state, &onoff))
{
log_err("DPMSInfo returned FALSE");
}
set_backlight(state);
last_state = state;
while(true)
{
if (!DPMSInfo(dpy, &state, &onoff))
{
log_err("DPMSInfo returned FALSE");
this_thread::sleep_for(seconds(2));
continue;
}
// If DPMS is not enabled, then display a message
if (!onoff)
{
log_err("DPMSInfo is not enabled");
this_thread::sleep_for(seconds(2));
continue;
}
if (last_state != state)
{
set_backlight(state);
last_state = state;
}
this_thread::sleep_for(milliseconds(200));
}
XCloseDisplay(dpy);
log_info("Exiting");
return 0;
}
==== Compile ====
Add the necessary development packages ...
sudo apt install libx11-dev libxext-dev
... then compile.
g++ backlight_service.cpp -lX11 -lXext -lpigpiod_if2 -o backlight_service
==== Bash Script Implementation ====
The same can be a achieved using the following Bash script:
#!/bin/bash
PWM_PIN=31
PIN=34
# Set pins as output
raspi-gpio set $PWM_PIN op
raspi-gpio set $PIN op
# Start with both pins HIGH. If either of the
# pins go LOW, the backlight will turn off.
raspi-gpio set $PWM_PIN dh
raspi-gpio set $PIN dh
# Get the current state
CURRENT_STATUS=$(xset q | grep "Monitor is" | awk '{print $3}')
LAST_STATUS=$CURRENT_STATUS
logger -p info -t "backlight_service" -s "Monitor is $CURRENT_STATUS"
# Loop indefinitely updating backlight in sync with monitor status
while true; do
# Check the current monitor status
CURRENT_STATUS=$(xset q | grep "Monitor is" | awk '{print $3}')
# Only turn the backlight on/off if the Monitor state has changed
if [ "$CURRENT_STATUS" != "$LAST_STATUS" ]; then
logger -p info -t "backlight_service" -s "Monitor is $CURRENT_STATUS"
# Control backlight pin according to the monitor status
if [ "$CURRENT_STATUS" = "On" ]; then
logger -p info -t "backlight_service" -s "Turning Backlight On"
raspi-gpio set $PIN dh
else
logger -p info -t "backlight_service" -s "Turning Backlight Off"
raspi-gpio set $PIN dl
fi
LAST_STATUS=$CURRENT_STATUS
fi
# Sleep before checking again
sleep 0.2s
done
==== Automatically Start the Service ====
Add the line ''@{/path/to/}backlight_service'' to the // /etc/xdg/lxsession/LXDE-pi/autostart // file or to the file // .config/lxsession/LXDE-pi/autostart // in the user's home directory to automatically start the //backlight_service// executable when the desktop starts. See [[comfilepi:configure_a_program_to_auto-start:index#configure_an_x_program_to_auto-start_eg_mono|Configure an X Program to Auto-Start]] for more information.
To set the timeout to 60 seconds run ''xset dpms 0 0 60'' from a terminal.
Add the line ''@xset dpms 0 0 {timeout_in_seconds}'' to the //autostart// file to set the timeout each time the desktop loads.
Run ''journalctl -t backlight_service -r'' to view the log entries.