Skip to main content

Qt-based interface for a two-dimensional polargraph scanner

Project description

QPolargraph

Tests Documentation DOI License: GPL v3 Python 3.10+

A Qt-based instrument interface for a two-dimensional polargraph scanner. Built on QInstrument.

A polargraph translates a payload to any position within its scan area using two stepper motors and a timing belt. Originally developed by Jürg Lehni and Uli Franke as a drawing machine, the design scales easily to large areas, delivers millimeter-scale positioning accuracy, and is very cost-effective to build.

QScanner interface

Hardware

Component Description
2× Nema-17 stepper motor Mounted above and to either side of the scan area
GT2 timing belt Spans both motors; payload hangs from its midpoint
GT2 drive gear (25-tooth) One per motor; engages the belt
Adafruit Motor Shield v2 Drives both steppers from a single Arduino
Arduino (Uno or compatible) Runs the acam3 firmware; connects to the host via USB

The belt forms a V-shape between the two motors. Each motor changes the length of one side of the V, moving the payload in two dimensions.

Firmware

The Arduino must be flashed with hardware/arduino/acam3/acam3.ino before first use. The easiest way is to use the built-in installer:

qpolargraph-flash

This opens a dialog that detects the attached Arduino, installs any missing Arduino libraries (Adafruit Motor Shield V2 Library, AccelStepper), compiles, and uploads the firmware — all without opening the Arduino IDE. It requires arduino-cli to be installed and on PATH.

Alternatively, open hardware/arduino/acam3/acam3.ino in the Arduino IDE and upload manually.

The firmware and package versions are coupled: Motors.identify() checks that the connected Arduino reports the expected firmware version and that the Adafruit Motor Shield is detected at I2C address 0x60, refusing to open the port if either check fails.

Installation

Clone the repository and install in editable mode:

git clone https://github.com/davidgrier/QPolargraph
cd QPolargraph
python -m venv .qp
source .qp/bin/activate          # Windows: .qp\Scripts\activate
pip install -e ".[dev]"
pip install PyQt6                # or PyQt5, PySide2, PySide6

QInstrument is installed automatically as a dependency.

Calibration

Five geometric parameters describe the polargraph. Set them in the QPolargraphWidget control panel or pass them directly to Polargraph():

Parameter Default Description
ell 1.0 m Horizontal distance between the two motor pulley centres
y0 0.1 m Vertical distance from the pulleys to the home position
pitch 2.0 mm GT2 belt tooth pitch
circumference 25 Number of belt teeth on the drive gear
steps 200 Motor steps per revolution

Measure ell and y0 with a ruler after mounting the motors. pitch, circumference, and steps are determined by the belt and gear specifications and normally do not need to change.

Settings are saved to ~/.QScanner/ automatically when the application closes, so calibration only needs to be done once.

Quick start

Scanner application

python -m QPolargraph
# or, after installation:
qpolargraph

The application opens a live plot showing the belt geometry and the scan trajectory. Use the Scan button to start a polar-arc sweep, or Home / Center to move the payload to the home or centre position.

Embedding in your own application

Subclass QScanner to add experiment-specific data acquisition:

from qtpy.QtWidgets import QApplication
from qtpy import QtCore
from QPolargraph.QScanner import QScanner
import sys


class MyScanner(QScanner):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.scanner.dataReady.connect(self.acquire)

    @QtCore.Slot(object)
    def acquire(self, position):
        x, y = position
        # measure something at (x, y) and call self.plotData(x, y, hue)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    scanner = MyScanner()
    scanner.show()
    sys.exit(app.exec())

Controlling the hardware directly

from qtpy.QtCore import QCoreApplication
from QPolargraph.Polargraph import Polargraph
import sys

app = QCoreApplication(sys.argv)
pg = Polargraph(ell=0.8, y0=0.15).find()   # auto-detects USB port
print(pg.position)                           # (x, y, running) in metres
pg.moveTo(0.0, 0.3)
while pg.running():
    pass
pg.release()

Architecture

QInstrument.QSerialInstrument
└── Motors               # acam3 serial protocol: goto, speed, position, …
    └── Polargraph       # geometry: step indexes ↔ Cartesian coordinates

QInstrument.QInstrumentWidget
└── QRasterScanWidget    # scan-pattern parameter controls

QInstrument.QInstrumentWidget
└── QPolargraphWidget    # polargraph hardware controls

QtCore.QObject
└── QScanPattern         # base: rectangular perimeter trajectory
    ├── RasterScan       # row-by-row zigzag raster
    └── PolarScan        # arc-by-arc sweep centred on the left pulley

QtWidgets.QMainWindow
└── QScanner             # full application: live plot + scan controls

Development

Run the test suite:

source .qp/bin/activate
pytest tests/

Tests run automatically before every git push. To install the pre-push hook in a fresh clone:

git config core.hooksPath .githooks

Acknowledgements

Work on this project at New York University is supported by the National Science Foundation of the United States under award number DMR-2438983.

References

H. W. Gao, K. I. Mishra, A. Winters, S. Wolin, and D. G. Grier, "Flexible wide-field high-resolution scanning camera for continuous-wave acoustic holography," Review of Scientific Instruments 89, 114901 (2018). https://doi.org/10.1063/1.5053666

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qpolargraph-1.1.4.tar.gz (40.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qpolargraph-1.1.4-py3-none-any.whl (39.9 kB view details)

Uploaded Python 3

File details

Details for the file qpolargraph-1.1.4.tar.gz.

File metadata

  • Download URL: qpolargraph-1.1.4.tar.gz
  • Upload date:
  • Size: 40.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qpolargraph-1.1.4.tar.gz
Algorithm Hash digest
SHA256 f15bad8eba13135c60bf4b3d828f6204e9c676275879ac0b94890fbf901b18ea
MD5 c4dab1a7371ff0da554be3f71a700a3d
BLAKE2b-256 4ae09d67570ef6fcd345cd8ea31f3dc0dd40550517ac70aff3d0e63221dadc12

See more details on using hashes here.

Provenance

The following attestation bundles were made for qpolargraph-1.1.4.tar.gz:

Publisher: publish.yml on davidgrier/QPolargraph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file qpolargraph-1.1.4-py3-none-any.whl.

File metadata

  • Download URL: qpolargraph-1.1.4-py3-none-any.whl
  • Upload date:
  • Size: 39.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qpolargraph-1.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 0a24953a13b1eae4ff4c673f339501596fdf3388c5838f0d68f75e8db04af32a
MD5 1383aa40da72ebb144d964516c8f5c37
BLAKE2b-256 cc5eb9b76a003ddb8dc8946e998a10b24e0afc44b5a83f4c2b6e51429ca25249

See more details on using hashes here.

Provenance

The following attestation bundles were made for qpolargraph-1.1.4-py3-none-any.whl:

Publisher: publish.yml on davidgrier/QPolargraph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page