# Voron filament dryer

Arduino Nano firmware for a chamber dryer with four SHT31 humidity/temperature sensors, PID heater control, and PWM fan mixing.

## Pinout (Arduino Nano)

All settings below are defined in `include/config.h`.

| Signal | Nano pin | Notes |
|--------|----------|-------|
| I2C SDA | A4 | Shared bus (Wire) |
| I2C SCL | A5 | Shared bus (Wire) |
| TCA9548A mux | I2C `0x70` | 8-channel I2C multiplexer |
| SHT31 sensors | Mux channels 2, 3, 4, 5 | One sensor per channel |
| SHT31 address | `0x44` | ADDR pin low; use `0x45` if ADDR is high |
| Fan | D5 | 24 V fan via N-channel MOSFET (hardware PWM) |
| Heater | A2 | Solid-state relay (burst control) |

USB serial: **115200 baud**.

## Dev setup

### PlatformIO

This repo uses the PlatformIO CLI (see `.vscode/tasks.json`). If PlatformIO is already installed under `~/.platformio/penv/`, use that directly — you do not need to run the web installer again.

```bash
~/.platformio/penv/bin/pio --version
~/.platformio/penv/bin/pio run              # build
~/.platformio/penv/bin/pio run -t upload    # flash
~/.platformio/penv/bin/pio device monitor   # serial monitor
```

On Arch Linux / CachyOS, install via the package manager if you prefer:

```bash
sudo pacman -S platformio
```

If upload cannot find the port, add to `platformio.ini`:

```ini
upload_port = /dev/ttyUSB0    ; or /dev/ttyACM0, or a /dev/serial/by-id/... path
monitor_port = /dev/ttyUSB0
```

List available ports:

```bash
ls -la /dev/serial/by-id/
```

### Serial port permissions (Linux)

**Recommended — udev rules (one-time, works in Cursor without re-login):**

```bash
sudo ./scripts/install-udev-rules.sh
# unplug and replug the Arduino
```

This installs PlatformIO’s `99-platformio-udev.rules` (covers CH340 clone Nanos and other common adapters).

**Alternative — group membership:**

```bash
# Arch / CachyOS
sudo usermod -aG uucp $USER
```

You must **fully log out of the desktop** (not just reboot or open a new terminal) so `id` shows the new group. Cursor’s terminal often keeps the old group list until you restart Cursor after logging out.

**Immediate workaround** (no sudo, current terminal only):

```bash
sg uucp -c "$HOME/.platformio/penv/bin/pio run -t upload"
```

Verify access: `test -w /dev/ttyUSB0 && echo ok`

## First run

1. Flash firmware and open the serial monitor at 115200 baud.
2. Confirm `TCA9548A detected` and four valid sensor channels (`ch2`–`ch5`).
3. Find **stir fan** speed (optional — default is **PWM 178**, ~70%):

   ```
   target 0
   fanchars
   ```

   Sweeps **30%, 100%, 60%, 80%** fan — heats to max **60°C** corner at **100%** heater. Cools to **40°C** avg between runs. Skips a fan speed if 60°C isn't reached in time. Optional midpoint refine if best isn't at 30% or 100%. Or: `python3 scripts/fan_characterize.py`. When done, `fanchars save` writes the winner to EEPROM (or skip and keep the 178 default).

4. Tune **heat PI** (stored in EEPROM on autotune complete):

   ```
   target 0
   pid default
   autotune 50
   ```

   Cutoff follows target (`target + 12°C`, max 95°C) — e.g. ABS at 55°C trips at 67°C corner, nylon at 80°C at 92°C.

5. Dry at your target — fan runs at stir PWM (default **178**) whenever target > 0, including heat-up. Override with `fan <pwm>`; `fan auto` returns to default. Fan auto-off below 40°C applies only in idle (`target 0`).

Send `help` over serial for all commands (`target`, `fanchars`, `fan`, `log on/off`, `status`, `pid`, etc.).

## Raspberry Pi control

On the Pi, use the curses TUI to set targets and monitor the chamber (SSH with a TTY: `ssh -t`):

```bash
python3 scripts/capture_csv.py tui
```

Keys: `0` idle · `t` target · `p` material presets · `f`/`F` fan · `l` CSV log · `a` autotune · `:` command · `q` quit

Headless CSV-only logging (e.g. systemd) is documented in [pi-instructions.md](pi-instructions.md).

## Filament drying table

| Filament | Dryer temperature | Drying time (hours) |
|----------|-------------------|---------------------|
| PLA | 50–55 °C (122–131 °F) | > 6 |
| ABS | 60–65 °C (140–149 °F) | > 6 |
| PETG | 60–65 °C (140–149 °F) | > 6 |
| Nylon | 70–75 °C (158–167 °F) | > 24 |
| Desiccants | 60–65 °C (149 °F) | > 12 |
| PVA | 40–45 °C (104–113 °F) | > 24 |
| TPU/TPE | 50–55 °C (122–131 °F) | > 8 |
| ASA | 60–65 °C (140–149 °F) | > 8 |
| PP | 50–55 °C (122–131 °F) | > 6 |
| HIPS | 60–65 °C (140–149 °F) | > 8 |
| PC | 70–75 °C (158–167 °F) | > 12 |
| PEEK | 120–125 °C (248–257 °F) | > 24 |