Anguraja Renganathan
Published © GPL3+

NanoVault

NanoVault is a pocket friendly compact, high-speed storage device (Computer) for travelers, photographers. Backup data to SSD or cloud

IntermediateFull instructions provided318
NanoVault

Things used in this project

Hardware components

raspberry pi compute 5
Core Component of the Project
×1
GL3224
USB 3.1 Card Reader IC to Interface with SD Cards
×1
SPI Flash
Flash memory For Storing Firmware For GL3224 Card Reader IC
×1
Texas Instruments ESD_DIODE
Protection ESD Diodes for HDMI, USB Type C and USB b Micro
×7
Buffer, 74VHC1G07
Buffer, 74VHC1G07
×2
Power Switch
×1
Texas Instruments Buck Converter
12V to 5V Buck Converter for Raspberry Pi CM5 Supply 12V to 3.3V Buck Converter for m.2 NVMe Memory Supply
×2
Load Switch
×1
NCP110
onsemi NCP110
×1
25MHz Clock oscillator
For the Card Reader IC Reference Clock
×1
32.768KHz Oscillator
nVME Reference Clock
×1
Slide Switch
For Controlling Power to Raspberry pi - ON/OFF Switch
×1
Push button Switch
For Shutting Down Raspberry pi CM5
×1
FAN Connec
Connecting Fan for Cooling Purpose
×1
HDMI Connector
HDMI Connector for Display
×1
USB_C Receptacle
Connecting to USB Type C SSD, Keyboard, MOuse Connection
×1
USB_B Micro
USB B For Debugging
×1
TE Connectivity M.2 M KEY nvme Connector
m.2 m KEY SSD 2230 Interfacing
×1
15 PIN DSI Connec
DSI Display Interfacing (Waveshare 2.8 inch With Touch Screen)
×1
12V DC JACK
Input Power Supply 12V
×1
SD CARD Connector
SDXC / SDHC Card Interfacing
×1
Resistor
×32
Capacitors
×45
10uH Inductor
+5V Buck Converter Inductor
×1
8.2uH Induct
+3.3V_nvme Buck Converter Inductor
×1
2.8 inch DSI Displa
Displaying Status and Touch Screen interface
×1
SSD M.2 M KEY 2230 Gen 3
×1
Machine Screw, M2.5
Machine Screw, M2.5
×4
3D Printed Top and Bottom case
×1

Software apps and online services

Raspbian
Raspberry Pi Raspbian
Raspberry Pi CM5 Operating System
CustomTkinter Python
Python Programming for GUI

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)
Mastech MS8217 Autorange Digital Multimeter
Digilent Mastech MS8217 Autorange Digital Multimeter

Story

Read more

Custom parts and enclosures

Enclosure_top

Step Files Designed using Autodesk Fusion 360

Enclosure_Bottom

Step Files Designed using Autodesk Fusion 360

Enclosure

Complete Enclosure of Board along with DSI Display

Schematics

NanoVault Ver 1.0

Schematic Diagram for Nanovault Ver 1.0

Code

NANOVAULT_GUI

Python
CustomTkinter GUI Code for Displaying Buttons Local backup and Cloud backup
it copies Data from removable disk to internal SSd and cloud
from sys import stdout

import customtkinter as ctk
import threading
import subprocess
import re

# Window Initialisation
ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("green")

app = ctk.CTk()
app.geometry("600x480")
app.title("NanoVault")

#Local Backup Progress bar
def open_progress_window_with_rsync():
    progress_window = ctk.CTkToplevel(app)
    progress_window.geometry("400x200")
    progress_window.title("Local Backup Progress")

    progress_bar = ctk.CTkProgressBar(progress_window, width=300)
    progress_bar.set(0)
    progress_bar.pack(pady=40)

    label = ctk.CTkLabel(progress_window, text="Starting...")
    label.pack()
#Local backup Source destination address
    def run_rsync():
        rsync_cmd = [
            "rsync",
            "-a",
            "--info=progress2",
            "/media/angu/sundar/DCIM.zip",           # USB Drive File Location
            "/media/angu/myssd"       # SSD Backup Location
        ]

        try:
            process = subprocess.Popen(
                rsync_cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                text=True
            )
            for line in process.stdout:
                print(line.strip())
                match = re.search(r'(\d+)%', line)
                if match:
                    percent = int(match.group(1))
                    progress_bar.set(percent / 100)
                    label.configure(text=f"Progress: {percent}%")

            process.wait()
            label.configure(text="Backup Complete ✅")
            progress_window.title("Done")

        except FileNotFoundError:
            label.configure(text="Error: rsync not found!")
        except Exception as e:
            label.configure(text=f"Error: {str(e)}")

    threading.Thread(target=run_rsync, daemon=True).start()

#Cloud backup Progress bar
def open_progress_window_with_rclone():
    progress_window = ctk.CTkToplevel(app)
    progress_window.geometry("400x200")
    progress_window.title("Cloud Backup Progress")

    progress_bar = ctk.CTkProgressBar(progress_window, width=300)
    progress_bar.set(0)
    progress_bar.pack(pady=40)

    label = ctk.CTkLabel(progress_window, text="Starting Dropbox Backup...")
    label.pack()

    def run_rclone():
        rclone_cmd = [
            "rclone",
            "copy",
            "/media/angu/myssd/DCIM.zip",            # <-- SSD Location
            "Dropbox: ",  # <-- Dropbox Location
            "--progress",
            "--stats=1s"
        ]

        try:
            process = subprocess.Popen(
                rclone_cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                text=True
            )
            for line in process.stdout:
                print(line.strip())
                # Try to find a percentage in line like "(123.45%)" or "45%"
                if "Transferred:" in line:
                    match = re.search(r'(\d+)%', line)
                    if match:
                        percent = int(match.group(1))
                        progress_bar.set(percent / 100)
                        label.configure(text=f"Progress: {percent}%")

                if match:
                    percent = int(match.group(1))
                    progress_bar.set(percent / 100)
                    label.configure(text=f"Progress: {percent}%")

            process.wait()
            label.configure(text="Cloud Backup Complete ✅")
            progress_window.title("Done")

        except FileNotFoundError:
            label.configure(text="Error: rclone not found!")
        except Exception as e:
            label.configure(text=f"Error: {str(e)}")

    threading.Thread(target=run_rclone, daemon=True).start()


def Local_backup():
    print("Local backup started...")
    open_progress_window_with_rsync()


def Cloud_backup():
    print("Cloud backup started...")
    open_progress_window_with_rclone()

#Button - Local backup
Button1 = ctk.CTkButton(
    app,
    corner_radius=25,
    width=200,
    height=100,
    text='Local Backup',
    text_color='white',
    font=("Segoe UI", 20, "bold"),
    command=Local_backup
)
Button1.pack(padx=10, side='right')

#Button - Cloud Backup
Button2 = ctk.CTkButton(
    app,
    corner_radius=25,
    width=200,
    height=100,
    text='Cloud Backup',
    font=("Segoe UI", 20, "bold"),
    command=Cloud_backup
)
Button2.pack(padx=10, side='left')

app.mainloop()

Credits

Anguraja Renganathan
1 project • 1 follower
Hardware engineer with 6+ Years of Experience in high Speed Design and Testing

Comments