update project structure
This commit is contained in:
214
README.md
214
README.md
@ -1,4 +1,212 @@
|
||||
files description:
|
||||
deploy -- creates venv and installs python libs in it
|
||||
run -- resets Generator_PCB by toggling PRi`s GPIO pin, activates venv and runs main program
|
||||
# RadioPhotonic PCB — Laser Controller
|
||||
|
||||
GUI application and embeddable Python module for controlling a dual-laser board
|
||||
over UART (115 200 baud). Designed to run on a Raspberry Pi or any Linux machine.
|
||||
|
||||
---
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
.
|
||||
├── _device_main.py # GUI application entry point
|
||||
├── gui.py # FreeSimpleGUI layout definition
|
||||
├── device_interaction.py # High-level device commands (legacy)
|
||||
├── device_commands.py # Low-level protocol helpers (legacy)
|
||||
├── device_conversion.py # Physical-unit conversion formulas (legacy)
|
||||
│
|
||||
├── laser_control/ # Standalone embeddable module
|
||||
│ ├── __init__.py # Public API
|
||||
│ ├── controller.py # LaserController class
|
||||
│ ├── protocol.py # Command encoding / response decoding
|
||||
│ ├── validators.py # Input validation
|
||||
│ ├── conversions.py # Physical-unit conversions
|
||||
│ ├── models.py # Dataclasses (Measurements, DeviceStatus, …)
|
||||
│ ├── constants.py # Protocol constants and physical limits
|
||||
│ ├── exceptions.py # Exception hierarchy
|
||||
│ └── example_usage.py # Usage examples
|
||||
│
|
||||
├── tests/ # pytest test suite (75 tests)
|
||||
│ ├── conftest.py
|
||||
│ ├── test_validation.py
|
||||
│ ├── test_protocol.py
|
||||
│ └── test_integration.py
|
||||
│
|
||||
├── pyproject.toml # Package metadata (laser_control)
|
||||
├── run # Launch script for the GUI app
|
||||
└── deploy # First-time environment setup script
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Setting up the virtual environment
|
||||
|
||||
### First-time setup
|
||||
|
||||
```bash
|
||||
# 1. Create virtual environment
|
||||
python3 -m venv .venv
|
||||
|
||||
# 2. Activate it
|
||||
source .venv/bin/activate
|
||||
|
||||
# 3. Install GUI and serial dependencies
|
||||
pip install FreeSimpleGUI pyserial
|
||||
|
||||
# 4. Install laser_control as an editable package
|
||||
# (required for imports to work in any subdirectory)
|
||||
pip install -e .
|
||||
|
||||
# 5. Install pytest (for running tests)
|
||||
pip install pytest
|
||||
```
|
||||
|
||||
> **Note:** Steps 3–5 can be run via the existing `deploy` script (steps 1–3),
|
||||
> then manually run `pip install -e . && pip install pytest` once inside the venv.
|
||||
|
||||
### Every subsequent session
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Running the GUI application
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
./run
|
||||
# or directly:
|
||||
python3 _device_main.py
|
||||
```
|
||||
|
||||
The application auto-detects the USB serial port. If more than one port is
|
||||
present, the first one found is used.
|
||||
|
||||
---
|
||||
|
||||
## Running the tests
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
python3 -m pytest tests/ -v
|
||||
```
|
||||
|
||||
Expected result: **75 passed**.
|
||||
|
||||
---
|
||||
|
||||
## Running the usage example
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
|
||||
# Auto-detect port:
|
||||
python3 laser_control/example_usage.py
|
||||
|
||||
# Specify port explicitly:
|
||||
python3 laser_control/example_usage.py /dev/ttyUSB0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Embedding laser_control in another application
|
||||
|
||||
After `pip install -e .` (or copying the `laser_control/` folder into your
|
||||
project and running `pip install -e .` there), import as follows:
|
||||
|
||||
```python
|
||||
from laser_control import (
|
||||
LaserController,
|
||||
VariationType,
|
||||
ValidationError,
|
||||
CommunicationError,
|
||||
)
|
||||
|
||||
# --- Manual mode ---
|
||||
with LaserController(port='/dev/ttyUSB0') as ctrl:
|
||||
try:
|
||||
ctrl.set_manual_mode(
|
||||
temp1=25.0, # °C [15 … 40]
|
||||
temp2=30.0, # °C [15 … 40]
|
||||
current1=40.0, # mA [15 … 60]
|
||||
current2=35.0, # mA [15 … 60]
|
||||
)
|
||||
data = ctrl.get_measurements()
|
||||
if data:
|
||||
print(f"3.3 V rail: {data.voltage_3v3:.3f} V")
|
||||
print(f"Laser 1 temperature: {data.temp1:.2f} °C")
|
||||
except ValidationError as e:
|
||||
print(f"Bad parameter: {e}")
|
||||
except CommunicationError as e:
|
||||
print(f"Device not responding: {e}")
|
||||
|
||||
|
||||
# --- Current variation mode ---
|
||||
def on_data(m):
|
||||
print(f"I1={m.current1:.3f} mA T1={m.temp1:.2f} °C")
|
||||
|
||||
with LaserController(port=None, on_data=on_data) as ctrl: # port=None → auto-detect
|
||||
ctrl.start_variation(
|
||||
variation_type=VariationType.CHANGE_CURRENT_LD1,
|
||||
params={
|
||||
'min_value': 20.0, # mA
|
||||
'max_value': 50.0, # mA
|
||||
'step': 0.5, # mA [0.002 … 0.5]
|
||||
'time_step': 50, # µs [20 … 100]
|
||||
'delay_time': 5, # ms [3 … 10]
|
||||
'static_temp1': 25.0,
|
||||
'static_temp2': 30.0,
|
||||
'static_current1': 35.0,
|
||||
'static_current2': 35.0,
|
||||
}
|
||||
)
|
||||
import time; time.sleep(2)
|
||||
ctrl.stop_task()
|
||||
```
|
||||
|
||||
### Parameter limits
|
||||
|
||||
| Parameter | Min | Max | Unit |
|
||||
|---|---|---|---|
|
||||
| Temperature (T1, T2) | 15.0 | 40.0 | °C |
|
||||
| Current (I1, I2) | 15.0 | 60.0 | mA |
|
||||
| Current variation step | 0.002 | 0.5 | mA |
|
||||
| Temperature variation step | 0.05 | 1.0 | °C |
|
||||
| Time step | 20 | 100 | µs |
|
||||
| Delay time | 3 | 10 | ms |
|
||||
|
||||
### Exception hierarchy
|
||||
|
||||
```
|
||||
LaserControlError
|
||||
├── ValidationError
|
||||
│ ├── TemperatureOutOfRangeError
|
||||
│ ├── CurrentOutOfRangeError
|
||||
│ └── InvalidParameterError
|
||||
├── CommunicationError
|
||||
│ ├── PortNotFoundError
|
||||
│ ├── DeviceNotRespondingError
|
||||
│ ├── CRCError
|
||||
│ └── ProtocolError
|
||||
└── DeviceError
|
||||
├── DeviceOverheatingError
|
||||
├── PowerSupplyError
|
||||
└── DeviceStateError
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Device output
|
||||
|
||||
Each measurement response contains:
|
||||
|
||||
| Field | Description | Unit |
|
||||
|---|---|---|
|
||||
| `temp1`, `temp2` | Laser temperatures | °C |
|
||||
| `temp_ext1`, `temp_ext2` | External thermistor temperatures | °C |
|
||||
| `current1`, `current2` | Photodiode currents | mA |
|
||||
| `voltage_3v3` | 3.3 V power rail | V |
|
||||
| `voltage_5v1`, `voltage_5v2` | 5 V power rails | V |
|
||||
| `voltage_7v0` | 7 V power rail | V |
|
||||
|
||||
12
pyproject.toml
Normal file
12
pyproject.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[build-system]
|
||||
requires = ["setuptools"]
|
||||
build-backend = "setuptools.backends.legacy:build"
|
||||
|
||||
[project]
|
||||
name = "laser_control"
|
||||
version = "1.0.0"
|
||||
dependencies = ["pyserial"]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["."]
|
||||
include = ["laser_control*"]
|
||||
Reference in New Issue
Block a user