The ComfilePi's LCD backlight is connected to GPIO 34. The backlight can be turned on or off via the command line or via a programming language.
To turn off the backlight:
# using Bullseye raspi-gpio set 34 op raspi-gpio set 34 dl # using Buster or prior OSes gpio mode 34 output gpio write 34 0
To turn on the backlight:
# using Bullseye raspi-gpio set 34 op raspi-gpio set 34 dh # using Buster or prior OSes gpio mode 34 output gpio write 34 1
To turn off the backlight:
# using Bullseye raspi-gpio set 44 op raspi-gpio set 44 dl # using Buster or prior OSes gpio mode 44 output gpio write 44 0
To turn on the backlight:
# using Bullseye raspi-gpio set 44 op raspi-gpio set 44 dh # using Buster or prior OSes gpio mode 44 output gpio write 44 1
The backlight can be controlled in the C programming language using the pigpio library.
#include <pigpiod_if2.h> #define PIN 34 // CPi-A/B/F/S // #define PIN 44 // CPi-C void backlight_on() { auto instance = pigpio_start(NULL, NULL); set_mode(instance, PIN, PI_OUTPUT); gpio_write(instance, PIN, 1); pigpio_stop(instance); } void backlight_off() { auto instance = pigpio_start(NULL, NULL); set_mode(instance, PIN, PI_OUTPUT); gpio_write(instance, PIN, 0); pigpio_stop(instance); }
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.
To put the backlight on a timer that turns OFF after a specified timeout, and turns back ON when the screen is touched, the following program can be used.
#include <cstdio> #include <cstdint> #include <fstream> #include <unistd.h> #include <errno.h> #include <getopt.h> #include <sys/file.h> #include <linux/input.h> #include <chrono> #include <thread> #include <pigpiod_if2.h> using namespace std; using namespace std::chrono; static int instance = -1; #define PIN 34 // CPi-A & CPi-B // #define PIN 44 // CPi-C void backlight_on() { auto instance = pigpio_start(NULL, NULL); set_mode(instance, PIN, PI_OUTPUT); gpio_write(instance, PIN, 1); pigpio_stop(instance); } void backlight_off() { auto instance = pigpio_start(NULL, NULL); set_mode(instance, PIN, PI_OUTPUT); gpio_write(instance, PIN, 0); pigpio_stop(instance); } bool backlight_isOn() { auto instance = pigpio_start(NULL, NULL); set_mode(instance, PIN, PI_INPUT); auto isOn = gpio_read(instance, PIN) == 1; pigpio_stop(instance); return isOn; } int main(int argc, char* argv[]) { int secs = 60; if (argc >= 2) { secs = stoi(argv[1]); } // Touch events happen on event0 auto input_fd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK); struct input_event ev; auto lastTouch = high_resolution_clock::now(); while (true) { // get the input event auto n = read(input_fd, &ev, sizeof(ev)); // If an input event if (n != (ssize_t)-1) { if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2) { if (ev.value == 1) // If a touch { backlight_on(); lastTouch = high_resolution_clock::now(); } } } auto now = chrono::high_resolution_clock::now(); auto sec = duration_cast<seconds>(now - lastTouch).count(); if (sec > secs) { backlight_off(); } this_thread::sleep_for(milliseconds(10)); } return 0; }
g++ main.cpp -lpigpiod_if2 -lpthread -o backlight
To cause the backlight to turn OFF after 60 seconds.
backlight 60
[Unit] Description=backlight service After=pigpio.service [Service] ExecStart={path/to/}backlight 60 Restart=always [Install] WantedBy=multi-user.target
Backlight dimming can be controlled using the PWM on GPIO31 on the CPi-A & CPi-B or GPIO26 on the CPi-C. Use the pigpio library to adjust the brightness of the backlight.
#include <pigpiod_if2.h> #include <iostream> #include <string> using namespace std; #define PIN 31 // CPi-A/B/F/S // #define PIN 26 // CPi-C int main(int argc, char *argv[]) { int value = stoi(argv[1]); auto instance = pigpio_start(NULL, NULL); set_mode(instance, PIN, PI_OUTPUT); set_PWM_frequency(instance, PIN, 200); set_PWM_dutycycle(instance, PIN, value); pigpio_stop(instance); }
Compile and run:
g++ backlight.cpp -lpigpiod_if2 -lpthread -o backlight ./backlight 0 # minimum brightness ./backlight 128 # medium brightness ./backlight 255 # maximum brightness
CPi_A070WR (S/N : A01001-17-7-11 ~ A01001-17-11-91)
CPi_A102WR (S/N : A01003-17-7-1 ~ A01003-17-10-26)
The initial ComfilePi that was produced did not populate R33 on the main board's PCB. On those models, switching the LCD backlight on or off will not work unless R33 is populated. Hardware revision v2.0 populates R33 with a 22 Ohm resistor, so switching the backlight on or off will work out of the box.
To test which hardware revision you have, simply run the commands illustrated above and see if they work.
Hardware revision v2.1 connects the backlight to GPIO 31 which supports PWM. See Dimming the Backlight.