New iOptron rotator backend

I have an potential initial release of a backend for iOptron alt-az mounts.
I have tested it and it appears to work well both from the command line and
driven by Gpredict with my iEQ45Pro. I ran the source through astyle and I
think that it's OK. Compiling and testing was done under Unbuntu 18.

   Bob KD8CGH
pull/68/head
Robert Benedict 2018-12-10 14:18:15 -05:00 zatwierdzone przez Nate Bargmann
rodzic 451bbfcf1f
commit 3724ce87ee
9 zmienionych plików z 428 dodań i 2 usunięć

1
NEWS
Wyświetl plik

@ -10,6 +10,7 @@ Version 4.0
* API/ABI changes, advance ABI to 4 0 0. * API/ABI changes, advance ABI to 4 0 0.
* Add GPIO and GPION options for DCD. Jeroen Vreeken * Add GPIO and GPION options for DCD. Jeroen Vreeken
* New backend: ELAD FDM DUO. Giovanni, HB9EIK. * New backend: ELAD FDM DUO. Giovanni, HB9EIK.
* New rotator backend: iOptron. Bob, KD8CGH
Version 3.3 Version 3.3
2018-08-12 2018-08-12

Wyświetl plik

@ -50,7 +50,7 @@ dnl Beware of duplication should a backend directory include both rig and
dnl rotor definitions, e.g. "dummy". Optional backends will not be listed dnl rotor definitions, e.g. "dummy". Optional backends will not be listed
dnl here but will be added later, e.g. "winradio". dnl here but will be added later, e.g. "winradio".
BACKEND_LIST="adat alinco aor barrett dorji drake dummy elad flexradio icom icmarine jrc kachina kenwood kit lowe pcr prm80 racal rft rs skanti tapr tentec tuner uniden wj yaesu" BACKEND_LIST="adat alinco aor barrett dorji drake dummy elad flexradio icom icmarine jrc kachina kenwood kit lowe pcr prm80 racal rft rs skanti tapr tentec tuner uniden wj yaesu"
ROT_BACKEND_LIST="amsat ars celestron cnctrk easycomm ether6 fodtrack gs232a heathkit m2 meade rotorez sartek spid ts7400 prosistel" ROT_BACKEND_LIST="amsat ars celestron cnctrk easycomm ether6 fodtrack gs232a heathkit m2 meade rotorez sartek spid ts7400 prosistel ioptron"
dnl See README.release on setting these values dnl See README.release on setting these values
# Values given to -version-info when linking. See libtool documentation. # Values given to -version-info when linking. See libtool documentation.
@ -737,6 +737,7 @@ macros/Makefile
include/Makefile include/Makefile
lib/Makefile lib/Makefile
dummy/Makefile dummy/Makefile
elad/Makefile
yaesu/Makefile yaesu/Makefile
icom/Makefile icom/Makefile
icmarine/Makefile icmarine/Makefile
@ -788,8 +789,9 @@ prosistel/Makefile
dorji/Makefile dorji/Makefile
barrett/Makefile barrett/Makefile
meade/Makefile meade/Makefile
ioptron/Makefile
hamlib.pc hamlib.pc
elad/Makefile]) ])
AC_OUTPUT AC_OUTPUT

Wyświetl plik

@ -361,6 +361,18 @@
#define ROT_BACKEND_MEADE "meade" #define ROT_BACKEND_MEADE "meade"
#define ROT_MODEL_MEADE ROT_MAKE_MODEL(ROT_MEADE, 1) #define ROT_MODEL_MEADE ROT_MAKE_MODEL(ROT_MEADE, 1)
/**
* \def ROT_MODEL_IOPTRON
* \brief A macro that returns the model number of the IOPTRON backend.
*
* The IOPTRON backen can be used with IOPTRON telescope mounts
*/
#define ROT_IOPTRON 19
#define ROT_BACKEND_IOPTRON "ioptron"
#define ROT_MODEL_IOPTRON ROT_MAKE_MODEL(ROT_IOPTRON, 1)
/** /**
* \typedef typedef int rot_model_t * \typedef typedef int rot_model_t

12
ioptron/Android.mk 100644
Wyświetl plik

@ -0,0 +1,12 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := rot_ioptron.c
LOCAL_MODULE := rot_ioptron
LOCAL_CFLAGS := -DHAVE_CONFIG_H
LOCAL_C_INCLUDES := android include src
LOCAL_LDLIBS := -lhamlib -Lobj/local/armeabi
include $(BUILD_STATIC_LIBRARY)

Wyświetl plik

@ -0,0 +1,6 @@
IOPTRONSRC = rot_ioptron.c rot_ioptron.h
noinst_LTLIBRARIES = libhamlib-ioptron.la
libhamlib_ioptron_la_SOURCES = $(IOPTRONSRC)
EXTRA_DIST = Android.mk

Wyświetl plik

@ -0,0 +1,10 @@
This is a small backend for iOptron alt-az mounts. It implements get position, goto position, stop and get info. It has been tested from the command line and with Gpredict with an iEQ45 Pro in alt-az mode. It should work for other iOptron alt-az mounts such as the AZ Mount Pro, Cube-II, CubePro and iEQ30 Pro in alt-az mode as iOptron claims that they all use the same command language.
A warning on iOptron command language. iOptron is in the process of moving from V2 to V3 of the command lamguage and presently (December 2018) uses a mix of the two. This back end should work with mounts with current firmware, but new firmware may change commands and break it.
Minor annoyance - the mount will automatically start siderial tracking after a slew. Adding a stop tracking command at the end of the goto set did not solve the problem.
Bigger annoyance - Be careful with the GEM mounts (iEQ30, iEQ45) in alt-az mode. The dec/el motor cord easily catches on the ra/az clutch knobs when slewing in az. I attached a small standoff to keep the cord out of the way.
Reccomendation - since the hand controller remains plugged, in I suggest that you use it for calibration, manual slews and setting and going to the zero position.

Wyświetl plik

@ -0,0 +1,350 @@
/*
* Hamlib Rotator backend - Celestron
* Copyright (c) 2011 by Stephane Fillod
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include "hamlib/rotator.h"
#include "serial.h"
#include "misc.h"
#include "register.h"
#include "rot_ioptron.h"
#define ACK "#"
#define ACK1 '1'
#define BUFSZ 128
/**
* ioptron_transaction
*
* cmdstr - Command to be sent to the rig.
* data - Buffer for reply string. Can be NULL, indicating that no reply is
* is needed, but answer will still be read.
* data_len - in: Size of buffer. It is the caller's responsibily to provide
* a large enough buffer for all possible replies for a command.
*
* COMMANDS note: as of 12/2018 a mixture of V2 and V3
* | TTTTTTTT(T) .01 arc seconds
* | alt- sign with 8 digits, az - 9 digits |
* | Command | Atribute | Return value | Description |
* -------------------------------------------------------------------|
* | :GAC# | .01 arcsec | sTTTTTTTTTTTTTTTTT# | gets alt(s8), az(9) |
* | :SzTTTTTTTTT# | .01 arcsec | '1' == OK | Set Target azimuth |
* | :SasTTTTTTTT# |.01 arcsec | '1' == OK | Set Target elevation |
* | :Q# | - | '1' == OK | Halt all slewing |
* | :ST0# | - | '1' == OK | Halt tracking |
* | :MS# | - | '1' == OK | GoTo Target |
* |
* returns:
* RIG_OK - if no error occured.
* RIG_EIO - if an I/O error occured while sending/receiving data.
* RIG_ETIMEOUT - if timeout expires without any characters received.
*/
static int
ioptron_transaction(ROT *rot, const char *cmdstr,
char *data, size_t data_len)
{
struct rot_state *rs;
int retval;
int retry_read = 0;
char replybuf[BUFSZ];
rs = &rot->state;
transaction_write:
serial_flush(&rs->rotport);
if (cmdstr)
{
retval = write_block(&rs->rotport, cmdstr, strlen(cmdstr));
if (retval != RIG_OK)
{
goto transaction_quit;
}
}
/** Always read the reply to know whether the cmd went OK */
if (!data)
{
data = replybuf;
}
if (!data_len)
{
data_len = BUFSZ;
}
/** the answer */
memset(data, 0, data_len);
retval = read_string(&rs->rotport, data, data_len, ACK, strlen(ACK));
if (retval < 0)
{
if (retry_read++ < rot->state.rotport.retry)
{
goto transaction_write;
}
goto transaction_quit;
}
/** check for acknowledge */
if (retval < 1)
{
rig_debug(RIG_DEBUG_ERR, "%s: unexpected response, len %d: '%s'\n", __func__,
retval, data);
return -RIG_EPROTO;
}
retval = RIG_OK;
transaction_quit:
return retval;
}
/**
* Opens the Port and sets all needed parametes for operation
* as of 12/2018 initiates mount with V3 :MountInfo#
*/
static int ioptron_open(ROT *rot)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return ioptron_transaction(rot, ":Mountinfo#", NULL, 0);
}
/** sets mount position, requires 4 steps
* set azmiuth
* set altitude
* goto set
* stop tracking - mount starts tracking after goto
*/
static int
ioptron_set_position(ROT *rot, azimuth_t az, elevation_t el)
{
char cmdstr[32];
char retbuf[10];
int retval;
float faz, fel;
rig_debug(RIG_DEBUG_TRACE, "%s called: %f %f\n", __func__, az, el);
/* units .01 arc sec */
faz = az * 360000;
fel = el * 360000;
/* set azmiuth, returns '1" if OK */
sprintf(cmdstr, ":Sz%09.0f#", faz);
retval = ioptron_transaction(rot, cmdstr, retbuf, sizeof(retbuf));
if (retval != RIG_OK || retbuf[0] != ACK1)
{
return -RIG_EPROTO;
}
/* set altitude, returns '1" if OK */
sprintf(cmdstr, ":Sa+%08.0f#", fel);
retval = ioptron_transaction(rot, cmdstr, retbuf, sizeof(retbuf));
if (retval != RIG_OK || retbuf[0] != ACK1)
{
return -RIG_EPROTO;
}
/* move to set target, V2 command, returns '1" if OK */
sprintf(cmdstr, ":MS#"); //
retval = ioptron_transaction(rot, cmdstr, retbuf, sizeof(retbuf));
if (retval != RIG_OK || retbuf[0] != ACK1)
{
return -RIG_EPROTO;
}
/* stop tracking, V2 command, returns '1" if OK */
sprintf(cmdstr, ":ST0#");
retval = ioptron_transaction(rot, cmdstr, retbuf, sizeof(retbuf));
if (retval != RIG_OK || retbuf[0] != ACK1)
{
return -RIG_EPROTO;
}
return retval;
}
/** gets current position */
static int
ioptron_get_position(ROT *rot, azimuth_t *az, elevation_t *el)
{
char posbuf[32];
int retval;
float w;
rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__);
/** Get Az-Alt */
retval = ioptron_transaction(rot, ":GAC#", posbuf, sizeof(posbuf));
if (retval != RIG_OK || strlen(posbuf) < 18)
{
return retval < 0 ? retval : -RIG_EPROTO;
}
if (sscanf(posbuf, "%9f", &w) != 1)
{
return -RIG_EPROTO;
}
/** convert from .01 arc sec to degrees */
*el = ((elevation_t)w / 360000.);
if (sscanf(posbuf + 9, "%9f", &w) != 1)
{
return -RIG_EPROTO;
}
*az = ((azimuth_t)w / 360000.);
rig_debug(RIG_DEBUG_TRACE, "%s: (az, el) = (%.1f, %.1f)\n",
__func__, *az, *el);
return RIG_OK;
}
/** stop everything **/
static int
ioptron_stop(ROT *rot)
{
int retval;
char retbuf[10];
rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__);
/** stop slew, returns "1" if OK */
retval = ioptron_transaction(rot, ":Q#", retbuf, 10);
if (retval != RIG_OK || retbuf[0] != ACK1)
{
return -RIG_EPROTO;
}
/** stops tracking returns "1" if OK */
retval = ioptron_transaction(rot, ":ST0#", retbuf, 10);
if (retval != RIG_OK || retbuf[0] != ACK1)
{
return -RIG_EPROTO;
}
return retval;
}
/** get mount type code, initializes mount */
static const char *
ioptron_get_info(ROT *rot)
{
static char info[16];
char str[6];
rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__);
int retval;
retval = ioptron_transaction(rot, ":MountInfo#", str, sizeof(str));
rig_debug(RIG_DEBUG_TRACE, "retval, RIG_OK str %d %d %str\n", retval, RIG_OK,
str);
sprintf(info, "MountInfo %s", str);
return info;
}
/** *************************************************************************
*
* ioptron mount capabilities.
*
* Protocol documentation:
* from ioptron:
* RS232-Command_Language pdf
* note that iOptron is currently (12/2018) using a mix of V2 and V3 commands :(
*/
const struct rot_caps ioptron_rot_caps =
{
.rot_model = ROT_MODEL_IOPTRON,
.model_name = "iOptron",
.mfg_name = "iOptron",
.version = "0.1",
.copyright = "LGPL",
.status = RIG_STATUS_ALPHA,
.rot_type = ROT_TYPE_AZEL,
.port_type = RIG_PORT_SERIAL,
.serial_rate_min = 9600,
.serial_rate_max = 9600,
.serial_data_bits = 8,
.serial_stop_bits = 1,
.serial_parity = RIG_PARITY_NONE,
.serial_handshake = RIG_HANDSHAKE_NONE,
.write_delay = 0,
.post_write_delay = 0,
.timeout = 1000, /* worst case scenario 3500 */
.retry = 1,
.min_az = 0.0,
.max_az = 360.0,
.min_el = 0.0,
.max_el = 180.0,
.rot_open = ioptron_open,
.get_position = ioptron_get_position,
.set_position = ioptron_set_position,
.stop = ioptron_stop,
.get_info = ioptron_get_info,
};
/* ****************************************************************** */
DECLARE_INITROT_BACKEND(ioptron)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
rot_register(&ioptron_rot_caps);
return RIG_OK;
}
/* ****************************************************************** */
/* end of file */

Wyświetl plik

@ -0,0 +1,31 @@
/*
* Hamlib Meade telescope rotor backend - main header
* Copyright (c) 2018 by Andreas Mueller (DC1MIL)
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _IOPTRON_H
#define _IOPTRON_H 1
#define BUFSIZE 128
#define CR "\r"
#define LF "\x0a"
extern const struct rot_caps ioptron_caps;
#endif /* _IOPTRON_H */

Wyświetl plik

@ -82,6 +82,7 @@ DEFINE_INITROT_BACKEND(ether6);
DEFINE_INITROT_BACKEND(cnctrk); DEFINE_INITROT_BACKEND(cnctrk);
DEFINE_INITROT_BACKEND(prosistel); DEFINE_INITROT_BACKEND(prosistel);
DEFINE_INITROT_BACKEND(meade); DEFINE_INITROT_BACKEND(meade);
DEFINE_INITROT_BACKEND(ioptron);
/** /**
* \def ROT_BACKEND_LIST * \def ROT_BACKEND_LIST
@ -119,6 +120,7 @@ static struct
{ ROT_CNCTRK, ROT_BACKEND_CNCTRK, ROT_FUNCNAMA(cnctrk) }, { ROT_CNCTRK, ROT_BACKEND_CNCTRK, ROT_FUNCNAMA(cnctrk) },
{ ROT_PROSISTEL, ROT_BACKEND_PROSISTEL, ROT_FUNCNAMA(prosistel) }, { ROT_PROSISTEL, ROT_BACKEND_PROSISTEL, ROT_FUNCNAMA(prosistel) },
{ ROT_MEADE, ROT_BACKEND_MEADE, ROT_FUNCNAMA(meade) }, { ROT_MEADE, ROT_BACKEND_MEADE, ROT_FUNCNAMA(meade) },
{ ROT_IOPTRON, ROT_BACKEND_IOPTRON, ROT_FUNCNAMA(ioptron) },
{ 0, NULL }, /* end */ { 0, NULL }, /* end */
}; };