Electronics 3 LabDesign Demo — Raspberry Pi 4 simulation

Official

An interactive Raspberry Pi 4 circuit simulation you can run free in your browser on Velxio, by lusyyy-am.

Components

Sketch code

import os
import csv
import time
import serial
import statistics
import threading
import traceback

from datetime import datetime
from collections import deque

import RPi.GPIO as GPIO
from RPLCD.i2c import CharLCD


# ==========================================
# SENSIKITTY
# RASPBERRY PI 4
#
# Sensors run in a background thread.
# Dashboard runs in the main console.
# ==========================================


# ==========================================
# CAT DATABASE
# ==========================================

CATS = {
    0: "Max",
    1: "Ruby",
    2: "Jasmine",
    3: "Belle",
    4: "Mango"
}


# ==========================================
# HARDWARE CONFIGURATION
# ==========================================

RFID_PORT = "/dev/ttyAMA0"
RFID_BAUD = 9600
RFID_REARM_DELAY = 0.8

HX_DOUT = 5
HX_SCK = 6

# Existing Velxio calibration
CLOCK_DELAY = 0.001
COUNTS_PER_KG = 420000.0

WEIGHT_INTERVAL = 0.5
MIN_CAT_WEIGHT = 0.3
MAX_CAT_WEIGHT = 15.0

LCD_ADDRESS = 0x27

RESET_SECONDS = 5.0


# ==========================================
# DASHBOARD CONFIGURATION
# ==========================================

# Refresh when a cat enters or exits.
AUTO_REFRESH = True

# Refresh active view every N seconds.
# 0 disables periodic refresh.
REFRESH_SECONDS = 0


# ==========================================
# DATABASE FILES
# ==========================================

DATA_DIR = "sensikitty_data"

CATS_FILE = DATA_DIR + "/cats.csv"
VISITS_FILE = DATA_DIR + "/visits.csv"
SUMMARY_FILE = DATA_DIR + "/daily_summary.csv"

FIELDS = [
    "Visit_ID",
    "Cat_ID",
    "RFID",
    "Name",
    "Entry_Time",
    "Exit_Time",
    "Duration_Seconds",
    "Weight_kg",
    "Status",
    "Media_Status",
    "Video_Reference",
    "Audio_Reference",
    "AI_Alert"
]


# ==========================================
# SYSTEM STATE
# ==========================================

current_cat = None
current_visit_id = None

tare_offset = None

weight_samples = deque(maxlen=5)

last_weight_time = 0.0
last_rfid_time = time.monotonic()

scan_armed = True
reset_until = None

lcd = None
rfid = None

active_view = "dashboard"

running = threading.Event()
running.set()

data_lock = threading.RLock()
console_lock = threading.RLock()

sensor_error = None
last_refresh = 0.0


# ==========================================
# DATABASE FUNCTIONS
# ==========================================

def load_visits():
    with data_lock:
        if not os.path.exists(VISITS_FILE):
            return []

        with open(
            VISITS_FILE,
            "r",
            newline="",
            encoding="utf-8"
        ) as file:
            return list(csv.DictReader(file))


def write_csv(filename, fields, rows):
    temporary = filename + ".tmp"

    with data_lock:
        with open(
            temporary,
            "w",
            newlin