37static std::unique_ptr<SestoSenso2> sesto(
new SestoSenso2());
39static const char *MOTOR_TAB =
"Motor";
51 m_MotionProgressTimer.
callOnTimeout(std::bind(&SestoSenso2::checkMotionProgressCallback,
this));
68 setConnectionParams();
71 FirmwareTP[FIRMWARE_SN].
fill(
"SERIALNUMBER",
"Serial Number",
"");
72 FirmwareTP[FIRMWARE_VERSION].
fill(
"VERSION",
"Version",
"");
76 VoltageInNP[0].
fill(
"VOLTAGEIN",
"Volts",
"%.2f", 0, 100, 0., 0.);
80 TemperatureNP[TEMPERATURE_MOTOR].
fill(
"TEMPERATURE",
"Motor (c)",
"%.2f", -50, 70., 0., 0.);
81 TemperatureNP[TEMPERATURE_EXTERNAL].
fill(
"TEMPERATURE_ETX",
"External (c)",
"%.2f", -50, 70., 0., 0.);
85 CalibrationMessageTP[0].
fill(
"CALIBRATION",
"Calibration stage",
"Press START to begin the Calibration.");
89 CalibrationSP[CALIBRATION_START].
fill(
"CALIBRATION_START",
"Start",
ISS_OFF);
90 CalibrationSP[CALIBRATION_NEXT].
fill(
"CALIBRATION_NEXT",
"Next",
ISS_OFF);
94 FastMoveSP[FASTMOVE_IN].
fill(
"FASTMOVE_IN",
"Move In",
ISS_OFF);
95 FastMoveSP[FASTMOVE_OUT].
fill(
"FASTMOVE_OUT",
"Move out",
ISS_OFF);
96 FastMoveSP[FASTMOVE_STOP].
fill(
"FASTMOVE_STOP",
"Stop",
ISS_OFF);
100 MotorHoldSP[MOTOR_HOLD_ON].
fill(
"HOLD_ON",
"Hold On",
ISS_OFF);
101 MotorHoldSP[MOTOR_HOLD_OFF].
fill(
"HOLD_OFF",
"Hold Off",
ISS_OFF);
110 MotorRateNP[MOTOR_RATE_ACC].
fill(
"ACC",
"Acceleration",
"%.f", 1, 10, 1, 1);
111 MotorRateNP[MOTOR_RATE_RUN].
fill(
"RUN",
"Run Speed",
"%.f", 1, 10, 1, 2);
112 MotorRateNP[MOTOR_RATE_DEC].
fill(
"DEC",
"Deceleration",
"%.f", 1, 10, 1, 1);
116 MotorCurrentNP[MOTOR_CURR_ACC].
fill(
"CURR_ACC",
"Acceleration",
"%.f", 1, 10, 1, 7);
117 MotorCurrentNP[MOTOR_CURR_RUN].
fill(
"CURR_RUN",
"Run",
"%.f", 1, 10, 1, 7);
118 MotorCurrentNP[MOTOR_CURR_DEC].
fill(
"CURR_DEC",
"Deceleration",
"%.f", 1, 10, 1, 7);
119 MotorCurrentNP[MOTOR_CURR_HOLD].
fill(
"CURR_HOLD",
"Hold",
"%.f", 0, 5, 1, 3);
123 MotorApplyPresetSP[MOTOR_APPLY_LIGHT].
fill(
"MOTOR_APPLY_LIGHT",
"Light",
ISS_OFF);
124 MotorApplyPresetSP[MOTOR_APPLY_MEDIUM].
fill(
"MOTOR_APPLY_MEDIUM",
"Medium",
ISS_OFF);
125 MotorApplyPresetSP[MOTOR_APPLY_HEAVY].
fill(
"MOTOR_APPLY_HEAVY",
"Heavy",
ISS_OFF);
129 MotorApplyUserPresetSP[MOTOR_APPLY_USER1].
fill(
"MOTOR_APPLY_USER1",
"User 1",
ISS_OFF);
130 MotorApplyUserPresetSP[MOTOR_APPLY_USER2].
fill(
"MOTOR_APPLY_USER2",
"User 2",
ISS_OFF);
131 MotorApplyUserPresetSP[MOTOR_APPLY_USER3].
fill(
"MOTOR_APPLY_USER3",
"User 3",
ISS_OFF);
136 MotorSaveUserPresetSP[MOTOR_SAVE_USER1].
fill(
"MOTOR_SAVE_USER1",
"User 1",
ISS_OFF);
137 MotorSaveUserPresetSP[MOTOR_SAVE_USER2].
fill(
"MOTOR_SAVE_USER2",
"User 2",
ISS_OFF);
138 MotorSaveUserPresetSP[MOTOR_SAVE_USER3].
fill(
"MOTOR_SAVE_USER3",
"User 3",
ISS_OFF);
188 if (updateTemperature())
191 if (updateVoltageIn())
194 if (getStartupValues())
195 LOG_INFO(
"Parameters updated, focuser ready for use.");
197 LOG_WARN(
"Failed to inquire parameters. Check logs.");
229 LOG_INFO(
"Error retrieving data from device, please ensure focuser is powered and the port is correct.");
238 return m_SestoSenso2->setBacklash(steps);
246 return "Sesto Senso 2";
252bool SestoSenso2::updateTemperature()
258 else if ( m_SestoSenso2->getMotorTemp(
temperature) ==
false)
264 TemperatureNP[TEMPERATURE_MOTOR].setValue(
temperature);
271 TemperatureNP[TEMPERATURE_EXTERNAL].setValue(
temperature);
273 TemperatureNP[TEMPERATURE_EXTERNAL].setValue(-273.15);
282bool SestoSenso2::updateMaxLimit()
284 uint32_t maxLimit = 0;
289 if (m_SestoSenso2->getMaxPosition(maxLimit) ==
false)
321bool SestoSenso2::updatePosition()
326 else if (m_SestoSenso2->getAbsolutePosition(steps) ==
false)
336bool SestoSenso2::updateVoltageIn()
338 double voltageIn = 0;
342 else if (m_SestoSenso2->getVoltage12v(voltageIn) ==
false)
348 VoltageInNP[0].setValue(voltageIn);
357bool SestoSenso2::fetchMotorSettings()
362 bool motorHoldActive =
false;
376 if (!m_SestoSenso2->getMotorSettings(ms, mc, motorHoldActive))
385 MotorRateNP[MOTOR_RATE_ACC].setValue(ms.
accRate);
386 MotorRateNP[MOTOR_RATE_RUN].setValue(ms.
runSpeed);
387 MotorRateNP[MOTOR_RATE_DEC].setValue(ms.
decRate);
391 MotorCurrentNP[MOTOR_CURR_ACC].setValue(mc.
accCurrent);
392 MotorCurrentNP[MOTOR_CURR_RUN].setValue(mc.
runCurrent);
393 MotorCurrentNP[MOTOR_CURR_DEC].setValue(mc.
decCurrent);
394 MotorCurrentNP[MOTOR_CURR_HOLD].setValue(mc.
holdCurrent);
396 MotorCurrentNP.
apply();
399 auto activeSwitchID = motorHoldActive ?
"HOLD_ON" :
"HOLD_OFF";
401 assert(sp !=
nullptr &&
"Motor hold switch not found");
412 LOG_WARN(
"Motor hold current set to 0, motor hold setting will have no effect");
421bool SestoSenso2::applyMotorRates()
428 mr.
accRate =
static_cast<uint32_t
>(MotorRateNP[MOTOR_RATE_ACC].getValue());
429 mr.
runSpeed =
static_cast<uint32_t
>(MotorRateNP[MOTOR_RATE_RUN].getValue());
430 mr.
decRate =
static_cast<uint32_t
>(MotorRateNP[MOTOR_RATE_DEC].getValue());
432 if (!m_SestoSenso2->setMotorRates(mr))
434 LOG_ERROR(
"Failed to apply motor rates");
445bool SestoSenso2::applyMotorCurrents()
452 mc.
accCurrent =
static_cast<uint32_t
>(MotorCurrentNP[MOTOR_CURR_ACC].getValue());
453 mc.
runCurrent =
static_cast<uint32_t
>(MotorCurrentNP[MOTOR_CURR_RUN].getValue());
454 mc.
decCurrent =
static_cast<uint32_t
>(MotorCurrentNP[MOTOR_CURR_DEC].getValue());
455 mc.
holdCurrent =
static_cast<uint32_t
>(MotorCurrentNP[MOTOR_CURR_HOLD].getValue());
457 if (!m_SestoSenso2->setMotorCurrents(mc))
459 LOG_ERROR(
"Failed to apply motor currents");
471bool SestoSenso2::isMotionComplete()
476 int32_t targPos =
static_cast<int32_t
>(targetPos);
478 if (targPos > nextPos)
480 else if (targPos < nextPos)
483 if (abs(nextPos - targPos) < 250)
485 else if (nextPos < 0)
491 return (std::abs(nextPos -
static_cast<int32_t
>(targetPos)) == 0);
494 return !m_SestoSenso2->isBusy();
507 CalibrationSP.
update(states, names, n);
510 CalibrationSP.
apply();
512 if (current_switch == CALIBRATION_START)
514 if (cStage == Idle || cStage == Complete )
519 CalibrationSP.
apply();
522 if (m_SestoSenso2->initCalibration() ==
false)
524 CalibrationMessageTP[0].setText(
"Manual Calibration: Set focus in MIN position and then press NEXT.");
525 CalibrationMessageTP.
apply();
526 fetchMotorSettings();
531 LOG_INFO(
"Already started calibration. Proceed to next step.");
532 CalibrationMessageTP[0].setText(
"Already started. Proceed to NEXT.");
533 CalibrationMessageTP.
apply();
536 else if (current_switch == CALIBRATION_NEXT)
538 if (cStage == GoToMiddle)
541 if (m_SestoSenso2->storeAsMinPosition() ==
false)
543 CalibrationMessageTP[0].setText(
"Manual Calibration: Press MOVE OUT to move focuser out (CAUTION!)");
544 CalibrationMessageTP.
apply();
547 else if (cStage == GoMinimum)
549 if (m_SestoSenso2->storeAsMaxPosition() ==
false)
551 CalibrationMessageTP[0].setText(
"Manual Calibration: Press NEXT to finish.");
552 CalibrationMessageTP.
apply();
555 else if (cStage == GoMaximum)
557 uint32_t maxLimit = 0;
559 if (m_SestoSenso2->getMaxPosition(maxLimit) ==
false)
562 LOGF_INFO(
"MAX setting is %d", maxLimit);
590 CalibrationMessageTP[0].setText(
"Calibration Completed.");
591 CalibrationMessageTP.
apply();
599 CalibrationSP.
apply();
601 CalibrationSP.
apply();
604 fetchMotorSettings();
608 CalibrationMessageTP[0].setText(
"Calibration not in progress.");
609 CalibrationMessageTP.
apply();
618 FastMoveSP.
update(states, names, n);
621 switch (current_switch)
624 if (m_SestoSenso2->fastMoveIn() ==
false)
628 if (m_SestoSenso2->goOutToFindMaxPos() ==
false)
630 CalibrationMessageTP[0].setText(
"Manual Calibration: Press STOP focuser almost at MAX position.");
631 CalibrationMessageTP.
apply();
632 fetchMotorSettings();
635 if (m_SestoSenso2->stop() ==
false)
637 CalibrationMessageTP[0].setText(
"Press NEXT to store max limit.");
638 CalibrationMessageTP.
apply();
651 MotorHoldSP.
update(states, names, n);
653 assert(sp !=
nullptr);
656 if (!strcmp(sp->name,
"HOLD_OFF"))
658 m_SestoSenso2->setMotorHold(
false);
660 LOG_INFO(
"Motor hold OFF. You may now manually adjust the focuser. Remember to enable motor hold once done.");
664 m_SestoSenso2->setMotorHold(
true);
666 LOG_INFO(
"Motor hold ON. Do NOT attempt to manually adjust the focuser!");
667 if (MotorCurrentNP[MOTOR_CURR_HOLD].getValue() < 2.0)
669 LOGF_WARN(
"Motor hold current set to %.1f: This may be insufficient to hold focus",
670 MotorCurrentNP[MOTOR_CURR_HOLD].getValue());
679 MotorApplyPresetSP.
update(states, names, n);
681 assert(index >= 0 && index < 3);
685 if (m_SestoSenso2->applyMotorPreset(presetName))
687 LOGF_INFO(
"Loaded motor preset: %s", presetName);
692 LOGF_ERROR(
"Failed to load motor preset: %s", presetName);
697 MotorApplyPresetSP.
apply();
699 fetchMotorSettings();
716 MotorRateNP.
update(values, names, n);
724 MotorCurrentNP.
update(values, names, n);
726 applyMotorCurrents();
727 MotorCurrentNP.
apply();
739 targetPos = targetTicks;
746 targetPos -= backlashTicks;
750 targetPos += backlashTicks;
752 if (m_SestoSenso2->goAbsolutePosition(targetPos) ==
false)
756 m_MotionProgressTimer.
start(10);
766 int relativeTicks = ((dir ==
FOCUS_INWARD) ? -ticks : ticks) * reversed;
767 double newPosition =
FocusAbsPosNP[0].getValue() + relativeTicks;
779 m_MotionProgressTimer.
stop();
784 return m_SestoSenso2->stop();
790void SestoSenso2::checkMotionProgressCallback()
794 if (isMotionComplete())
801 const char * names[2] = { CalibrationSP[CALIBRATION_START].
getName(), CalibrationSP[CALIBRATION_NEXT].
getName() };
805 LOG_INFO(
"Focuser reached requested position.");
811 m_MotionProgressTimer.
start(500);
828 bool rc = updatePosition();
838 if (m_TemperatureCounter++ == SESTO_TEMPERATURE_FREQ)
840 rc = updateTemperature();
843 if (fabs(lastTemperature - TemperatureNP[0].getValue()) >= 0.1)
845 TemperatureNP.
apply();
846 lastTemperature = TemperatureNP[0].getValue();
851 rc = updateVoltageIn();
854 if (fabs(lastVoltageIn - VoltageInNP[0].getValue()) >= 0.1)
857 lastVoltageIn = VoltageInNP[0].getValue();
859 if (VoltageInNP[0].getValue() < 11.0)
861 LOG_WARN(
"Please check 12v DC power supply is connected.");
866 m_TemperatureCounter = 0;
875bool SestoSenso2::getStartupValues()
877 bool rc = updatePosition();
883 rc &= fetchMotorSettings();
900bool SestoSenso2::Ack()
902 std::string response;
905 response =
"1.0 Simulation";
908 if(initCommandSet() ==
false)
910 LOG_ERROR(
"Failed setting attributes on serial port and init command sets");
913 if(m_SestoSenso2->getSerialNumber(response))
915 LOGF_INFO(
"Serial number: %s", response.c_str());
922 std::string modelName;
923 if (m_SestoSenso2->getModel(modelName))
925 LOGF_INFO(
"Model name: %s", modelName.c_str());
929 FirmwareTP[FIRMWARE_SN].setText(response.c_str());
931 if (m_SestoSenso2->getFirmwareVersion(response))
933 LOGF_INFO(
"Firmware version: %s", response.c_str());
934 IUSaveText(&FirmwareTP[FIRMWARE_VERSION], response.c_str());
947void SestoSenso2::setConnectionParams()
956bool SestoSenso2::initCommandSet()
963 LOG_ERROR(
"setTTYFlags: failed getting tty attributes.");
969 LOG_ERROR(
"setTTYFlags: failed setting attributes on serial port.");
980 Focuser::saveConfigItems(fp);
981 MotorRateNP.
save(fp);
982 MotorCurrentNP.
save(fp);
void setWordSize(const uint8_t &value)
setWordSize Set word size to be used in the serial connection. Default 8
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
bool isSimulation() const
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INDI::PropertyNumber FocusRelPosNP
INDI::PropertySwitch FocusReverseSP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertyNumber FocusBacklashNP
INDI::PropertyNumber FocusAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
Connection::Serial * serialConnection
INDI::PropertyNumber PresetNP
void setState(IPState state)
WidgetView< T > * findWidgetByName(const char *name) const
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
const char * getName() const
bool isNameMatch(const char *otherName) const
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
INDI::WidgetViewSwitch * findOnSwitch() const
int findOnSwitchIndex() const
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
void setSingleShot(bool singleShot)
Set whether the timer is a single-shot timer.
void callOnTimeout(const std::function< void()> &callback)
void start()
Starts or restarts the timer with the timeout specified in interval.
void stop()
Stops the timer.
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
virtual bool saveConfigItems(FILE *fp) override
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
const char * getDefaultName() override
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
const char * CONNECTION_TAB
CONNECTION_TAB Where all device connection settings (serial, usb, ethernet) are defined and controlle...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
Implementations for common driver routines.
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
#define LOGF_INFO(fmt,...)
#define LOGF_WARN(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
const char * MOTOR_PRESET_NAMES[]
struct termios tty_setting