Astronomical Observatory Visnjan
Tech lead and primary developer on the multi-year effort to computerize a 24-ton, 1-metre-mirror telescope at the Tičan observatory in Croatia — a stack that stretches from Arduino firmware and a Linux kernel driver for a PCI encoder up to ASCOM C# drivers that let MaximDL and Stellarium talk to a volunteer-built mount as if it were a factory telescope.

A volunteer telescope, held to professional standards
Trainee and professional astronomers both expect to run observations from the same industry software — MaximDL for imaging, Stellarium for planning, anything that speaks ASCOM for pointing. A volunteer-built 1-metre telescope doesn't get to demand that astronomers learn a custom app. It has to earn its keep by slotting into the tools they already use, while surviving the realities of hardware that was assembled and rewired over many seasons.
The brief, in practice: get pro-grade control software onto a telescope that was stitched together from steppers, encoders, Arduino-driven subsystems, and a Linux machine — and keep it precise and safe enough to leave running overnight.

One stack, three worlds
The system is five layers deep and hides most of them on purpose. At the bottom, Arduino firmware runs dome rotation, the focuser, fan relays, and a GPS-locked clock. A Linux kernel driver for the Heidenhain IK220 PCI encoder card exposes absolute axis positions through a character device. Python modules sit one level above — Modbus RTU to motor controllers, custom serial to the Arduinos, file-based IPC for the encoder feed. A Flask REST API wraps every subsystem and is the only public surface. On the Windows side, a set of ASCOM drivers written in C# / .NET make HTTP calls back to that API, so any planetarium client that speaks ASCOM — MaximDL, Stellarium, others — can drive the telescope without knowing it's Linux underneath.





Firmware, kernel driver, and the bits in between
Arduino firmware. Each subsystem — dome, focuser, fans — runs its own sketch on an AVR, composed from small modules with a shared registry pattern. A new feature ships as another module registered into setup() and loop() rather than as another tangled main.ino. That keeps memory-constrained boards maintainable across years of incremental additions.
Linux kernel driver for the IK220. The Heidenhain IK220 is a PCI encoder card; the vendor driver shipped for kernels that are now ancient, so the driver had to be carried forward across several 2.6.x API changes — register regions, ioctl signatures, and character-device registration all moved. It exposes a /dev/ik220 node whose ioctls feed a text file that the Python layer consumes. Using a file as the boundary between real-time PCI reads and userspace code sounds crude; it is very robust.
Python per-subsystem modules. Each subsystem gets a small, single-purpose module used both from the CLI and from the REST layer: Modbus RTU over serial for the Baldor / Parker motor controllers, line-based custom protocols for the Arduinos, and coordinate transforms via PyEphem that move a position between raw encoder counts, internal hour-angle / declination, local sidereal, celestial, and alt-az.









Pathfinding over an allowed-space polygon
The telescope physically can't reach every combination of hour-angle and altitude — the optical tube collides with the pier and dome in parts of the sky. Rather than hard-coding "don't go below X degrees," the system loads an allowed-space polygon (an ASCII table of HA × Alt safe zones) and runs A* pathfinding over that polygon to compute slew routes that stay inside. A SanityFailure is raised — and motion stops — whenever a commanded state would step outside. Below that, a physical altitude limiter is the last line of defence; it gets calibrated by hand.
The tracking loop runs at roughly ten hertz with speed ramping, an on-target tolerance of a few arc-seconds, and hard caps on sensible delta-per-tick so encoder glitches don't turn into commanded slews. It coasts for a few seconds on power-loss before it stops.


ASCOM in front, REST behind
Astronomers already own their workflow. MaximDL runs the camera; Stellarium plans the session; countless other Windows tools assume ASCOM for pointing. Each subsystem astronomers need to reach from those apps gets an ASCOM driver in C# / .NET — mount, focuser, filter wheel, dome, lights, fans — and each of those drivers is a thin HTTP client against the Flask REST API. Where ASCOM doesn't reach, AutoIt scripts fill the seams, mostly around MaximDL's scripting surface. From the astronomer's seat, the telescope is just another ASCOM mount.
Third in the world, two years running
The telescope went into full-time operation in 2017. In 2018 and 2019 it ranked third worldwide by number of confirmation and follow-up measurements of newly discovered asteroids. The astrometry work is the astronomers' — the system exists to get out of their way.



