void ioptronHC8406::syncSideOfPier() { const char *cmd = ":pS#"; // Response char response[16] = { 0 }; int rc = 0, nbytes_read = 0, nbytes_written = 0; DEBUGF(INDI::Logger::DBG_DEBUG, "CMD: <%s>", cmd); tcflush(PortFD, TCIOFLUSH); if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK) { char errmsg[256]; tty_error_msg(rc, errmsg, 256); DEBUGF(INDI::Logger::DBG_ERROR, "Error writing to device %s (%d)", errmsg, rc); return; } // Read Side if ((rc = tty_read_section(PortFD, response, '#', 3, &nbytes_read)) != TTY_OK) { char errmsg[256]; tty_error_msg(rc, errmsg, 256); DEBUGF(INDI::Logger::DBG_ERROR, "Error reading from device %s (%d)", errmsg, rc); return; } response[nbytes_read - 1] = '\0'; tcflush(PortFD, TCIOFLUSH); DEBUGF(INDI::Logger::DBG_DEBUG, "RES: <%s>", response); if (!strcmp(response, "East")) setPierSide(INDI::Telescope::PIER_EAST); else setPierSide(INDI::Telescope::PIER_WEST); }
bool SynscanDriver::ReadScopeStatus() { if (isSimulation()) { mountSim(); return true; } char res[SYN_RES] = {0}; // Goto in progress? if (sendCommand("L", res)) m_MountInfo[MI_GOTO_STATUS] = res[0]; // Pier side if (m_isAltAz == false && sendCommand("p", res)) { m_MountInfo[MI_POINT_STATUS] = res[0]; // INDI and mount pier sides are opposite to each other setPierSide(res[0] == 'W' ? PIER_EAST : PIER_WEST); } if (readTracking()) { if (TrackState == SCOPE_SLEWING) { if (isSlewComplete()) { TrackState = (m_TrackingFlag == 2) ? SCOPE_TRACKING : SCOPE_IDLE; HorizontalCoordsNP.s = (m_TrackingFlag == 2) ? IPS_OK : IPS_IDLE; IDSetNumber(&HorizontalCoordsNP, nullptr); } } else if (TrackState == SCOPE_PARKING) { if (isSlewComplete()) { HorizontalCoordsNP.s = IPS_IDLE; IDSetNumber(&HorizontalCoordsNP, nullptr); TrackState = SCOPE_PARKED; SetTrackEnabled(false); SetParked(true); } } else if (TrackState == SCOPE_IDLE && m_TrackingFlag > 0) TrackState = SCOPE_TRACKING; else if (TrackState == SCOPE_TRACKING && m_TrackingFlag == 0) TrackState = SCOPE_IDLE; } sendStatus(); // Get Precise RA/DE memset(res, 0, SYN_RES); if (!sendCommand("e", res)) return false; uint32_t n1 = 0, n2 = 0; sscanf(res, "%x,%x#", &n1, &n2); double ra = static_cast<double>(n1) / 0x100000000 * 360.0; double de = static_cast<double>(n2) / 0x100000000 * 360.0; ln_equ_posn epochPos { 0, 0 }, J2000Pos { 0, 0 }; J2000Pos.ra = range360(ra); J2000Pos.dec = rangeDec(de); // Synscan reports J2000 coordinates so we need to convert from J2000 to JNow ln_get_equ_prec2(&J2000Pos, JD2000, ln_get_julian_from_sys(), &epochPos); CurrentRA = epochPos.ra / 15.0; CurrentDE = epochPos.dec; char Axis1Coords[MAXINDINAME] = {0}, Axis2Coords[MAXINDINAME] = {0}; fs_sexa(Axis1Coords, J2000Pos.ra / 15.0, 2, 3600); fs_sexa(Axis2Coords, J2000Pos.dec, 2, 3600); LOGF_DEBUG("J2000 RA <%s> DE <%s>", Axis1Coords, Axis2Coords); memset(Axis1Coords, 0, MAXINDINAME); memset(Axis2Coords, 0, MAXINDINAME); fs_sexa(Axis1Coords, CurrentRA, 2, 3600); fs_sexa(Axis2Coords, CurrentDE, 2, 3600); LOGF_DEBUG("JNOW RA <%s> DE <%s>", Axis1Coords, Axis2Coords); // Now feed the rest of the system with corrected data NewRaDec(CurrentRA, CurrentDE); // Get precise az/alt memset(res, 0, SYN_RES); if (!sendCommand("z", res)) return false; sscanf(res, "%x,%x#", &n1, &n2); double az = static_cast<double>(n1) / 0x100000000 * 360.0; double al = static_cast<double>(n2) / 0x100000000 * 360.0; al = rangeDec(al); HorizontalCoordsN[AXIS_AZ].value = az; HorizontalCoordsN[AXIS_ALT].value = al; memset(Axis1Coords, 0, MAXINDINAME); memset(Axis2Coords, 0, MAXINDINAME); fs_sexa(Axis1Coords, az, 2, 3600); fs_sexa(Axis2Coords, al, 2, 3600); LOGF_DEBUG("AZ <%s> ALT <%s>", Axis1Coords, Axis2Coords); IDSetNumber(&HorizontalCoordsNP, nullptr); return true; }
bool ScopeSim::ReadScopeStatus() { static struct timeval ltv { 0, 0 }; struct timeval tv { 0, 0 }; double dt = 0, da_ra = 0, da_dec = 0, dx = 0, dy = 0, ra_guide_dt = 0, dec_guide_dt = 0; int nlocked, ns_guide_dir = -1, we_guide_dir = -1; #ifdef USE_EQUATORIAL_PE static double last_dx = 0, last_dy = 0; char RA_DISP[64], DEC_DISP[64], RA_GUIDE[64], DEC_GUIDE[64], RA_PE[64], DEC_PE[64], RA_TARGET[64], DEC_TARGET[64]; #endif /* update elapsed time since last poll, don't presume exactly POLLMS */ gettimeofday(&tv, nullptr); if (ltv.tv_sec == 0 && ltv.tv_usec == 0) ltv = tv; // Time diff is seconds dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6; ltv = tv; if (fabs(targetRA - currentRA) * 15. >= GOTO_LIMIT) da_ra = GOTO_RATE * dt; else if (fabs(targetRA - currentRA) * 15. >= SLEW_LIMIT) da_ra = SLEW_RATE * dt; else da_ra = FINE_SLEW_RATE * dt; if (fabs(targetDEC - currentDEC) >= GOTO_LIMIT) da_dec = GOTO_RATE * dt; else if (fabs(targetDEC - currentDEC) >= SLEW_LIMIT) da_dec = SLEW_RATE * dt; else da_dec = FINE_SLEW_RATE * dt; if (MovementNSSP.s == IPS_BUSY || MovementWESP.s == IPS_BUSY) { int rate = IUFindOnSwitchIndex(&SlewRateSP); switch (rate) { case SLEW_GUIDE: da_ra = TrackRateN[AXIS_RA].value/(3600.0*15) * GuideRateN[RA_AXIS].value * dt; da_dec = TrackRateN[AXIS_RA].value/3600.0 * GuideRateN[DEC_AXIS].value * dt;; break; case SLEW_CENTERING: da_ra = FINE_SLEW_RATE * dt * .1; da_dec = FINE_SLEW_RATE * dt * .1; break; case SLEW_FIND: da_ra = SLEW_RATE * dt; da_dec = SLEW_RATE * dt; break; default: da_ra = GOTO_RATE * dt; da_dec = GOTO_RATE * dt; break; } switch (MovementNSSP.s) { case IPS_BUSY: if (MovementNSS[DIRECTION_NORTH].s == ISS_ON) currentDEC += da_dec; else if (MovementNSS[DIRECTION_SOUTH].s == ISS_ON) currentDEC -= da_dec; break; default: break; } switch (MovementWESP.s) { case IPS_BUSY: if (MovementWES[DIRECTION_WEST].s == ISS_ON) currentRA -= da_ra / 15.; else if (MovementWES[DIRECTION_EAST].s == ISS_ON) currentRA += da_ra / 15.; break; default: break; } NewRaDec(currentRA, currentDEC); return true; } /* Process per current state. We check the state of EQUATORIAL_EOD_COORDS_REQUEST and act acoordingly */ switch (TrackState) { /*case SCOPE_IDLE: EqNP.s = IPS_IDLE; break;*/ case SCOPE_SLEWING: case SCOPE_PARKING: /* slewing - nail it when both within one pulse @ SLEWRATE */ nlocked = 0; dx = targetRA - currentRA; // Always take the shortcut, don't go all around the globe // If the difference between target and current is more than 12 hours, then we need to take the shortest path if (dx > 12) dx -= 24; else if (dx < -12) dx += 24; // In meridian flip, alway force eastward motion (increasing RA) until target is reached. if (forceMeridianFlip) { dx = fabs(dx); if (dx == 0) { dx = 1; da_ra = GOTO_LIMIT; } } if (fabs(dx) * 15. <= da_ra) { currentRA = targetRA; nlocked++; } else if (dx > 0) currentRA += da_ra / 15.; else currentRA -= da_ra / 15.; currentRA = range24(currentRA); dy = targetDEC - currentDEC; if (fabs(dy) <= da_dec) { currentDEC = targetDEC; nlocked++; } else if (dy > 0) currentDEC += da_dec; else currentDEC -= da_dec; EqNP.s = IPS_BUSY; if (nlocked == 2) { forceMeridianFlip = false; if (TrackState == SCOPE_SLEWING) { // Initially no PE in both axis. #ifdef USE_EQUATORIAL_PE EqPEN[0].value = currentRA; EqPEN[1].value = currentDEC; IDSetNumber(&EqPENV, nullptr); #endif TrackState = SCOPE_TRACKING; if (IUFindOnSwitchIndex(&SlewRateSP) != SLEW_CENTERING) { IUResetSwitch(&SlewRateSP); SlewRateS[SLEW_CENTERING].s = ISS_ON; IDSetSwitch(&SlewRateSP, nullptr); } EqNP.s = IPS_OK; LOG_INFO("Telescope slew is complete. Tracking..."); } else { SetParked(true); EqNP.s = IPS_IDLE; } } break; case SCOPE_IDLE: //currentRA += (TRACKRATE_SIDEREAL/3600.0 * dt) / 15.0; currentRA += (TrackRateN[AXIS_RA].value/3600.0 * dt) / 15.0; currentRA = range24(currentRA); break; case SCOPE_TRACKING: // In case of custom tracking rate if (TrackModeS[1].s == ISS_ON) { currentRA += ( ((TRACKRATE_SIDEREAL/3600.0) - (TrackRateN[AXIS_RA].value/3600.0)) * dt) / 15.0; currentDEC += ( (TrackRateN[AXIS_DE].value/3600.0) * dt); } dt *= 1000; if (guiderNSTarget[GUIDE_NORTH] > 0) { LOGF_DEBUG("Commanded to GUIDE NORTH for %g ms", guiderNSTarget[GUIDE_NORTH]); ns_guide_dir = GUIDE_NORTH; } else if (guiderNSTarget[GUIDE_SOUTH] > 0) { LOGF_DEBUG("Commanded to GUIDE SOUTH for %g ms", guiderNSTarget[GUIDE_SOUTH]); ns_guide_dir = GUIDE_SOUTH; } // WE Guide Selection if (guiderEWTarget[GUIDE_WEST] > 0) { we_guide_dir = GUIDE_WEST; LOGF_DEBUG("Commanded to GUIDE WEST for %g ms", guiderEWTarget[GUIDE_WEST]); } else if (guiderEWTarget[GUIDE_EAST] > 0) { we_guide_dir = GUIDE_EAST; LOGF_DEBUG("Commanded to GUIDE EAST for %g ms", guiderEWTarget[GUIDE_EAST]); } if ( (ns_guide_dir != -1 || we_guide_dir != -1) && IUFindOnSwitchIndex(&SlewRateSP) != SLEW_GUIDE) { IUResetSwitch(&SlewRateSP); SlewRateS[SLEW_GUIDE].s = ISS_ON; IDSetSwitch(&SlewRateSP, nullptr); } if (ns_guide_dir != -1) { dec_guide_dt = (TrackRateN[AXIS_RA].value * GuideRateN[DEC_AXIS].value * guiderNSTarget[ns_guide_dir] / 1000.0 * (ns_guide_dir == GUIDE_NORTH ? 1 : -1)) / 3600.0; guiderNSTarget[ns_guide_dir] = 0; GuideNSNP.s = IPS_IDLE; IDSetNumber(&GuideNSNP, nullptr); #ifdef USE_EQUATORIAL_PE EqPEN[DEC_AXIS].value += dec_guide_dt; #else currentDEC += dec_guide_dt; #endif } if (we_guide_dir != -1) { ra_guide_dt = (TrackRateN[AXIS_RA].value * GuideRateN[RA_AXIS].value * guiderEWTarget[we_guide_dir] / 1000.0 * (we_guide_dir == GUIDE_WEST ? -1 : 1)) / (3600.0*15.0); ra_guide_dt /= (cos(currentDEC * 0.0174532925)); guiderEWTarget[we_guide_dir] = 0; GuideWENP.s = IPS_IDLE; IDSetNumber(&GuideWENP, nullptr); #ifdef USE_EQUATORIAL_PE EqPEN[RA_AXIS].value += ra_guide_dt; #else currentRA += ra_guide_dt; #endif } //Mention the followng: // Current RA displacemet and direction // Current DEC displacement and direction // Amount of RA GUIDING correction and direction // Amount of DEC GUIDING correction and direction #ifdef USE_EQUATORIAL_PE dx = EqPEN[RA_AXIS].value - targetRA; dy = EqPEN[DEC_AXIS].value - targetDEC; fs_sexa(RA_DISP, fabs(dx), 2, 3600); fs_sexa(DEC_DISP, fabs(dy), 2, 3600); fs_sexa(RA_GUIDE, fabs(ra_guide_dt), 2, 3600); fs_sexa(DEC_GUIDE, fabs(dec_guide_dt), 2, 3600); fs_sexa(RA_PE, EqPEN[RA_AXIS].value, 2, 3600); fs_sexa(DEC_PE, EqPEN[DEC_AXIS].value, 2, 3600); fs_sexa(RA_TARGET, targetRA, 2, 3600); fs_sexa(DEC_TARGET, targetDEC, 2, 3600); if (dx != last_dx || dy != last_dy || ra_guide_dt != 0.0 || dec_guide_dt != 0.0) { last_dx = dx; last_dy = dy; //LOGF_DEBUG("dt is %g\n", dt); LOGF_DEBUG("RA Displacement (%c%s) %s -- %s of target RA %s", dx >= 0 ? '+' : '-', RA_DISP, RA_PE, (EqPEN[RA_AXIS].value - targetRA) > 0 ? "East" : "West", RA_TARGET); LOGF_DEBUG("DEC Displacement (%c%s) %s -- %s of target RA %s", dy >= 0 ? '+' : '-', DEC_DISP, DEC_PE, (EqPEN[DEC_AXIS].value - targetDEC) > 0 ? "North" : "South", DEC_TARGET); LOGF_DEBUG("RA Guide Correction (%g) %s -- Direction %s", ra_guide_dt, RA_GUIDE, ra_guide_dt > 0 ? "East" : "West"); LOGF_DEBUG("DEC Guide Correction (%g) %s -- Direction %s", dec_guide_dt, DEC_GUIDE, dec_guide_dt > 0 ? "North" : "South"); } if (ns_guide_dir != -1 || we_guide_dir != -1) IDSetNumber(&EqPENV, nullptr); #endif break; default: break; } char RAStr[64], DecStr[64]; fs_sexa(RAStr, currentRA, 2, 3600); fs_sexa(DecStr, currentDEC, 2, 3600); DEBUGF(DBG_SCOPE, "Current RA: %s Current DEC: %s", RAStr, DecStr); NewRaDec(currentRA, currentDEC); // pier side might only change with a slew or parking if (TrackState == SCOPE_SLEWING || TrackState == SCOPE_PARKING) { double az = getAzimuth(currentRA, currentDEC); bool north = lnobserver.lat >= 0.; if ((0 <= az && az < 90) || (180 <= az && az < 270)) setPierSide(north ? INDI::Telescope::PIER_EAST : INDI::Telescope::PIER_WEST); else setPierSide(north ? INDI::Telescope::PIER_WEST : INDI::Telescope::PIER_EAST); } return true; }