Introduction: Raspberry Pi USB Flatbed Document Scanner

About: I tinker with electronics and software (Python/Tkinter/Arduino/VB.net/PHP),also, MacGyver the shit outta things, hahahaaaa!

This is my Raspberry Pi 3 Model B+ Flatbed Document Scanner project. It uses a SANE compatible Canon USB Printer Scanner to create a stand alone document scanner, rather than using software installed on a PC.

The scanned files are saved to the SD Card on the Raspberry Pi, and you simply access them via the local network from any device. I haven't incorporated a direct scan then print function, as it was not part of this project, but having said that, it would not be too hard to get that feature to work, pretty much like a stand alone photocopier.

Full details on my website - http://ozmacguyver.com/projects/index.php/2-canonpiscanner

But I will also post here too.

Supplies

  • Raspberry Pi 3 Model B+ (or similar)
  • Official 7" Touchscreen (or similar or just a non-touch screen)
  • Keyboard
  • Mouse
  • 12v DC 3A Power Supply
  • 12v DC 3A to 5V converter module (ebay is full of them)
  • Adafruit 3.7w Class D Amplifier Module and appropriate speakers (laptop or similar) - OR just a set of normal speakers with 3.5mm plug
  • USB Scanner (compatible with SANE)
  • USB cable
  • Hook up Wire

Step 1: Python Code

As you can see, this is the GUI that you use on a touchscreen 

It can be mouse driven and use a non-touch screen also, but how 80's is that?

Here's the code for the GUI (Python code, bash scripts, audio and image files)

https://drive.google.com/file/d/1YJNoiFuf5jd6LuqmRgo8HKtN15SmuxU6/view?usp=sharing

Here's a view of the Python GUI code

<code>from tkinter import *
import tkinter as tk
import tkinter.font as font
import subprocess
import os
import socket
import sys
from time import *
from time import sleep
import time
from pydub import AudioSegment
from pydub.playback import play
import os.path
from os import path
import pathlib
from tkinter import ttk #PROGRESS BAR
import tempfile


# ------------------------------------------------------------------------------
#                  RASPBERRY PI CANON SCANNER by OZMACGUYVER 2019
# ------------------------------------------------------------------------------
# SET UP MAIN WINDOW GUI
root = tk.Tk()
root.configure(bg='#402F2F')
# WINDOW TITLE
root.title("Cano-Pi-Scanner")
# WINDOW SIZE
root.geometry("614x1024")  # 7" SCREEN MODIFIED
# FULL SCREEN - NO TITLE BAR
root.wm_attributes('-fullscreen','true')
# ------------------------------------------------------------------------------
# SET UP FONT SIZES AND TYPES
myFont0 = font.Font(family='Courier', size=6)
myFont1 = font.Font(family='Courier', size=8, weight="bold")
myFont2 = font.Font(family='Courier', size=12, weight="bold")
myFont3 = font.Font(family='Courier', size=4, weight="bold")
# ------------------------------------------------------------------------------
# SET UP FOLDER
folder = pathlib.Path("/home/pi/CanoPyScannerGUI/scanner")
checkFOLDERempty = os.listdir('/home/pi/CanoPyScannerGUI/scanner')
# ------------------------------------------------------------------------------
# SETUP SOUND
soundERROR = AudioSegment.from_mp3('/home/pi/CanoPyScannerGUI/audio/Beep_Short.mp3')
soundGOOD = AudioSegment.from_mp3('/home/pi/CanoPyScannerGUI/audio/complete.mp3')
soundCONNECTIONlost = AudioSegment.from_mp3('/home/pi/CanoPyScannerGUI/audio/device-removed.mp3')
soundCONNECTIONfound = AudioSegment.from_mp3('/home/pi/CanoPyScannerGUI/audio/device-added.mp3')
# SET UP IMAGES
LOGO = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/logo.png")
BW = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/blacknwhite.png")
COLOUR = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/color.png")
GREY = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/greyscale.png")
USB = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/usb.png")
WIFI = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/wifi.png")
POWER_OFF = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/poweroff.png")
REBOOT = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/reboot.png")
TRASH = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/trash.png")
FOLDER = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/folder.png")
HAPPY = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/happy.png")
PUZZLED = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/puzzled.png")
ERROR = tk.PhotoImage(file = "/home/pi/CanoPyScannerGUI/images/error.png")
# ------------------------------------------------------------------------------
# LOGO
iconLOGO = (LOGO)
theLabelIMAGE = tk.Label(root, image = iconLOGO, bg='#402F2F')
theLabelIMAGE.grid(row=0, column=0, columnspan=2)
# ------------------------------------------------------------------------------
# SPACE
theLabelEMPTY1 = Label(root, text="", bg='#402F2F')
theLabelEMPTY1.grid(row=1, column=1)
theLabelEMPTY1 = Label(root, text="", bg='#402F2F')
theLabelEMPTY1.grid(row=4, column=1)
# ------------------------------------------------------------------------------
# CHECK SCANNER IS CONNECTED/POWERED ON GUI START
scannerCONNECTEDinitial = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
# ------------------------------------------------------------------------------
# SET UP BUTTONS
# A4 BW 600 DPI.
def A4_BW_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    print('A4 600 DPI B&W Scanning......')
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    if scannerCHECKbeforeSCAN == 0:
       buttonRECHECKusb['text'] = 'USB CONNECTED'
       buttonA4BW600['text'] = 'A4 600 DPI - B&W'
       os.setuid(os.geteuid())
       A4_BW_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/A4_BW.sh", shell=True)
       play(soundGOOD)
       print('Finished')
    if scannerCHECKbeforeSCAN == 1:
       buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
       buttonA4BW600['text'] = 'NOT CONNECTED'
       play(soundCONNECTIONlost)



iconbuttonA4BW600 = (BW)
iconbuttonA4BW600RESIZE = iconbuttonA4BW600.subsample(2, 2)
buttonA4BW600 = Button(text = 'A4 600 DPI - B&W', image = iconbuttonA4BW600RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = A4_BW_GO)
buttonA4BW600['font'] = myFont2
buttonA4BW600.grid(row=5, column=0)
# ------------------------------------------------------------------------------
# A4 COLOUR 300 DPI
def A4COLOUR300_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('A4 300 DPI COLOUR Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonA4COLOUR300['text'] = 'A4 300 DPI - COLOUR'
        os.setuid(os.geteuid())
        A4COLOUR300_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/A4_Colour_300.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonA4COLOUR300['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonA4COLOUR300 = (COLOUR)
iconbuttonA4COLOUR300RESIZE = iconbuttonA4COLOUR300.subsample(2, 2)
buttonA4COLOUR300 = Button(text = 'A4 300 DPI - COLOUR', image = iconbuttonA4COLOUR300RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = A4COLOUR300_GO)
buttonA4COLOUR300['font'] = myFont2
buttonA4COLOUR300.grid(row=5, column=1)
# ------------------------------------------------------------------------------
# A4 COLOUR 600 DPI
def A4COLOUR600_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('A4 600 DPI COLOUR Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        os.setuid(os.geteuid())
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonA4COLOUR600['text'] = 'A4 600 DPI - COLOUR'
        A4COLOUR600_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/A4_Colour_600.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonA4COLOUR600['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonA4COLOUR600 = (COLOUR)
iconbuttonA4COLOUR600RESIZE = iconbuttonA4COLOUR600.subsample(2, 2)
buttonA4COLOUR600 = Button(text = 'A4 600 DPI - COLOUR', image = iconbuttonA4COLOUR600RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = A4COLOUR600_GO)
buttonA4COLOUR600['font'] = myFont2
buttonA4COLOUR600.grid(row=6, column=0)
# ------------------------------------------------------------------------------
# A4 GREY 300 DPI
def A4GREY300_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('A4 300 DPI GREY Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonA4GREY300['text'] = 'A4 300 DPI - GREY'
        os.setuid(os.geteuid())
        A4GREY300_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/A4_Grey_300.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonA4GREY300['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonA4GREY300 = (GREY)
iconbuttonA4GREY300RESIZE = iconbuttonA4GREY300.subsample(2, 2)
buttonA4GREY300 = Button(text = 'A4 300 DPI - GREY', image = iconbuttonA4GREY300RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = A4GREY300_GO)
buttonA4GREY300['font'] = myFont2
buttonA4GREY300.grid(row=6, column=1)
# ------------------------------------------------------------------------------
# A4 GREY 600 DPI
def A4GREY600_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('A4 600 DPI GREY Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonA4GREY600['text'] = 'A4 600 DPI - GREY'
        os.setuid(os.geteuid())
        A4GREY600_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/A4_Grey_600.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonA4GREY600['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonA4GREY600 = (GREY)
iconbuttonA4GREY600RESIZE = iconbuttonA4GREY600.subsample(2, 2)
buttonA4GREY600 = Button(text = 'A4 600 DPI - GREY', image = iconbuttonA4GREY600RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = A4GREY600_GO)
buttonA4GREY600['font'] = myFont2
buttonA4GREY600.grid(row=7, column=0)
# ------------------------------------------------------------------------------
# ID COLOUR 600 DPI
def IDCOLOUR600_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('ID 600 DPI COLOUR Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonIDCOLOUR600['text'] = 'ID 600 DPI - COLOUR'
        os.setuid(os.geteuid())
        IDCOLOUR600_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/ID_Colour_600.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonIDCOLOUR600['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonIDCOLOUR600 = (COLOUR)
iconbuttonIDCOLOUR600RESIZE = iconbuttonIDCOLOUR600.subsample(2, 2)
buttonIDCOLOUR600 = Button(text = 'ID 600 DPI - COLOUR', image = iconbuttonIDCOLOUR600RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = IDCOLOUR600_GO)
buttonIDCOLOUR600['font'] = myFont2
buttonIDCOLOUR600.grid(row=7, column=1)
# ------------------------------------------------------------------------------
# ID GREY 600 DPI
def IDGREY600_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('ID 600 DPI GREY Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonIDGREY600['text'] = 'ID 600 DPI - GREY'
        os.setuid(os.geteuid())
        IDGREY600_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/ID_Grey_600.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonIDGREY600['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonIDGREY600 = (GREY)
iconbuttonIDGREY600RESIZE = iconbuttonIDGREY600.subsample(2, 2)
buttonIDGREY600 = Button(text = 'ID 600 DPI - GREY', image = iconbuttonIDGREY600RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = IDGREY600_GO)
buttonIDGREY600['font'] = myFont2
buttonIDGREY600.grid(row=8, column=0)
# ------------------------------------------------------------------------------
# PHOTO COLOUR 300 DPI
def PHOTOCOLOUR300DPI_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('PHOTO 300 DPI COLOUR Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonPHOTOCOLOUR300['text'] = 'PHOTO 300 DPI - COLOUR'
        os.setuid(os.geteuid())
        PHOTOCOLOUR300DPI_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/Photo_Colour_300.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonPHOTOCOLOUR300['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonPHOTOCOLOUR300 = (COLOUR)
iconbuttonPHOTOCOLOUR300RESIZE = iconbuttonPHOTOCOLOUR300.subsample(2, 2)
buttonPHOTOCOLOUR300 = Button(text = 'PHOTO 300 DPI - COLOUR', image = iconbuttonPHOTOCOLOUR300RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = PHOTOCOLOUR300DPI_GO)
buttonPHOTOCOLOUR300['font'] = myFont2
buttonPHOTOCOLOUR300.grid(row=8, column=1)
# ------------------------------------------------------------------------------
# PHOTO COLOUR 600 DPI
def PHOTOCOLOUR600DPI_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('PHOTO 600 DPI COLOUR Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonPHOTOCOLOUR600['text'] = 'PHOTO 600 DPI - COLOUR'
        os.setuid(os.geteuid())
        PHOTOCOLOUR600DPI_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/Photo_Colour_600.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonPHOTOCOLOUR600['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonPHOTOCOLOUR600 = (COLOUR)
iconbuttonPHOTOCOLOUR600RESIZE = iconbuttonPHOTOCOLOUR600.subsample(2, 2)
buttonPHOTOCOLOUR600 = Button(text = 'PHOTO 600 DPI - COLOUR', image = iconbuttonPHOTOCOLOUR600RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = PHOTOCOLOUR600DPI_GO)
buttonPHOTOCOLOUR600['font'] = myFont2
buttonPHOTOCOLOUR600.grid(row=9, column=0)
# ------------------------------------------------------------------------------
# PHOTO GREY 300DPI
def PHOTOGREY300DPI_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('PHOTO 300 DPI GREY Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonPHOTOGREY300['text'] = 'PHOTO 300 DPI - GREY'
        os.setuid(os.geteuid())
        PHOTOGREY300DPI_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/Photo_Grey_300.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonPHOTOGREY300['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonPHOTOGREY300 = (GREY)
iconbuttonPHOTOGREY300RESIZE = iconbuttonPHOTOGREY300.subsample(2, 2)
buttonPHOTOGREY300 = Button(text = 'PHOTO 300 DPI - GREY', image = iconbuttonPHOTOGREY300RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = PHOTOGREY300DPI_GO)
buttonPHOTOGREY300['font'] = myFont2
buttonPHOTOGREY300.grid(row=9, column=1)
# ------------------------------------------------------------------------------
# PHOTO GREY 600DPI
def PHOTOGREY600DPI_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('PHOTO 600 DPI GREY Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonPHOTOGREY600['text'] = 'PHOTO 600 DPI - GREY'
        os.setuid(os.geteuid())
        PHOTOGREY600DPI_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/Photo_Grey_600.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonPHOTOGREY600['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonPHOTOGREY600 = (GREY)
iconbuttonPHOTOGREY600RESIZE = iconbuttonPHOTOGREY600.subsample(2, 2)
buttonPHOTOGREY600 = Button(text = 'PHOTO 600 DPI - GREY', image = iconbuttonPHOTOGREY600RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = PHOTOGREY600DPI_GO)
buttonPHOTOGREY600['font'] = myFont2
buttonPHOTOGREY600.grid(row=10, column=0)
# ------------------------------------------------------------------------------
# PASSPORT 600 DPI
def PASSPORT600DPI_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('PASSPORT 600 DPI COLOUR Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonPASSPORT600['text'] = 'PASSPORT 600 DPI - COLOUR'
        os.setuid(os.geteuid())
        PASSPORT600DPI_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/Passport_600.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonPASSPORT600['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonPASSPORT600 = (COLOUR)
iconbuttonPASSPORT600RESIZE = iconbuttonPASSPORT600.subsample(2, 2)
buttonPASSPORT600 = Button(text = 'PASSPORT 600 DPI - COLOUR', image = iconbuttonPASSPORT600RESIZE, width=280, height=60, anchor='w', compound = LEFT, command = PASSPORT600DPI_GO)
buttonPASSPORT600['font'] = myFont2
buttonPASSPORT600.grid(row=10, column=1)
# ------------------------------------------------------------------------------
# RECEIPT_BW
def RECEIPT_BW_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('RECEIPT 600 DPI B&W Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonRECEIPT_BW['text'] = 'RECEIPT 600 DPI - B&W'
        os.setuid(os.geteuid())
        RECEIPT_BW_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/Receipt_BW.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonRECEIPT_BW['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonRECEIPT_BW = (BW)
iconbuttonRECEIPT_BWRESIZE = iconbuttonRECEIPT_BW.subsample(2, 2)
buttonRECEIPT_BW = Button(text = 'RECEIPT 600 DPI - B&W', image = iconbuttonRECEIPT_BWRESIZE, width=280, height=60, anchor='w', compound = LEFT, command = RECEIPT_BW_GO)
buttonRECEIPT_BW['font'] = myFont2
buttonRECEIPT_BW.grid(row=11, column=0)
# ------------------------------------------------------------------------------
# SPACE
theLabelEMPTY1 = Label(root, text="", bg='#402F2F')
theLabelEMPTY1.grid(row=12, column=1)
# ------------------------------------------------------------------------------
# A4_IMAGE_ONLY
def A4_IMAGE_ONLY_GO():
    # THIS IS THE SCANNING PROCESS OF EVENTS
    scannerCHECKbeforeSCAN = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    print('IMAGE 600 DPI COLOUR Scanning......')
    if scannerCHECKbeforeSCAN == 0:
        buttonRECHECKusb['text'] = 'USB CONNECTED'
        buttonA4_IMAGE_ONLY['text'] = 'IMAGE 600 DPI - COLOUR'
        os.setuid(os.geteuid())
        A4_IMAGE_ONLY_GO = subprocess.call("sudo /home/pi/CanoPyScannerGUI/A4_Image_only.sh", shell=True)
        play(soundGOOD)
        print('Finished')
    if scannerCHECKbeforeSCAN == 1:
        buttonRECHECKusb['text'] = 'USB NOT CONNECTED'
        buttonRECEIPT_BW['text'] = 'NOT CONNECTED'
        play(soundCONNECTIONlost)

iconbuttonA4_IMAGE_ONLY = (COLOUR)
iconbuttonA4_IMAGE_ONLYRESIZE = iconbuttonA4_IMAGE_ONLY.subsample(2, 2)
buttonA4_IMAGE_ONLY = Button(text = 'IMAGE 600 DPI - COLOUR', image = iconbuttonA4_IMAGE_ONLYRESIZE, width=280, height=60, anchor='w', compound = LEFT, command = A4_IMAGE_ONLY_GO)
buttonA4_IMAGE_ONLY['font'] = myFont2
buttonA4_IMAGE_ONLY.grid(row=11, column=1)

# FOLDER CHECKING
icontheLabelFOLDERfound = (HAPPY)
icontheLabelFOLDERfoundRESIZE = icontheLabelFOLDERfound.subsample(1, 1)
icontheLabelFOLDERmissing = (ERROR)
icontheLabelFOLDERmissingRESIZE = icontheLabelFOLDERmissing.subsample(1, 1)

def main():
    if folder.exists ():
        print ("Folder Exists!")
        theLabelFOLDER = Label(root, text="    Scanned Documents Folder OK", image = icontheLabelFOLDERfoundRESIZE, compound = LEFT, bg='#402F2F', fg='#ffffff')
        theLabelFOLDER['font'] = myFont2
        theLabelFOLDER.grid(row=13, column=0, columnspan=2)
    else:
        print ("Folder Missing!")
        theLabelFOLDER = Label(root, text="    Scanned Documents Folder Missing!", image = icontheLabelFOLDERmissingRESIZE, compound = LEFT, bg='#402F2F', fg='#ff0000')
        theLabelFOLDER['font'] = myFont2
        theLabelFOLDER.grid(row=13, column=0, columnspan=2)

# RUNS WHEN THE MAINLOOP (GUI) STARTS
if __name__== "__main__":
   main()
# ------------------------------------------------------------------------------
theLabelEMPTY1 = Label(root, text="", bg='#402F2F')
theLabelEMPTY1.grid(row=14, column=1)
# ------------------------------------------------------------------------------
# IP ADDRESS
IP = subprocess.getoutput('hostname -I')
icontheLabelIP = (WIFI)
theLabelIP = Label(text = "    " + IP, fg="white", image = icontheLabelIP, compound = LEFT, bg='#402F2F')
theLabelIP['font'] = myFont2
theLabelIP.grid(row=17, column=0, columnspan=2)
# ------------------------------------------------------------------------------
# SPACE
theLabelEMPTY1 = Label(root, text="", bg='#402F2F')
theLabelEMPTY1.grid(row=20, column=0)
# ------------------------------------------------------------------------------
# DELETE ALL
def DELETEALL_GO():
    # THIS IS THE PROCESS OF EVENTS
    os.setuid(os.geteuid())
    if checkFOLDERempty:
        subprocess.call("sudo /home/pi/CanoPyScannerGUI/Delete_All_Documents.sh", shell=True)
        buttonDELETEALL['text'] = 'Delete All'
        play(soundGOOD)
        print('Finished')
    else:
        buttonDELETEALL['text'] = 'Delete All'
        play(soundGOOD)

iconbuttonDELETEALL = (TRASH)
buttonDELETEALL = Button(text = 'Delete All', image = iconbuttonDELETEALL, width=280, height=60, compound = LEFT, command = DELETEALL_GO, bg='#DD5B5B')
buttonDELETEALL['font'] = myFont2
buttonDELETEALL.grid(row=50, column=1)
# ------------------------------------------------------------------------------
# REBOOT
def Reboot_GO():
    subprocess.call("sudo reboot now", shell=True)

iconbuttonREBOOT = (REBOOT)
iconbuttonREBOOTRESIZE = iconbuttonREBOOT.subsample(1, 1)
buttonREBOOT = Button(text = 'Re-Boot', image = iconbuttonREBOOTRESIZE, width=280, height=60, compound = LEFT, command = Reboot_GO, bg='#767BEC')
buttonREBOOT['font'] = myFont2
buttonREBOOT.grid(row=50, column=0)
# ------------------------------------------------------------------------------
# POWER OFF
def ShutDown_GO():
    subprocess.call("sudo shutdown now", shell=True)

iconbuttonPOWEROFF = (POWER_OFF)
iconbuttonPOWEROFFRESIZE = iconbuttonPOWEROFF.subsample(1, 1)
buttonPOWEROFF = Button(text = 'Power Off', image = iconbuttonPOWEROFFRESIZE, width=280, height=60, compound = LEFT, command = ShutDown_GO, bg='#A9F659')
buttonPOWEROFF['font'] = myFont2
buttonPOWEROFF.grid(row=51, column=0)
# ------------------------------------------------------------------------------
# SCANNER CONNECTED ICON
# MANUAL USB RE-PING
def RECHECKusbGO():
    # RESET BUTTONS BACK TO START UP STATE
    buttonRECEIPT_BW['text'] = 'RECEIPT 600 DPI - B&W'
    buttonPASSPORT600['text'] = 'PASSPORT 600 DPI - COLOUR'
    buttonPHOTOGREY600['text'] = 'PHOTO 600 DPI - GREY'
    buttonPHOTOGREY300['text'] = 'PHOTO 300 DPI - GREY'
    buttonPHOTOCOLOUR600['text'] = 'PHOTO 600 DPI - COLOUR'
    buttonPHOTOCOLOUR300['text'] = 'PHOTO 300 DPI - COLOUR'
    buttonIDGREY600['text'] = 'ID 600 DPI - GREY'
    buttonIDCOLOUR600['text'] = 'ID 600 DPI - COLOUR'
    buttonA4GREY600['text'] = 'A4 600 DPI - GREY'
    buttonA4GREY300['text'] = 'A4 300 DPI - GREY'
    buttonA4COLOUR600['text'] = 'A4 600 DPI - COLOUR'
    buttonA4COLOUR300['text'] = 'A4 300 DPI - COLOUR'
    buttonA4BW600['text'] = 'A4 600 DPI - B&W'
    # CHECKING USB CONNECTION
    os.setuid(os.geteuid())
    RECHECKusbGO = subprocess.call("sudo lsusb |grep 04a9:176d", shell=True)
    if RECHECKusbGO == 0:
        buttonRECHECKusb['text'] = 'USB RE-CHECK SUCCESSFUL'
        play(soundCONNECTIONfound)
    if RECHECKusbGO == 1:
        buttonRECHECKusb['text'] = 'USB RE-CHECK FAIL'
        play(soundCONNECTIONlost)

if scannerCONNECTEDinitial == 0:
    iconRECHECKusb = (USB)
    buttonRECHECKusb = Button(text = "USB CONNECTED", image = iconRECHECKusb, width=280, height=60, compound = LEFT, command = RECHECKusbGO, bg='#938C8C')
    play(soundCONNECTIONfound)
    buttonRECHECKusb['font'] = myFont2
    buttonRECHECKusb.grid(row=51, column=1)

if scannerCONNECTEDinitial == 1:
    iconRECHECKusb = (USB)
    buttonRECHECKusb = Button(text = "USB NOT CONNECTED", image = iconRECHECKusb, width=280, height=60, compound = LEFT, command = RECHECKusbGO, bg='#938C8C')
    play(soundCONNECTIONlost)
    buttonRECHECKusb['font'] = myFont2
    buttonRECHECKusb.grid(row=51, column=1)
# ------------------------------------------------------------------------------

root.mainloop()

What is this code that I see?

sudo lsusb | grep 04a9:176d

Basically, you need to check the Scanner is connected when running the Python GUI commands, otherwise, it will just sit there asking to scan a document, but there won't be a response, or the code will terminate.

When you just run the following

sudo lsusb

It will probe the USB Bus, and give you a list of USB devices connected to the USB Bus

The screenshot above shows a list of my devices, mine is the Canon, Inc. PIXMA MG2500 Series

If you take not of the identifier, then add this to the end, it will probe the USB bus, but only look for your Scanner

sudo lsusb | grep 04a9:176d

As per the other screenshot above

A4_BW.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# A4_BW.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 600 --mode Lineart -x 210 -y 297 | pnmtops -imagewidth 11.3 -imageheight 11.7 -nocenter | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

A4_Colour_300.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# A4_Colour_300.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 300 --mode Color -x 210 -y 297 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

A4_Colour_600.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# A4_Colour_600.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 600 --mode Color -x 210 -y 297 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

A4_Grey_300.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# A4_Grey_300.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 300 --mode Gray -x 210 -y 297 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

A4_Grey_600.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# A4_Grey_600.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 600 --mode Gray -x 210 -y 297 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

A4_Image_only.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Image_${datetime}"

#For a normal image (colour or grey scale)
scanimage -d 'pixma:04A9176D_EEEA33' --progress --format=tiff --resolution 600 -x 2550 -y 3300 > /home/pi/CanoPyScannerGUI/scanner/$filename.tiff

Delete_All_Documents.sh

#!/bin/bash<br>
# DELETE ALL DOCUMENTS FROM SCANNER FOLDER
rm /home/pi/CanoPyScannerGUI/scanner/*.pdf
rm /home/pi/CanoPyScannerGUI/scanner/*.tiff

ID_Colour_600.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# ID_Colour_600.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 600 --mode Color -x 54 -y 85.5 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

ID_Grey_600.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# ID_Grey_600.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 600 --mode Gray -x 54 -y 85.5 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

Passport_600.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# Passport_600.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 600 --mode Color -x 88 -y 125 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

Photo_Colour_300.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# Photo_Colour_300.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 300 --mode Color -x 104 -y 154 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

Photo_Colour_600.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# Photo_Colour_600.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 600 --mode Color -x 104 -y 154 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

Photo_Grey_300.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# Photo_Grey_300.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 300 --mode Gray -x 104 -y 154 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

Photo_Grey_600.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# Photo_Grey_600.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 600 --mode Gray -x 104 -y 154 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

ID_Grey_600.sh

#!/bin/bash<br>
# Scanning the document, and saving with timestamp
datetime="`date '+%Y%m%d%H%M%S'`"
filename="Scanned_Document_${datetime}"

# ID_Grey_600.sh
scanimage -d 'pixma:04A9176D_EEEA33' --progress --resolution 600 --mode Gray -x 80 -y 297 | pnmtops -imageheight 11.7 -imagewidth 8.3 | ps2pdf - /home/pi/CanoPyScannerGUI/scanner/$filename.pdf

start_saned.py

import subprocess
subprocess.call("sudo su -s /bin/sh - saned", shell=True)

startup_gui.sh

#!/usr/bin/sh<br>sleep 4
python3 /home/pi/CanoPyScannerGUI/gui.py

Step 2: Configuring the Raspberry Pi

Boot up the Raspberry Pi, and open a terminal so we can enable SSH

sudo raspi-config

I won't delve into changing users or the initial password. For the purposes of this project, I've left everything stock so it's easier to follow the process

Now we can SSH into the Raspberry Pi, and complete our settings remotely (IP address will differ) ssh

pi@192.168.1.xxx

Add user to SUDOERS group

sudo usermod -aG sudo pi

Make sure you update/upgrade the OS

sudo apt update && sudo apt upgrade

Now we install what we need

sudo apt install python3 python3-tk
sudo apt install python-pip
sudo apt install python3-pip
sudo pip install pydub
sudo pip3 install pydub
sudo apt install netpbm ghostscript samba sane

Now we copy our folder that contains the python gui, bash scripts, images and audio files from the LOCAL machine to the RASPBERRY PI (I have included my local folder structure and the destination folder structure as an example)

scp -r /home/debianos/projects/CanoPyScannerGUI/ pi@192.168.1.xxx:/home/pi/CanoPyScannerGUI/

Change the permissions of the scanner folder - https://linuxize.com/post/what-does-chmod-777-mea...

chmod 777 /home/pi/CanoPyScannerGUI/scanner

We now need to edit the config.txt file, and add code to make the Official 7" Touchscreen work

cd /boot
sudo nano config.txt 

Add the following

# LCD SCREEN SIZE (FOR 7")
framebuffer_width=614
framebuffer_height=1024

# ROTATES THE LCD ONLY
display_rotate=1

# ROTATES THE LCD TOUCH DRIVER TO MATCH THE LCD ROTATION
dtoverlay=rpi-ft5406,touchscreen-
swapped-x-y=1,touchscreen-inverted-x=1,touchscreen-inverted-y=1

Reboot, and let's check the resolution

sudo reboot now
ssh pi@192.168.1.xxx 
fbset -s

Make scripts executable

chmod +x /home/pi/CanoPyScannerGUI/*.sh

Set up a SAMBA share

sudo nano /etc/samba/smb.conf

add this to the end

[scanner]
    comment = Samba on Ubuntu
    path = /home/pi/CanoPyScannerGUI/scanner
    read only = no
    browsable = yes

Restart the SAMBA service

sudo service smbd restart

Set up a password for the SAMBA share

sudo smbpasswd -a pi

Connect to the SAMBA share from the LOCAL PC

smb://raspberrypi.local/scanner/

Lets now make the GUI Auto start when the OS boots up

sudo nano /etc/xdg/lxsession/LXDE-pi/autostart

add this to the end

@sh /home/pi/CanoPyScannerGUI/startup_gui.sh

Remove the rainbow screen

sudo nano /boot/config.txt 

add this to the end

disable_splash=1

Remove the text that is displayed under the boot splash screen

sudo nano /usr/share/plymouth/themes/pix/pix.script

Comment out as follows

#message_sprite = Sprite();
#message_sprite.SetPosition(screen_width * 0.1, screen_height * 0.9, 10000);
#       my_image = Image.Text(text, 1, 1, 1);
#       message_sprite.SetImage(my_image);

Remove Boot Messages

sudo nano /boot/cmdline.txt 

Replace “console=tty1” with “console=tty3” (This redirects boot messages to tty3)

add this to the end

splash quiet plymouth.ignore-serial-consoles logo.nologo vt.global_cursor_default=0

Here are brief explanations.

‘splash’ : enables splash image,

‘quiet’ : disable boot message texts,

‘plymouth.ignore-serial-consoles’ : not sure about this but seems it’s required when use Plymouth,

‘logo.nologo’ : removes Raspberry Pi logo in top left corner,

‘vt.global_cursor_default=0’ : removes blinking cursor.

Replace the default splash screen

sudo cp /usr/share/plymouth/themes/pix/splash.png /home/pi/
sudo cp /home/pi/CanoPyScannerGUI/images/logo.png /usr/share/plymouth/themes/pix/splash.png

We need to now control the Raspberry Pi locally, so grab the mouse and keyboard you plugged in earlier, and navigate as follows:

APPEARANCE PREFERENCES > CHOOSE logo.png from /home/pi/CanoPyScannerGUI/images 
SET CENTRED 
CHANGE WALLPAPER COLOUR TO DARK

The display will blank out due to power saving mode, we need to disable this

sudo nano /etc/lightdm/lightdm.conf

add to the [SEATS] options

# don't sleep the screen
xserver-command=X -s 0 dpms

Now, let's see if it all works!

sudo reboot

Step 3: Final Result