Raspberry Pi Wireless USB for Scanner & PaperlessNGX

A simple eBay mistake missing a "W" led to a frustrating project trying to save $10. Lesson learned: buy the ADS-1500W (make sure it's the W!). This is for PaperlessNGX, using an ADS-1200 and a Raspberry Pi Zero W.

Raspberry Pi Wireless USB for Scanner & PaperlessNGX

This project has been a rabbit hole for me. It started with hosting the PaperlessNGX container on my Unraid Machine, and I quickly found a ton of value in digitizing my filing cabinet with all kinds of important documents. I've had a Brother MFC-L2700DW multi-function laser printer and scanner for the last 12 years or so but it is lacking in connectivity options - specifically FTP or SMB for PaperlessNGX.

While reading the PaperlessNGX supported devices list, I came across the small form-factor Brother ADS-1200W. Emphasis on the W, as the $30 "for-parts" version (was missing a power cable! worked fine!) I bought on eBay without double-checking was lacking the W - for wireless.

(In my defense, if you click the ADS-1200W on that devices list, it takes you to the ADS-1200 page).

💸
I do not recommend repeating this effort. Unless you can find the scanner for cheap and already have a RPI Zero W laying around- this is a waste of time and effort. Go purchase a used scanner with Wi-Fi already built-in from the supported devices list.

I used this scanner connected to my PC for awhile but didn't like the workflow for hundreds of documents. Granted, it works fine - I just knew there had to be a better way.

The first thing I thought of was an old Eye-Fi Wi-Fi SD card I had on a camera in the 2010's. One PDF scan at a time isn't a huge amount of data and I just want to wirelessly place them in the consume folder for PaperlessNGX. I realized Eye-Fi doesn't really exist anymore and that niche market never took off (Crazy that 10 years later Wi-Fi SD cards barely exist and not for the $20 that card was!).

Next thing I discovered on the ADS-1200 forum for Paperless-NGX was this discussion about using a Raspberry Pi Zero W to be a USB OTG (On the Go) host for the scanner.

Linux script for Scan + API call for any Scanner · paperless-ngx paperless-ngx · Discussion #3946
The idea is to enable non-smart/connected scanners to scan and use API for a more direct integration with paperless. I was already thinking on this quite some time ago, and now I noticed this text…

Which leads to this German forum post with the instructions on how to set up the USB OTG.

USB Gadget: Mass Storage Emulation - Deutsches Raspberry Pi Forum
Leider finden sich über diese Variante nicht so viele Informationen im Netz beziehungsweise die meisten Artikel sind schon älter... Hintergrund: Der SoC aller (bisherigen) Pi’s hat intern einen einzigen USB Port, einen sog. USB-OTG den man in Master-…

I got this to work for ONE DAY in January 2024 and have failed to get it to be reliable since then. Granted, I've taken breaks, forgot about it, realized the USB cable was bad, and a whole list of excuses for not being able to follow the above instructions - BUT - I have been struggling to get this to work!

So, with a healthy dose of ChatGPT diagnosing, I have been slowly documenting the steps to get this to work, which are below. I plan to make a video on this as well but I want to give full credit to Marvo2011's github comment and also meigrafd 's 2017 forum post for USB OTG instructions.

Keep a note with your IP, Username, and Password for SSH - We will need to restart a few times

Section 1: Setting Up RPI Zero W for USB OTG

  1. Create RPI Image on Micro-SD card using Raspberry Pi Imager
    1. I recommend using the Lite Image
    2. Make sure you set SSH to be enabled, WiFi info, and user info.
  2. Connect your RPI Zero W to your PC using the USB port, NOT the PWR port
    1. The PWR port has no data connection!
    2. Make sure you are using a KNOWN good Micro-USB cable. I've weirdly had a ton of issues with cables on the RPI Zero W
  3. SSH in to your RPI
    1. I like to use Putty
  4. Execute the following (each code box is one paste / enter, don't stack too many):
echo "dtoverlay=dwc2" | sudo tee -a /boot/firmware/config.txt

followed by:

echo "dwc2" | sudo tee -a /etc/modules

then:

sudo dd if=/dev/zero of=/usbdisk.img bs=1M count=2048

then:

(
echo x # switch to eXpert mode
echo s # set sectors/track
echo 8 # g_mass_storage uses a sector size of 512 bytes, so 8 sectors/track will give us 4096 bytes per track
echo h # set number of heads
echo 16
echo c # set number of cylinders
echo 32768 # 2GB = 2097152 kb / 64 tracks = 32768 cylinders
echo r # return to normal mode
echo n # new partition
echo p # primary
echo 1
echo   # accept default
echo   # accept default
echo t # new partition is created by default as a Linux partition. Since you want to use the gadget with a Windows host, you should change the partition type to FAT32
echo b
echo a # partition should be set as active or USB drive will not be attached to the file-system when plugged in.
echo p # print new partition table to verify..
echo w # Write changes
) | sudo fdisk /usbdisk.img

then:

sudo losetup -o $((2048*512)) /dev/loop0 /usbdisk.img
sudo mkfs -t vfat -v /dev/loop0 -n usbdisk
sudo losetup -d /dev/loop0

Finally,

sudo reboot
  1. Once the RPI restarts, reconnect via SSH, then execute the following code while it is connected to your PC
sudo modprobe g_mass_storage file=/usbdisk.img stall=0 removable=1 idVendor=0x0781 idProduct=0x5572 bcdDevice=0x011a iManufacturer="SanDisk" iProduct="Cruzer Switch" iSerialNumber=1234567890

Section 2: Setting Up for SMB

  1. Execute:
sudo apt install poppler-utils
  1. Once that completes, we are going to add SMB info to access the PaperlessNGX inbox
    1. You need to make sure you know the IP of your Paperless Host
    2. You need to create SMB credentials for your host
sudo nano /etc/fstab

followed by:

//192.168.86.182/data/consume/PaperlessImport /mnt/scan cifs credentials=/root/.smbcredentials,uid=1000,gid=1000,noauto,x-systemd.automount,x-systemd.idle-timeout=30  0 0
  1. Exit with ctrl+x then Y to save
  2. add SMB credentials
sudo nano /root/.smbcredentials

followed by

username=ScanPi
password=PASSWORD
  1. Exit with ctrl+x the Y to save

Section 3: Wifi Reconnect

  1. Execute:
sudo nano /usr/local/sbin/wifi-reconnect
  1. then add:
        #!/bin/bash
        SSID=$(/sbin/iwgetid --raw)

        if [ -z "$SSID" ]; then
            echo "`date -Is` WiFi interface is down, trying to reconnect" >> /home/pi/wifi-log.txt
            sudo ifconfig wlan0 down
            sleep 30
            sudo ifconfig wlan0 up
        fi

        echo "WiFi check finished"
  1. Exit with ctrl+x the Y to save

Step 4: Make it executable

sudo chmod +x /usr/local/sbin/wifi-reconnect

Section 4: Automate PDF transfer from RPI SD to Paperless Inbox

  1. Execute:
sudo nano /usr/local/sbin/copyPDFtoInbox
  1. add:
#!/bin/bash

# Path to the USB image
FILE=/usbdisk.img
LOGFILE="/tmp/copyPDFtoInbox.log"

# Ensure the directory exists for mounting the image
mkdir -p ${FILE/img/d}

# Log start time
echo "$(date): Script started." >> $LOGFILE

# Mount the image if it's not already mounted
if ! mountpoint -q ${FILE/img/d}; then
    echo "$(date): Mounting the USB image..." >> $LOGFILE
    /usr/bin/mount -o loop,offset=$((2048*512)),rw -t vfat $FILE ${FILE/img/d} >> $LOGFILE 2>&1
    if [ $? -ne 0 ]; then
        echo "$(date): Failed to mount $FILE" >> $LOGFILE
        exit 1
    fi
else
    echo "$(date): Image already mounted." >> $LOGFILE
fi

# Sleep to ensure the mount is complete
sleep 1

# Find PDF files and process them
echo "$(date): Looking for PDF files in /usbdisk.d/Brother/..." >> $LOGFILE
/usr/bin/find /usbdisk.d/Brother/ -iname '*.pdf' | while read -r f
do
    if /usr/bin/pdfinfo "$f" 2>/tmp/pdfinfo.err; then
        echo "$(date): $f was ok" >> $LOGFILE
        /usr/bin/touch "$f"
        mv "$f" /mnt/scan/
        echo "$(date): Moved $f to /mnt/scan/" >> $LOGFILE
    else
        echo "$(date): $f is not ready. Error: $(cat /tmp/pdfinfo.err)" >> $LOGFILE
    fi
done

# Unmount the image
sleep 2
/usr/bin/umount ${FILE/img/d} >> $LOGFILE 2>&1
if [ $? -eq 0 ]; then
    echo "$(date): Unmounted $FILE successfully." >> $LOGFILE
else
    echo "$(date): Failed to unmount $FILE." >> $LOGFILE
fi

echo "$(date): Script finished." >> $LOGFILE

OLD: VVVV

#!/bin/bash

FILE=/usbdisk.img
mkdir -p ${FILE/img/d}
/usr/bin/mount -o loop,offset=$((2048*512)),rw -t vfat $FILE ${FILE/img/d}

sleep 1
/usr/bin/find /usbdisk.d/Brother/ -iname '*.pdf' | while read -r f
do
    if stderr=$((/usr/bin/pdfinfo "$f") 2>&1 >/dev/null) && test -z "$stderr"; then
        echo "$f was ok"
        /usr/bin/touch "$f"
        mv "$f" /mnt/scan/
    else
        echo "$f is not ready"
    fi
done

sleep 2
/usr/bin/umount ${FILE/img/d}
  1. Make it executable
sudo chmod +x /usr/local/sbin/copyPDFtoInbox

Section 4: Cron Job

  1. Add the following to cron by executing:
sudo crontab -e
  1. then add:
@reboot /sbin/modprobe g_mass_storage file=/usbdisk.img stall=0 removable=1 idVendor=0x0781 idProduct=0x5572 bcdDevice=0x011a iManufacturer="SanDisk" iProduct="Cruzer Switch" iSerialNumber=1234567890
* * * * * /usr/local/sbin/wifi-reconnect
* * * * * /usr/local/sbin/copyPDFtoInbox
  1. Exit with ctrl+x the Y to save
  2. Execute:
systemctl daemon-reload
  1. Finally we will restart with:
sudo reboot

Privacy Policy
Terms and Conditions