GVO-Conversion
1:1 Code conversion of GVO pascal code
- Active · last change 5-7-2026
- ★ 1 on GitHub
README
GVO Telescope Control
GVO Telescope Control is a Windows C++ console program for controlling a two-axis telescope mount through an OMS motion controller. It is a C++ conversion/modernization of an older Pascal/Delphi telescope-control workflow.
The program loads the OMS 68SERMC.DLL, initializes the controller over a serial COM port, starts RA tracking, communicates with TheSky through teleapi.dll shared memory, and handles telescope parking, syncing, GOTO slews, normal hand paddle corrections, and fast/manual paddle movement.
Hardware warning: This program sends real motion commands to telescope hardware. Verify COM port, controller wiring, axis direction, tracking rate, park position, sync behavior, and all safety limits before running it on the telescope.
Project Status
This project has completed development. The current C++ version supports:
- OMS controller initialization.
- 32-bit Windows DLL loading.
- Serial communication through a configured COM port.
- RA tracking startup.
- TheSky shared-memory coordinate exchange.
- GOTO request handling.
- Sync request handling.
- Parking command flow.
- Normal hand paddle movement.
- Manual/fast paddle movement.
- Configurable speeds and telescope location values through
config.ini.
Some behavior, especially controller origin, park alignment, TPoint/TheSky offset behavior, and physical axis direction, should still be verified carefully on hardware. Some parts of the project could be improved or reworked.
Platform Compatibility
This project was written and developed with MinGW in C++.
Supported environment:
- Windows only.
- 32-bit build target.
- Requires a Windows version that supports 32-bit programs.
- Not configured for macOS.
- Not configured for Linux.
The program uses Windows-specific APIs and headers, including:
windows.hLoadLibraryAGetProcAddressSleep_kbhit_getch
The project is built as a 32-bit program because the telescope controller DLL workflow uses 32-bit Windows DLL compatibility.
Required Runtime Files
The setup folder should contain:
GVO_Telescope_Control.exe
teleapi.dll
68SERMC.DLL
config.iniIf the executable is renamed after compiling, the setup folder may instead contain something like:
Main.exe
teleapi.dll
68SERMC.DLL
config.iniThe important requirement is that the compiled executable, teleapi.dll, 68SERMC.DLL, and config.ini are all available together at runtime, unless absolute DLL paths are provided in config.ini.
Hardware / Device Setup
Before running the program:
- Connect the telescope controller to the computer.
- Open Windows Device Manager:
- Press
Win + X. - Choose Device Manager.
- Expand Ports (COM & LPT).
- Press
- Look for the serial device connected to the OMS controller.
- Note the COM port number.
- Update
config.ini:
com_port=1For example, if Device Manager shows the controller on COM3, use:
com_port=3Configuration File
The program reads config.ini from the same folder where it is run.
Example:
# ---- Communication ----
com_port=1
oms_dll=68SERMC.DLL
# ---- Paths ----
teleapi_dll=teleapi.dll
# ---- Tracking / motion ----
TrkRate=500.6
RAFact=120000
# ---- Location ----
C_Lat=38.5
C_Long=-106.9
# ---- Normal hand paddle speeds ----
# Used when Manual/Fast button is NOT held
handpad_ra_east_rate=400
handpad_ra_west_rate=750
handpad_dec_rate=250
# ---- Fast paddle ONLY ----
fastpad_x_fine=2000
fastpad_y_fine=2000
# ---- REAL SLEW SPEEDS (used by quad routines) ----
xvlslew=75000
yvlslew=50000
# ---- DEC bump behavior ----
dec_bump_rate=75
dec_bump_ms=100
# ---- Optional axis defaults ----
xvl=10000
xac=35000
yvl=5000
yac=25000
xacmax=35000
xvlmax=75000
yacmax=25000
yvlmax=100000
# ---- Debug ----
verbose=1Important Configuration Values
| Setting | Purpose |
|---|---|
com_port |
Serial COM port number from Windows Device Manager. |
oms_dll |
Path to 68SERMC.DLL. Usually 68SERMC.DLL if it is beside the executable. |
teleapi_dll |
Path to teleapi.dll. Usually teleapi.dll if it is beside the executable. |
TrkRate |
RA tracking rate used by AX JF<rate>;. |
RAFact |
RA conversion factor used to convert hour angle/degrees into controller counts. |
C_Lat |
Observatory latitude. |
C_Long |
Observatory longitude. |
handpad_ra_east_rate |
Normal hand paddle east correction rate. |
handpad_ra_west_rate |
Normal hand paddle west correction rate. |
handpad_dec_rate |
Normal hand paddle DEC correction rate. |
fastpad_x_fine |
Fast/manual paddle RA/X fine speed. |
fastpad_y_fine |
Fast/manual paddle DEC/Y fine speed. |
xvlslew |
Intended X/RA GOTO slew speed for quadrant routines. |
yvlslew |
Intended Y/DEC GOTO slew speed for quadrant routines. |
dec_bump_rate |
DEC bump speed used before some DEC direction changes. |
dec_bump_ms |
DEC bump duration in milliseconds. |
xvl, yvl |
General X/Y velocity values. |
xac, yac |
General X/Y acceleration values. |
xvlmax, yvlmax |
Maximum X/Y velocity values. |
xacmax, yacmax |
Maximum X/Y acceleration values. |
Build Instructions
This project does not currently use a tasks.json file. It can be built directly with a 32-bit MinGW g++ command.
Static build
"C:\Program Files\GCC\winlibs-i686-posix-dwarf-gcc-15.2.0-mingw-w64ucrt-13.0.0-r4\mingw32\bin\g++.exe" -m32 -Wall -static -static-libgcc -static-libstdc++ Main.cpp OMS68SERMC.cpp CommUtils.cpp Utils.cpp Sync.cpp Slew.cpp quad1to1.cpp quad1to2.cpp quad1to3.cpp quad2to1.cpp quad2to2.cpp quad3to1.cpp quad3to3.cpp GetQandYU.cpp CalcCoord.cpp TimerUnit.cpp HandPaddle.cpp ManualPaddle.cpp Config.cpp -o GVO_Telescope_Control_Strict.exeLess aggressive build
"C:\Program Files\GCC\winlibs-i686-posix-dwarf-gcc-15.2.0-mingw-w64ucrt-13.0.0-r4\mingw32\bin\g++.exe" -m32 -Wall -static-libgcc -static-libstdc++ Main.cpp OMS68SERMC.cpp CommUtils.cpp Utils.cpp Sync.cpp Slew.cpp quad1to1.cpp quad1to2.cpp quad1to3.cpp quad2to1.cpp quad2to2.cpp quad3to1.cpp quad3to3.cpp GetQandYU.cpp CalcCoord.cpp TimerUnit.cpp HandPaddle.cpp ManualPaddle.cpp Config.cpp -o GVO_Telescope_Control.exeThe static build is intended to reduce dependency issues by statically linking GCC runtime libraries. The less aggressive build still links the standard GCC runtime libraries statically but does not use full -static.
Note: "C:\Program Files\GCC\winlibs-i686-posix-dwarf-gcc-15.2.0-mingw-w64ucrt-13.0.0-r4\mingw32\bin\g++.exe" should link to wherever mingw is installed in the environment. This path likely will not work as is.
Running the Program
After compiling, place the executable in the setup folder with:
teleapi.dll
68SERMC.DLL
config.iniThen run:
GVO_Telescope_Control.exeor:
GVO_Telescope_Control_Strict.exedepending on which build command was used.
On startup, the program:
- Loads default telescope and controller parameters.
- Sets sidereal time.
- Loads
config.ini. - Applies configuration overrides.
- Prints the active configuration.
- Initializes TheSky shared memory through
teleapi.dll. - Loads
68SERMC.DLL. - Sets the configured COM port.
- Initializes communication with the OMS controller.
- Resets the controller.
- Configures controller I/O and axes.
- Starts RA tracking.
- Opens the console menu.
Console Menu
=== Telescope Control Menu ===
1. Park Telescope
2. Connect to TheSky
0. Exit1. Park Telescope
Starts the park request flow. The timer loop detects the park flag and sends the controller command sequence for moving toward controller position 0,0.
2. Connect to TheSky
Runs the timer loop so the program can respond to TheSky shared-memory requests. While this loop is running, the program can process:
- GOTO requests.
- Sync requests.
- Coordinate updates.
- Hand paddle input.
- Park completion.
- Move-complete polling.
Press ESC to return to the menu.
0. Exit
Exits the menu and unloads the OMS DLL.
Main Program Features
OMS DLL Loading
The program dynamically loads 68SERMC.DLL and resolves the required functions:
InitOmsCommPortSendStringSendAndGetString
The controller communication record uses a baud rate of 9600.
Controller Initialization
Startup sends:
RS;Then waits approximately 5 seconds.
After that, it sends:
EF; IO0,0; AX; DBI; LP0; SC; AY; DBI; LP0; SC;Then it starts RA tracking:
AX JF<TrkRate>;Example:
AX JF500.600000;TheSky Shared Memory
The program communicates with TheSky through teleapi.dll shared memory using a coordinate structure containing:
struct Coord {
double RA;
double Dec;
double RAGoto;
double DecGoto;
double RASync;
double DecSync;
};The timer loop checks this shared memory for GOTO and sync requests.
GOTO Slews
When both RAGoto and DecGoto are nonzero, the timer loop calls:
SlewScope(raTarget, decTarget);SlewScope() calculates altitude, hour angle, target motor counts, target quadrant, and target Y polarity. It blocks slews below 20 degrees altitude or invalid target polarity.
Supported quadrant routes in the provided code include:
GoQuad1to1GoQuad1to3GoQuad3to1
Sync
When both RASync and DecSync are nonzero, the timer loop calls:
SyncScope();SyncScope() calculates the controller count position for the supplied RA/DEC, loads the position into the controller with AX LP... and AY LP..., restarts RA tracking, clears the sync request, and updates the current coordinates.
Parking
Parking is requested by:
Park();The timer loop then sends:
AX KL;
AA VL75000,50000; MA0,0,,; GD; ID;This moves toward controller position 0,0.
Verify that controller position
0,0matches the real physical park position before relying on this command on hardware.
Normal Hand Paddle
The normal hand paddle reads controller I/O with:
BX;The response is decoded into:
- Manual/Fast button.
- South button.
- North button.
- East button.
- West button.
Normal RA corrections:
- East uses
TrkRate - handpad_ra_east_rate. - West uses
TrkRate + handpad_ra_west_rate. - Releasing East/West stops RA and restarts tracking.
Normal DEC corrections:
- North jogs positive Y after optional DEC bump logic.
- South jogs negative Y after optional DEC bump logic.
- Releasing North/South stops DEC.
Manual / Fast Paddle
If the manual/fast button is active, the program calls:
HandleFastPaddle();Fast paddle uses fine speeds which directly control motor speeds. These should not be set above the max motor slew speeds (x max = 75000, y max = 50000)
fastpad_x_fine=2000
fastpad_y_fine=2000Fast RA movement stops the X axis, jogs in the selected direction, and restarts tracking when released.
Fast DEC movement jogs Y in the selected direction and stops when released.
DEC Bump Behavior
Before some DEC moves, the program sends a short bump to handle backlash or direction reversal behavior.
Config values:
dec_bump_rate=75
dec_bump_ms=100Related functions:
BumpNorth()BumpSouth()
Useful Functions
| Function | Purpose |
|---|---|
loadparams() |
Loads default values before reading config.ini. |
LoadConfig() |
Reads config.ini. |
ApplyConfig() |
Applies config values to runtime globals. |
PrintConfig() |
Prints active configuration. |
LoadDLL() |
Loads 68SERMC.DLL and resolves function pointers. |
UnloadDLL() |
Frees the loaded OMS DLL. |
InitComm() |
Initializes communication with the OMS controller. |
SendCommand() |
Sends a command string to the controller. |
SendAndGetCommand() |
Sends a controller query and reads the response. |
TimerUpdate() |
Main update function for movement, sync, GOTO, park, coordinate updates, and hand paddle input. |
RunTimerLoopUntilIdleOrEscape() |
Runs TimerUpdate() until park completes, lockout occurs, or ESC is pressed. |
ManualControlMenu() |
Console menu. |
Park() |
Sets flags to request parking. |
StopAll() |
Sends AA ST; to stop all axes. |
HandleHandPaddle() |
Normal hand paddle behavior. |
HandleFastPaddle() |
Manual/fast paddle behavior. |
BumpNorth() |
Short DEC bump in one direction. |
BumpSouth() |
Short DEC bump in the opposite direction. |
SlewScope() |
Processes GOTO slew requests. |
SyncScope() |
Processes sync requests. |
GetQandY() |
Converts RA/DEC into altitude, hour angle, motor counts, quadrant, and Y polarity. |
UpdateCoord() |
Updates current coordinate state. |
Known Issues / Items to Verify
- Park moves to controller position
0,0; the controller origin must match the intended physical park location. - The relationship between controller origin, TheSky, and TPoint corrections should be verified before regular operation.
- Axis signs and hand paddle directions should be tested on hardware.
- GOTO quadrant routing currently depends on the available
quad*.cpproutines. config.iniincludesxvlslewandyvlslew. Confirm that the active code applies these values wherever the quadrant routines expect them.- The program is Windows-only and currently set up for 32-bit MinGW builds.
Troubleshooting
The program cannot find the controller
Check:
- The controller is powered on.
- The serial cable is connected.
- Device Manager shows the serial device.
com_portinconfig.inimatches the Device Manager COM port.- No other program is using the same COM port.
LoadLibrary fails
Check:
68SERMC.DLLis in the setup folder or the path inconfig.iniis correct.teleapi.dllis in the setup folder or the path inconfig.iniis correct.- The DLLs are compatible with the 32-bit executable.
Hand paddle input does not work correctly
Check:
- The initialization sequence completed.
- The controller received
EF; IO0,0; AX; DBI; LP0; SC; AY; DBI; LP0; SC;. - The
RS;reset delay is long enough. - The I/O bit wiring matches the code.
- The manual/fast button bit is wired correctly.
Telescope moves the wrong way
Check:
- Axis motor wiring.
- Sign of
AX JG...andAY JG...commands. yPoleand quadrant logic.- Whether the target is east/west of the meridian.
- Whether the controller origin was loaded correctly.
Parking is offset
Check:
- Controller internal
0,0position. - Last sync operation.
- TheSky/TPoint model state.
- Whether the original Pascal/Delphi program loaded a controller position before parking.
- Mechanical zero alignment.
Development Notes
- The project uses global state because it is a direct conversion from an older Pascal/Delphi-style control program.
StateVardefines the axis state machine:OffTrackingCorrectingECorrectingWCorrectingNCorrectingSSlewing
TimerUpdate()is the central runtime function.SlewScope()and thequad*.cppfiles handle quadrant-specific GOTO behavior.SyncScope()loads calculated motor positions into the controller.HandPaddle.cpphandles normal hand paddle input.ManualPaddle.cpp/ fast paddle logic handles manual high-speed or fine paddle movement.

