From 7824731565888077e69f8f4ae90ae3fb02b6dc86 Mon Sep 17 00:00:00 2001 From: Frank Wang <103447783+WandererAstro@users.noreply.github.com> Date: Wed, 21 Feb 2024 16:41:38 +0800 Subject: [PATCH] Driver for WandererRotator Mini V1&V2 added (#2000) Co-authored-by: WandererAstro --- drivers.xml | 6 +- drivers/rotator/CMakeLists.txt | 9 + drivers/rotator/wanderer_rotator_mini.cpp | 375 ++++++++++++++++++++++ drivers/rotator/wanderer_rotator_mini.h | 79 +++++ 4 files changed, 468 insertions(+), 1 deletion(-) create mode 100644 drivers/rotator/wanderer_rotator_mini.cpp create mode 100644 drivers/rotator/wanderer_rotator_mini.h diff --git a/drivers.xml b/drivers.xml index 0914131b28..642fc737e5 100644 --- a/drivers.xml +++ b/drivers.xml @@ -437,9 +437,13 @@ indi_simulator_rotator 1.0 - + indi_wanderer_lite_rotator 1.0 + + + indi_wanderer_rotator_mini + 1.0 indi_microtouch_focus diff --git a/drivers/rotator/CMakeLists.txt b/drivers/rotator/CMakeLists.txt index 86b012a8e0..6b2ee9e293 100644 --- a/drivers/rotator/CMakeLists.txt +++ b/drivers/rotator/CMakeLists.txt @@ -62,6 +62,15 @@ add_executable(indi_wanderer_lite_rotator ${WandererRotatorLite_SRC}) target_link_libraries(indi_wanderer_lite_rotator indidriver) install(TARGETS indi_wanderer_lite_rotator RUNTIME DESTINATION bin) +# ############### Wanderer Rotator Mini ################ +SET(WandererRotatorMini_SRC + wanderer_rotator_mini.cpp) + +add_executable(indi_wanderer_rotator_mini ${WandererRotatorMini_SRC}) +target_link_libraries(indi_wanderer_rotator_mini indidriver) +install(TARGETS indi_wanderer_rotator_mini RUNTIME DESTINATION bin) + + # ############### Integra85 Focusing Rotator ################ SET(integra_SRC integra.cpp) diff --git a/drivers/rotator/wanderer_rotator_mini.cpp b/drivers/rotator/wanderer_rotator_mini.cpp new file mode 100644 index 0000000000..4c3e4758d1 --- /dev/null +++ b/drivers/rotator/wanderer_rotator_mini.cpp @@ -0,0 +1,375 @@ +/******************************************************************************* + Copyright(c) 2024 Frank Wang. All rights reserved. + + WandererRotator Mini V1/V2 + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program 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 General Public License for + more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. +*******************************************************************************/ + +#include "wanderer_rotator_mini.h" +#include "indicom.h" +#include "connectionplugins/connectionserial.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +// We declare an auto pointer to WandererRotatorMini. +static std::unique_ptr wandererrotatormini(new WandererRotatorMini()); + +WandererRotatorMini::WandererRotatorMini() +{ + setVersion(1, 0); + +} +bool WandererRotatorMini::initProperties() +{ + + INDI::Rotator::initProperties(); + + SetCapability(ROTATOR_CAN_REVERSE | ROTATOR_CAN_ABORT | ROTATOR_CAN_HOME | ROTATOR_HAS_BACKLASH); + + addAuxControls(); + // Calibrate + SetZeroSP[0].fill("Set_Zero", "Mechanical Zero", ISS_OFF); + SetZeroSP.fill(getDeviceName(), "Set_Zero", "Set Current As", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1,60, IPS_IDLE); + + + serialConnection->setDefaultBaudRate(Connection::Serial::B_19200); + + + return true; +} + +bool WandererRotatorMini::updateProperties() +{ + INDI::Rotator::updateProperties(); + + if (isConnected()) + { + defineProperty(SetZeroSP); + if(firmware<20240208) + { + LOG_ERROR("The firmware is outdated, please upgrade to the latest firmware, or the driver cannot function properly!"); + } + } + else + { + deleteProperty(SetZeroSP); + } + return true; +} + +bool WandererRotatorMini::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) +{ + + if (dev && !strcmp(dev, getDeviceName())) + { + if (SetZeroSP.isNameMatch(name)) + { + SetZeroSP.setState(sendCommand("1500002") ? IPS_OK : IPS_ALERT); + SetZeroSP.apply(); + GotoRotatorN[0].value=0; + IDSetNumber(&GotoRotatorNP, nullptr); + LOG_INFO("Virtual Mechanical Angle is set to zero."); + return true; + } + } + return Rotator::ISNewSwitch(dev, name, states, names, n); +} + + + +const char *WandererRotatorMini::getDefaultName() +{ + return "WandererRotator Mini"; +} + +bool WandererRotatorMini::Handshake() +{ + PortFD = serialConnection->getPortFD(); + tcflush(PortFD, TCIOFLUSH); + int nbytes_read_name = 0,nbytes_written=0,rc=-1; + char name[64] = {0}; + + if ((rc = tty_write_string(PortFD, "1500001", &nbytes_written)) != TTY_OK) + { + char errorMessage[MAXRBUF]; + tty_error_msg(rc, errorMessage, MAXRBUF); + LOGF_ERROR("Serial write error: %s", errorMessage); + return false; + } + + //Device Model////////////////////////////////////////////////////////////////////////////////////////////////////// + if ((rc = tty_read_section(PortFD, name, 'A', 3, &nbytes_read_name)) != TTY_OK) + { + tcflush(PortFD, TCIOFLUSH); + if ((rc = tty_write_string(PortFD, "1500001", &nbytes_written)) != TTY_OK) + { + char errorMessage[MAXRBUF]; + tty_error_msg(rc, errorMessage, MAXRBUF); + LOGF_ERROR("Serial write error: %s", errorMessage); + return false; + } + if ((rc = tty_read_section(PortFD, name, 'A', 3, &nbytes_read_name)) != TTY_OK) + { + char errorMessage[MAXRBUF]; + tty_error_msg(rc, errorMessage, MAXRBUF); + LOGF_INFO("No data received, the device may not be WandererRotator, please check the serial port!","Updated"); + LOGF_ERROR("Device read error: %s", errorMessage); + return false; + } + } + name[nbytes_read_name - 1] = '\0'; + if(strcmp(name, "WandererRotatorMini")!=0) + { + LOGF_ERROR("The device is not WandererRotator Mini!","Updated"); + LOGF_INFO("The device is %s",name); + return false; + } + // Frimware version///////////////////////////////////////////////////////////////////////////////////////////// + int nbytes_read_version = 0; + char version[64] = {0}; + tty_read_section(PortFD, version, 'A', 5, &nbytes_read_version); + + version[nbytes_read_version - 1] = '\0'; + LOGF_INFO("Firmware Version:%s", version); + firmware=std::atoi(version); + // Angle////////////////////////////////////////////////////////////////////////////////////////// + char M_angle[64] = {0}; + int nbytes_read_M_angle= 0; + tty_read_section(PortFD, M_angle, 'A', 5, &nbytes_read_M_angle); + M_angle[nbytes_read_M_angle - 1] = '\0'; + M_angleread = std::strtod(M_angle,NULL); + + if(abs(M_angleread)>400000) + { + rc=sendCommand("1500002"); + LOG_WARN("Virtual Mechanical Angle is too large, it is now set to zero!"); + rc=sendCommand("1500001"); + rc=tty_read_section(PortFD, M_angle, 'A', 5, &nbytes_read_M_angle); + rc=tty_read_section(PortFD, M_angle, 'A', 5, &nbytes_read_M_angle); + rc=tty_read_section(PortFD, M_angle, 'A', 5, &nbytes_read_M_angle); + M_angle[nbytes_read_M_angle - 1] = '\0'; + M_angleread = std::strtod(M_angle,NULL); + + } + GotoRotatorN[0].value=abs(M_angleread/1000); + tcflush(PortFD, TCIOFLUSH); + return true; +} + + +IPState WandererRotatorMini::MoveRotator(double angle) +{ + angle = angle - GotoRotatorN[0].value; + if (angle * positionhistory < 0 && angle > 0) + { + angle = angle + backlash; + } + if (angle * positionhistory < 0 && angle < 0) + { + angle = angle - backlash; + } + char cmd[16]; + int position = (int)(reversecoefficient * angle * 1142); + positionhistory = angle; + snprintf(cmd, 16, "%d", position); + Move(cmd); + + return IPS_BUSY; +} + + + +bool WandererRotatorMini::AbortRotator() +{ + + haltcommand = true; + + int nbytes_written = 0, rc = -1; + tcflush(PortFD, TCIOFLUSH); + if ((rc = tty_write_string(PortFD, "Stop", &nbytes_written)) != TTY_OK) + { + char errorMessage[MAXRBUF]; + tty_error_msg(rc, errorMessage, MAXRBUF); + LOGF_ERROR("Serial write error: %s", errorMessage); + return false; + } + + SetTimer(100); + return true; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +/// \brief WandererRotatorMini::HomeRotator +/// \return +/// +IPState WandererRotatorMini::HomeRotator() +{ + + double angle = -1 * reversecoefficient * GotoRotatorN[0].value; + positionhistory = -1* GotoRotatorN[0].value; + char cmd[16]; + int position = (int)(angle * 1142); + snprintf(cmd, 16, "%d", position); + GotoRotatorNP.s = IPS_BUSY; + Move(cmd); + LOG_INFO("Moving to zero..."); + return IPS_OK; +} + + +bool WandererRotatorMini::ReverseRotator(bool enabled) +{ + + if (enabled) + { + if(M_angleread>0) + { + HomeRotator(); + LOG_WARN("The rotator will first move to zero and then reverse the rotation direction to prevent cable wrap..."); + } + reversecoefficient = -1; + ReverseState = true; + return true; + } + else + { + if(M_angleread<0) + { + HomeRotator(); + LOG_WARN("The rotator will first move to zero and then reverse the rotation direction to prevent cable wrap..."); + } + reversecoefficient = 1; + ReverseState = false; + return true; + } + return false; +} + + + +void WandererRotatorMini::TimerHit() +{ + + if (GotoRotatorNP.s == IPS_BUSY || haltcommand == true) + { + + if(nowtime", cmd); + if ((rc = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK) + { + char errorMessage[MAXRBUF]; + tty_error_msg(rc, errorMessage, MAXRBUF); + LOGF_ERROR("Serial write error: %s", errorMessage); + return false; + } + SetTimer(2000); + nowtime=0; + estime=abs(std::atoi(cmd)/1142*260); + return true; +} + + +bool WandererRotatorMini::sendCommand(std::string command) +{ + int nbytes_written = 0, rc = -1; + std::string command_termination = "\n"; + LOGF_DEBUG("CMD: %s", command.c_str()); + if ((rc = tty_write_string(PortFD, (command + command_termination).c_str(), &nbytes_written)) != TTY_OK) + { + char errorMessage[MAXRBUF]; + tty_error_msg(rc, errorMessage, MAXRBUF); + LOGF_ERROR("Serial write error: %s", errorMessage); + return false; + } + return true; +} + + +bool WandererRotatorMini::SetRotatorBacklash(int32_t steps) +{ + backlash = (double)(steps / 1142); + return true; +} + +bool WandererRotatorMini::SetRotatorBacklashEnabled(bool enabled) +{ + if(enabled) + { + return SetRotatorBacklash(RotatorBacklashN[0].value); + } + else + { + return SetRotatorBacklash(0); + } + +} + + diff --git a/drivers/rotator/wanderer_rotator_mini.h b/drivers/rotator/wanderer_rotator_mini.h new file mode 100644 index 0000000000..280ba1deb7 --- /dev/null +++ b/drivers/rotator/wanderer_rotator_mini.h @@ -0,0 +1,79 @@ +/******************************************************************************* + Copyright(c) 2024 Frank Wang. All rights reserved. + + WandererRotator Mini V1/V2 + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program 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 General Public License for + more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. +*******************************************************************************/ + +#pragma once + +#include "defaultdevice.h" +#include "indirotator.h" +#include "indirotatorinterface.h" +#include "indipropertyswitch.h" +class WandererRotatorMini : public INDI::Rotator +{ +public: + WandererRotatorMini(); + + virtual bool initProperties() override; + virtual bool updateProperties() override; + virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; + + + + +protected: + const char * getDefaultName() override; + virtual IPState MoveRotator(double angle) override; + virtual IPState HomeRotator() override; + virtual bool ReverseRotator(bool enabled) override; + + virtual bool AbortRotator() override; + virtual void TimerHit() override; + virtual bool SetRotatorBacklash(int32_t steps) override; + virtual bool SetRotatorBacklashEnabled(bool enabled) override; + + + + +private: + int firmware=0; + double M_angleread=0; + double initangle=0; + bool Handshake() override; + INDI::PropertySwitch SetZeroSP{1}; + bool sendCommand(std::string command); + bool Move(const char *cmd); + bool haltcommand = false; + bool ReverseState=false; + int reversecoefficient=1; + double backlash=0.5; + double positionhistory=0; + int estime=0; + int nowtime=0; + +}; + + + + + +