#!/bin/bash
# =================================================================
# Bushnell Northstar / Meade Autostar Telescope Control Script
# =================================================================
# Controls a telescope via serial port using Arrow Keys and Number Keys.
# Protocol: Meade LX200 / Autostar Generic
#
# CONTROLS:
# Arrow Keys : Start moving (North/South/East/West)
# Spacebar : STOP Moving (Important!)
# 1-9 : Set Speed (1=Slowest/Guide, 9=Fastest/Slew)
# q : Quit the program
# =================================================================
# Default Serial Port (can be changed by user input)
SERIAL_PORT="/dev/ttyS0"
# Function to attempt to auto-detect the telescope
scan_ports() {
echo "Scanning ports for telescope response (sending :GR#)..."
FOUND_PORT=""
# Check common serial device patterns
for port in /dev/ttyUSB* /dev/ttyS[0-9]; do
# Check if port exists
if [ -e "$port" ]; then
# Configure port temporarily for the check (timeout 1s)
# 9600 baud, raw input
if stty -F "$port" 9600 cs8 -cstopb -parenb raw -echo 2>/dev/null; then
# Clear any existing data in buffer (background read with short timeout)
timeout 0.2s cat "$port" >/dev/null 2>&1
# Send "Get RA" command
echo -ne ":GR#" > "$port" 2>/dev/null
# Try to read response (up to 10 chars, 1 second timeout)
# Meade/Northstar response format is typically "HH:MM.T#"
# We pipe to 'tr -d \0' to remove null bytes that cause Bash warnings
RESPONSE=$(timeout 1s head -c 10 "$port" 2>/dev/null | tr -d '\0')
# Check if response contains typical telescope characters (# or digits)
if [[ "$RESPONSE" == *"#"* ]] || [[ "$RESPONSE" =~ [0-9] ]]; then
echo " [FOUND] Telescope detected on $port (Response: $RESPONSE)"
FOUND_PORT="$port"
else
echo " [ ... ] Checked $port - No valid response"
fi
else
echo " [ ERR ] Could not configure $port (Permission denied?)"
fi
fi
done
if [ ! -z "$FOUND_PORT" ]; then
echo ""
echo "Auto-selected likely port: $FOUND_PORT"
SERIAL_PORT="$FOUND_PORT"
else
echo "Scan complete. No obvious telescope response found."
fi
}
# -----------------------------------------------------------------
# 1. Setup Serial Port
# -----------------------------------------------------------------
echo "-----------------------------------------------------"
echo " Telescope Control Interface (Bash)"
echo "-----------------------------------------------------"
# Run the scan function
scan_ports
echo "-----------------------------------------------------"
echo "Available Serial Ports:"
ls /dev/ttyS* /dev/ttyUSB* 2>/dev/null
echo ""
read -p "Enter Serial Port [default: $SERIAL_PORT]: " USER_PORT
if [ ! -z "$USER_PORT" ]; then
SERIAL_PORT="$USER_PORT"
fi
if [ ! -e "$SERIAL_PORT" ]; then
echo "Error: Port $SERIAL_PORT does not exist."
exit 1
fi
# Configure the serial port using stty
# 9600 baud, 8N1 (Standard for Northstar/Autostar), raw mode to prevent buffering
stty -F "$SERIAL_PORT" 9600 cs8 -cstopb -parenb raw -echo
echo "Connected to $SERIAL_PORT at 9600 baud."
echo "Initializing..."
# Send a Stop command just in case
echo -ne ":Q#" > "$SERIAL_PORT"
# -----------------------------------------------------------------
# 2. Control Loop
# -----------------------------------------------------------------
CURRENT_SPEED="Max"
print_ui() {
clear
echo "====================================================="
echo " TELESCOPE CONTROL PANEL"
echo "====================================================="
echo " Port: $SERIAL_PORT | Status: Ready"
echo "-----------------------------------------------------"
echo " [ UP ] Move North"
echo " [DOWN] Move South"
echo " [LEFT] Move West"
echo " [RGHT] Move East"
echo " [SPACE] STOP ALL MOTORS"
echo "-----------------------------------------------------"
echo " Current Speed Setting: $CURRENT_SPEED"
echo " [1-2] Guide (Slowest/Nudge)"
echo " [3-5] Center (Slow)"
echo " [6-8] Find (Medium)"
echo " [9] Slew (Max Speed)"
echo "-----------------------------------------------------"
echo " Press 'q' to Quit Script"
echo "====================================================="
}
print_ui
# Loop to capture keystrokes one by one
while true; do
# Read 1 character silently (-s), 3 chars if it's an escape sequence
read -rsn1 key
# If key is empty (sometimes happens), skip
if [[ -z "$key" ]]; then continue; fi
# Handle Escape Sequences (Arrow Keys start with ESC)
if [[ "$key" == $'\x1b' ]]; then
read -rsn2 key # Read the next 2 characters
case "$key" in
'[A') # UP Arrow
echo -ne ":Mn#" > "$SERIAL_PORT"
;;
'[B') # DOWN Arrow
echo -ne ":Ms#" > "$SERIAL_PORT"
;;
'[D') # LEFT Arrow
echo -ne ":Mw#" > "$SERIAL_PORT"
;;
'[C') # RIGHT Arrow
echo -ne ":Me#" > "$SERIAL_PORT"
;;
esac
else
# Handle Standard Keys
case "$key" in
# SPACEBAR - The most important key! Stops the telescope.
' ')
echo -ne ":Q#" > "$SERIAL_PORT"
;;
# Speed Controls (Mapped to Meade Standard Rate Commands)
'1'|'2')
# Guide Rate (Very Slow / Nudge)
echo -ne ":RG#" > "$SERIAL_PORT"
CURRENT_SPEED="Guide (Slowest)"
print_ui
;;
'3'|'4'|'5')
# Center Rate (Slow)
echo -ne ":RC#" > "$SERIAL_PORT"
CURRENT_SPEED="Center (Slow)"
print_ui
;;
'6'|'7'|'8')
# Find Rate (Medium)
echo -ne ":RM#" > "$SERIAL_PORT"
CURRENT_SPEED="Find (Medium)"
print_ui
;;
'9')
# Slew Rate (Fastest)
echo -ne ":RS#" > "$SERIAL_PORT"
CURRENT_SPEED="Slew (Max)"
print_ui
;;
# Quit Application
'q')
echo "Stopping telescope..."
echo -ne ":Q#" > "$SERIAL_PORT"
exit 0
;;
esac
fi
done