Files
pi-dro/docs/INSTALLATION.md
2026-03-21 23:51:53 +01:00

308 lines
6.4 KiB
Markdown

# DRO Installation & Setup Guide
This guide walks through setting up the Digital Read Out application on a Raspberry Pi.
## System Requirements
- **Hardware**: Raspberry Pi 4 (or later)
- **OS**: Raspbian/Raspberry Pi OS (Bullseye or later)
- **Python**: 3.7+
- **Arduino**: Arduino Nano with I2C encoder firmware
## Step 1: Install Dependencies
### Enable I2C
```bash
sudo raspi-config
# Navigate to: Interfacing Options → I2C → Yes
# Reboot
sudo reboot
```
### Install Python Libraries
```bash
# Update package manager
sudo apt-get update
sudo apt-get upgrade
# Install required packages
sudo apt-get install python3-tk python3-dev python3-pip
# Install Python dependencies
pip3 install smbus2
pip3 install adafruit-circuitpython-ads1x15 # Optional: for ADC
```
### Optional: System Calculator
```bash
sudo apt-get install galculator
```
## Step 2: Configure I2C for Shutdown
Allow the application to shutdown without a password:
```bash
sudo visudo
```
Add this line to the end of the file (replace `pi` with your username):
```
pi ALL=(ALL) NOPASSWD: /sbin/poweroff, /sbin/reboot, /sbin/shutdown
```
Save with Ctrl+X, then Y, then Enter.
## Step 3: Upload Arduino Firmware
The Arduino must run firmware that:
1. Reads from two rotary encoders
2. Maintains position counters
3. Responds to I2C read requests at address 0x08
See [ARDUINO_I2C_PROTOCOL.md](./ARDUINO_I2C_PROTOCOL.md) for protocol details.
Example firmware structure:
```cpp
#include <Wire.h>
volatile int16_t x_position = 0;
volatile int16_t z_position = 0;
void setup() {
Wire.begin(0x08);
Wire.onRequest(requestEvent);
// Setup encoder interrupts
pinMode(2, INPUT);
pinMode(3, INPUT);
attachInterrupt(0, x_encoder_isr, CHANGE);
attachInterrupt(1, z_encoder_isr, CHANGE);
}
void requestEvent() {
byte buffer[4];
buffer[0] = (byte)x_position;
buffer[1] = (byte)(x_position >> 8);
buffer[2] = (byte)z_position;
buffer[3] = (byte)(z_position >> 8);
Wire.write(buffer, 4);
}
// Encoder ISR routines...
void loop() {}
```
Refer to the `i2c_encoder/` directory for the complete Arduino sketch.
## Step 4: Verify I2C Connection
Test I2C communication:
```bash
# Install I2C tools
sudo apt-get install i2c-tools
# Scan for I2C devices
i2cdetect -y 1
# Should show Arduino at address 0x08:
# 0 1 2 3 4 5 6 7 8 9 a b c d e f
# 00: -- -- -- -- -- -- -- -- 08 -- -- -- --
```
## Step 5: Auto-Start Configuration
### Option A: Desktop File (GUI Autostart)
Create `/home/pi/.config/autostart/dro.desktop`:
```ini
[Desktop Entry]
Type=Application
Name=DRO
Exec=python3 /home/pi/dro/dro.py --zoomed
StartupNotify=false
X-GNOME-Autostart-always-run=true
```
### Option B: Systemd Service
Create `/etc/systemd/system/dro.service`:
```ini
[Unit]
Description=Digital Read Out (DRO) Application
After=graphical.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/dro
ExecStart=/usr/bin/python3 /home/pi/dro/dro.py --zoomed
Restart=on-failure
RestartSec=5
[Install]
WantedBy=graphical.target
```
Enable and start:
```bash
sudo systemctl daemon-reload
sudo systemctl enable dro.service
sudo systemctl start dro.service
```
### Option C: Shell Script Autostart
Create `/home/pi/dro/autostart.sh`:
```bash
#!/bin/bash
cd /home/pi/dro
python3 dro.py --zoomed
```
Make executable:
```bash
chmod +x /home/pi/dro/autostart.sh
```
Add to crontab (for user pi):
```bash
crontab -e
# Add line:
@reboot /home/pi/dro/autostart.sh
```
## Step 6: Test the Installation
### Test Mode (without Arduino)
```bash
cd ~/dro
python3 dro.py --test
# Use keyboard to test:
# A/Z = X encoder up/down
# S/X = Z encoder up/down
```
### With Hardware
```bash
# Start the application
python3 dro.py --zoomed
# Check logs (if systemd service)
journalctl -u dro.service -f
```
## Step 7: Calibration
### Set Scale Factors
Edit `dro.py` and adjust these lines based on your encoder specifications:
```python
# X axis: negative to flip direction
model.set_scale('x', -2.5/200) # mm per step
# Z axis
model.set_scale('z', 90/1000) # mm per step
```
**How to determine:**
1. Move the tool a known distance (e.g., 10 mm)
2. Record the encoder step count
3. Scale = Distance (mm) / Steps
4. Use negative for X if the direction is backwards
### Set Zero Points
1. Position tool at starting location
2. Press **X_0** button to zero X axis
3. Press **Z_0** button to zero Z axis
## Troubleshooting
### No I2C Communication
```bash
# Check I2C is enabled
raspi-config
# Verify devices are connected
i2cdetect -y 1
# Check for USB connections (if Arduino is USB)
ls -la /dev/ttyUSB*
```
### GUI Not Appearing
```bash
# Check display settings
export DISPLAY=:0
python3 dro.py
# Verify Tkinter is installed
python3 -c "import tkinter; print('Tkinter OK')"
```
### I2C Errors
- Check pull-up resistors (4.7 kΩ is standard)
- Verify Arduino firmware is running
- Try slower I2C speed: edit smbus2 initialization
### Position Drift
- Recalibrate scale factors
- Check encoder hardware connections
- Verify encoder isn't slipping
## File Structure
```
/home/pi/dro/
├── dro.py # Main application
├── autostart.sh # Auto-start script
├── power.png # Power button icon
├── test_model.py # Unit tests
├── README.md # Project overview
├── docs/
│ ├── DRO.md # Application documentation
│ └── ARDUINO_I2C_PROTOCOL.md # I2C protocol
└── i2c_encoder/
├── i2c_encoder.ino # Arduino firmware
└── i2c_test.py # Arduino test script
```
## Performance Tips
1. **Reduce Update Interval** (for faster response):
```python
self._update_interval_ms = 50 # 20 Hz instead of 10 Hz
```
2. **Increase I2C Speed**:
```python
bus = smbus2.SMBus(1)
bus.bus.set_clock(400000) # 400 kHz fast mode
```
3. **Use GPIO Directly** (instead of I2C) for more performance:
- Requires hardware changes
- RPi.GPIO library for direct GPIO reading
## Security Notes
- The DRO needs `sudo` access to shutdown (configured via sudoers)
- Store any sensitive config files outside the repo
- Use `.env` files for sensitive data (not committed to git)
## Getting Help
- Check logs: `journalctl -u dro.service -f`
- Test I2C: `i2cget -y 1 0x08 0 i 4`
- Python console test:
```bash
python3
import smbus2
bus = smbus2.SMBus(1)
print(bus.read_i2c_block_data(0x08, 0, 4))
```