35 static std::unique_ptr<MyFocuserPro2> myFocuserPro2(
new MyFocuserPro2());
74 BacklashInStepsN[0].min = 0;
75 BacklashInStepsN[0].max = 512;
76 BacklashInStepsN[0].value = 0;
77 BacklashInStepsN[0].step = 2;
79 BacklashOutStepsN[0].min = 0;
80 BacklashOutStepsN[0].max = 512;
81 BacklashOutStepsN[0].value = 0;
82 BacklashOutStepsN[0].step = 2;
91 IUFillNumber(&BacklashInStepsN[0],
"Steps",
"",
"%3.0f", 0, 512, 2, 0);
101 IUFillNumber(&BacklashOutStepsN[0],
"Steps",
"",
"%3.0f", 0, 512, 2, 0);
106 IUFillNumber(&TemperatureN[0],
"TEMPERATURE",
"Celsius",
"%6.2f", -40, 80., 0., 0.);
111 IUFillNumber(&TemperatureSettingN[0],
"Coefficient",
"",
"%6.2f", 0, 50, 1, 0);
177 setTemperatureCelsius();
179 LOG_INFO(
"MyFocuserPro2 parameters updated, focuser ready for use.");
203 LOG_INFO(
"MyFocuserPro2 is online. Getting focus parameters...");
211 "Error retrieving data from MyFocuserPro2, please ensure MyFocuserPro2 controller is powered and the port is correct.");
217 return "MyFocuserPro2";
220 bool MyFocuserPro2::Ack()
222 int nbytes_written = 0, nbytes_read = 0, rc = -1;
225 int firmWareVersion = 0;
227 tcflush(
PortFD, TCIOFLUSH);
236 bool success =
false;
237 while(numChecks < 3 && !success)
243 if(!transmissionSuccess)
246 LOGF_ERROR(
"Handshake Attempt %i, Connection transmission error: %s.", numChecks, errstr);
249 bool responseSuccess;
252 responseSuccess = (rc =
tty_read(
PortFD, resp, 5, MYFOCUSERPRO2_SERIAL_TIMEOUT, &nbytes_read)) ==
TTY_OK;
257 responseSuccess = (rc =
tty_read(
PortFD, resp, 5, MYFOCUSERPRO2_TCPIP_TIMEOUT, &nbytes_read)) ==
TTY_OK;
263 LOGF_ERROR(
"Handshake Attempt %i, updatePosition response error: %s.", numChecks, errstr);
265 success = transmissionSuccess && responseSuccess;
270 LOG_INFO(
"Handshake failed after 3 attempts");
274 tcflush(
PortFD, TCIOFLUSH);
276 rc = sscanf(resp,
"F%d#", &firmWareVersion);
281 LOGF_INFO(
"MyFP2 reported firmware %d", firmWareVersion);
282 LOG_INFO(
"Connection to focuser is successful.");
287 LOGF_ERROR(
"Invalid Response: focuser firmware version value (%s)", resp);
292 bool MyFocuserPro2::readCoilPowerState()
294 char res[ML_RES] = {0};
296 if (sendCommand(
":11#", res) ==
false)
303 int rc = sscanf(res,
"O%u#", &temp);
317 LOGF_ERROR(
"Invalid Response: focuser Coil Power value (%s)", res);
323 LOGF_ERROR(
"Unknown error: focuser Coil Power value (%s)", res);
329 bool MyFocuserPro2::readReverseDirection()
331 char res[ML_RES] = {0};
333 if (sendCommand(
":13#", res) ==
false)
338 int rc = sscanf(res,
"R%u#", &temp);
352 LOGF_ERROR(
"Invalid Response: focuser Reverse direction value (%s)", res);
358 LOGF_ERROR(
"Unknown error: focuser Reverse direction value (%s)", res);
364 bool MyFocuserPro2::readStepMode()
366 char res[ML_RES] = {0};
368 if (sendCommand(
":29#", res) ==
false)
373 uint32_t stepmode = 0;
375 int rc = sscanf(res,
"S%u#", &stepmode);
409 LOGF_ERROR(
"Unknown error: Step mode value (%d)", stepmode);
416 LOGF_ERROR(
"Unknown error: Step mode value (%s)", res);
422 bool MyFocuserPro2::readTemperature()
424 char res[ML_RES] = {0};
426 if (sendCommand(
":06#", res) ==
false)
430 int rc = sscanf(res,
"Z%lf#", &temp);
433 TemperatureN[0].value = temp;
437 LOGF_ERROR(
"Unknown error: focuser temperature value (%s)", res);
443 bool MyFocuserPro2::readTempCompensateEnable()
445 char res[ML_RES] = {0};
447 if (sendCommand(
":24#", res) ==
false)
454 int rc = sscanf(res,
"1%u#", &temp);
468 LOGF_ERROR(
"Invalid Response: focuser T.Compensate value (%s)", res);
474 LOGF_ERROR(
"Unknown error: focuser T.Compensate value (%s)", res);
481 bool MyFocuserPro2::readPosition()
483 char res[ML_RES] = {0};
485 if (sendCommand(
":00#", res) ==
false)
491 int rc = sscanf(res,
"%*c%d#", &pos);
499 LOGF_ERROR(
"Unknown error: focuser position value (%s)", res);
505 bool MyFocuserPro2::readTemperatureCoefficient()
507 char res[ML_RES] = {0};
509 if (sendCommand(
":26#", res) ==
false)
515 int rc = sscanf(res,
"B%d#", &val);
519 TemperatureSettingN[0].value = val;
523 LOGF_ERROR(
"Unknown error: Temperature Coefficient value (%s)", res);
529 bool MyFocuserPro2::readSpeed()
531 char res[ML_RES] = {0};
533 if (sendCommand(
":43#", res) ==
false)
539 int rc = sscanf(res,
"C%d#", &speed);
547 LOGF_ERROR(
"Unknown error: focuser speed value (%s)", res);
553 bool MyFocuserPro2::readMaxPos()
555 char res[ML_RES] = {0};
557 if (sendCommand(
":08#", res) ==
false)
563 int rc = sscanf(res,
"M%u#", &maxPos);
568 Focuser::SyncPresets(maxPos);
572 LOGF_ERROR(
"Unknown error: focuser max position value (%s)", res);
578 bool MyFocuserPro2::readBacklashInSteps()
580 char res[ML_RES] = {0};
582 if (sendCommand(
":78#", res) ==
false)
587 uint32_t backlash = 0;
588 int rc = sscanf(res,
"6%u#", &backlash);
592 BacklashInStepsN[0].value = backlash;
596 BacklashInStepsN[0].value = 0;
597 LOGF_ERROR(
"Unknown error: focuser Backlash IN value (%s)", res);
603 bool MyFocuserPro2::readBacklashInEnabled()
605 char res[ML_RES] = {0};
607 if (sendCommand(
":74#", res) ==
false)
613 int rc = sscanf(res,
"4%u#", &temp);
627 LOGF_ERROR(
"Unknown Repsonse: focuser Backlash IN enabled (%s)", res);
633 LOGF_ERROR(
"Unknown error: focuser Backlash IN enabled (%s)", res);
639 bool MyFocuserPro2::readBacklashOutSteps()
641 char res[ML_RES] = {0};
643 if (sendCommand(
":80#", res) ==
false)
648 uint32_t backlash = 0;
649 int rc = sscanf(res,
"7%u#", &backlash);
653 BacklashOutStepsN[0].value = backlash;
657 LOGF_ERROR(
"Unknown error: focuser Backlash OUT value (%s)", res);
663 bool MyFocuserPro2::readBacklashOutEnabled()
665 char res[ML_RES] = {0};
667 if (sendCommand(
":76#", res) ==
false)
673 int rc = sscanf(res,
"5%u#", &temp);
687 LOGF_ERROR(
"Unknown response: focuser Backlash OUT enabled (%s)", res);
693 LOGF_ERROR(
"Unknown error: focuser Backlash OUT enabled (%s)", res);
699 bool MyFocuserPro2::readDisplayVisible()
701 char res[ML_RES] = {0};
703 if (sendCommand(
":37#", res) ==
false)
710 int rc = sscanf(res,
"D%u#", &temp);
724 LOGF_ERROR(
"Invalid Response: focuser Display value (%s)", res);
730 LOGF_ERROR(
"Unknown error: focuser Display value (%s)", res);
736 bool MyFocuserPro2::isMoving()
738 char res[ML_RES] = {0};
740 if (sendCommand(
":01#", res) ==
false)
747 int rc = sscanf(res,
"I%u#", &temp);
761 LOGF_ERROR(
"Invalid Response: focuser isMoving value (%s)", res);
767 LOGF_ERROR(
"Unknown error: focuser isMoving value (%s)", res);
772 bool MyFocuserPro2::setTemperatureCelsius()
774 char cmd[ML_RES] = {0};
775 snprintf(
cmd, ML_RES,
":16#");
776 return sendCommand(
cmd);
779 bool MyFocuserPro2::setTemperatureCoefficient(
double coefficient)
781 char cmd[ML_RES] = {0};
782 int coeff = coefficient;
783 snprintf(
cmd, ML_RES,
":22%d#", coeff);
784 return sendCommand(
cmd);
789 char cmd[ML_RES] = {0};
790 snprintf(
cmd, ML_RES,
":31%u#", ticks);
791 return sendCommand(
cmd);
796 char cmd[ML_RES] = {0};
801 snprintf(
cmd, ML_RES,
":05%u#", position);
802 return sendCommand(
cmd);
805 bool MyFocuserPro2::setBacklashInSteps(int16_t steps)
807 char cmd[ML_RES] = {0};
808 snprintf(
cmd, ML_RES,
":77%d#", steps);
809 return sendCommand(
cmd);
812 bool MyFocuserPro2::setBacklashInEnabled(
bool enabled)
814 char cmd[ML_RES] = {0};
815 snprintf(
cmd, ML_RES,
":73%c#", enabled ?
'1' :
'0');
816 return sendCommand(
cmd);
819 bool MyFocuserPro2::setBacklashOutSteps(int16_t steps)
821 char cmd[ML_RES] = {0};
822 snprintf(
cmd, ML_RES,
":79%d#", steps);
823 return sendCommand(
cmd);
826 bool MyFocuserPro2::setBacklashOutEnabled(
bool enabled)
828 char cmd[ML_RES] = {0};
829 snprintf(
cmd, ML_RES,
":75%c#", enabled ?
'1' :
'0');
830 return sendCommand(
cmd);
833 bool MyFocuserPro2::setCoilPowerState(CoilPower enable)
835 char cmd[ML_RES] = {0};
837 snprintf(
cmd, ML_RES,
":12%d#", enable);
838 return sendCommand(
cmd);
843 char cmd[ML_RES] = {0};
844 snprintf(
cmd, ML_RES,
":14%d#",
static_cast<int>(enable));
845 return sendCommand(
cmd);
848 bool MyFocuserPro2::setDisplayVisible(DisplayMode enable)
850 char cmd[ML_RES] = {0};
851 snprintf(
cmd, ML_RES,
":36%d#", enable);
852 return sendCommand(
cmd);
855 bool MyFocuserPro2::setGotoHome()
857 char cmd[ML_RES] = {0};
862 snprintf(
cmd, ML_RES,
":28#");
863 return sendCommand(
cmd);
866 bool MyFocuserPro2::setStepMode(FocusStepMode smode)
868 char cmd[ML_RES] = {0};
906 snprintf(
cmd, ML_RES,
":30%d#", stepmode);
907 return sendCommand(
cmd);
910 bool MyFocuserPro2::setSpeed(uint16_t speed)
912 char cmd[ML_RES] = {0};
913 snprintf(
cmd, ML_RES,
":150%d#", speed);
914 return sendCommand(
cmd);
917 bool MyFocuserPro2::setTemperatureCompensation(
bool enable)
919 char cmd[ML_RES] = {0};
920 snprintf(
cmd, ML_RES,
":23%c#", enable ?
'1' :
'0');
921 return sendCommand(
cmd);
929 if (strcmp(StepModeSP.
name,
name) == 0)
937 if (current_mode == target_mode)
943 bool rc = setStepMode(
static_cast<FocusStepMode>(target_mode));
947 StepModeS[current_mode].s =
ISS_ON;
959 if (strcmp(GotoHomeSP.
name,
name) == 0)
961 bool rc = setGotoHome();
976 if (strcmp(CoilPowerSP.
name,
name) == 0)
984 if (current_mode == target_mode)
990 bool rc = setCoilPowerState(
static_cast<CoilPower>(target_mode));
994 CoilPowerS[current_mode].s =
ISS_ON;
1006 if (strcmp(DisplaySP.
name,
name) == 0)
1014 if (current_mode == target_mode)
1020 bool rc = setDisplayVisible(
static_cast<DisplayMode>(target_mode));
1024 DisplayS[current_mode].s =
ISS_ON;
1036 if (strcmp(BacklashInSP.
name,
name) == 0)
1044 if (current_mode == target_mode)
1050 bool rc = setBacklashInEnabled(target_mode ==
INDI_ENABLED);
1054 BacklashInS[current_mode].s =
ISS_ON;
1066 if (strcmp(BacklashOutSP.
name,
name) == 0)
1074 if (current_mode == target_mode)
1080 bool rc = setBacklashOutEnabled(target_mode ==
INDI_ENABLED);
1084 BacklashOutS[current_mode].s =
ISS_ON;
1096 if (strcmp(TemperatureCompensateSP.
name,
name) == 0)
1101 bool rc = setTemperatureCompensation((TemperatureCompensateS[0].s ==
ISS_ON));
1107 TemperatureCompensateS[last_index].s =
ISS_ON;
1112 TemperatureCompensateSP.
s =
IPS_OK;
1126 if (strcmp(
name, TemperatureSettingNP.
name) == 0)
1129 if (!setTemperatureCoefficient(TemperatureSettingN[0].value))
1136 TemperatureSettingNP.
s =
IPS_OK;
1142 if (strcmp(
name, BacklashInStepsNP.
name) == 0)
1145 if (!setBacklashInSteps(BacklashInStepsN[0].value))
1158 if (strcmp(
name, BacklashOutStepsNP.
name) == 0)
1161 if (!setBacklashOutSteps(BacklashOutStepsN[0].value))
1168 BacklashOutStepsNP.
s =
IPS_OK;
1178 void MyFocuserPro2::getStartupValues()
1183 readTemperatureCoefficient();
1185 readTempCompensateEnable();
1187 readCoilPowerState();
1188 readDisplayVisible();
1189 readReverseDirection();
1190 readBacklashInEnabled();
1191 readBacklashOutEnabled();
1192 readBacklashInSteps();
1193 readBacklashOutSteps();
1198 return setSpeed(speed);
1204 char cmd[ML_RES] = {0};
1206 snprintf(
cmd, ML_RES,
":07%06d#", maxPos);
1208 if(sendCommand(
cmd))
1210 Focuser::SyncPresets(maxPos);
1218 if (speed !=
static_cast<int>(
FocusSpeedN[0].value))
1220 if (!setSpeed(speed))
1246 void MyFocuserPro2::timedMoveCallback()
1260 targetPos = targetTicks;
1271 int32_t newPosition = 0;
1305 if (Position_Counter++ == GET_POSITION_FREQ)
1308 Position_Counter = 0;
1309 bool rc = readPosition();
1327 LOG_INFO(
"Focuser reached requested position.");
1341 LOG_INFO(
"Focuser reached requested position.");
1346 if (Temperature_Counter++ == GET_TEMPERATURE_FREQ)
1349 Temperature_Counter = 0;
1350 bool rc = readTemperature();
1353 if (fabs(lastTemperature - TemperatureN[0].value) >= 0.5)
1356 lastTemperature = TemperatureN[0].value;
1365 return sendCommand(
":27#");
1370 Focuser::saveConfigItems(fp);
1385 int MyFocuserPro2::msleep(
long duration)
1396 ts.tv_sec = duration / 1000;
1397 ts.tv_nsec = (duration % 1000) * 1000000;
1401 res = nanosleep(&ts, &ts);
1403 while (res &&
errno == EINTR);
1408 void MyFocuserPro2::clearbufferonerror()
1411 char res[ML_RES] = {0};
1412 int nbytes_read = 0;
1416 pthread_mutex_lock(&cmdlock);
1417 msleep(MYFOCUSERPRO2_RECOVER_DELAY);
1427 pthread_mutex_unlock(&cmdlock);
1434 LOGF_ERROR(
"Data read from controller: %s.", res);
1438 bool MyFocuserPro2::sendCommand(
const char *
cmd,
char * res)
1440 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1442 tcflush(
PortFD, TCIOFLUSH);
1446 pthread_mutex_lock(&cmdlock);
1451 LOGF_ERROR(
"Connection write error: %s.", errstr);
1452 pthread_mutex_unlock(&cmdlock);
1459 pthread_mutex_unlock(&cmdlock);
1465 msleep(MYFOCUSERPRO2_SMALL_DELAY);
1483 LOGF_ERROR(
"Connection read error: %s.", errstr);
1484 pthread_mutex_unlock(&cmdlock);
1490 tcflush(
PortFD, TCIOFLUSH);
1491 pthread_mutex_unlock(&cmdlock);