This program will turn the backlight ON or OFF according to the ON/OFF state of the display as reported by DPMS (run xset q from a terminal to see the DPMS report).
#include <cstdlib> #include <cstdio> #include <X11/Xlib.h> #include <X11/extensions/dpms.h> #include <chrono> #include <thread> #include <sys/syslog.h> #include <pigpiod_if2.h> 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; }
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
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
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 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.