Dies ist eine alte Version des Dokuments!
virtelles Java-Teleskop
Übersicht
Die grundsätzliche Arbeitsweise zwischen Linux und dem Teleskop (Steuerung) kann man auch ohne Elektronik (& Teleskop) studieren. Die drei großen Clients (KStart, Skychart und Stellarium) können mit der Indi-Schnittstelle kommunizieren und virtuelle Teleskopmontierungen einbinden. Diese Teleskopsimulatoren sind technisch gesehen INDI-C-Treiber. Ich erzeuge hier z.B. mit Java eine virtuelle serielle Schnittstelle und benutze "täusche" eine rudimentäre LX200 Montierung vor, die mit Stellarium verwendet werden kann. == Software == <WRAP center round info 95%> Um mit Java auf die serielle Schnittstelle zugreifen zu können, verwenden wir die jSSC (Java Simple Serial Connector) API. Sie besteht aus nur einer jar-Datei und wird auch von der Arduino-IDE selbst verwendet. In Eclipse wird sie über Eigenschaften (Java Build Path - Add External JAR's...) dem Projekt hinzugefügt. https://code.google.com/archive/p/java-simple-serial-connector/ oder {{ :serial.zip
socat - universelles Linux Netwerk Tool
==== Installation und Inbetriebnahme ==== - Eclipseprojekt erzeugen und die Datei (unten) SimulatorTeleskop einfügen - jssc-2.0.0.jar als Externe Library dem Projekt hinzufügen - Projekt mit Eclipse übersetzen (kann nicht fehlerfrei gestartet werden, da die Schnittstelle „/dev/ttyUSB60“ nicht vorhanden ist) - Virtuelle serielle Schnittstelle erzeugen - Rechte setzen - Testen == Details == Die folgenden beiden befehle erfordern Rootrechte. Außerdem müssen auf diese Weise angelegte Schnittstellen muss häufig neu eingerichtet werden. Nicht vergessen, dieses Projekt soll zum eigenen Experimentieren anregen und lediglich die grundlegende Kommunikation aufzeigen. Die virtuelle Schnittstelle wird mit dem folgenden Befehl gesetzt
socat -d -d PTY,link=/dev/ttyUSB60 PTY,link=/dev/ttyUSB61
Anschließend werden zum Testen alle Rechte vergeben
# chmod 777 /dev/ttyUSB6*
Überprüfen Sie (Konsole ls-Befehl) ob alles richtig gemacht wurde
== Test 1: Konsole ==
Ein erste Test erfolgt mit einer User-Konsole, indem folgender Befehlt an das Gerät gesendet wird, zuvor muss das Programm (z.B. über Eclipse gestartet werden).
echo ":GD#" > /dev/ttyUSB61
Auf der Konsole (Eclipse) sollten jetzt die Anzahl der gelesenen Bytes angezeigt werden. Damit funktioniert die Kommunikation über die virtuelle serielle Schnittstelle. == Test 2: Stellarium == Der zweite Test ist spannender, da wir mit Stellarium kommunizieren. - LX200 Teleskop einrichten mit /dev/ttyUSB61 als Device (noch nicht verbinden!) - Schnittstelle einrichten (socat, chmod) - Java SimulatorTeleskop starten - LX200 Teleskop in Stellarium verbinden
==== Quellcode Projekt A ====
/** LX200 Protocol * @author torsten.roehl@fsg-preetz.org * simple demo to communicate with a indi-client! */ import java.util.Timer; import java.util.TimerTask; import jssc.SerialPort; import jssc.SerialPortException; public class SimulatorTeleskop { static String currentRA = "02:31:50#"; static String currentDE = "+89*15#"; static String targetRA = currentRA; static String targetDE = currentDE; static String dev = "/dev/ttyUSB60"; public static void main(String[] args) throws InterruptedException { SerialPort serialPort = new SerialPort(dev); try { serialPort.openPort(); serialPort.setParams(9600, 8, 1, 0); System.out.println("... initializing the serial port"); Thread.sleep(4000); // necessary, otherwise serial will fail!!! } catch (SerialPortException e1) { e1.printStackTrace(); } try { while (true) { // read message String msg = decode(serialPort); // run through protocol if (isMessage(msg)) { System.out.println("Received: " + msg); if (msg.startsWith("#:GR#")) { // GET RA writeMessage(serialPort, currentRA); } if (msg.startsWith("#:GD#")) { // GET DEC writeMessage(serialPort, currentDE); } if (msg.startsWith("#:Q#:S")) { // SYNC to Slew 1/2 HH:MM:SS targetRA = msg.substring(msg.indexOf(' ')).trim(); writeMessage(serialPort, "1"); } if (msg.startsWith(":Sd ")) { // SYNC to Slew 2/2 sDD*MM:SS currentDE = msg.substring(msg.indexOf(' ')).trim(); targetDE = currentDE; writeMessage(serialPort, "1"); } if (msg.startsWith(":MS#")) { // Slew to Target Object writeMessage(serialPort, "0"); simulateMove(); } } Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } try { serialPort.closePort(); } catch (SerialPortException e) { e.printStackTrace(); } } static String decode(SerialPort serialPort) { try { // step 1: read bytes from port byte[] buffer = serialPort.readBytes(); // step 2: verify if (buffer == null) return "UNKNOWN COMMAND"; int numRead = buffer.length; if (buffer.length <= 0) return "UNKNOWN COMMAND"; // step 3: convert buffer to string String res = ""; for (int i = 0; i < numRead; i++) { byte b = buffer[i]; // fixme: problem with Star * char c = (char) b; if (b == -33) c = '*'; res += c; } return res; } catch (SerialPortException e) { e.printStackTrace(); } return "UNKNOWN COMMAND"; } /** * helper method convert a ra-string to a number (for arithmetic use) */ static int string2int(String str) { String tmp = str.substring(0, str.length() - 1); String lsTmp[] = tmp.split(":"); int res = 3600 * Integer.valueOf(lsTmp[0]) + 60 * Integer.valueOf(lsTmp[1]) + Integer.valueOf(lsTmp[2]); return res; } /** * helper method to convert a number into ra-string */ static String number2string(double number) { int h = (int) (number - (number % 3600)) / 3600; int rest = (int) (number - h * 3600); int m = (int) (rest - (rest % 60)) / 60; rest = rest - m * 60; int s = rest; String strH = String.format("%02d", h); String strM = String.format("%02d", m); String strS = String.format("%02d", s); return strH + ":" + strM + ":" + strS + "#"; } /** * dummy method to simulate kind of telescope motion - using ten steps only * in ra-axis */ static void simulateMove() { TimerTask repeatedTask = new TimerTask() { int run = 0; double stepwidth = 0; int iTo = 0; int iFrom = 0; public void run() { System.out.println(run + " ...move simulation "); // step 0: calculate stepwidth once if (run == 0) { iFrom = string2int(currentRA); iTo = string2int(targetRA); stepwidth = (iTo - iFrom) / 10.0; } // step 1: adjust currentRA with stepwidth if (run > 0) { currentRA = number2string(iFrom + run * stepwidth); } // step 2: finish motion run++; if (run > 10) { currentRA = targetRA; cancel(); } } }; Timer timer = new Timer("Timer"); timer.scheduleAtFixedRate(repeatedTask, 0, 250); } static boolean isMessage(String msg) { if (msg.equals("UNKNOWN COMMAND")) return false; return true; } static void writeMessage(SerialPort p, String msg) { try { byte[] buffer = msg.getBytes(); p.writeBytes(buffer); } catch (SerialPortException e) { e.printStackTrace(); } } }