A Flask-based climate chamber control system for Raspberry Pi providing precise temperature control using Peltier elements, real-time monitoring, and flow-based control sequences.
This technical documentation is intended for developers and system administrators who need to understand the architecture, modify the system, or add new hardware components.
For Users: See USER_GUIDE.md for connection instructions and INTERFACE_MANUAL.md for application usage.
Key Technologies:
- Flask 3.1.1 web framework with Jinja2 templates
- RPi.GPIO for hardware control
- Adafruit CircuitPython libraries for sensors
- SQLite for data logging
- Chart.js for real-time visualization
- PID-based temperature control
The frontend is a Flask-rendered web application using HTML templates, JavaScript, and CSS.
Location: app/frontend/
Technologies:
- Flask Templates (Jinja2): Server-side HTML rendering
- JavaScript: Client-side interactivity and real-time updates
- CSS: Custom styling with responsive design
- AJAX: Asynchronous communication with backend APIs
Key Pages:
home.html- Main dashboard with quick temperature inputsetupGraph.html- Temperature profile creation interfacedisplayGraph.html- Real-time graph display during active cyclesmanualControl.html- Manual hardware control interfaceflow_designer.html- Visual flow-based control designerconfigEditor.html- System configuration editordatabaseViewer.html- Historical data viewerlogs_viewer.html- System logs browserwifi_networks.html- WiFi network configuration
Frontend Features:
- Real-time temperature plotting using Chart.js or similar
- Drag-and-drop flow designer for creating temperature sequences
- Responsive forms for configuration editing
- Live status updates via periodic AJAX polling
- Flash messages for user feedback
The backend follows a modular, interface-driven architecture with clear separation of concerns.
Location: app/backend/
Technologies:
- Flask 3.1.1: Web framework and API routing
- RPi.GPIO: Raspberry Pi GPIO control for hardware interfacing
- Adafruit CircuitPython Libraries:
adafruit-circuitpython-mpl3115a2- Pressure/temperature sensoradafruit-circuitpython-ads1x15- Analog-to-Digital converter
- SQLite: Local database for data logging (
database.db) - Python 3.x: Core programming language
Architecture Layers:
Define contracts for all major components:
ISensor.py- Sensor reading interfaceIDriver.py- Hardware driver interfaceIClimateChamber.py- Climate control interfaceIConfigManager.py- Configuration managementIDatabaseManager.py- Database operations- And more...
Concrete implementations of interfaces:
ClimateChamber.py- Main climate control logic with PID controlClimateChamberController.py- High-level controller orchestrationSensorReader.py- Reads all configured sensorsConfigManager.py- Loads and validates JSON configurationsDatabaseManager.py- SQLite operations for logging and retrievalFanController.py- Fan speed controlRelayController.py- Relay switching (e.g., for fridge control)
Low-level hardware drivers for motor controllers:
BTS7960Driver.py- High-power motor driver for Peltier modules (up to 43A)TB6612FNGDriver.py- Dual motor driver for smaller Peltier/fan modules
Sensor implementations:
NTCTemperatureSensor.py- NTC thermistor reading via ADCDS18B20.py- Digital temperature sensor (1-Wire)DS18B20Cluster.py- Multiple DS18B20 sensorsMPL3115A2.py- I2C pressure and temperature sensorADS1115.py- 16-bit ADC for analog sensors
Higher-level hardware abstractions:
PeltierModule.py- Peltier element control (heating/cooling)FanModule.py- Fan control with PWM speed adjustment
Business logic and orchestration:
GuardingService.py- Safety monitoring and emergency stopsTemperatuurService.py- Temperature validation and processingCalculationService.py- PID calculations and control algorithms
JSON-based configuration files:
raspberry_pi_config.json- Hardware pin mappings and sensor definitionscontrol_config.json- PID parameters and control settingsgraph_config.json- Stored temperature profiles
FlowExecutor.py- Executes visual flow-based temperature sequences
Singleton pattern for managing global application state:
- Initializes all components via factory methods
- Provides shared access to services and controllers
- Handles system reload and restart operations
The system uses a PID (Proportional-Integral-Derivative) control loop:
- Sensor Reading:
SensorReaderpolls all configured temperature sensors - Calculation:
CalculationServicecompares current vs. desired temperature and calculates PID output - Hardware Control: Based on PID output:
- Positive output → Heat mode: Peltier modules heat, fridge relay OFF
- Negative output → Cool mode: Peltier modules cool or fridge relay ON
- Safety Monitoring:
GuardingServicecontinuously checks sensor limits - Logging:
DatabaseManagerrecords all data points to SQLite database
Peltier elements are thermoelectric devices that can heat or cool based on current direction:
- Heating: Current flows one direction (RPWM active, LPWM off)
- Cooling: Current flows opposite direction (LPWM active, RPWM off)
- PWM Duty Cycle: Controls heating/cooling intensity (0-100%)
- Driver Selection: System supports BTS7960 (high power) or TB6612FNG (lower power)
- User creates temperature profile via web interface
- Frontend sends AJAX request to Flask route
- Route handler validates input and calls backend service
- Backend starts control loop and begins logging
- Frontend polls for updates and renders real-time graphs
All hardware is defined in raspberry_pi_config.json:
{
"Temperature_inside_top": {
"type": "NTC",
"editable": {
"SDA": 2,
"SCL": 3,
"read_pin": 0,
"i2c_address": "0x4A",
"beta_coefficient": 3600.0
}
},
"Peltier_240W": {
"type": "peltier",
"editable": {
"driver_type": "BTS7960",
"RPWM": 13,
"LPWM": 19,
"R_EN": 5,
"L_EN": 6,
"PWM_FREQUENCY": 5000,
"Duty cycle limit": 100
}
}
}- NTC Thermistors: Via ADS1115 16-bit ADC
- DS18B20: Digital 1-Wire temperature sensors
- MPL3115A2: I2C pressure and temperature sensor
- BTS7960: High-current (up to 43A) dual H-bridge for large Peltier modules
- TB6612FNG: Dual DC motor driver for smaller modules
- Fans: PWM-controlled cooling fans
- Relays: For controlling external devices (e.g., refrigerator)
- Create sensor class in
app/backend/Sensors/:
from app.backend.Interfaces.ISensor import ISensor
class MySensor(ISensor):
def __init__(self, config):
self.config = config
def read(self):
# Your sensor reading logic
return temperature_value- Add to SensorReader in
app/backend/Implementations/SensorReader.py:
elif sensor_config.type == "MySensor":
from app.backend.Sensors.MySensor import MySensor
sensor = MySensor(sensor_config)- Update configuration in
raspberry_pi_config.json:
{
"My_Temperature_Sensor": {
"name": "My_Temperature_Sensor",
"type": "MySensor",
"editable": {
"gpio_pin": 17,
"custom_parameter": 123
},
"unit": "degrees"
}
}- Create driver class in
app/backend/Drivers/:
from app.backend.Interfaces.IDriver import IDriver
class MyDriver(IDriver):
def __init__(self, config):
# Initialize GPIO pins
pass
def heat(self, duty_cycle):
# Implement heating logic
pass
def cool(self, duty_cycle):
# Implement cooling logic
pass
def stop(self):
# Stop all outputs
pass- Add to PeltierModule in
app/backend/Modules/PeltierModule.py:
class DriverType(Enum):
TB6612FNG = "TB6612FNG"
BTS7960 = "BTS7960"
MY_DRIVER = "MY_DRIVER" # Add your driver
# In __init__:
if self.driver_type == DriverType.MY_DRIVER.value:
from app.backend.Drivers.MyDriver import MyDriver
self.driver = MyDriver(config)- Update configuration:
{
"Peltier_Custom": {
"type": "peltier",
"editable": {
"driver_type": "MY_DRIVER",
"pin1": 13,
"pin2": 19,
"pwm_frequency": 5000
}
}
}Edit app/backend/config/raspberry_pi_config.json to change pin numbers:
{
"Peltier_240W": {
"editable": {
"RPWM": 13, // Change to your pin number
"LPWM": 19, // Change to your pin number
"R_EN": 5,
"L_EN": 6
}
}
}Important: After changing GPIO pins, restart the service:
sudo systemctl restart climatechamber.service- Clone repository and create virtual environment:
git clone https://gitlab.com/tmc-climatechamber/climatechamber.git
cd climatechamber
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements.txt- Run development server:
python run.py- Access at
http://localhost:5000
The system is pre-configured to run as a systemd service on Raspberry Pi. For fresh installations:
- Clone repository on Raspberry Pi
- Run setup script:
./setup_rp4.sh - Service starts automatically on boot
climatechamber/
├── app/
│ ├── __init__.py # Flask app factory
│ ├── backend/
│ │ ├── app_state.py # Singleton application state
│ │ ├── Dataclasses/ # Data models and configurations
│ │ ├── Drivers/ # Low-level hardware drivers
│ │ ├── Sensors/ # Sensor implementations
│ │ ├── Modules/ # Hardware module abstractions
│ │ ├── Implementations/ # Core business logic
│ │ ├── Interfaces/ # Abstract interfaces
│ │ ├── Services/ # Business services
│ │ ├── FlowExecution/ # Flow-based control
│ │ ├── Providers/ # GPIO and hardware providers
│ │ ├── Technical/ # Logging and utilities
│ │ └── config/ # JSON configuration files
│ ├── frontend/
│ │ ├── static/ # CSS, JS, fonts
│ │ └── templates/ # HTML templates
│ └── routes/ # Flask route handlers
├── run.py # Application entry point
├── requirements.txt # Python dependencies
├── database.db # SQLite database
├── setup_rp4.sh # Raspberry Pi setup script
└── README.md # This file
| Route | Method | Description |
|---|---|---|
/ |
GET | Home page with quick temperature input |
/status |
GET | Health check endpoint |
/submit-temperature |
POST | Start constant temperature cycle |
/manual-control |
GET | Manual hardware control interface |
/setup-graph |
GET/POST | Create temperature profiles |
/display-graph |
GET | Real-time monitoring |
/flow-designer |
GET/POST | Visual flow designer |
/database-viewer |
GET | View historical data |
/config-editor |
GET/POST | Edit system configuration |
/logs |
GET | View system logs |
/wifi |
GET/POST | Manage WiFi connections |
Defines all hardware components and GPIO pin mappings.
Contains PID tuning parameters and control loop settings.
Stores saved temperature profiles.
- Temperature Limits: Configurable min/max values per sensor
- Safety-Critical Sensors: Emergency stops if limits exceeded
- Guarding Service: Continuous monitoring of all sensors
- Emergency Stop: Immediate hardware shutdown capability
- Duty Cycle Limits: Prevents over-driving Peltier elements
- Cycle Locking: Prevents starting multiple cycles simultaneously
The system follows the Interface-Implementation pattern:
- Define interface in
Interfaces/ - Create implementation in
Implementations/ - Register in
app_state.pyfactory methods - Add route handler in
routes/ - Create frontend template if needed
Unit tests are located in unittest/ directory.
sudo usermod -a -G gpio $USER
# Log out and back in for changes to take effectsudo raspi-config
# Interface Options → I2C → Enable# View real-time logs
sudo journalctl -u climatechamber.service -f
# Check service status
sudo systemctl status climatechamber.service
# Restart service
sudo systemctl restart climatechamber.serviceEnsure virtual environment is activated and all dependencies are installed:
source .venv/bin/activate
pip install -r requirements.txtWhen adding new features:
- Follow the Interface-Implementation pattern
- Add corresponding route handlers in
app/routes/ - Update frontend templates as needed
- Document changes in code comments
- Test thoroughly before committing
[Add your license information here]
For technical issues, check the logs and review this documentation. For user-facing questions, direct users to USER_GUIDE.md and INTERFACE_MANUAL.md.