{"id":46037844,"url":"https://github.com/abduznik/instrumation","last_synced_at":"2026-05-30T09:01:19.657Z","repository":{"id":334923355,"uuid":"1143385101","full_name":"abduznik/instrumation","owner":"abduznik","description":"A high-level Hardware Abstraction Layer (HAL) for RF test stations with Digital Twin support, SCPI control, and async measurements.","archived":false,"fork":false,"pushed_at":"2026-05-21T19:07:48.000Z","size":1576,"stargazers_count":87,"open_issues_count":5,"forks_count":6,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-22T04:14:28.797Z","etag":null,"topics":["anritsu","digital-twin","hal","instrumentation","keysight","pyserial","python","pyvisa","rf-hal","rigol","rohde-schwarz","scpi","siglent","test-automation"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abduznik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["abduznik"],"ko_fi":"abduznik","custom":["https://github.com/abduznik/instrumation"]}},"created_at":"2026-01-27T14:15:31.000Z","updated_at":"2026-05-21T19:18:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/abduznik/instrumation","commit_stats":null,"previous_names":["abduznik/instrumation"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/abduznik/instrumation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abduznik%2Finstrumation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abduznik%2Finstrumation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abduznik%2Finstrumation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abduznik%2Finstrumation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abduznik","download_url":"https://codeload.github.com/abduznik/instrumation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abduznik%2Finstrumation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33633468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anritsu","digital-twin","hal","instrumentation","keysight","pyserial","python","pyvisa","rf-hal","rigol","rohde-schwarz","scpi","siglent","test-automation"],"created_at":"2026-03-01T05:38:54.851Z","updated_at":"2026-05-30T09:01:19.650Z","avatar_url":"https://github.com/abduznik.png","language":"Python","funding_links":["https://github.com/sponsors/abduznik","https://ko-fi.com/abduznik","https://github.com/abduznik/instrumation"],"categories":[],"sub_categories":[],"readme":"# Instrumation\n\n[![PyPI version](https://img.shields.io/pypi/v/instrumation)](https://pypi.org/project/instrumation/)\n[![License](https://img.shields.io/pypi/l/instrumation)](https://pypi.org/project/instrumation/)\n[![Python Versions](https://img.shields.io/pypi/pyversions/instrumation)](https://pypi.org/project/instrumation/)\n[![Stars](https://img.shields.io/github/stars/abduznik/instrumation?style=flat)](https://github.com/abduznik/instrumation/stargazers)\n[![Downloads](https://static.pepy.tech/personalized-badge/instrumation?period=total\u0026units=INTERNATIONAL_SYSTEM\u0026left_color=BLACK\u0026right_color=GREEN\u0026left_text=downloads)](https://pepy.tech/projects/instrumation)\n\n![Example](assets/example.gif)\n\nA high-level Hardware Abstraction Layer (HAL) for RF test stations. Stop wrestling with PyVISA boilerplate — write test logic, not connection code.\n\n---\n\n## Why Instrumation?\n\nRF test bench automation is painful. Every instrument brand has its own quirks, SCPI dialects vary, and testing your scripts requires physical hardware on your desk. Instrumation fixes all three:\n\n- **One API for everything** — same code works on Keysight, Rigol, and any other supported brand\n- **Digital Twin mode** — develop and debug offline with simulated instruments that emit realistic Gaussian noise\n- **Smart auto-detection** — scans connected devices and loads the right driver automatically, no manual config\n\n---\n\n## Real Hardware Validation\n\nInstrumation has been validated against real lab hardware. See our experiment reports:\n\n- [🔬 AFG ↔ DSOX Loopback Validation](https://abduznik.github.io/instrumation/experiments/afg_dso_loopback/) — Plug-and-play AUTO discovery with Tektronix AFG3022C + Keysight DSOX2002A\n- [📡 PXA N9030A Spectrum Analyzer](https://abduznik.github.io/instrumation/experiments/pxa_validation/) — 32-bit binary trace transfers at high speed\n- [🎛️ MXG N5183B Signal Generator](https://abduznik.github.io/instrumation/experiments/mxg_validation/) — Pulse modulation and frequency sweeps\n- [📊 PNA N5232A Network Analyzer](https://abduznik.github.io/instrumation/experiments/vna_validation/) — S-parameter measurements and Smith charts\n\n---\n\n## PyVISA vs Instrumation: See the Difference\n\nProgramming a signal generator the traditional way vs. with Instrumation:\n\n| Aspect | PyVISA (raw SCPI) | Instrumation |\n| :--- | :--- | :--- |\n| **Discovery** | Manual — find the resource string, manage `ResourceManager` | **Auto** — just pass `\"AUTO\"` and the HAL scans USB + LAN for you |\n| **Connection** | `rm.open_resource(\"TCPIP0::192.168.1.100::...\")` — hardcoded address | `connect_instrument(\"AUTO\", \"SG\")` — type-aware routing |\n| **Configuration** | `sg.write(\":FREQ:CW 2.4e9\")` — raw SCPI strings, no validation | `sg.set_frequency(2.4e9)` — typed method with bounds checking |\n| **Cleanup** | Manual `sg.close()` — easy to forget | Context manager — automatic `with` block cleanup |\n| **Offline Dev** | Requires real hardware connected | Digital Twin — set `INSTRUMATION_MODE=SIM` and develop anywhere |\n| **Portability** | Vendor-specific SCPI — rewrite for each brand | **One API** — works on Keysight, Rigol, Tektronix, Siglent, R\u0026S, Anritsu |\n\n### Side-by-Side Code\n\n```python\n# ─── PyVISA: 8 lines of boilerplate ───\nimport pyvisa\nrm = pyvisa.ResourceManager()\n# Manually find the right resource...\nsg = rm.open_resource(\"TCPIP0::192.168.1.100::inst0::INSTR\")\nsg.write(\"*RST\")\nsg.write(\":FREQ:CW 2.4e9\")\nsg.write(\":POW:AMPL -10\")\nsg.write(\":OUTP ON\")\nsg.close()\n\n# ─── Instrumation: 5 lines, zero config ───\nfrom instrumation import connect_instrument\n\nwith connect_instrument(\"AUTO\", \"SG\") as sg:\n    sg.set_frequency(2.4e9)\n    sg.set_amplitude(-10)\n    sg.set_output(True)\n```\n\nNo resource manager. No SCPI strings. No hardcoded addresses. Just your test logic.\n\n---\n\n## Live Data Streaming \n\nInstrumation includes a built-in `DataBroadcaster` for streaming live readings over UDP. This allows you to build real-time dashboards or loggers with zero external dependencies. \n\n- **Zero-lag** — UDP delivery doesn't block your test flow. \n- **Zero-config** — Broadcast to any host/port as JSON packets. \n- **Zero-dep** — Built-in with Python standard library. \n\nSee [examples/broadcast_demo.py](examples/broadcast_demo.py) and [examples/dashboard.py](examples/dashboard.py) for usage. \n\n## Features\n\n- **Auto-Discovery** — scans VISA and Serial buses, identifies what's connected\n- **Smart Factory** — detects instrument brand and loads the correct driver\n- **Digital Twin** — full simulation mode for offline development and CI pipelines\n- **Unified API** — write once, run on any supported hardware\n- **Built-in CSV logging** — test results logged out of the box\n\n---\n\n## Installation\n\n```bash\npip install instrumation\n```\n\nOr install from source:\n\n```bash\ngit clone https://github.com/abduznik/instrumation.git\ncd instrumation\npip install .\n```\n\n\u003e **Windows users:** You may need [NI-VISA](https://www.ni.com/en/support/downloads/drivers/download.ni-visa.html) or [Keysight IO Libraries Suite](https://www.keysight.com/us/en/lib/software-detail/computer-software/io-libraries-suite-downloads-2175637.html) for physical hardware access.\n\n---\n\n## Quick Start\n\n### Real hardware\n\n```python\nimport instrumation\n\nsa = instrumation.connect_instrument(\"USB0::0x2A8D::...\")\n\npeak_power = sa.get_peak_value()\nprint(f\"Peak Power: {peak_power} dBm\")\n```\n\n### Digital Twin (no hardware needed)\n\n```python\n# Linux/macOS\nexport INSTRUMATION_MODE=SIM\n\n# Windows PowerShell\n$env:INSTRUMATION_MODE=\"SIM\"\n```\n\n```python\nfrom instrumation.factory import get_instrument\n\n# Safer usage with context manager\nwith get_instrument(\"DUMMY_ADDRESS\", \"DMM\") as dmm:\n    print(dmm.get_id())\n    result = dmm.measure_voltage()\n    print(f\"Voltage: {result}\")\n```\n\n---\n\n## Station Manager (TOML)\n\nManage complex test stations with multiple instruments using a `station.toml` file.\n\n```toml\n[instruments.sa_main]\ndriver = \"SA\"\naddress = \"USB0::0x2A8D::0x0101::MY12345678::0::INSTR\"\n\n[instruments.psu_dut]\ndriver = \"PSU\"\naddress = \"TCPIP0::192.168.1.100::inst0::INSTR\"\n```\n\nUse it in your code:\n\n```python\nfrom instrumation import Station\n\nstation = Station(\"station.toml\")\nstation.connect()\n\n# Access instruments via dot notation\nres = station.instr.sa_main.get_peak_value()\nprint(f\"Peak: {res}\")\n\nstation.disconnect()\n```\n\n---\n\n## Command Line Interface\n\nInstrumation comes with a powerful CLI for quick interaction and diagnostics.\n\n```bash\n# Scan for connected hardware\ninstrumation scan\n\n# Take a quick measurement\ninstrumation measure USB0::... DMM measure_voltage\n\n# List instruments in your station.toml\ninstrumation station list\n\n# Measure using a named instrument from your station\ninstrumation station measure sa_main get_peak_value\n```\n\n---\n\n## API Reference\n\n| Command | Description |\n| :--- | :--- |\n| `scan()` | Lists all connected Serial and VISA devices |\n| `connect()` | Auto-connects to a generic Test Station (Box + Instrument) |\n| `connect_instrument(addr)` | Connects to a specific instrument with auto driver detection |\n\n---\n\n## Platform Support\n\n| Platform | Status |\n| :--- | :--- |\n| Windows | Supported |\n| Linux | Supported |\n| Termux (Android) | Supported |\n| macOS | Supported |\n\n---\n\n## Development\n\n```bash\n# Install in editable mode (required for tests to pick up local changes)\npip install -e .\n# This project uses pyproject.toml (PEP 517/518). No setup.py is required.\n\n\n# Install test dependencies\npip install pytest flake8\n\n# Run tests (simulation mode)\nexport INSTRUMATION_MODE=SIM  # Linux/macOS\npytest\n```\n\n---\n\n## Tech Stack\n\n- **Language:** Python 3.7+\n- **Libraries:** PyVISA, PySerial\n- **Architecture:** Smart Factory Pattern, Polymorphism\n- **Standards:** SCPI (Standard Commands for Programmable Instruments)\n\n---\n\n## Support the Project\n\nInstrumation is maintained in my spare time alongside a full-time RF technician job. If it's saved you hours of boilerplate or made your test bench easier to automate, consider supporting:\n\n[![GitHub Sponsors](https://img.shields.io/badge/Sponsor-%E2%9D%A4-ea4aaa?logo=github)](https://github.com/sponsors/abduznik)\n\nCommercial support or custom driver development? Reach out via GitHub Issues or Discussions.\n\n---\n\n## Contributing\n\nPRs and driver contributions are welcome. Open an issue first to discuss larger changes.\n\n## License\n\nSee [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabduznik%2Finstrumation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabduznik%2Finstrumation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabduznik%2Finstrumation/lists"}