Unfortunately PiBox and KubeSail ended operations in September 2025. I had not used my PiBox too much, just as a scratchpad for WordPress. I decided to reflash it with Raspbian. Below are the steps that I took to reuse my PiBox.
I’m using a Windows PC to flash the PiBox. I followed the directions at https://docs.kubesail.com/guides/pibox/rpiboot/. One thing that was not clear is that rpiboot.exe should be run before plugging the PiBox into the PC. It looked like there were errors but it still works. The errors are about optional files for configuring the connection, so they may be ignored. The connection is slow even with a high quality USB-C to USB-C cable.
Remove the cover from the PiBox and move the internal switch from “normal” to “rpiboot”.
Remove the carrier board from the backplane
Run rpiboot.exe on the PC.
Plug the PiBox into the PC using a USB-C Cable.
Open Raspberry Pi Imager.
Click Storage and make certain that the PiBox is showing as “RPi-MSD- 0001”.
Click “Choose Device” and select “No filtering”.
Click Operating System and select the 64-bit version you wish to install.
Click the “Next” button to write the image to the PiBox.
Once the image is written and verified, unplug the PiBox from the PC.
Move the internal switch from “rpiboot” to “normal”.
Reassemble the PiBox.
Updating Raspbian
If SSH is enabled and the Wi-Fi settings are configured or it is connected via ethernet , you may open an SSH session to run commands. If not, you may need to connect a monitor and keyboard to continue.
sudo apt update sudo apt upgrade
Setup SSD Drives
I have two 1TB Samsung SSDs installed. I wanted to wipe them and remount them to the PiBox. Below are the steps that I followed.
/dev/sda
Run the parted tool sudo parted /dev/sda
Change the units used by parted unit s
Delete the existing partitions
Run the print command to list all the partitions. print
Remove each partition (Repeat if more than one partition is present.) rm 1
Create a single partition for the whole drive mkpart primary ext4 0% 100%
Exit parted quit
Format the partition sudo mkfs.ext4 -L data1 /dev/sda1
Create a mounts point for the drive (The rancher mount point is only so it will display on the LCD display.) sudo mkdir -p /var/lib/rancher
/dev/sdb
Run the parted tool sudo parted /dev/sdb
Change the units used by parted unit s
Delete the existing partitions
Run the print command to list all the partitions. print
Remove each partition (Repeat if more than one partition is present.) rm 1
Create a single partition for the whole drive mkpart primary ext4 0% 100%
Exit parted quit
Format the partition sudo mkfs.ext4 -L data2 /dev/sdb1
Create a mount point for the drive sudo mkdir -p /mnt/data2
Update fstab
Open text editor to edit fstab sudo nano /etc/fstab
Add the following lines /dev/sda1 /var/lib/rancher ext4 defaults,nofail,noatime,discard,errors=remount-ro 0 0
Clone the PiBox OS Scripts git clone https://github.com/kubesail/pibox-os.git
Change to the Fan folder cd pibox-os/pwm-fan
Uncompress the Fan scripts tar zxvf bcm2835-1.68.tar.gz
Change to the Fan scripts folder cd bcm2835-1.68
Run the make command ./configure && make && sudo make install
Go to the parent folder cd ..
Make and run the installation make && sudo make install
The fan should run quieter now.
Optimize system for EMMC
Store system logs in memory, instead of writing to disk, and lower log verbosity sudo sed -i "s/#Storage.*/Storage=volatile/" /etc/systemd/journald.conf
sudo sed -i 's/.MaxLevelStore.*/MaxLevelStore=info/' /etc/systemd/journald.conf
sudo sed -i 's/.MaxLevelSyslog.*/MaxLevelSyslog=info/' /etc/systemd/journald.conf
sudo systemctl restart systemd-journald.service
Disable swapfile sudo swapoff -a sudo dphys-swapfile swapoff
Mount /var/tmp as tmpfs filesystems to extend EMMC lifetime echo "tmpfs /var/tmp tmpfs defaults,noatime,nosuid,nodev,noexec,mode=0755,size=1M 0 0" | sudo tee -a /etc/fstab
Optional if you want the ability to control the top RGB LED
Install the RPi.GPIO library. sudo apt install python3-RPi.GPIO
Open Nano to create a script file. nano blinkLED.py
import RPi.GPIO as GPIO
import time
# Red 17
# Green 27
# Blue 23
leds = [17, 27, 23]
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
for led in leds:
GPIO.setup(led, GPIO.OUT)
for led in leds:
for i in range(3):
GPIO.output(led, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(led, GPIO.LOW)
time.sleep(0.5)
# Commented next line so the LED stays off.
# Added GPIO.setwarnings(False) at the start of the script
# to hide warnings that the channel is in use on future runs.
# GPIO.cleanup()
Run the script and observe the top LED on the front of the PiBox. python ./blinkLED.py
It is recommended to use Home Assistant with a wired connection, however you may need or want to use a Wi-Fi connection. Follow these steps to setup a Wi-Fi connection within Home Assistant.
Setup Wi-Fi
Navigate to your Home Assistant server and login.
Select Settings near the bottom of the left menu, then click on “System”.
Select “Network” from the System Options.
Click the “wlan0” tab in “Configure network interfaces” then click the “Search networks” button.
Select the network SSID from the list, select the encryption method and enter the password. Once finished, click the “Save” button.
You may now connect to Home Assistant using the Wi-Fi address if needed. You may view the IP address by expanding the “IPv4” box under the “wlan0” tab of the “Configure network interfaces”.
You have successfully connected Home Assistant server to your Wi-Fi network.
I can’t believe I have not written up my Home Assistant setup. Perhaps that is a good thing as I needed to become comfortable with the setup and how to use it. I’ve been using it for nearly a year at this point. What prompted me to do a writeup now is I’m setting up another one for my mom so I can control some things remotely and to help her manage some things around the house.
My current installation was on a Raspberry Pi 4 setup to boot from a USB drive. This has been working well, but I’m setting up a Raspberry Pi 5 for mom’s installation with a NVMe SSD drive as the boot device.
Bill of Materials for this project
All product links are affiliate links to Amazon Products.
The first step is fitting the NVMe hat to the Raspberry Pi 5. I have found that the 3cm cable that came with my hat did not work properly. I purchased a set of cables to swap out and found that the 3cm cable in the new set had the same issue. I tried the longer 5cm cable and the hat worked well. I would have thought that a shorter cable would be better but I suspect that there is an impedance or timing mismatch with the shorter cable.
When I travel, I need to have a second monitor. I have a small Wisecoco monitor that I purchased from Amazon. It works well, but it is one more thing that I take with me when I travel. I had thought about turning my iPad mini into a monitor as it is about the same size as the Wisecoco monitor.
I started looking around and found some options, but not pleased as many seem to require an internet connection or at least a monthly subscription. I don’t mind paying a small fee for software so I can use it for many years but do not want to pay on a reoccurring basis for something that will only be used occasionally.
I found a blog post on Joey’s Retro Handhelds that talked about setting up Apollo on the PC and using a client such as Moonlight on the iPad to add the iPad as a second monitor. I was able to follow the post at https://www.joeysretrohandhelds.com/guides/apollo-artemis-streaming-setup-guide/ and have it setup in no time. I did run into one issue while playing Udemy videos, but there is a quick fix in Chrome, which is to disable graphics acceleration in the System settings. Once I did that, I could use the iPad. The audio does play on both the iPad and PC no matter which way the audio settings are setup. I will need to play with it a bit more to have it only on one or the other. This has an easy workaround, which is to mute the audio on one of the devices.
Hope this helps you lighten your load and increase your productivity on the road.
When working with a Raspberry Pi, you will need to format an SD Card to boot the Raspberry Pi the first time. The most straight forward way to get the Raspberry Pi Operating System (OS), Raspbian, onto an SD Card is to use the Raspberry Pi Imager software. It may be downloaded by visiting https://www.raspberrypi.com/software/.
There are alternative methods for flashing the OS to an SD Card, such as balenaEtcher, but they will not be covered in this guide.
Materials Needed
SD Card – Most Raspberry Pi boards use microSD cards. The original Raspberry Pi boards used a full-size SD card.
PC with SD Card Reader – This may be Linux, Windows, or Mac.
Optional – If your PC has only a full size SD Card reader, you will need a microSD to SD card adapter.
Steps for Flashing the SD Card
Once you have Raspberry Pi Imager installed, you may follow the steps below to flash the OS to the SD Card.
Click the “Choose Device” button and select the Raspberry Pi model from the list. In the following examples, “Raspberry Pi 3” will be used. Replace “Raspberry Pi 3” to match your Raspberry Pi board.
Click the “Choose OS” button and select “Raspberry Pi OS (64-bit)”. NOTE: Raspberry Pi 1 and 2 as well as Raspberry Pi Zero and Zero W only support 32-bit OS. For those models, select 32-bit OS rather than a 64-bit OS. (64-bit should not be an option if one of those devices are selected.)
Click the “Choose Storage” button and select the SD Card from the list.
Click the “Next” button and follow the prompts. Once the card is validated and you receive a confirmation message that the image has been written to the SD Card, remove the card from the computer and move it to the Raspberry Pi Zero 2 W board and power it on.
When using a touchscreen with your Raspberry Pi, depending on the screen size, you may soon be annoyed with the amount of screen real estate the on-screen keyboard utilizes. While it can be useful if you do not have a keyboard attached, it can make it difficult if not impossible to complete forms an know what you are entering.
You may want to connect a physical keyboard via USB or Bluetooth but find that the on-screen keyboard pops up anyway. How do you disable it? Follow the steps below to disable the on-screen keyboard for touch screens.
Go to the Start Menu and select Preferences > Raspberry Pi Configuration.
Go to the Display Tab, then select “Disabled” from the On-screen Keyboard option.
Click the “OK” button.
If prompted to reboot, select “Yes”
You will find that the on-screen keyboard no longer blocks the screen content.
I had built a Photobooth in 2019 based on Wyolum’s Raspberry Pi Photobooth project as posted in Make Magazine. Caroline Dunn made a YouTube video of her build, which explains different aspects of the project.
I had two events where the photobooths could be used, so I pulled them off the self and tested them. The first one started just fine, but the SD Card soon became corrupted and would no longer boot. I flashed the SD Card with the latest Raspbian OS and installed the software, but it would not run. There have been changes to Raspbian and in particular with Python on the latest Raspbian build which will not allow the previous code to run. The Wyolum TouchSelfie project has not been updated in 6 years, so there have been no updates to allow it to run on the latest Raspbian distribution. There is the option of using the older distribution, but I did not want to take that path.
I moved forward by attempting to make fixes to the software but ran into several issues, which led me to do a complete rewrite. Not all features are working at this time, but the important ones, such as taking the photo, creating collages & animated GIFs, adding frames with logos, and uploading the photos to a Google Album are working. I also have some ideas for taking the project further, which will be covered at the end.
Bill of Materials (BOM)
Raspberry Pi 3 or newer I would recommend a Raspberry Pi 4 or 5 as it may handle rendering of the photos better than the Raspberry Pi 3, although the Raspberry Pi 3 works well.
Raspberry Camera Module 2 or newer with cable NOTE: Raspberry Pi 5 requires a different cable than earlier versions.
Raspberry Pi 7″ touch screen NOTE: The original Raspberry Pi 7″ touch screen (800×600) was used but the new version 2 (720×1280) will work as well. Raspberry Pi 5 requires a different cable than earlier versions.
Power Supply NOTE: The official Raspberry Pi Power Adapter for the Raspberry Pi 3 was not sufficient. It required a 12W iPad charger to work. Amazon has some Anker 2-Pack Dual Port 12W USB A Charger Blocks that I purchased, which work as well.
(Optional)Waveshare Barcode Scanner Module Plugs into Raspberry Pi USB port and Acts like a keyboard. Makes it convenient to run specific commands or shortcuts without connecting a keyboard. Also may be used to enter email addresses for sending photos.
(Optional)GPS USB Dongle Allows geotagging of photos
Write the latest Raspbian image to an SD Card using Raspberry Pi Imager.
Click the “Choose Device” button and select “Raspberry Pi 3” from the list.
Click the “Choose OS” button and select “Raspberry Pi OS (64-bit)”.
Click the “Choose Storage” button and select the SD Card from the list.
Click the “Next” button and follow the prompts. Once the card is validated and you receive a confirmation message that the image has been written to the SD Card, remove the card from the computer and move it to the Raspberry Pi Zero 2 W board and power it on.
Once the Raspberry Pi boots up, and finishes setting up, log into the Raspberry Pi. You may do this directly with an attached keyboard and monitor or by connecting with SSH.
Connect to the Raspberry Pi or use a connected keyboard.
If you had edited the settings prior to writing the OS to the SD Card and the setting included the information to connect to your WiFi and enabled SSH, you may SSH into the Raspberry Pi to run the following commands.
If you did not setup those options or if wish to use Raspberry Pi Connect, you may connect a keyboard to the Raspberry or use the on-screen keyboard. Recommend using a connected keyboard if you working directly with the Pi.
Recommend Turning on Raspberry Pi Connect, Sign In, and work from another computer.
Update Raspbian and Install Packages
Update the Raspberry Pi OS and install packages by running the following code.
# Install google data api and upgrade it pip install gdata pip install --upgrade google-api-python-client pip install --upgrade oauth2client
# Install ImageTk, Image from PIL # Appears we need to do this in the virtual environment too. pip install pillow # pip install numpy
# Leave the virtual environment deactivate
Setup Google API Access
Open a web browser and log into your Google Account. If you do not have one, create one. NOTE: You may want to create a separate account, just for the photobooth to keep it separate from your main account.
If you are not in the correct profile, select the correct profile.
Create a project Click on the project selector near the top of the screen, then click the “New project” button in the dialog.
Enter a name for the project and click the “Create” button.
Make certain the project is the selected project in the Console. Look at the upper left corner. If the project is not displayed, click and select the project before continuing.
Add access rights to the services you need (namely Gmail Service and Google Photos Library Service)
Click on the “+ Enable APIs and services” button
Search for Gmail using the Search box and click on “Gmail API”
Click the “Enable” button to enable the Gmail API
Return to the Google API Console, click the “+ Enable APIs and services” button, search for Photos, and click on “Google Photos Library API”
Click the “Enable” button to enable the Google Photos Library API
Return to the Google API Console and select “Credentials” on the left menu.
Click the “+ Create credentials” button on the top and select “OAuth client ID”
If you are prompted to “Configure consent screen”, do that, then return to the next step. NOTE: The values entered are not important as you will be the only one authenticating to the app.
App Information
App Name: Only you will see this.
User support email: Enter a valid email.
Audience
External is the only option available
Contact Information
Enter a valid email
Finish
Check the checkbox and click the create button
Select the “Desktop app” for Application type, enter a name, and click the “Create” button.
Copy the Client ID, Client secret, and Download JSON. Keep the information in a safe place.
Back to the Credentials, click on the OAuth Client ID that you created.
Select “Audience” from the left panel, and click the “Publish app” button.
# Clean up empty folders & zip file rm -r ~/pb/home rm ~/main.zip
# Make BASH scripts and desktop files executable chmod +x ~/*.sh chmod +x ~/TouchSelfie/*.sh chmod +x ~/Desktop/*.desktop chmod +x ~/.config/autostart/*.desktop
# cd ~/TouchSelfie # ./setup.sh
Disable On-Screen Keyboard (Optional)
This step is optional but highly recommended as the on-screen keyboard takes up a significant amount of available screen space, making it difficult to navigate and see the screen. This is especially true with the original Raspberry Pi Touch Screen.
We will turn off the on-screen keyboard to get it out of the way.
Go to the Start Menu and select Preferences > Raspberry Pi Configuration.
Go to the Display Tab, then select “Disabled” from the On-screen Keyboard option.
Click the “OK” button.
When prompted to reboot, select “Yes”
When the Raspberry Pi reboot, the Photobooth application should be running.
Press <ctrl> + q to exit the application and click the “Yes” button on the dialog.
Authenticate to the Google APIs
Copy the JSON file that was downloaded from the Google API Console and rename it to “google_client_id.json”.
If you did not download it, go to the Google API Console, go to Credentials, then click on the Client Id (link).
You may transfer the JSON file to the Raspberry Pi using an application such as WinSCP or other method and place it in the /home/pi/TouchSelfie/scripts/ folder.
Copy the “google_client_id.json” file to “OpenSelfie.json”. You may copy it by running the following command in the terminal. cp ~/TouchSelfie/scripts/google_client_id.json ~/TouchSelfie/scripts/OpenSelfie.json
NOTE: There should be two JSON files in the scripts folder, google_client_id.json and OpenSelfie.json.
On the Raspberry Pi, open a terminal and type the following commands to run the setup application.
cd TouchSelfie ./setup.sh
The “TouchSelfie – Options” window opens. Select the options you wish to enable, then click the “Next” button. NOTES: – It is recommended NOT to enable the software keyboard if using the Raspberry Pi touchscreen as screen resolution is too small. – Image Effects is not implemented at this time so enabling it has no impact.
The “TouchSelfie – Credentials” window opens. Click the “Get AppID” button.
The “TouchSelfie – Credentials” second window opens. Click the “Launch browser” button.
The browser will open prompting you to log into Google.
Enter your Google Account and click the “Next” button.
Enter your account password and click the “Next” button.
If you have 2-step verification setup, then complete the 2-step verification process.
You will see a page stating that Google hasn’t verified this app. Click the “Advanced” link at the bottom of the page.
Click on the “Go to … (unsafe)” link at the bottom of the page.
Check the “Select all” checkbox to select all the permissions, then click the “Continue” button.
The browser window will state “The authentication flow has completed” and the TouchSelfie – Options screen will be displayed. NOTE: There is a new file in the /TouchSelfie/scripts/ folder named, google_credentials.dat.
Modify any options if necessary and click the “Next” button.
Enter the Google Account, verify that the Credentials have green checkmarks, and click the “Next” button.
Enter an email address that you can check and change any items you wish for the test email. Click the “Send test email to test the Gmail API connection. Check your email for the test message, then click the “Next” button.
The select Photo Album screen needs some work yet. The list must be navigated with the up/down keys on the keyboard and selection is done with the spacebar. This will be fixed in a future release. If you do not have an album, choose “<Create New>” and click tab to the “Select” button and press the spacebar. It will create a new album named “TouchSelfie” and add a small single colored small image to the album. Do not delete the image from the album unless you have uploaded another image. There must be an image in the album.
Click the “Test Upload” button. You may go out to Google Photos to verify that the album has been created and the image was uploaded.
If necessary, modify the options for snapshots, then click the “Save” button.
You may now close the terminal window and browser.
Customizing the frames for the photos and collages
The \TouchSelfie\logos\ folder has the frames that are applied over the photos.
Single Photo: single_logo.png
4 Collage Photo: collage_four_square_logo.png
9 Collage Photo: collage_nine_square_logo.png
There is a Frames.svg that may be used for creating or updating the photos. The folder also contains some examples from various events.
Configuration File Settings
The configuration file is in the /TouchSelfie/scripts/ folder and is named, configuration.json. It is a JSON file with several options.
archive_to_all_usb_drives
Type: boolean
Values: true or false
Allows archiving of photos to a USB drive if one is attached to the Raspberry Pi
NOTE: This functionality is not behaving properly. Some photos are archived but not all. All are written to the SD card though. This will be fixed in a later release.
cameraMake
Type: string
A quoted string value indicating the make of the camera. You may set this to any value you wish. The value is written to the image Exchangeable Image File Format (EXIF) data.
cameraModel
Type: string
A quoted string value indicating the model of the camera. You may set this to any value you wish. The value is written to the image EXIF data.
countdown_before_snap
Type: integer
The seconds between button press and taking the photo. There needs to be images in the /TouchSelfie/scripts/resources/ folder to support the count. Currently there are 5 images named count_down _1.png to count_down _5.png. The images are 128×128 pixels in size.
countdown_inter_snap
Type integer
The seconds between taking photos for collage images
email_body
Type: string
A quoted string value for the body of the emails being sent from the application.
email_subject
Type: string
A quoted string value for the subject of the emails being sent from the application.
enable_effects
Type: boolean
Values: true or false
Indicates if the effects button will be shown.
enable_email
Type: boolean
Values: true or false
Indicates if the mail button will be shown.
enable_email_logging
Type: boolean
Values: true or false
Indicates if emails will be logged to a file.
enable_hardware_buttons
Type: boolean
Values: true or false
Indicates if hardware buttons are available for application functions. Hardware buttons are not supported at this time.
enable_print
Type: boolean
Values: true or false
Indicates if the print button will be shown
enable_upload
Type: boolean
Values: true or false
Indicates if photos will be uploaded to a Google Album
full_screen
Type: boolean
Values: true or false
This is deprecated and may be removed from future releases.
gmail_user
Type: string
A quoted value for the Google Account email address.
google_photo_album_id
Type: string
A quoted text value that is the id of the Google Album. It is a Globally Unique Identifier (GUID) that is inserted by the setup program.
google_photo_album_name
Type: string
A quoted text value of the name of the Photo Album.
imageArtist
Type: string
A quoted string for the name of the artist/photographer. You may set this to any value you wish. The value is written to the image EXIF data.
imageComment
Type: string
A quoted string for the note or comment to be added to the EXIF data. You may set this to any value you wish. The value is written to the image EXIF data.
imageDescription
Type: string
A quoted string for the description to be added to the EXIF data. You may set this to any value you wish. The value is written to the image EXIF data.
imageKeyWords
Type: string
A quoted string for comma separated keywords to be added to the EXIF data. You may set this to any value you wish. The value is written to the image EXIF data.
local_archive
Type: boolean
Values: true or false
If true, photos are saved to the SD card in addition to being uploaded to the Google Album. Recommended to have this value set to true.
local_archive_dir
Type: string
A quoted string with the path to the local archive folder.
location_lat
Type: float
A quoted decimal value for the latitude. The value is written to the image EXIF data.
location_long
Type: float
A quoted decimal value for the longitude. The value is written to the image EXIF data.
logo_file
selected_printer
snap_caption
software
Type: string
A quoted string for the software to be added to the EXIF data. You may set this to any value you wish. The value is written to the image EXIF data.
test_email_address
Type: string
A quoted value for the test email address. This is only used in the setup.
(Optional) Stop Execution File dialog box
You may want to stop seeing the Execute File dialog when clicking on the Photobooth desktop icon. Below are the steps to stop displaying the dialog.
Click on the File Manager at the top of the screen.
From the menu, select Edit > Preferences
With “General” selected on the left panel, check the “Don’t ask options on launch executable file” option.
Close File Manager and click on the Photobooth icon on the desktop. The application will launch.
Next Steps
There are several things that need to be completed and some changes that plan to be made. Below is a list of those items.
The code is looking for the client id in two different JSON files. Modify the code so only one copy of the JSON file is needed. The two JSON files are:
google_client_id.json
OpenSelfie.json
Use connected GPS to geotag photos. Currently the configuration file has location_lat and location_long which are used to geotag photos, but that requires that the configuration file is updated when the photobooth is brought to a new location.
Add text to the buttons to make it easier for users to know what each button is used for. An alternative may be to add an info button.
Email photo(s) function. Would like the option to review and select photos to email.
Add effects back into the application.
Add support to print photos.
Improve the UI to let people know when a photo will be taken for each image of the collage and animation. Not certain how to make this intuitive.
Fix the issues with the setup application and add additional options.
30 June 2025 UPDATE: The fix outlined here seemed to work, but I noticed that some things were not right yesterday. I dug in deeper and I seem to have it working now. It appears that gpsd may have been the problem from the start. Below is a Copilot session that seemed to zero in on gpsd and the need to build a newer version.
After applying the changes, I tested three times and each time the correct location was identified, yes that was an issue, and the GPS had a fix in a reasonable time.
Uptime 11 Minutes to fix (reboot)
Uptime 9 Minutes to fix (reboot)
Uptime 21 Minutes to fix (shutdown, power removed, sat for a few minutes and restarted)
The rest of this post is here for information only. I plan to write another post once I test on another SD Card.
I purchased a WWZMDiB VK-172 USB GPS Dongle Receiver from Amazon to use with my Raspberry Pi Photobooth but ran into some issues with it. The Raspberry Pi recognized the GPS module straight away but I noticed the GPS was not getting a location fix even when it was outside with a clear view of the sky. I had read that some people had a similar issue or it would take nearly an hour or longer to get a fix on the location. Obviously this is not acceptable. My experience with u-blox products is that their products are very good, so this was not normal. Something else must have been amiss.
For context, I had already installed and configured gpsd on the Pi, using tools like cgps and xgps for monitoring. The cgps application appeared that everything was working, but it was not getting a fix.
Screenshot of cgps not having a fix.
To verify that the GPS could obtain a location fix and how long it would take, I connected the GPS to my Windows PC and installed the u-blox u-center software. On the Windows PC, I was able to get a location fix quickly. This helped me to target the configuration on the Raspberry Pi.
U-center running on the PC with a fix. (Lat/Long blacked out.)
Back on the Raspberry Pi, I looked at several things but suspected that the GPS unit was not configured properly. With the help of Copilot, I attempted to resolve the issue. What I uncovered is the GPS was not configured to send the proper NMEA messages.
I was able to properly configure the GPS to send NMEA messages but the GPS unit would not retain the configuration as it has no battery. I was able to write a script to run as a service and run on startup. All seemed to work well, but I needed to leave it and come back the next day. When I tested it again, things were no longer working as expected. Upon further investigation, it was noted that unplugging the USB GPS dongle and plugging it back in got everything working as expected.
I was able to land on a solution that mimicked the unplugging and plugging the dongle in. This final configuration seems to allow the dongle to work properly on the Raspberry Pi. I have not verified, but other Raspberry Pi versions may or may not have this issue.
Screen capture of cgps with location fix after applying the changes.
Below is the list of steps necessary to get the GPS module to work properly with gpsd on the Raspberry Pi.
My setup
Raspberry Pi 3
Raspbian bookworm
All updates applied as of 28 June 2025
Steps
Update the Raspberry Pi OS and install packages by running the following code.
sudo apt update -y && sudo apt upgrade -y
Install gpsd and related packages
sudo apt -y install gpsd gpsd-tools gpsd-clients
Install Python GPS client library
sudo apt install python3-gps
Configure gpsd
sudo nano /etc/default/gpsd
Edit the file to include the following content DEVICES="/dev/ttyACM0"
USBAUTO="true"
GPSD_OPTIONS="-n"
Enable and start gpsd service
sudo systemctl enable gpsd
sudo systemctl start gpsd
Reboot to ensure all changes take effect
sudo reboot now
Create the following script at /home/pi/setup-gps.sh to configure the USB GPS dongle on startup.
nano /home/pi/setup-gps.sh
#!/bin/bash # VK-172 USB GPS dongle was having issues sending messages # dmesg | tail -n 20 # Showed that the USB Bus was having with dwc_otg_hcd_urb_dequeue # The following commands mimic unplugging the USB and plugging it back in.
# Look for a serial device with 'u-blox' in the ID string DEVICE_PATH=$(readlink -f /dev/serial/by-id/*u-blox*)
# Extract the most specific USB path (e.g. 1-1.3) USB_ID=$(udevadm info -a -n "$DEVICE_PATH" | awk -F'"' '/KERNELS=="1-/ { if ($2 !~ /:/) { print $2; exit } }')
# Log what we found (optional for debugging) echo "Reinitializing USB device at $USB_ID"
Your USB Dongle may be appear as device other than /dev/ttyACM0. Running the command dmesg | grep tty or ls /dev/tty* tip will allow you to verify if your GPS is appearing as /dev/ttyACM0 or another device path.
Some of the commands used to troubleshoot were the following.
Disabling gpsd so it will not become active between reboots.
sudo systemctl disable gpsd.socket
sudo systemctl disable gpsd
sudo systemctl mask gpsd.socket
sudo systemctl mask gpsd
Run one of the following sets of commands
sudo systemctl stop gpsd.socket
sudo systemctl stop gpsd — or —
sudo reboot now
Reenabling gpsd once done troubleshooting.
sudo systemctl unmask gpsd.socket
sudo systemctl unmask gpsd
sudo systemctl enable gpsd.socket
sudo systemctl enable gpsd
Run one of the following sets of commands
sudo systemctl start gpsd.socket
sudo systemctl start gpsd
or
sudo reboot now
Checking if the GPS is sending NEMA messages. First disable gpsd Run one of the following commands
cat /dev/ttyACM0
cat < /dev/ttyACM0
stty -F /dev/ttyACM0 9600
With either command, you should see GPS NEMA messages being streamed to the output. If the command immediately returns with no output, then the GPS is not sending messages, which is a problem.
View USB Devices
lsusb
Sample output
pi@PhotoBooth1:~/TouchSelfie $ lsusb
Bus 001 Device 007: ID 1546:01a7 U-Blox AG [u-blox 7]
Bus 001 Device 004: ID 090c:1000 Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) Flash Drive
Bus 001 Device 005: ID 2010:7638 USBKey Chip USBKey Module
Bus 001 Device 006: ID 0424:7800 Microchip Technology, Inc. (formerly SMSC)
Bus 001 Device 003: ID 0424:2514 Microchip Technology, Inc. (formerly SMSC) USB 2.0 Hub
Bus 001 Device 002: ID 0424:2514 Microchip Technology, Inc. (formerly SMSC) USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
pi@PhotoBooth1:~/TouchSelfie $
View the last 20 debug messages
dmesg | tail -n 20
Sample output This is a capture after the fix was applied.
[ 25.607598] WARN::dwc_otg_handle_mode_mismatch_intr:67: Mode Mismatch Interrupt: currently in Host mode
[ 26.641294] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device [ 57.963631] pps_ldisc: PPS line discipline registered
[ 117.664194] WARN::dwc_otg_hcd_handle_hc_fsm:2441: Unexpected IRQ state on FSM transaction:dev_addr=7 ep=2 fsm=7, hcint=0x00000022
pi@PhotoBooth1:~/TouchSelfie $
If there are several WARN messages such as below, then you may be having the same issue with the USB dongle not working unless it is unplugged and reinserted. The output below is before the issue was resolved and includes unplugging and plugging in the USB GPS dongle.
pi@PhotoBooth1:~ $ dmesg | tail -n 20 [ 39.437463] WARN::dwc_otg_hcd_urb_dequeue:639: Timed out waiting for FSM NP transfer to complete on 6 [ 39.437954] WARN::dwc_otg_hcd_urb_dequeue:639: Timed out waiting for FSM NP transfer to complete on 5 [ 39.438512] WARN::dwc_otg_hcd_urb_dequeue:639: Timed out waiting for FSM NP transfer to complete on 0 [ 39.439038] WARN::dwc_otg_hcd_urb_dequeue:639: Timed out waiting for FSM NP transfer to complete on 3 [ 111.617441] WARN::dwc_otg_hcd_urb_dequeue:639: Timed out waiting for FSM NP transfer to complete on 5 [ 111.617895] WARN::dwc_otg_hcd_urb_dequeue:639: Timed out waiting for FSM NP transfer to complete on 6 [ 111.618337] WARN::dwc_otg_hcd_urb_dequeue:639: Timed out waiting for FSM NP transfer to complete on 1 [ 138.125231] usb 1-1.3: USB disconnect, device number 6 [ 142.162832] usb 1-1.3: new full-speed USB device number 7 using dwc_otg [ 142.253315] usb 1-1.3: New USB device found, idVendor=1546, idProduct=01a7, bcdDevice= 1.00 [ 142.253362] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [ 142.253379] usb 1-1.3: Product: u-blox 7 - GPS/GNSS Receiver [ 142.253393] usb 1-1.3: Manufacturer: u-blox AG - www.u-blox.com [ 142.255827] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device pi@PhotoBooth1:~ $
Check the status of the gps-init service we created.
sudo systemctl status gps-init.service
Sample output The error, “Failed to start gps-init.service – Configure u-blox GPS at Boot.” may be ignored as it is expected when the line “gpsctl -s -f /dev/ttyACM0” is not commented out in /home/pi/setup-gps.sh.
pi@PhotoBooth1:~/TouchSelfie $ sudo systemctl status gps-init.service × gps-init.service - Configure u-blox GPS at Boot Loaded: loaded (/etc/systemd/system/gps-init.service; enabled; preset: enabled) Active: failed (Result: exit-code) since Sun 2025-06-29 14:21:24 EDT; 39min ago Process: 904 ExecStart=/home/pi/setup-gps.sh (code=exited, status=1/FAILURE) Main PID: 904 (code=exited, status=1/FAILURE) CPU: 15.794s
Jun 29 14:21:14 PhotoBooth1 setup-gps.sh[1378]: inProtoMask (UBX NMEA RTCM2) Jun 29 14:21:14 PhotoBooth1 setup-gps.sh[1378]: outProtoMask (UBX NMEA) Jun 29 14:21:14 PhotoBooth1 setup-gps.sh[1378]: UBX-ACK-ACK: Jun 29 14:21:14 PhotoBooth1 setup-gps.sh[1378]: ACK to Class x06 (CFG) ID x00 (PRT) Jun 29 14:21:24 PhotoBooth1 setup-gps.sh[1383]: gpsctl:ERROR: timed out after 8 seconds Jun 29 14:21:24 PhotoBooth1 setup-gps.sh[1383]: gpsctl:ERROR: no DEVICES response received. Jun 29 14:21:24 PhotoBooth1 systemd[1]: gps-init.service: Main process exited, code=exited, status=1/FAILURE Jun 29 14:21:24 PhotoBooth1 systemd[1]: gps-init.service: Failed with result 'exit-code'. Jun 29 14:21:24 PhotoBooth1 systemd[1]: Failed to start gps-init.service - Configure u-blox GPS at Boot. Jun 29 14:21:24 PhotoBooth1 systemd[1]: gps-init.service: Consumed 15.794s CPU time. pi@PhotoBooth1:~/TouchSelfie $
Once cgps is showing that gpsd is working properly, telnet may be used to view the messages being sent by gpsd.
If telnet is not installed, install telnet with the following command.
sudo apt install telnet
telnet localhost 2947
Sample output
pi@PhotoBooth1:~/TouchSelfie $ telnet localhost 2947
Trying ::1...
Connected to localhost.
Escape character is '^]'.
{"class":"VERSION","release":"3.22","rev":"3.22","proto_major":3,"proto_minor":14}
Issue the following command to view polling output.
?POLL;
Issue the following command to see JSON output.
?WATCH={“enable”:true,”json”:true}
Press <Ctrl>+] then type “quit” to exit the telnet session.
CAUTION: I did notice one time that the location reported by gpsd was off by 1,000 miles to the NW. Not certain what happened but I could not replicate it. I had let cgps run for about 10 minutes to see if gpsd would update with the correct location, but it did not.
Some other useful commands to see what is happening with USB and GPS on boot.
journalctl | grep -i gps
journalctl | grep -i usb
Additional commands to monitor GPS output while gpsd is running.
My Raspberry Pi cameras have been running well for a while now, but I’ve had one camera that seems to be having issues. I did have some issues earlier with two camera and believe it was due to using cheap Micro Center SD cards and having the Wi-Fi monitoring script write to the card every 5 minutes. I used new cards and did not include the Wi-Fi monitoring script. All was well until a couple of weeks ago, when one camera, that is closest to my Wi-Fi router, would not show up in Blue Iris. I unplugged it and plug it in to hard reboot it, but it still would not come back up.
I finally pulled it out to take a look at it but it seemed to work just fine. It may be that the CD Card was not seated properly, but uncertain why it worked then did not work. If and only if the last state and current state are different, will it update the state file and create a log entry. Below is my resulting script. This is much better than my original version. It is easier to view the log and see when the Wi-Fi went down and when it reconnected.
#!/bin/bash
# Shell script to monitor Wi-Fi status and operating conditions
# and attempt Wi-Fi restart if down
IWCONFIG="/usr/sbin/iwconfig wlan0"
# The IP for the server you wish to ping (8.8.8.8 is a public Google DNS server)
SERVER=192.168.1.1
LOGFILE="/var/log/wifi.log"
STATEFILE="/var/log/wifistate.txt"
DATE=`date`
I=$((`cat /sys/class/thermal/thermal_zone0/temp`/100))
TEMP="Temp="$(($I/10))"."$(($I%10))" C"
STATUS=`$IWCONFIG | grep level | awk '{$1=$1};1'`
STATUS+=" "
STATUS+=`$IWCONFIG | grep Rate | awk '{$1=$1};1'`
CURRENTSTATE=""
LASTSTATE=""
if [ -f ${STATEFILE} ]; then
LASTSTATE=$(cat ${STATEFILE})
fi
# Only send two pings, sending output to /dev/null
ping -c2 ${SERVER} > /dev/null
# If the return code from ping ($?) is not 0 (meaning there was an error)
if [ $? = 0 ]
then
CURRENTSTATE="UP"
UPDOWN="\033[32m UP \033[0m"
else
CURRENTSTATE="DOWN"
UPDOWN="\033[31mDOWN \033[0m"
STATUS+=" Attempting wlan0 restart"
# Restart the wireless interface
sh -c 'ifconfig wlan0 down; sleep 5; ifconfig wlan0 up'
fi
if [ "$CURRENTSTATE" != "$LASTSTATE" ]; then
echo -e $CURRENTSTATE > $STATEFILE
echo -e "WiFi @ $DATE: $UPDOWN $TEMP $STATUS" >> ${LOGFILE}
fi
echo -e "WiFi @ $DATE: $UPDOWN $TEMP $STATUS"
# Check daemon
# Name of the daemon to check
DAEMON_NAME="mediamtx"
LOGFILE="/var/log/mediamtx.log"
STATEFILE="/var/log/mediamtxstate.txt"
STATUS=""
CURRENTSTATE=""
LASTSTATE=""
if [ -f ${STATEFILE} ]; then
LASTSTATE=$(cat ${STATEFILE})
fi
# Check if the daemon is running
if pgrep -x "$DAEMON_NAME" > /dev/null; then
CURRENTSTATE="RUNNING"
STATUS="$DAEMON_NAME is running"
else
CURRENTSTATE="NOT RUNNING"
STATUS="$DAEMON_NAME is not running, restarting..."
# Use appropriate command to restart the daemon
sudo systemctl restart "$DAEMON_NAME"
fi
if [ "$CURRENTSTATE" != "$LASTSTATE" ]; then
echo -e $CURRENTSTATE > $STATEFILE
echo -e "MediaMTX @ $DATE: $STATUS" >> ${LOGFILE}
fi
echo -e "MediaMTX @ $DATE: $STATUS"
I have been trying out the UGREEN HDMI Video Capture Card and it works well for my use case. I use it to capture the screen of the Raspberry Pi and PC screens.
You may wonder why you may want to use the device to capture a PC screen, but there are several reasons. The first use case is to capture images and videos of BIOS settings. Another is for capturing screen captures or videos of a PC recovery process. Lastly is to capture the installation of software that prompts the user to accept a security dialog that is not accessible to screen capture software.
Thee UGREEN HDMI Video Capture Card may be used to capture game play from gaming consoles with HDMI output. I have not tested game play capture but have tested capturing the screens of Linux and Windows systems.
Overall I’m very happy with the UGREEN HDMI Video Capture Card. I do feel funny calling it a card rather than a device as it is not a card that is connected internally in the PC but that is the name given to it
It provides pass-through capability with no noticeable lag. If you play a video game it may be possible to notice a lag but in my use, I did not notice a lag when typing. It was very responsive.
The device has an attached USB C cable that cannot be removed. It does come with a USB C to USB A adapter. The only issue i have is being able to tell which port is the input and which is the output. The text is very difficult to read. You can read it if the lighting angle is just right. It would have been helpful if the text had more contrast with the color of the case. This is a minor issue though. I would recommend the UGREEN HDMI Video Capture Card if you have thee need to capture HDMI video.
Below is a video review of the UGREEN HDI Video Capture Card.
VIDEO
Below is my Amazon Affiliate link to the UGREEN HDMI Vide Capture Card.
You must be logged in to post a comment.