Smart USB flash drive
By J Peake – January 2023
Bill of Materials
• Raspberry Pi Zero W or 2W
• Micro SD card with 8GB or more storage space
• Old USB cable with USB A male connector
• Short piece of 16-20mm heatshrink
• Hot glue or 5 minute epoxy
• Standard 6mm tactile push button switch
• Bi-colour LED with common cathode and 100 Ohm resistor
• 1A diode (optional)
• 3d printed case from Printables.com
• M2.5 threaded brass heat-set inserts (or print the plastic thread version) (x4)
• M2.5 x 8mm screws (x4)
Tools
• Soldering iron
• 3D printer
• Hand tools (side cutters, knife, screw drivers)
Assembly
1. Cut the USB A connector off of the spare USB lead leaving about 65mm (2.5”) of wire still
attached to the USB A connector (as show above).
2. Carefully cut the plastic moulded shell away from the USB A
connector to expose the internals, enough needs to be cut away so
that the cable can be folded over at 90 degrees from the connector.
Reinforce with hot glue or 5 minute epoxy and cover with heatshrink.
3. Cut two of the 4 legs off one side of the push button, and bend the other two legs at 90
degrees so the button can be mounted as shown below. Cut the LED centre leg short so a
resistor can be soldered to it. Now solder the button, LED and resistor as shown below. Note
– resistor below is a tiny surface mount resistor, use one of these if you are a sucker for
punishment, or a leaded resistor if you prefer an easier job!
The LED is soldered into pins 7 (GPIO 4), 9 (GND via resistor) and 11 (GPIO 17). The push
button is soldered into pins 14 (GND) and 18 (GPIO 24). The top half of the case is designed
to sit behind the push button to reinforce it from the top.
4. Solder the modified USB cable to the back of the pi as shown below, either use a diode or
leave the red wire disconnected so that external power does not back-feed the printer. Black
to GND, White to D-, Green to D+, Red to 5V (via diode).
5. Slip the pi into the case back inserting the LED and button into their holes first.
6. Seat the pi home onto the screw hole stand-offs and push in the USB connector.
7. Finally, set the threaded inserts into the case front and screw case together. Note that the
USB wires need to be routed away from the push button in order to clear the button support
built into the case front.
Software
1. Install your favourite flavour of
Linux on the μSD card (I used the
latest Raspberry Pi OS 32 bit
standard version):
The easiest option is to download
Raspberry Pi Imager, select the
extra setup button:
and put in hostname, enable SSH,
set username and password and
configure wireless LAN as shown
here.
Select your SD card, hit Write and wait for it to complete.
2. Boot the pi with SD card inserted, and start an SSH session using your favourite terminal
program (I use PuTTY). With any luck you should be able to connect via the hostname you
set previously (smartUSB.local).
3. Update apt repository listing and install ftp and samba servers for easy network file access
sudo apt update
sudo apt install vsftpd samba winbind -y
pip install RPi.GPIO
4. Edit FTP config file and enable FTP server
sudo nano /etc/vsftpd.conf
Uncomment the line: write_enable=YES
Ctrl + X, Y, Enter
sudo systemctl start vsftpd
sudo systemctl enable vsftpd
sudo reboot
5. Enable the kernel USB driver
sudo nano /boot/config.txt
Add the following line to the end of the file: dtoverlay=dwc2
Ctrl + X, Y, Enter
sudo nano /etc/modules
Add the following line to the end of the file: dwc2
Ctrl + X, Y, Enter
sudo reboot
6. Create the flash storage data file, the count argument specifies the size (8192 = 8GB), make
sure the size specified is not too large for your μSD card. An 8GB storage file will need a
16GB μSD card! This takes a while so time for a cup of tea…
sudo dd bs=1M if=/dev/zero of=/usb_flash.bin count=8192
sudo mkdosfs /usb_flash.bin -F 32 -I
Now make a directory to mount it into, and edit fstab
sudo mkdir /mnt/usb_flash
sudo nano /etc/fstab
Add the following to the end of the file: /usb_flash.bin /mnt/usb_flash vfat users,umask=000 0 2
Ctrl + X, Y, Enter
sudo reboot
7. Create a test file and check to see if it works
sudo nano /mnt/usb_flash/test.txt
Add the following to the end of the file: It works!
Ctrl + X, Y, Enter
sudo modprobe g_mass_storage file=/usb_flash.bin stall=0 removable=1
With the pi plugged into a PC it should now show up as a USB flash drive with the file test.txt in
it. Open the file to check the contents were saved.
8. Create a python script to start the USB mass storage on boot, remove and reinsert on button
press, update LED status and provide a safe shutdown of the pi on long press.
nano ~/usbctl.py
Add the following script to the file:
import RPi.GPIO as GPIO
import os
import time
# Define our GPIO assignments
pushButton = 24
ledRed = 17
ledGreen = 4
# Define output states (reverse these if you are using a common annode LED connected to 3.3V!)
led_ON = 1
led_OFF = 0
GPIO.setmode(GPIO.BCM)
# Setup GPIO
GPIO.setup(pushButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(ledRed, GPIO.OUT)
GPIO.setup(ledGreen, GPIO.OUT)
# Stop and re-start mass storage gadget
os.system("sudo modprobe -r g_mass_storage")
time.sleep(1)
os.system("sudo modprobe g_mass_storage file=/usb_flash.bin stall=0 removable=1")
# Turn the Green LED on to show we have started the script
GPIO.output(ledGreen, led_ON)
GPIO.output(ledRed, led_OFF)
while 1:
# Check the button status every 50 milliseconds
if GPIO.input(pushButton) == 0:
# If pressed, chnange LED to red, unload mass storage and wait a second
GPIO.output(ledGreen, led_OFF)
GPIO.output(ledRed, led_ON)
os.system("sudo modprobe -r g_mass_storage")
time.sleep(1)
GPIO.output(ledGreen, led_ON)
# If the button is still pressed after 1 second, shut down the pi
if GPIO.input(pushButton) == 0:
os.system("sudo halt")
else:
GPIO.output(ledRed, led_OFF)
os.system("sudo modprobe g_mass_storage file=/usb_flash.bin stall=0 removable=1")
time.sleep(0.05)
Test to ensure it works
python3 ~/usbctl.py
The pi should show up as a USB flash drive on the computer it is connected to, with test.txt
inside. The green LED should be on, and when you press the button briefly the led will change to
red, disconnect the USB flash drive and then re-connect it.
Copy the script to a safe directory
sudo cp ~/usbctl.py /usr/local/share/usbctl.py
9. Create a service entry for the script to run in
sudo nano /etc/systemd/system/usbctl.service
Add the following to the file:
[Unit]
Description=Smart USB Device Management
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=3
ExecStart=/usr/bin/python3 /usr/local/share/usbctl.py
[Install]
WantedBy=multi-user.target
Ctrl + X, Y, Enter
Now enable the service to start on boot and then reboot
sudo systemctl daemon-reload
sudo systemctl enable usbctl
sudo reboot
All going to plan the service should have started automatically as indicated by the LED, double
check it works as expected.
10. Setup Samba server for MS Windows network drive access.
sudo nano /etc/samba/smb.conf
Add the following to the end of the file:
[smartUSB]
browseable = yes
path = /mnt/usb_flash
guest ok = yes
read only = no
create mask = 777
Ctrl + X, Y, Enter
sudo systemctl restart smbd.service
Test the network drive from a Windows PC – open file explorer and type \\smartUSB\smartUSB\
into the URL bar.
11. That’s it! Time to test in your printer. Note – I have found for my Anycubic Photon Mono X
that although the printer is able to power the pi just fine, it does not work if the pi boots
while connected to the printer. When the pi boots it seems to lock up the printer’s USB
interface, so instead power the pi separately through the power connector. The pi needs to
be booted before you turn on or connect it to the printer. Once that is done you can either
leave the pi powered externally and switch your printer on and off as needed, or you can
leave your printer on to power the pi, and disconnect the external supply.
Now to test, you should be able to see the test.txt file with the printer(if your printer can see
.txt files of course). Now connect to the pi via its network drive as above and copy a print file
across. The printer will need to see the drive “removed and reinserted” so just press the
push button on the pi, you should now see an updated view of the drive with your newly
added file.
Lastly, unless your printer is fully loading the print file into its own memory before starting
the print job, remember that pushing the button disconnects the drive! So, if you push it
during a print, the print will immediately fail.