Metadata-Version: 2.4
Name: pololu
Version: 0.1.15
Summary: Sterowanie silnikiem krokowym bipolarnym przez Pololu Tic T249 z obsługą wyłączników krańcowych i procedury homing
Project-URL: Homepage, https://github.com/maskservice/rpi-motor-tic249
Project-URL: Repository, https://github.com/maskservice/rpi-motor-tic249
Project-URL: Issues, https://github.com/maskservice/rpi-motor-tic249/issues
Author: MaskService
Author-email: Tom Sapletta <tom@sapletta.com>
License: Apache-2.0
License-File: LICENSE
Keywords: controller,motor,pololu,raspberry-pi,stepper,t249,tic
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Hardware
Requires-Python: >=3.9
Requires-Dist: flask>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: pyusb>=1.2.0
Requires-Dist: requests>=2.31.0
Requires-Dist: ticlib>=0.3.0
Provides-Extra: gpio
Requires-Dist: gpiozero>=2.0; extra == 'gpio'
Requires-Dist: rpi-gpio>=0.7.0; extra == 'gpio'
Provides-Extra: test
Requires-Dist: playwright>=1.45.0; extra == 'test'
Requires-Dist: pytest-playwright>=0.5.0; extra == 'test'
Requires-Dist: pytest>=8.0.0; extra == 'test'
Description-Content-Type: text/markdown

# Pololu Tic T249 - Stepper Motor Controller


## AI Cost Tracking

![AI Cost](https://img.shields.io/badge/AI%20Cost-$3.00-green) ![AI Model](https://img.shields.io/badge/AI%20Model-openrouter%2Fqwen%2Fqwen3-coder-next-lightgrey)

This project uses AI-generated code. Total cost: **$3.0000** with **20** AI commits.

Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/models/openrouter/qwen/qwen3-coder-next)

---

![img.png](img.png)

https://www.waveshare.com/wiki/Infrared_Reflective_Sensor

Kompletne rozwiązanie do sterowania silnikiem krokowym bipolarnym przez **Pololu Tic T249** (TB67S249FTG) z pełną obsługą **wyłączników krańcowych** (limit switches), procedurą **homing**, oraz nowoczesnym **panelem web**.

## Funkcje

- **Panel Web** - Intuicyjny interfejs w przeglądarce (Flask)
- **Wybór urządzenia USB** - Auto-detekcja i ręczny wybór portu USB
- **Konfiguracja .env** - Łatwa konfiguracja przez zmienne środowiskowe
- **Docker** - Pełne wsparcie dla Docker i docker-compose
- **Testy E2E** - Automatyczne testy Playwright
- **CLI** - Pełna obsługa z linii komend
- **Homing** - Automatyczne zerowanie pozycji
- **Krańcówki** - Obsługa sprzętowa (Tic) i programowa (GPIO)

## Aktualne poprawki (2026-05-05)

Najważniejsze poprawki po diagnostyce na realnym sterowniku Tic T249:

- Usunięto fałszywy stan "obie krańcówki aktywne" wynikający z konfiguracji pinów limit switch bez pull-up.
- Potwierdzono poprawną konfigurację dla wejść limit switch:
  - `SCL`: reverse limit + pull-up
  - `SDA`: forward limit + pull-up
- Po naprawie wejść limit switch błąd ruchu zmienia się na rzeczywisty stan zasilania, jeśli występuje: `low_vin` / "Motor supply voltage is too low".

To rozróżnienie jest kluczowe: wcześniej ruch był blokowany logicznie przez błędny stan wejść, teraz blokada (jeśli występuje) wynika z fizycznego braku zasilania silnika.

### Szybka weryfikacja po uruchomieniu

```bash
make limits
```

Oczekiwany wynik w stanie spoczynku:

- `Forward limit: inactive`
- `Reverse limit: inactive`

Następnie sprawdź napięcie zasilania silnika (VIN) przez status web/CLI. Jeśli pojawia się `low_vin`, problem dotyczy zasilacza (VIN/GND), a nie logiki krańcówek.

## Szybki start

### Instalacja (automatyczna)

Wspierane systemy: **Debian/Ubuntu/Raspberry Pi OS**, **Fedora**, **RHEL/CentOS**

```bash
# Klonowanie repo
git clone https://github.com/maskservice/rpi-motor-tic249.git
cd rpi-motor-tic249

# Instalacja (z sudo dla udev rules)
sudo make install

# Lub bez sudo (tylko zależności Python)
make install
```

### Instalacja na Fedorze/RHEL

Na systemach Fedora lub RHEL/CentOS używane są pakiety `dnf`/`yum` zamiast `apt-get`:

```bash
# Instalacja zależności systemowych na Fedora
sudo dnf install -y libusbx-devel python3-pip python3-virtualenv git

# Na RHEL 8+ / CentOS Stream
sudo dnf install -y libusbx-devel python3-pip python3-virtualenv git

# Na RHEL 7 / CentOS 7
sudo yum install -y libusbx-devel python3-pip python3-virtualenv git

# Następnie standardowa instalacja
make install
```

### Uruchomienie panelu web

```bash
# Lokalnie
make web

# W Dockerze
docker-compose up -d
```

Panel dostępny pod adresem: **http://localhost:5000**

## Tryby obsługi krańcówek

### 1. Tryb `tic` — sprzętowy (zalecany)

Wyłączniki krańcowe podłączone do pinów Tic T249 **SCL** i **SDA** — po jednym wejściu na kierunek:
- `Limit switch forward` → `SCL`
- `Limit switch reverse` → `SDA`

**Krańcówka jest aktywna, gdy na wejście podawana jest masa (GND)** — tryb `active LOW`.

Konfiguracja pinów w **Tic Control Center** → Advanced → Pin configuration. Wymaga firmware ≥1.06.

Tic automatycznie blokuje ruch w kierunku aktywnego wyłącznika i obsługuje sprzętową procedurę homing (go_home → jedzie do krańcówki → cofa → pozycja = 0).

**Podłączenie:**
```
Tic T249 Pin SCL ───[NC Switch forward]─── GND
Tic T249 Pin SDA ───[NC Switch reverse]─── GND
```
- **NC** (Normally Closed) = domyślnie zamknięty, otwiera się gdy wciśnięty
- **Aktywny stan:** masa/GND na wejściu (active LOW)
- **Pull-up włączony:** pin ma stan wysoki (5V) gdy switch otwarty

### 2. Tryb `gpio` — programowy (Raspberry Pi)

Wyłączniki podłączone do dowolnych pinów GPIO, monitorowane z przerwaniami. Natychmiastowe zatrzymanie silnika (emergency stop) przy aktywacji krańcówki w kierunku ruchu.

```
RPi GPIO 17 ─── Limit Switch Forward ─── GND  (pull-up wewnętrzny)
RPi GPIO 27 ─── Limit Switch Reverse ─── GND  (pull-up wewnętrzny)
```

Wymaga `gpiozero` lub `RPi.GPIO`:
```bash
pip install gpiozero
```

## Instalacja

```bash
sudo apt-get install libusb-1.0-0-dev
pip install -r requirements.txt

# Reguła udev
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1ffb", MODE="0666"' | \
    sudo tee /etc/udev/rules.d/99-pololu-tic.rules
sudo udevadm control --reload-rules
```

## Użycie — Web Panel

### Panel web - funkcje

- **Wybór urządzenia USB** - Lista wykrytych urządzeń Pololu z możliwością wyboru
- **Status w czasie rzeczywistym** - Pozycja, prędkość, stan krańcówek (odświeżanie 2x/s)
- **Sterowanie** - Homing, jog, ruch do pozycji, zasilanie silnika
- **Skróty klawiszowe** - ← → (jog), Spacja (stop), H (homing)

### Konfiguracja przez .env

```bash
# Kopiowanie przykładowej konfiguracji
cp .env.example .env

# Edycja ustawień
nano .env
```

Przykładowa konfiguracja `.env`:

```ini
# Flask
FLASK_HOST=0.0.0.0
FLASK_PORT=5000

# USB - auto-detect gdy puste, lub konkretne wartości
USB_VENDOR_ID=0x1ffb
USB_PRODUCT_ID=0x00c9

# Motor
DEFAULT_MAX_SPEED=2000000
DEFAULT_CURRENT_LIMIT_MA=1000
```

## Docker (zalecane na Fedora i innych systemach)

Docker działa niezależnie od dystrybucji Linux i jest **najprostszą metodą** uruchomienia projektu na Fedorze, RHEL i innych systemach bez potrzeby instalowania zależności systemowych.

### Wymagania

```bash
# Fedora - instalacja Docker
sudo dnf install -y docker docker-compose
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker $USER
# Wyloguj się i zaloguj ponownie, aby grupa docker zadziałała
```

### Szybki start z Docker

```bash
# Uruchomienie pełnego stacku w Docker (alias: make web-docker)
make docker-up

# Lub bezpośrednio
make web-docker
```

Serwisy dostępne pod:
- **Frontend**: http://localhost:3000
- **Backend API**: http://localhost:8000
- **MQTT**: localhost:1883

### Zarządzanie Docker

```bash
# Zatrzymanie stacku
make docker-down

# Podgląd logów
make docker-logs

# Rebuild obrazów
make docker-build
```

## Makefile - komendy

Wspierane systemy: Debian/Ubuntu, Raspberry Pi OS, Fedora, RHEL/CentOS

```bash
make help           # Lista komend
make install        # Pełna instalacja (autodetekcja systemu)
make web            # Uruchom panel web (natywnie)
make web-docker     # Uruchom w Docker (zalecane na Fedora)
make web-stop       # Zatrzymaj panel
make detect-usb     # Wykryj urządzenia USB
make cli            # CLI kontroler
make cli-shell      # Interaktywny shell Python
make shell          # Legacy bash shell przez API web panelu
make home           # Homing
make status         # Status silnika
make standby        # Stan spoczynku (de-energize, no heat)
make limits         # Stan krańcówek
make test-limit     # Test krańcówki z auto-reverse (MAX speed)

# ticcmd fallback (gdy Python niedostępny)
make tic-list       # Lista urządzeń via ticcmd
make tic-status     # Status via ticcmd
make tic-home-reverse  # Homing reverse via ticcmd
make tic-deenergize    # Wyłączenie silnika via ticcmd

make docker-up      # Uruchom w Docker
docker-down         # Zatrzymaj Docker
make test           # Testy jednostkowe
make clean          # Wyczyść build
```

## CLI Shell

### 1. Python CLI shell — bezpośrednio do Tic T249

To jest interaktywny shell do bezpośredniego sterowania sterownikiem i odczytu statusu krańcówek:

```bash
make cli-shell

# albo bezpośrednio
.venv/bin/python -m firmware.cli_shell
```

### 2. Legacy bash shell — przez API web panelu

Ten wariant steruje przez API panelu webowego i wymaga uruchomionego backendu:

```bash
make shell

# albo bezpośrednio
bash cli_shell.sh

# z innym adresem API
API_BASE=http://192.168.1.100:5000 bash cli_shell.sh
```

### Komendy w shellu

```
tic> status              # Status silnika
tic> devices             # Lista urządzeń USB
tic> connect 0           # Połącz z urządzeniem #0
tic> home                # Homing reverse
tic> home forward        # Homing forward
tic> move 1000           # Idź do pozycji 1000
tic> move-rel 500        # Przesuń o +500 kroków
tic> jog forward 100     # Jog forward 100 kroków
tic> jog reverse 200     # Jog reverse 200 kroków
tic> stop                # Emergency stop
tic> energize on         # Włącz zasilanie silnika
tic> energize off        # Wyłącz zasilanie silnika
tic> limits              # Stan krańcówek (FWD/REV)
tic> reciprocate 500 100000 5 0.5  # Ruch P-Z: kroki, prędkość, cykle, pauza
tic> settings            # Pokaż ustawienia
tic> logs                # Pokaż logi
tic> help                # Pomoc
tic> quit                # Wyjście
```

## Testy E2E

### Uruchomienie testów

```bash
# Lokalnie (wymaga playwright)
pip install pytest-playwright
pytest tests/e2e/ -v

# W Dockerze
docker-compose --profile test up
```

### Struktura testów

```
tests/e2e/
├── test_web_panel.py    # Testy UI (Playwright)
└── conftest.py          # Konfiguracja pytest
```

## Użycie — CLI

### Homing (zerowanie na krańcówce)

```bash
# Homing sprzętowy Tic — jedź reverse aż limit switch, cofnij, pozycja=0
python tic_t249_controller.py home-reverse --limit-mode tic

# Homing forward
python tic_t249_controller.py home-forward --limit-mode tic

# Homing GPIO — piny BCM 17 (forward) i 27 (reverse)
python tic_t249_controller.py home-reverse --limit-mode gpio --gpio-fwd 17 --gpio-rev 27

# Z pliku konfiguracji
python tic_t249_controller.py home-reverse --config config.json
python tic_t249_controller.py home-reverse --config config-gpio.json
```

### Wyznaczanie zakresu ruchu

```bash
# Jedź do reverse limit (pozycja=0), potem do forward limit → odczytaj zakres
python tic_t249_controller.py demo-range --limit-mode tic
```

### Ruch z ochroną krańcówek

```bash
# Ruch do pozycji (Tic blokuje sprzętowo przy limit switch)
python tic_t249_controller.py move -p 5000 --limit-mode tic

# Ruch z soft limitami (przycina do zakresu - margin)
python tic_t249_controller.py move-safe -p 3000

# GPIO — emergency stop jeśli krańcówka aktywna w kierunku ruchu
python tic_t249_controller.py move -p 5000 --limit-mode gpio --gpio-fwd 17 --gpio-rev 27
```

### Status krańcówek

```bash
python tic_t249_controller.py limit-status --limit-mode tic
python tic_t249_controller.py status --limit-mode tic
```

### Pozostałe komendy

```bash
python tic_t249_controller.py demo-positions
python tic_t249_controller.py demo-velocity
python tic_t249_controller.py demo-homing --limit-mode tic
python tic_t249_controller.py velocity --speed 1000000 --duration 5
python tic_t249_controller.py home  # ręczne zerowanie, bez krańcówek
```

## Użycie — Python API

```python
from tic_t249_controller import (
    TicT249Controller, MotorConfig, LimitSwitchConfig,
    StepMode, HomingDirection,
)

# --- Tryb Tic (sprzętowy) ---
config = MotorConfig(
    current_limit_ma=1200,
    step_mode=StepMode.SIXTEENTH,
    limit_switches=LimitSwitchConfig(mode="tic"),
)

with TicT249Controller(config) as ctrl:
    # Homing na reverse limit switch → pozycja = 0
    ctrl.go_home(HomingDirection.REVERSE)

    # Ruch — Tic automatycznie blokuje przy limit switch
    ctrl.move_to(5000)
    ctrl.wait_for_position()

    # Status krańcówek
    status = ctrl.get_limit_switch_status()
    print(f"Forward: {status['forward_active']}")
    print(f"Reverse: {status['reverse_active']}")

    # Wyznacz zakres ruchu
    travel = ctrl.find_travel_range()
    print(f"Zakres: {travel} kroków")

    # Ruch bezpieczny (z soft limitami)
    ctrl.move_to_safe(travel // 2)
    ctrl.wait_for_position()


# --- Tryb GPIO (Raspberry Pi) ---
config_gpio = MotorConfig(
    limit_switches=LimitSwitchConfig(
        mode="gpio",
        gpio_forward_pin=17,
        gpio_reverse_pin=27,
        gpio_active_low=True,  # NO switch z pull-up
        homing_speed_towards=300_000,
        homing_speed_away=100_000,
    ),
)

with TicT249Controller(config_gpio) as ctrl:
    ctrl.go_home(HomingDirection.REVERSE)
    ctrl.move_to(3000)
    ctrl.wait_for_position()  # przerywa jeśli krańcówka aktywna
```

## Examples

Multiple format examples with **auto-diagnostics** - no manual setup required.

### Quick Start with Examples

```bash
cd /home/tom/github/maskservice/rpi-motor-tic249

# Bash scripts with auto-diagnostics
bash examples/bash/basic_test.sh
bash examples/bash/simple/basic_test_simple.sh

# DSL scripts via runner
bin/pololu-dsl examples/dsl/basic_test.dsl

# Via CLI shell
tic> EXEC examples/bash/basic_test.sh
tic> EXEC examples/dsl/basic_test.dsl
```

### Available Formats

- **[Bash Scripts](examples/bash/README.md)** - Auto-diagnostics, standalone & library versions
- **[DSL Scripts](examples/dsl/README.md)** - Domain-specific language with validation
- **[JSON Format](examples/json/README.md)** - Command lists and sequences
- **[YAML Format](examples/yaml/README.md)** - Clean syntax configuration
- **[All Formats Overview](examples/README.md)** - Complete examples guide

### Auto-Diagnostics Features

Examples automatically:
- Detect Python environment (`.venv`, `venv`, system)
- Create virtual environment if missing
- Install `ticlib` dependency
- Configure USB permissions (if needed)

See [Examples Troubleshooting](examples/README.md#troubleshooting) for USB permissions and common issues.

## Konfiguracja JSON

### `config.json` (tryb Tic)

```json
{
  "limit_switches": {
    "mode": "tic",
    "homing_speed_towards": 500000,
    "homing_speed_away": 200000,
    "soft_limit_margin": 50
  }
}
```

### `config-gpio.json` (tryb GPIO)

```json
{
  "limit_switches": {
    "mode": "gpio",
    "gpio_forward_pin": 17,
    "gpio_reverse_pin": 27,
    "gpio_active_low": true,
    "gpio_bounce_time_ms": 5,
    "homing_speed_towards": 500000,
    "homing_speed_away": 200000,
    "soft_limit_margin": 50
  }
}
```

## Procedura homing — jak działa

### Tryb Tic (sprzętowy)

1. Komenda `go_home(direction)` → Tic jedzie w zadanym kierunku
2. Tic napotyka limit switch → natychmiastowe zatrzymanie (sprzętowe)
3. Tic czeka 20 ms
4. Tic cofa wolno aż limit switch się dezaktywuje
5. Pozycja = 0, flaga "position uncertain" skasowana

### Tryb GPIO (programowy)

1. Jeśli już na krańcówce → najpierw odjazd
2. Ruch wolny w kierunku krańcówki (`homing_speed_towards`)
3. GPIO przerwanie → `halt_and_hold()` (natychmiastowy stop)
4. Cofanie wolne (`homing_speed_away`) aż GPIO zwolni
5. `halt_and_set_position(0)`

## Tryb Standby (oszczędzanie energii)

Gdy silnik nie jest używany, można przejść w tryb standby żeby **obniżyć temperaturę sterownika** i **wydłużyć żywotność silnika**:

```bash
make standby         # De-energize silnika + release USB
```

Co robi standby:
- **Wyłącza zasilanie cewek** (motor de-energized)
- **Zwalnia uchwyt USB** (inny proces może przejąć kontrolę)
- **Czyści błędy** drivera

Aby wznowić pracę:
```bash
make cli-shell       # Przejmij kontrolę, silnik się energizuje
```

## Krańcówki i Ruch z Limitami

### Konfiguracja sprzętowa (Tic Control Center)

Piny Tic T249 skonfigurowane jako **active LOW** (aktywne na masę GND):

| Pin Tic | Funkcja | Konfiguracja |
|---------|---------|-------------|
| **SCL** | Limit switch FORWARD | Uncheck "Active high", check "Pull-up" |
| **SDA** | Limit switch REVERSE | Uncheck "Active high", check "Pull-up" |

### Ciągły ruch posuwisto-zwrotny z krańcówkami — `make run-limit`

**Główny tryb pracy produkcyjnej.**

```bash
make run-limit       # Start — silnik energizuje się i jedzie w pętli
                     # Ctrl+C — silnik de-energizuje się (no heat)
```

Parametry w `.env`:
```ini
LIMIT_RECIPROCATE_STEPS=2000                # kroków w jedną stronę
LIMIT_RECIPROCATE_SPEED_PULSES_PER_SEC=5000 # prędkość
LIMIT_RECIPROCATE_ACCEL_PULSES_PER_SEC2=15000
```

Działanie:
1. ⚡ Energizuje silnik (tylko podczas działania skryptu)
2. Jedzie 2000 kroków naprzód, 2000 kroków wstecz — w pętli
3. Jeśli SCL (forward) lub SDA (reverse) aktywna mid-cycle → **natychmiastowy reverse**
4. Ctrl+C → de-energizuje silnik + zwalnia USB (brak ciepła w spoczynku)

### Test jednorazowy krańcówki — `make test-limit`

```bash
make test-limit      # Forward → limit → reverse → standby (jednorazowy)
```

Scenariusz:
1. Rusza do przodu, czeka na SCL (forward limit)
2. Gdy limit wykryty → odwraca kierunek
3. Jedzie wstecz, czeka na SDA (reverse limit)
4. Przechodzi w **standby** (de-energize)

### Sprawdzenie stanu krańcówek

```bash
make limits          # Szybki odczyt FWD/REV limit switches
```

Wynik:
```
🔍 Checking limit switches...
Forward limit: inactive
Reverse limit: ACTIVE
⚠️  Limit triggered - motor blocked in that direction
```

### Test z ticcmd (fallback bez Pythona)

Jeśli Python ma problemy, użyj natywnego `ticcmd`:

```bash
make tic-list              # Lista urządzeń
make tic-status            # Pełny status
make tic-home-reverse      # Homing via ticcmd
make tic-deenergize        # Wyłączenie silnika
```

## Bezpieczeństwo

- **Ctrl+C** → bezpieczne deenergize (cewki wyłączone)
- **GPIO emergency stop** → natychmiastowe `halt_and_hold()` przy krańcówce
- **Soft limity** → `move_to_safe()` przycina pozycję do zakresu ± margines
- **Nigdy nie odłączaj silnika przy zasilonym sterowniku**
- Bez radiatora max ~1800 mA na cewkę

## Licencja

Program: **MIT** (Softreck, softreck.dev)
Zależność ticlib: **BSD-2-Clause** (Julien Phalip) — dozwolona komercyjnie

## License

Licensed under Apache-2.0.
## Author

Tom Sapletta
