From f7405346556539aa9bb8180649b226120eee35e9 Mon Sep 17 00:00:00 2001 From: grm Date: Sat, 25 Jan 2025 22:14:57 +0100 Subject: [PATCH 1/2] Update wanderer rotator lite to support latest firmware and correct bug in the rotators mini and lite v2 driver (bad angle estiamtion while homing --- drivers/rotator/wanderer_rotator_lite.cpp | 517 +++++++++---------- drivers/rotator/wanderer_rotator_lite.h | 101 ++-- drivers/rotator/wanderer_rotator_lite_v2.cpp | 1 + drivers/rotator/wanderer_rotator_mini.cpp | 1 + 4 files changed, 295 insertions(+), 325 deletions(-) diff --git a/drivers/rotator/wanderer_rotator_lite.cpp b/drivers/rotator/wanderer_rotator_lite.cpp index f823232735..76d67b80f0 100644 --- a/drivers/rotator/wanderer_rotator_lite.cpp +++ b/drivers/rotator/wanderer_rotator_lite.cpp @@ -1,22 +1,26 @@ -/* - WandererAstro WandererRotatorLite - Copyright (C) 2022 Frank Wang (1010965596@qq.com) +/******************************************************************************* + Copyright(c) 2024 Frank Wang. All rights reserved. - 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. + WandererRotator Lite V1 - 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. + 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. - 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 + 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_lite.h" #include "indicom.h" @@ -30,96 +34,113 @@ #include #include +#define STEPS_PER_DEGREE 1155 + -// We declare an auto pointer to WandererRotatorLite. -static std::unique_ptr RotatorLite(new WandererRotatorLite()); +// We declare an auto pointer to WandererRotatorLiteV1. +static std::unique_ptr wandererrotatorlitev1(new WandererRotatorLiteV1()); -WandererRotatorLite::WandererRotatorLite() +WandererRotatorLiteV1::WandererRotatorLiteV1() { setVersion(1, 0); - RI::SetCapability(ROTATOR_CAN_REVERSE | ROTATOR_CAN_SYNC | ROTATOR_CAN_ABORT | ROTATOR_CAN_HOME | ROTATOR_HAS_BACKLASH); + } -bool WandererRotatorLite::initProperties() +bool WandererRotatorLiteV1::initProperties() { + INDI::Rotator::initProperties(); - setDefaultPollingPeriod(500); + + SetCapability(ROTATOR_CAN_REVERSE | ROTATOR_CAN_ABORT | ROTATOR_CAN_HOME); + + 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); + + // BACKLASH + BacklashNP[BACKLASH].fill( "BACKLASH", "Degree", "%.2f", 0, 3, 0.1, 0); + BacklashNP.fill(getDeviceName(), "BACKLASH", "Backlash", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); + serialConnection->setDefaultBaudRate(Connection::Serial::B_19200); - HomeSP[0].fill("SetHomeButton", "Set Current Position as Home", ISS_OFF); - HomeSP.fill(getDeviceName(), "SetHome", "Set Home", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1, 5, - IPS_IDLE); + return true; } -bool WandererRotatorLite::updateProperties() +bool WandererRotatorLiteV1::updateProperties() { INDI::Rotator::updateProperties(); if (isConnected()) { - - defineProperty(HomeSP); - deleteProperty(PresetNP.name); - deleteProperty(PresetGotoSP.name); + defineProperty(SetZeroSP); + defineProperty(BacklashNP); } else { - deleteProperty(HomeSP); - deleteProperty(PresetNP.name); - deleteProperty(PresetGotoSP.name); + deleteProperty(SetZeroSP); + deleteProperty(BacklashNP); } return true; } -bool WandererRotatorLite::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) +bool WandererRotatorLiteV1::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) { + if (dev && !strcmp(dev, getDeviceName())) { - if (HomeSP.isNameMatch(name)) + if (SetZeroSP.isNameMatch(name)) { - - HomeSP.setState(SetHomePosition() ? IPS_OK : IPS_ALERT); - GotoRotatorN[0].value = 0; - LOG_INFO("Home is set"); - HomeSP.apply(); + 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; - - } - if (!strcmp(name, HomeRotatorSP.name)) - { - - HomeRotatorSP.s = HomeRotator(); - LOG_INFO("Homing...."); - IDSetSwitch(&HomeRotatorSP, nullptr); - return true; - } } - return Rotator::ISNewSwitch(dev, name, states, names, n); } +bool WandererRotatorLiteV1::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n) +{ + if (dev && !strcmp(dev, getDeviceName())) + { + // backlash + if (BacklashNP.isNameMatch(name)) + { + bool rc1 = false; + BacklashNP.update(values, names, n); + backlash=BacklashNP[BACKLASH].value; + + char cmd[16]; + snprintf(cmd, 16, "%d", (int)(backlash*10+1600000)); + rc1=sendCommand(cmd); + + BacklashNP.setState( (rc1) ? IPS_OK : IPS_ALERT); + if (BacklashNP.getState() == IPS_OK) + BacklashNP.update(values, names, n); + BacklashNP.apply(); + LOG_INFO("Backlash Set"); + return true; + } + } + return Rotator::ISNewNumber(dev, name, values, names, n); +} -const char *WandererRotatorLite::getDefaultName() +const char *WandererRotatorLiteV1::getDefaultName() { - return "WandererRotatorLite"; + return "WandererRotator Lite V1"; } -////////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::Handshake -/// \return -/// -bool WandererRotatorLite::Handshake() + +bool WandererRotatorLiteV1::Handshake() { + PortFD = serialConnection->getPortFD(); tcflush(PortFD, TCIOFLUSH); - int nbytes_read1 = 0, nbytes_written = 0, rc = -1; - int nbytes_read2 = 0; - int nbytes_read3 = 0; - char res1[64] = {0}; - char res2[64] = {0}; - char res3[64] = {0}; - LOGF_DEBUG("CMD <%s>", "150001"); + 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]; @@ -128,87 +149,119 @@ bool WandererRotatorLite::Handshake() return false; } - if ((rc = tty_read_section(PortFD, res1, 'A', 5, &nbytes_read1)) != TTY_OK) + //Device Model////////////////////////////////////////////////////////////////////////////////////////////////////// + if ((rc = tty_read_section(PortFD, name, 'A', 3, &nbytes_read_name)) != TTY_OK) { - char errorMessage[MAXRBUF]; - tty_error_msg(rc, errorMessage, MAXRBUF); - LOGF_ERROR("Device read error: %s", errorMessage); - return false; + 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; + } } - if ((rc = tty_read_section(PortFD, res2, 'A', 5, &nbytes_read2)) != TTY_OK) + name[nbytes_read_name - 1] = '\0'; + if(strcmp(name, "WandererRotatorLite")!=0) { - char errorMessage[MAXRBUF]; - tty_error_msg(rc, errorMessage, MAXRBUF); - LOGF_ERROR("Firmware read error: %s", errorMessage); + LOG_ERROR("The device is not WandererRotator Lite V1!"); + LOGF_INFO("The device is %s.",name); return false; } - if ((rc = tty_read_section(PortFD, res3, 'A', 5, &nbytes_read3)) != TTY_OK) + // 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); + if(firmware<20240403) { - char errorMessage[MAXRBUF]; - tty_error_msg(rc, errorMessage, MAXRBUF); - LOGF_ERROR("Position read error: %s", errorMessage); + LOG_ERROR("The firmware is outdated, please upgrade to the latest firmware!"); + LOGF_ERROR("The current firmware is %s.", firmware); return false; } - if(atof(res3) >= 100000) + + // 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) { - GotoRotatorN[0].value = (atof(res3) - 100000) / 100; + 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); + //backlash///////////////////////////////////////////////////////////////////// + char M_backlash[64] = {0}; + int nbytes_read_M_backlash= 0; + tty_read_section(PortFD, M_backlash, 'A', 5, &nbytes_read_M_backlash); + M_backlash[nbytes_read_M_angle - 1] = '\0'; + M_backlashread = std::strtod(M_backlash,NULL); + + BacklashNP[BACKLASH].setValue(M_backlashread); + BacklashNP.setState(IPS_OK); + BacklashNP.apply(); + //reverse///////////////////////////////////////////////////////////////////// + char M_reverse[64] = {0}; + int nbytes_read_M_reverse= 0; + tty_read_section(PortFD, M_reverse, 'A', 5, &nbytes_read_M_reverse); + M_reverse[nbytes_read_M_angle - 1] = '\0'; + M_reverseread = std::strtod(M_reverse,NULL); + if(M_reverseread==0) + { + ReverseRotator(false); } else { - GotoRotatorN[0].value = atof(res3) / 100; + ReverseRotator(true); } - res1[nbytes_read1 - 1] = '\0'; - res2[nbytes_read2 - 1] = '\0'; - res3[nbytes_read3 - 1] = '\0'; - LOGF_DEBUG("RES <%s>", res1); - LOGF_INFO("Handshake successful:%s", res1); - LOGF_INFO("Firmware Version:%s", res2); + tcflush(PortFD, TCIOFLUSH); return true; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::MoveRotator -/// \param angle -/// \return -/// -IPState WandererRotatorLite::MoveRotator(double angle) +IPState WandererRotatorLiteV1::MoveRotator(double angle) { - backlashcompensation = 0; angle = angle - GotoRotatorN[0].value; - if (angle * positionhistory < 0 && angle > 0) - { - angle = angle + backlash; - backlashcompensation = -1 * backlash; - } - if (angle * positionhistory < 0 && angle < 0) - { - angle = angle - backlash; - backlashcompensation = backlash; - } + char cmd[16]; - int position = (int)(reversecoefficient * angle * 1155); + int position = (int)(angle * STEPS_PER_DEGREE+1000000); positionhistory = angle; snprintf(cmd, 16, "%d", position); Move(cmd); + return IPS_BUSY; } -///////////////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::AbortRotator -/// \return -bool WandererRotatorLite::AbortRotator() +bool WandererRotatorLiteV1::AbortRotator() { - haltcommand = true; - positioncount = 0; - SetTimer(10); - int nbytes_read1 = 0, nbytes_written = 0, rc = -1; - int nbytes_read2 = 0; - char res1[16] = {0}; - char res2[16] = {0}; + + if (GotoRotatorNP.s == IPS_BUSY) + { + haltcommand = true; + int nbytes_written = 0, rc = -1; tcflush(PortFD, TCIOFLUSH); if ((rc = tty_write_string(PortFD, "Stop", &nbytes_written)) != TTY_OK) { @@ -217,168 +270,116 @@ bool WandererRotatorLite::AbortRotator() LOGF_ERROR("Serial write error: %s", errorMessage); return false; } - - if ((rc = tty_read_section(PortFD, res1, 'A', 5, &nbytes_read1)) != TTY_OK) - { - char errorMessage[MAXRBUF]; - tty_error_msg(rc, errorMessage, MAXRBUF); - LOGF_ERROR("Relative position read error: %s", errorMessage); - return false; - } - if ((rc = tty_read_section(PortFD, res2, 'A', 5, &nbytes_read2)) != TTY_OK) - { - char errorMessage[MAXRBUF]; - tty_error_msg(rc, errorMessage, MAXRBUF); - LOGF_ERROR("Mechanical position read error: %s", errorMessage); - return false; - } - else - { - haltcommand = false; + SetTimer(100); } - GotoRotatorN[0].value = atof(res2) / 100; - res1[nbytes_read1 - 1] = '\0'; - res2[nbytes_read2 - 1] = '\0'; - LOGF_DEBUG("Move Relative:%s", res1); - LOGF_DEBUG("Move to Mechanical:%s", res2); - tcflush(PortFD, TCIOFLUSH); return true; } ////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::HomeRotator +/// \brief WandererRotatorLiteV1::HomeRotator /// \return /// -IPState WandererRotatorLite::HomeRotator() +IPState WandererRotatorLiteV1::HomeRotator() { - - double angle = -1 * reversecoefficient * GotoRotatorN[0].value; + if(GotoRotatorN[0].value!=0) + { + double angle = -1 * GotoRotatorN[0].value; positionhistory = angle; char cmd[16]; - int position = (int)(angle * 1155); + int position = (int)(angle * STEPS_PER_DEGREE+1000000); snprintf(cmd, 16, "%d", position); + GotoRotatorNP.s = IPS_BUSY; Move(cmd); - return IPS_BUSY; + LOG_INFO("Moving to zero..."); + } + return IPS_OK; } -///////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::ReverseRotator -/// \param enabled -/// \return -/// -bool WandererRotatorLite::ReverseRotator(bool enabled) + +bool WandererRotatorLiteV1::ReverseRotator(bool enabled) { if (enabled) { - reversecoefficient = -1; + char cmd[16]; + snprintf(cmd, 16, "%d", 1700001); + if (sendCommand(cmd)!= true) + { + LOG_ERROR("Serial write error."); + return false; + } ReverseState = true; return true; } - else { - reversecoefficient = 1; + char cmd[16]; + snprintf(cmd, 16, "%d", 1700000); + if (sendCommand(cmd)!= true) + { + LOG_ERROR("Serial write error."); + return false; + } ReverseState = false; return true; } return false; } -/////////////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::TimerHit -/// -void WandererRotatorLite::TimerHit() + +void WandererRotatorLiteV1::TimerHit() { - if(haltcommand) - { - GotoRotatorNP.s = IPS_OK; - HomeRotatorSP.s = IPS_OK; - IDSetSwitch(&HomeRotatorSP, nullptr); - haltcommand = false; - positioncount = 0; - return; - } - if(positioncount > 0) - { - GotoRotatorN[0].value += reversecoefficient * abs(positionhistory) / positionhistory; - positioncount--; - IDSetNumber(&GotoRotatorNP, nullptr); - SetTimer(150); - return; - } - if (GotoRotatorNP.s == IPS_BUSY || HomeRotatorSP.s == IPS_BUSY) + if (GotoRotatorNP.s == IPS_BUSY || haltcommand == true) { - LOG_INFO("Done"); - int nbytes_read1 = 0, rc = -1; - int nbytes_read2 = 0; - char res1[16] = {0}; - char res2[16] = {0}; - if ((rc = tty_read_section(PortFD, res1, 'A', 5, &nbytes_read1)) != TTY_OK) + if(nowtime", cmd); - positioncount = abs(atoi(cmd) / 1155); - 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; - } - usleep(1200000); - SetTimer(150); - return true; + SetTimer(2000); } -/////////////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::sendCommand -/// \param cmd -/// \return -/// -bool WandererRotatorLite::sendCommand(const char *cmd) +bool WandererRotatorLiteV1::Move(const char *cmd) { - int nbytes_read = 0, nbytes_written = 0, rc = -1; - char res[32] = {0}; + initangle=GotoRotatorN[0].value; + int nbytes_written = 0, rc = -1; LOGF_DEBUG("CMD <%s>", cmd); - - tcflush(PortFD, TCIOFLUSH); if ((rc = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK) { char errorMessage[MAXRBUF]; @@ -386,68 +387,26 @@ bool WandererRotatorLite::sendCommand(const char *cmd) LOGF_ERROR("Serial write error: %s", errorMessage); return false; } - - - if ((rc = tty_read_section(PortFD, res, 'A', 60, &nbytes_read)) != TTY_OK) - { - char errorMessage[MAXRBUF]; - tty_error_msg(rc, errorMessage, MAXRBUF); - LOGF_ERROR("Serial read error: %s", errorMessage); - return false; - } - tcflush(PortFD, TCIOFLUSH); - res[nbytes_read - 1] = '\0'; - LOGF_DEBUG("RES <%s>", res); + SetTimer(2000); + nowtime=0; + estime=abs((std::atoi(cmd)-1000000)/STEPS_PER_DEGREE*240); return true; } -///////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::SetHomePosition -/// \return -/// -bool WandererRotatorLite::SetHomePosition() +bool WandererRotatorLiteV1::sendCommand(std::string command) { int nbytes_written = 0, rc = -1; - LOGF_DEBUG("CMD <%s>", "1500002"); - - tcflush(PortFD, TCIOFLUSH); - if ((rc = tty_write_string(PortFD, "1500002", &nbytes_written)) != TTY_OK) + 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; } - - tcflush(PortFD, TCIOFLUSH); - GotoRotatorN[0].value = 0; return true; } -///////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::SetRotatorBacklash -/// \param steps -/// \return -/// -bool WandererRotatorLite::SetRotatorBacklash(int32_t steps) -{ - backlash = (double)(steps / 1155); - return true; -} -//////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLite::SetRotatorBacklashEnabled -/// \param enabled -/// \return -/// -bool WandererRotatorLite::SetRotatorBacklashEnabled(bool enabled) -{ - if(enabled) - { - return SetRotatorBacklash(RotatorBacklashN[0].value); - } - else - { - return SetRotatorBacklash(0); - } -} + diff --git a/drivers/rotator/wanderer_rotator_lite.h b/drivers/rotator/wanderer_rotator_lite.h index b399a09358..480f0f3a7d 100644 --- a/drivers/rotator/wanderer_rotator_lite.h +++ b/drivers/rotator/wanderer_rotator_lite.h @@ -1,22 +1,26 @@ -/* - WandererAstro WandererRotatorLite - Copyright (C) 2022 Frank Wang (1010965596@qq.com) +/******************************************************************************* + Copyright(c) 2024 Frank Wang. All rights reserved. - 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. + WandererRotator Lite V1 - 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. + 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. - 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 + 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 @@ -24,48 +28,53 @@ #include "indirotator.h" #include "indirotatorinterface.h" #include "indipropertyswitch.h" -class WandererRotatorLite : public INDI::Rotator +class WandererRotatorLiteV1 : public INDI::Rotator { - public: - WandererRotatorLite(); - - virtual bool initProperties() override; - virtual bool updateProperties() override; - virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; +public: + WandererRotatorLiteV1(); + virtual bool initProperties() override; + virtual bool updateProperties() override; + virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; + virtual bool ISNewNumber(const char *dev, const char *name, double values[], 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; +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; - private: - bool Handshake() override; - bool sendCommand(const char *cmd); - bool Move(const char *cmd); - INDI::PropertySwitch HomeSP {1}; - bool SetHomePosition(); - bool haltcommand = false; - bool ReverseState; - double positiontemp; - int reversecoefficient; - double backlash; - double positionhistory; - double backlashcompensation; - int positioncount; -}; +private: + int firmware=0; + double M_angleread=0; + double M_backlashread=0; + double M_reverseread=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; + double backlash=0.5; + double positionhistory=0; + int estime=0; + int nowtime=0; + INDI::PropertyNumber BacklashNP{1}; + enum + { + BACKLASH, + }; +}; \ No newline at end of file diff --git a/drivers/rotator/wanderer_rotator_lite_v2.cpp b/drivers/rotator/wanderer_rotator_lite_v2.cpp index ad54666778..649f2fb152 100644 --- a/drivers/rotator/wanderer_rotator_lite_v2.cpp +++ b/drivers/rotator/wanderer_rotator_lite_v2.cpp @@ -281,6 +281,7 @@ IPState WandererRotatorLiteV2::HomeRotator() if(GotoRotatorN[0].value!=0) { double angle = -1 * GotoRotatorN[0].value; + positionhistory = angle; char cmd[16]; int position = (int)(angle * 1199+1000000); diff --git a/drivers/rotator/wanderer_rotator_mini.cpp b/drivers/rotator/wanderer_rotator_mini.cpp index c5780de18a..81d7f5ad87 100644 --- a/drivers/rotator/wanderer_rotator_mini.cpp +++ b/drivers/rotator/wanderer_rotator_mini.cpp @@ -240,6 +240,7 @@ bool WandererRotatorMini::Handshake() IPState WandererRotatorMini::MoveRotator(double angle) { angle = angle - GotoRotatorN[0].value; + positionhistory = angle; char cmd[16]; int position = (int)(angle * 1142+1000000); From e7b44d99dffb90da52bb5f10828fed063f5f2e2a Mon Sep 17 00:00:00 2001 From: grm Date: Sun, 26 Jan 2025 12:16:42 +0100 Subject: [PATCH 2/2] Refactoring wanderer rotators code to put the code in common --- drivers/rotator/CMakeLists.txt | 3 + drivers/rotator/wanderer_rotator_base.cpp | 403 +++++++++++++++++++ drivers/rotator/wanderer_rotator_base.h | 77 ++++ drivers/rotator/wanderer_rotator_lite.cpp | 382 +----------------- drivers/rotator/wanderer_rotator_lite.h | 55 +-- drivers/rotator/wanderer_rotator_lite_v2.cpp | 380 +---------------- drivers/rotator/wanderer_rotator_lite_v2.h | 55 +-- drivers/rotator/wanderer_rotator_mini.cpp | 369 +---------------- drivers/rotator/wanderer_rotator_mini.h | 55 +-- 9 files changed, 531 insertions(+), 1248 deletions(-) create mode 100644 drivers/rotator/wanderer_rotator_base.cpp create mode 100644 drivers/rotator/wanderer_rotator_base.h diff --git a/drivers/rotator/CMakeLists.txt b/drivers/rotator/CMakeLists.txt index f9e2bc0710..ee4aaec92b 100644 --- a/drivers/rotator/CMakeLists.txt +++ b/drivers/rotator/CMakeLists.txt @@ -64,6 +64,7 @@ install(TARGETS indi_falconv2_rotator RUNTIME DESTINATION bin) # ############### Wanderer Rotator Lite ################ SET(WandererRotatorLite_SRC + wanderer_rotator_base.cpp wanderer_rotator_lite.cpp) add_executable(indi_wanderer_lite_rotator ${WandererRotatorLite_SRC}) @@ -72,6 +73,7 @@ install(TARGETS indi_wanderer_lite_rotator RUNTIME DESTINATION bin) # ############### Wanderer Rotator Mini ################ SET(WandererRotatorMini_SRC + wanderer_rotator_base.cpp wanderer_rotator_mini.cpp) add_executable(indi_wanderer_rotator_mini ${WandererRotatorMini_SRC}) @@ -80,6 +82,7 @@ install(TARGETS indi_wanderer_rotator_mini RUNTIME DESTINATION bin) # ############### Wanderer Rotator Lite V2 ################ SET(WandererRotatorLiteV2_SRC + wanderer_rotator_base.cpp wanderer_rotator_lite_v2.cpp) add_executable(indi_wanderer_rotator_lite_v2 ${WandererRotatorLiteV2_SRC}) diff --git a/drivers/rotator/wanderer_rotator_base.cpp b/drivers/rotator/wanderer_rotator_base.cpp new file mode 100644 index 0000000000..fad619fe87 --- /dev/null +++ b/drivers/rotator/wanderer_rotator_base.cpp @@ -0,0 +1,403 @@ +/******************************************************************************* + Copyright(c) 2025 Frank Wang & Jérémie Klein. All rights reserved. + + WandererRotator Lite V1 + + 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_base.h" +#include "indicom.h" +#include "connectionplugins/connectionserial.h" +#include +#include +#include +#include +#include +#include +#include +#include + + + +WandererRotatorBase::WandererRotatorBase() +{ + setVersion(1, 0); + +} +bool WandererRotatorBase::initProperties() +{ + + INDI::Rotator::initProperties(); + + SetCapability(ROTATOR_CAN_REVERSE | ROTATOR_CAN_ABORT | ROTATOR_CAN_HOME); + + 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); + + // BACKLASH + BacklashNP[BACKLASH].fill( "BACKLASH", "Degree", "%.2f", 0, 3, 0.1, 0); + BacklashNP.fill(getDeviceName(), "BACKLASH", "Backlash", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); + + serialConnection->setDefaultBaudRate(Connection::Serial::B_19200); + + + return true; +} + +bool WandererRotatorBase::updateProperties() +{ + INDI::Rotator::updateProperties(); + + if (isConnected()) + { + defineProperty(SetZeroSP); + defineProperty(BacklashNP); + } + else + { + deleteProperty(SetZeroSP); + deleteProperty(BacklashNP); + } + return true; +} + +bool WandererRotatorBase::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); +} + +bool WandererRotatorBase::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n) +{ + if (dev && !strcmp(dev, getDeviceName())) + { + // backlash + if (BacklashNP.isNameMatch(name)) + { + bool rc1 = false; + BacklashNP.update(values, names, n); + backlash=BacklashNP[BACKLASH].value; + + char cmd[16]; + snprintf(cmd, 16, "%d", (int)(backlash*10+1600000)); + rc1=sendCommand(cmd); + + BacklashNP.setState( (rc1) ? IPS_OK : IPS_ALERT); + if (BacklashNP.getState() == IPS_OK) + BacklashNP.update(values, names, n); + BacklashNP.apply(); + LOG_INFO("Backlash Set"); + return true; + } + + } + return Rotator::ISNewNumber(dev, name, values, names, n); +} + +bool WandererRotatorBase::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, getRotatorHandshakeName())!=0) + { + LOGF_ERROR("The device is not %s", getDefaultName()); + 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); + if(firmware400000) + { + 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); + //backlash///////////////////////////////////////////////////////////////////// + char M_backlash[64] = {0}; + int nbytes_read_M_backlash= 0; + tty_read_section(PortFD, M_backlash, 'A', 5, &nbytes_read_M_backlash); + M_backlash[nbytes_read_M_angle - 1] = '\0'; + M_backlashread = std::strtod(M_backlash,NULL); + + BacklashNP[BACKLASH].setValue(M_backlashread); + BacklashNP.setState(IPS_OK); + BacklashNP.apply(); + //reverse///////////////////////////////////////////////////////////////////// + char M_reverse[64] = {0}; + int nbytes_read_M_reverse= 0; + tty_read_section(PortFD, M_reverse, 'A', 5, &nbytes_read_M_reverse); + M_reverse[nbytes_read_M_angle - 1] = '\0'; + M_reverseread = std::strtod(M_reverse,NULL); + if(M_reverseread==0) + { + ReverseRotator(false); + } + else + { + ReverseRotator(true); + } + + tcflush(PortFD, TCIOFLUSH); + return true; +} + + +IPState WandererRotatorBase::MoveRotator(double angle) +{ + angle = angle - GotoRotatorN[0].value; + + char cmd[16]; + int position = (int)(angle * getStepsPerDegree()+1000000); + positionhistory = angle; + snprintf(cmd, 16, "%d", position); + Move(cmd); + + return IPS_BUSY; +} + + +bool WandererRotatorBase::AbortRotator() +{ + + + if (GotoRotatorNP.s == IPS_BUSY) + { + 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 WandererRotatorBase::HomeRotator +/// \return +/// +IPState WandererRotatorBase::HomeRotator() +{ + if(GotoRotatorN[0].value!=0) + { + double angle = -1 * GotoRotatorN[0].value; + positionhistory = angle; + char cmd[16]; + int position = (int)(angle * getStepsPerDegree()+1000000); + snprintf(cmd, 16, "%d", position); + GotoRotatorNP.s = IPS_BUSY; + Move(cmd); + LOG_INFO("Moving to zero..."); + } + return IPS_OK; +} + + +bool WandererRotatorBase::ReverseRotator(bool enabled) +{ + + if (enabled) + { + char cmd[16]; + snprintf(cmd, 16, "%d", 1700001); + if (sendCommand(cmd)!= true) + { + LOG_ERROR("Serial write error."); + return false; + } + ReverseState = true; + return true; + } + else + { + char cmd[16]; + snprintf(cmd, 16, "%d", 1700000); + if (sendCommand(cmd)!= true) + { + LOG_ERROR("Serial write error."); + return false; + } + ReverseState = false; + return true; + } + return false; +} + + + +void WandererRotatorBase::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)-1000000)/getStepsPerDegree()*240); + return true; +} + + +bool WandererRotatorBase::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; +} + + diff --git a/drivers/rotator/wanderer_rotator_base.h b/drivers/rotator/wanderer_rotator_base.h new file mode 100644 index 0000000000..a3c84322f4 --- /dev/null +++ b/drivers/rotator/wanderer_rotator_base.h @@ -0,0 +1,77 @@ +/******************************************************************************* + Copyright(c) 2025 Frank Wang & Jérémie Klein. All rights reserved. + + WandererRotator Base + + 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 WandererRotatorBase : public INDI::Rotator +{ +public: + WandererRotatorBase(); + + bool initProperties() override; + bool updateProperties() override; + bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; + bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override; + +protected: + virtual const char * getDefaultName() override = 0; + virtual const char * getRotatorHandshakeName() = 0; + virtual int getMinimumCompatibleFirmwareVersion() = 0; + virtual int getStepsPerDegree() = 0; + + IPState MoveRotator(double angle) override; + IPState HomeRotator() override; + bool ReverseRotator(bool enabled) override; + bool AbortRotator() override; + void TimerHit() override; + + bool Handshake() override; + bool sendCommand(std::string command); + bool Move(const char *cmd); + + INDI::PropertySwitch SetZeroSP{1}; + INDI::PropertyNumber BacklashNP{1}; + + int firmware = 0; + double M_angleread = 0; + double M_backlashread = 0; + double M_reverseread = 0; + double initangle = 0; + bool haltcommand = false; + bool ReverseState = false; + double backlash = 0.5; + double positionhistory = 0; + int estime = 0; + int nowtime = 0; + + enum + { + BACKLASH, + }; +}; diff --git a/drivers/rotator/wanderer_rotator_lite.cpp b/drivers/rotator/wanderer_rotator_lite.cpp index 76d67b80f0..5a4ef740d9 100644 --- a/drivers/rotator/wanderer_rotator_lite.cpp +++ b/drivers/rotator/wanderer_rotator_lite.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - Copyright(c) 2024 Frank Wang. All rights reserved. + Copyright(c) 2025 Frank Wang & Jérémie Klein. All rights reserved. WandererRotator Lite V1 @@ -23,390 +23,26 @@ *******************************************************************************/ #include "wanderer_rotator_lite.h" -#include "indicom.h" -#include "connectionplugins/connectionserial.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#define STEPS_PER_DEGREE 1155 - // We declare an auto pointer to WandererRotatorLiteV1. static std::unique_ptr wandererrotatorlitev1(new WandererRotatorLiteV1()); -WandererRotatorLiteV1::WandererRotatorLiteV1() -{ +WandererRotatorLiteV1::WandererRotatorLiteV1(){ setVersion(1, 0); - -} -bool WandererRotatorLiteV1::initProperties() -{ - - INDI::Rotator::initProperties(); - - SetCapability(ROTATOR_CAN_REVERSE | ROTATOR_CAN_ABORT | ROTATOR_CAN_HOME); - - 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); - - // BACKLASH - BacklashNP[BACKLASH].fill( "BACKLASH", "Degree", "%.2f", 0, 3, 0.1, 0); - BacklashNP.fill(getDeviceName(), "BACKLASH", "Backlash", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); - - serialConnection->setDefaultBaudRate(Connection::Serial::B_19200); - - - return true; -} - -bool WandererRotatorLiteV1::updateProperties() -{ - INDI::Rotator::updateProperties(); - - if (isConnected()) - { - defineProperty(SetZeroSP); - defineProperty(BacklashNP); - } - else - { - deleteProperty(SetZeroSP); - deleteProperty(BacklashNP); - } - return true; -} - -bool WandererRotatorLiteV1::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); -} - -bool WandererRotatorLiteV1::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n) -{ - if (dev && !strcmp(dev, getDeviceName())) - { - // backlash - if (BacklashNP.isNameMatch(name)) - { - bool rc1 = false; - BacklashNP.update(values, names, n); - backlash=BacklashNP[BACKLASH].value; - - char cmd[16]; - snprintf(cmd, 16, "%d", (int)(backlash*10+1600000)); - rc1=sendCommand(cmd); - - BacklashNP.setState( (rc1) ? IPS_OK : IPS_ALERT); - if (BacklashNP.getState() == IPS_OK) - BacklashNP.update(values, names, n); - BacklashNP.apply(); - LOG_INFO("Backlash Set"); - return true; - } - - } - return Rotator::ISNewNumber(dev, name, values, names, n); } -const char *WandererRotatorLiteV1::getDefaultName() -{ +const char *WandererRotatorLiteV1::getDefaultName(){ return "WandererRotator Lite V1"; } -bool WandererRotatorLiteV1::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, "WandererRotatorLite")!=0) - { - LOG_ERROR("The device is not WandererRotator Lite V1!"); - 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); - if(firmware<20240403) - { - LOG_ERROR("The firmware is outdated, please upgrade to the latest firmware!"); - LOGF_ERROR("The current firmware is %s.", firmware); - return false; - } - - // 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); - //backlash///////////////////////////////////////////////////////////////////// - char M_backlash[64] = {0}; - int nbytes_read_M_backlash= 0; - tty_read_section(PortFD, M_backlash, 'A', 5, &nbytes_read_M_backlash); - M_backlash[nbytes_read_M_angle - 1] = '\0'; - M_backlashread = std::strtod(M_backlash,NULL); - - BacklashNP[BACKLASH].setValue(M_backlashread); - BacklashNP.setState(IPS_OK); - BacklashNP.apply(); - //reverse///////////////////////////////////////////////////////////////////// - char M_reverse[64] = {0}; - int nbytes_read_M_reverse= 0; - tty_read_section(PortFD, M_reverse, 'A', 5, &nbytes_read_M_reverse); - M_reverse[nbytes_read_M_angle - 1] = '\0'; - M_reverseread = std::strtod(M_reverse,NULL); - if(M_reverseread==0) - { - ReverseRotator(false); - } - else - { - ReverseRotator(true); - } - - tcflush(PortFD, TCIOFLUSH); - return true; +const char *WandererRotatorLiteV1::getRotatorHandshakeName() { + return "WandererRotatorLite"; } - -IPState WandererRotatorLiteV1::MoveRotator(double angle) -{ - angle = angle - GotoRotatorN[0].value; - - char cmd[16]; - int position = (int)(angle * STEPS_PER_DEGREE+1000000); - positionhistory = angle; - snprintf(cmd, 16, "%d", position); - Move(cmd); - - return IPS_BUSY; -} - - -bool WandererRotatorLiteV1::AbortRotator() -{ - - - if (GotoRotatorNP.s == IPS_BUSY) - { - 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; +int WandererRotatorLiteV1::getMinimumCompatibleFirmwareVersion() { + return 20240403; } -////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLiteV1::HomeRotator -/// \return -/// -IPState WandererRotatorLiteV1::HomeRotator() -{ - if(GotoRotatorN[0].value!=0) - { - double angle = -1 * GotoRotatorN[0].value; - positionhistory = angle; - char cmd[16]; - int position = (int)(angle * STEPS_PER_DEGREE+1000000); - snprintf(cmd, 16, "%d", position); - GotoRotatorNP.s = IPS_BUSY; - Move(cmd); - LOG_INFO("Moving to zero..."); - } - return IPS_OK; +int WandererRotatorLiteV1::getStepsPerDegree() { + return 1155; } - - -bool WandererRotatorLiteV1::ReverseRotator(bool enabled) -{ - - if (enabled) - { - char cmd[16]; - snprintf(cmd, 16, "%d", 1700001); - if (sendCommand(cmd)!= true) - { - LOG_ERROR("Serial write error."); - return false; - } - ReverseState = true; - return true; - } - else - { - char cmd[16]; - snprintf(cmd, 16, "%d", 1700000); - if (sendCommand(cmd)!= true) - { - LOG_ERROR("Serial write error."); - return false; - } - ReverseState = false; - return true; - } - return false; -} - - - -void WandererRotatorLiteV1::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)-1000000)/STEPS_PER_DEGREE*240); - return true; -} - - -bool WandererRotatorLiteV1::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; -} - - diff --git a/drivers/rotator/wanderer_rotator_lite.h b/drivers/rotator/wanderer_rotator_lite.h index 480f0f3a7d..74fb945274 100644 --- a/drivers/rotator/wanderer_rotator_lite.h +++ b/drivers/rotator/wanderer_rotator_lite.h @@ -1,5 +1,5 @@ /******************************************************************************* - Copyright(c) 2024 Frank Wang. All rights reserved. + Copyright(c) 2025 Frank Wang & Jérémie Klein. All rights reserved. WandererRotator Lite V1 @@ -24,57 +24,16 @@ #pragma once -#include "defaultdevice.h" -#include "indirotator.h" -#include "indirotatorinterface.h" -#include "indipropertyswitch.h" -class WandererRotatorLiteV1 : public INDI::Rotator +#include "wanderer_rotator_base.h" + +class WandererRotatorLiteV1 : public WandererRotatorBase { public: WandererRotatorLiteV1(); - virtual bool initProperties() override; - virtual bool updateProperties() override; - virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; - virtual bool ISNewNumber(const char *dev, const char *name, double values[], 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; - - - - - -private: - int firmware=0; - double M_angleread=0; - double M_backlashread=0; - double M_reverseread=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; - double backlash=0.5; - double positionhistory=0; - int estime=0; - int nowtime=0; - - INDI::PropertyNumber BacklashNP{1}; - enum - { - BACKLASH, - }; - + const char * getRotatorHandshakeName() override; + int getMinimumCompatibleFirmwareVersion() override; + int getStepsPerDegree() override; }; \ No newline at end of file diff --git a/drivers/rotator/wanderer_rotator_lite_v2.cpp b/drivers/rotator/wanderer_rotator_lite_v2.cpp index 649f2fb152..9f3448fdfe 100644 --- a/drivers/rotator/wanderer_rotator_lite_v2.cpp +++ b/drivers/rotator/wanderer_rotator_lite_v2.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - Copyright(c) 2024 Frank Wang. All rights reserved. + Copyright(c) 2025 Frank Wang & Jérémie Klein. All rights reserved. WandererRotator Lite V2 @@ -23,388 +23,26 @@ *******************************************************************************/ #include "wanderer_rotator_lite_v2.h" -#include "indicom.h" -#include "connectionplugins/connectionserial.h" -#include -#include -#include -#include -#include -#include -#include -#include - // We declare an auto pointer to WandererRotatorLiteV2. static std::unique_ptr wandererrotatorlitev2(new WandererRotatorLiteV2()); -WandererRotatorLiteV2::WandererRotatorLiteV2() -{ +WandererRotatorLiteV2::WandererRotatorLiteV2(){ setVersion(1, 0); - -} -bool WandererRotatorLiteV2::initProperties() -{ - - INDI::Rotator::initProperties(); - - SetCapability(ROTATOR_CAN_REVERSE | ROTATOR_CAN_ABORT | ROTATOR_CAN_HOME); - - 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); - - // BACKLASH - BacklashNP[BACKLASH].fill( "BACKLASH", "Degree", "%.2f", 0, 3, 0.1, 0); - BacklashNP.fill(getDeviceName(), "BACKLASH", "Backlash", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); - - serialConnection->setDefaultBaudRate(Connection::Serial::B_19200); - - - return true; -} - -bool WandererRotatorLiteV2::updateProperties() -{ - INDI::Rotator::updateProperties(); - - if (isConnected()) - { - defineProperty(SetZeroSP); - defineProperty(BacklashNP); - } - else - { - deleteProperty(SetZeroSP); - deleteProperty(BacklashNP); - } - return true; -} - -bool WandererRotatorLiteV2::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); -} - -bool WandererRotatorLiteV2::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n) -{ - if (dev && !strcmp(dev, getDeviceName())) - { - // backlash - if (BacklashNP.isNameMatch(name)) - { - bool rc1 = false; - BacklashNP.update(values, names, n); - backlash=BacklashNP[BACKLASH].value; - - char cmd[16]; - snprintf(cmd, 16, "%d", (int)(backlash*10+1600000)); - rc1=sendCommand(cmd); - - BacklashNP.setState( (rc1) ? IPS_OK : IPS_ALERT); - if (BacklashNP.getState() == IPS_OK) - BacklashNP.update(values, names, n); - BacklashNP.apply(); - LOG_INFO("Backlash Set"); - return true; - } - - } - return Rotator::ISNewNumber(dev, name, values, names, n); } -const char *WandererRotatorLiteV2::getDefaultName() -{ +const char *WandererRotatorLiteV2::getDefaultName(){ return "WandererRotator Lite V2"; } -bool WandererRotatorLiteV2::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, "WandererRotatorLiteV2")!=0) - { - LOGF_ERROR("The device is not WandererRotator Lite V2!","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); - if(firmware<20240226) - { - LOG_ERROR("The firmware is outdated, please upgrade to the latest firmware!"); - return false; - } - - // 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); - //backlash///////////////////////////////////////////////////////////////////// - char M_backlash[64] = {0}; - int nbytes_read_M_backlash= 0; - tty_read_section(PortFD, M_backlash, 'A', 5, &nbytes_read_M_backlash); - M_backlash[nbytes_read_M_angle - 1] = '\0'; - M_backlashread = std::strtod(M_backlash,NULL); - - BacklashNP[BACKLASH].setValue(M_backlashread); - BacklashNP.setState(IPS_OK); - BacklashNP.apply(); - //reverse///////////////////////////////////////////////////////////////////// - char M_reverse[64] = {0}; - int nbytes_read_M_reverse= 0; - tty_read_section(PortFD, M_reverse, 'A', 5, &nbytes_read_M_reverse); - M_reverse[nbytes_read_M_angle - 1] = '\0'; - M_reverseread = std::strtod(M_reverse,NULL); - if(M_reverseread==0) - { - ReverseRotator(false); - } - else - { - ReverseRotator(true); - } - - tcflush(PortFD, TCIOFLUSH); - return true; +const char *WandererRotatorLiteV2::getRotatorHandshakeName() { + return "WandererRotatorLiteV2"; } - -IPState WandererRotatorLiteV2::MoveRotator(double angle) -{ - angle = angle - GotoRotatorN[0].value; - - char cmd[16]; - int position = (int)(angle * 1199+1000000); - positionhistory = angle; - snprintf(cmd, 16, "%d", position); - Move(cmd); - - return IPS_BUSY; -} - - -bool WandererRotatorLiteV2::AbortRotator() -{ - - - if (GotoRotatorNP.s == IPS_BUSY) - { - 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; +int WandererRotatorLiteV2::getMinimumCompatibleFirmwareVersion() { + return 20240226; } -////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorLiteV2::HomeRotator -/// \return -/// -IPState WandererRotatorLiteV2::HomeRotator() -{ - if(GotoRotatorN[0].value!=0) - { - double angle = -1 * GotoRotatorN[0].value; - positionhistory = angle; - - char cmd[16]; - int position = (int)(angle * 1199+1000000); - snprintf(cmd, 16, "%d", position); - GotoRotatorNP.s = IPS_BUSY; - Move(cmd); - LOG_INFO("Moving to zero..."); - } - return IPS_OK; +int WandererRotatorLiteV2::getStepsPerDegree() { + return 1199; } - - -bool WandererRotatorLiteV2::ReverseRotator(bool enabled) -{ - - if (enabled) - { - char cmd[16]; - snprintf(cmd, 16, "%d", 1700001); - if (sendCommand(cmd)!= true) - { - LOG_ERROR("Serial write error."); - return false; - } - ReverseState = true; - return true; - } - else - { - char cmd[16]; - snprintf(cmd, 16, "%d", 1700000); - if (sendCommand(cmd)!= true) - { - LOG_ERROR("Serial write error."); - return false; - } - ReverseState = false; - return true; - } - return false; -} - - - -void WandererRotatorLiteV2::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)-1000000)/1199*240); - return true; -} - - -bool WandererRotatorLiteV2::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; -} - - diff --git a/drivers/rotator/wanderer_rotator_lite_v2.h b/drivers/rotator/wanderer_rotator_lite_v2.h index f2c16279eb..2c49d7b1ea 100644 --- a/drivers/rotator/wanderer_rotator_lite_v2.h +++ b/drivers/rotator/wanderer_rotator_lite_v2.h @@ -1,5 +1,5 @@ /******************************************************************************* - Copyright(c) 2024 Frank Wang. All rights reserved. + Copyright(c) 2025 Frank Wang & Jérémie Klein. All rights reserved. WandererRotator Lite V2 @@ -24,59 +24,18 @@ #pragma once -#include "defaultdevice.h" -#include "indirotator.h" -#include "indirotatorinterface.h" -#include "indipropertyswitch.h" -class WandererRotatorLiteV2 : public INDI::Rotator +#include "wanderer_rotator_base.h" + +class WandererRotatorLiteV2 : public WandererRotatorBase { public: WandererRotatorLiteV2(); - virtual bool initProperties() override; - virtual bool updateProperties() override; - virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; - virtual bool ISNewNumber(const char *dev, const char *name, double values[], 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; - - - - - -private: - int firmware=0; - double M_angleread=0; - double M_backlashread=0; - double M_reverseread=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; - double backlash=0.5; - double positionhistory=0; - int estime=0; - int nowtime=0; - - INDI::PropertyNumber BacklashNP{1}; - enum - { - BACKLASH, - }; - + const char * getRotatorHandshakeName() override; + int getMinimumCompatibleFirmwareVersion() override; + int getStepsPerDegree() override; }; diff --git a/drivers/rotator/wanderer_rotator_mini.cpp b/drivers/rotator/wanderer_rotator_mini.cpp index 81d7f5ad87..23116763e3 100644 --- a/drivers/rotator/wanderer_rotator_mini.cpp +++ b/drivers/rotator/wanderer_rotator_mini.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - Copyright(c) 2024 Frank Wang. All rights reserved. + Copyright(c) 2025 Frank Wang & Jérémie Klein. All rights reserved. WandererRotator Mini V1/V2 @@ -38,373 +38,22 @@ // We declare an auto pointer to WandererRotatorMini. static std::unique_ptr wandererrotatormini(new WandererRotatorMini()); -WandererRotatorMini::WandererRotatorMini() -{ +WandererRotatorMini::WandererRotatorMini(){ setVersion(1, 1); - -} -bool WandererRotatorMini::initProperties() -{ - - INDI::Rotator::initProperties(); - - SetCapability(ROTATOR_CAN_REVERSE | ROTATOR_CAN_ABORT | ROTATOR_CAN_HOME); - - 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); - - // BACKLASH - BacklashNP[BACKLASH].fill( "BACKLASH", "Degree", "%.2f", 0, 3, 0.1, 0); - BacklashNP.fill(getDeviceName(), "BACKLASH", "Backlash", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); - - serialConnection->setDefaultBaudRate(Connection::Serial::B_19200); - - - return true; -} - -bool WandererRotatorMini::updateProperties() -{ - INDI::Rotator::updateProperties(); - - if (isConnected()) - { - defineProperty(SetZeroSP); - defineProperty(BacklashNP); - } - else - { - deleteProperty(SetZeroSP); - deleteProperty(BacklashNP); - } - 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); } -bool WandererRotatorMini::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n) -{ - if (dev && !strcmp(dev, getDeviceName())) - { - // backlash - if (BacklashNP.isNameMatch(name)) - { - bool rc1 = false; - BacklashNP.update(values, names, n); - backlash=BacklashNP[BACKLASH].value; - - char cmd[16]; - snprintf(cmd, 16, "%d", (int)(backlash*10+1600000)); - rc1=sendCommand(cmd); - - BacklashNP.setState( (rc1) ? IPS_OK : IPS_ALERT); - if (BacklashNP.getState() == IPS_OK) - BacklashNP.update(values, names, n); - BacklashNP.apply(); - LOG_INFO("Backlash Set"); - return true; - } - - } - return Rotator::ISNewNumber(dev, name, values, names, n); -} - -const char *WandererRotatorMini::getDefaultName() -{ +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); - if(firmware<20240226) - { - LOG_ERROR("The firmware is outdated, please upgrade to the latest firmware!"); - return false; - } - - // 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); - //backlash///////////////////////////////////////////////////////////////////// - char M_backlash[64] = {0}; - int nbytes_read_M_backlash= 0; - tty_read_section(PortFD, M_backlash, 'A', 5, &nbytes_read_M_backlash); - M_backlash[nbytes_read_M_angle - 1] = '\0'; - M_backlashread = std::strtod(M_backlash,NULL); - - BacklashNP[BACKLASH].setValue(M_backlashread); - BacklashNP.setState(IPS_OK); - BacklashNP.apply(); - //reverse///////////////////////////////////////////////////////////////////// - char M_reverse[64] = {0}; - int nbytes_read_M_reverse= 0; - tty_read_section(PortFD, M_reverse, 'A', 5, &nbytes_read_M_reverse); - M_reverse[nbytes_read_M_angle - 1] = '\0'; - M_reverseread = std::strtod(M_reverse,NULL); - if(M_reverseread==0) - { - ReverseRotator(false); - } - else - { - ReverseRotator(true); - } - - tcflush(PortFD, TCIOFLUSH); - return true; -} - - -IPState WandererRotatorMini::MoveRotator(double angle) -{ - angle = angle - GotoRotatorN[0].value; - positionhistory = angle; - - char cmd[16]; - int position = (int)(angle * 1142+1000000); - positionhistory = angle; - snprintf(cmd, 16, "%d", position); - Move(cmd); - - return IPS_BUSY; +const char *WandererRotatorMini::getRotatorHandshakeName() { + return "WandererRotatorMini"; } - -bool WandererRotatorMini::AbortRotator() -{ - - - if (GotoRotatorNP.s == IPS_BUSY) - { - 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; +int WandererRotatorMini::getMinimumCompatibleFirmwareVersion() { + return 20240226; } -////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief WandererRotatorMini::HomeRotator -/// \return -/// -IPState WandererRotatorMini::HomeRotator() -{ - if(GotoRotatorN[0].value!=0) - { - double angle = -1 * GotoRotatorN[0].value; - - char cmd[16]; - int position = (int)(angle * 1142+1000000); - snprintf(cmd, 16, "%d", position); - GotoRotatorNP.s = IPS_BUSY; - Move(cmd); - LOG_INFO("Moving to zero..."); - } - return IPS_OK; +int WandererRotatorMini::getStepsPerDegree() { + return 1142; } - - -bool WandererRotatorMini::ReverseRotator(bool enabled) -{ - - if (enabled) - { - char cmd[16]; - snprintf(cmd, 16, "%d", 1700001); - if (sendCommand(cmd)!= true) - { - LOG_ERROR("Serial write error."); - return false; - } - ReverseState = true; - return true; - } - else - { - char cmd[16]; - snprintf(cmd, 16, "%d", 1700000); - if (sendCommand(cmd)!= true) - { - LOG_ERROR("Serial write error."); - return false; - } - 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)-1000000)/1142*220); - 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; -} - - diff --git a/drivers/rotator/wanderer_rotator_mini.h b/drivers/rotator/wanderer_rotator_mini.h index eb2c34bea1..03adbab792 100644 --- a/drivers/rotator/wanderer_rotator_mini.h +++ b/drivers/rotator/wanderer_rotator_mini.h @@ -1,5 +1,5 @@ /******************************************************************************* - Copyright(c) 2024 Frank Wang. All rights reserved. + Copyright(c) 2025 Frank Wang & Jérémie Klein. All rights reserved. WandererRotator Mini V1/V2 @@ -24,59 +24,18 @@ #pragma once -#include "defaultdevice.h" -#include "indirotator.h" -#include "indirotatorinterface.h" -#include "indipropertyswitch.h" -class WandererRotatorMini : public INDI::Rotator +#include "wanderer_rotator_base.h" + +class WandererRotatorMini : public WandererRotatorBase { 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; - virtual bool ISNewNumber(const char *dev, const char *name, double values[], 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; - - - - - -private: - int firmware=0; - double M_angleread=0; - double M_backlashread=0; - double M_reverseread=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; - double backlash=0.5; - double positionhistory=0; - int estime=0; - int nowtime=0; - - INDI::PropertyNumber BacklashNP{1}; - enum - { - BACKLASH, - }; - + const char * getRotatorHandshakeName() override; + int getMinimumCompatibleFirmwareVersion() override; + int getStepsPerDegree() override; };