- Modular Design: Each hardware/software function (e.g., camera, light source, cuvette sensor, analysis, logger, GUI) is implemented as a separate module class (see
camera.py,lightSource.py, etc.), inheriting from the abstractModulebase class (module.py). - EventManager: Central orchestrator (
eventManager.py) runs as a process, routes messages between modules, and manages lifecycle (registration, shutdown, etc.). - Inter-Process Communication: Modules communicate via message queues managed by the
Communicatorclass. Messages are dictionaries withSender,Destination, andMessage(withtypeandpayload). - Configuration: All runtime configuration is loaded from
config.jsonviaConfigLoader. Module enablement, hardware parameters, and network settings are defined here. - Startup:
main.pyloads config, starts enabled modules as separate processes, and launches the EventManager. Shutdown is coordinated via signals.
- Dependencies:
apt install libcap-dev python3-dev qtbase5-dev python3-libcamera python3-kms++pip install -r requirements.txt - Debugging: Each module logs via the Logger module. Use log messages for tracing inter-module communication and errors.
- Configuration Changes: Edit
config.jsonto enable/disable modules or change hardware/network settings. Restart the app to apply changes.
- Message Routing: All inter-module communication uses the message queue pattern. Always use
sendMessage(destination, msgType, payload)fromModule. - Lifecycle Hooks: Modules override
onStart,mainLoop,handleMessage, andonStopfor custom logic. - Registration: Modules register with EventManager on startup by sending a
Registermessage. - Logging: Use the
log(level, message)method to send logs to the Logger module. Do not print directly except for startup/shutdown. - Threading: Each module runs its own thread for communication. Main logic runs in a separate process.
- Kivy GUI: The GUI module (
gui.py,gui.kv) uses Kivy for the user interface. It is started as a module and communicates via the same message system. - Hardware: GPIO, camera, and sensor modules use hardware-specific libraries (see
requirements.txt). - Diagrams: Architecture and activity diagrams are in
diagrams/for reference.
- To add a new module, inherit from
Module, implement lifecycle methods, and updatemain.pyandconfig.json. - To send a message from a module:
self.sendMessage("EventManager", "Register") self.sendMessage("Logger", "LogMessage", {"level": "INFO", "message": "Started"})
main.py: Startup and process orchestrationmodule.py: Base class for all moduleseventManager.py: Central message routerconfig.json: Configuration for modules and systemrequirements.txt: Python dependenciestests/unit/: Unit tests for each modulediagrams/: Architecture diagrams
This dark chamber is the hardware companion to Raspiscope, the Raspberry Pi 4-based spectrophotometer that runs the software linked above. Every part is tuned for resin 3D printing to keep the optical path opaque and dimensionally accurate.
- Bidirectional level shifter to translate the Raspberry Pi 4 GPIO 3.3 V logic to the 5 V required by the LED and the Hall effect sensor (Amazon link).
- 12 V -> 5 V DC-DC converter when powering the LED and sensor with eight AA batteries; otherwise rely on a dedicated 5 V power supply. You can tap the Raspberry Pi’s 5 V rail, but it often proves unstable for this load (Amazon link).
- SS49E Hall effect sensor to monitor the presence of the cuvette (Amazon link).
- Diffraction grating to decompose the light spectrum (Amazon link)
- RGB LED as light source (Amazon link)
- Raspberry Pi Camera V2 or V3 (Amazon link) (Amazon link)
- Raspberry Pi (Amazon link)
The project is released as free software under the Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.
- Progettazione modulare: Ogni funzione hardware/software (ad es. camera, sorgente luminosa, sensore della cuvetta, analisi, logger, GUI) è implementata come classe modulo separata (vedi
camera.py,lightSource.py, ecc.), che eredita dalla classe base astrattaModule(module.py). - EventManager: L'orchestratore centrale (
eventManager.py) gira come processo, instrada i messaggi tra i moduli e gestisce il ciclo di vita (registrazione, spegnimento, ecc.). - Comunicazione inter-processo: I moduli comunicano tramite code di messaggi gestite dalla classe
Communicator. I messaggi sono dizionari conSender,DestinationeMessage(contypeepayload). - Configurazione: Tutta la configurazione runtime è caricata da
config.jsontramiteConfigLoader. Qui sono definiti l'abilitazione dei moduli, i parametri hardware e le impostazioni di rete. - Avvio:
main.pycarica la configurazione, avvia i moduli abilitati come processi separati e lancia l'EventManager. L'arresto è coordinato tramite segnali.
- Dipendenze:
apt install libcap-dev python3-dev qtbase5-dev python3-libcamera python3-kms++pip install -r requirements.txt - Debug: Ogni modulo registra tramite il modulo Logger. Usa i log per tracciare la comunicazione inter-modulo e gli errori.
- Modifiche di configurazione: Modifica
config.jsonper abilitare/disabilitare i moduli o cambiare impostazioni hardware/rete. Riavvia l'app per applicare le modifiche.
- Instradamento dei messaggi: Tutta la comunicazione inter-modulo usa il pattern delle code di messaggi. Usa sempre
sendMessage(destination, msgType, payload)daModule. - Hook del ciclo di vita: I moduli sovrascrivono
onStart,mainLoop,handleMessageeonStopper la logica personalizzata. - Registrazione: I moduli si registrano con EventManager all'avvio inviando un messaggio
Register. - Logging: Usa
log(level, message)per inviare i log al modulo Logger. Non stampare direttamente se non in avvio/spegnimento. - Threading: Ogni modulo esegue il proprio thread per la comunicazione. La logica principale gira in un processo separato.
- GUI Kivy: Il modulo GUI (
gui.py,gui.kv) usa Kivy per l'interfaccia utente. È avviato come modulo e comunica tramite lo stesso sistema di messaggi. - Hardware: I moduli GPIO, camera e sensore usano librerie specifiche per l'hardware (vedi
requirements.txt). - Diagrammi: I diagrammi di architettura e attività sono in
diagrams/come riferimento.
- Per aggiungere un nuovo modulo, eredita da
Module, implementa i metodi di ciclo di vita e aggiornamain.pyeconfig.json. - Per inviare un messaggio da un modulo:
self.sendMessage("EventManager", "Register") self.sendMessage("Logger", "LogMessage", {"level": "INFO", "message": "Started"})
main.py: Avvio e orchestrazione dei processimodule.py: Classe base per tutti i modulieventManager.py: Router centrale dei messaggiconfig.json: Configurazione per moduli e sistemarequirements.txt: Dipendenze Pythontests/unit/: Test unitari per ciascun modulodiagrams/: Diagrammi di architettura
Questa camera oscura è il compagno hardware di Raspiscope, lo spettrofotometro UV-Vis basato su Raspberry Pi 4 che esegue il software linkato sopra. Ogni parte è ottimizzata per la stampa 3D a resina per mantenere il cammino ottico opaco e dimensionalmente accurato.
- Traslatore di livello bidirezionale per convertire la logica a 3,3 V dei GPIO del Raspberry Pi 4 ai 5 V richiesti dal LED e dal sensore di effetto Hall (link Amazon).
- Convertitore DC-DC 12 V -> 5 V quando si alimentano LED e sensore con otto batterie AA; altrimenti affidarsi a un'alimentazione dedicata da 5 V. È possibile prelevare la linea da 5 V del Raspberry Pi, ma spesso risulta instabile per questo carico (link Amazon).
- Sensore di effetto Hall SS49E per monitorare la presenza della cuvetta (link Amazon).
- Reticolo di diffrazione per scomporre lo spettro luminoso (link Amazon)
- LED RGB come sorgente luminosa (link Amazon)
- Raspberry Pi Camera V2 o V3 (link Amazon) (link Amazon)
- Raspberry Pi (link Amazon)
Il progetto è rilasciato come software libero sotto la licenza Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0).
If any section is unclear or missing, please provide feedback for further refinement.









