diff --git a/Align.h b/Align.h index dc05bff73..5ecd54505 100644 --- a/Align.h +++ b/Align.h @@ -1,111 +1,80 @@ -// --------------------------------------------------------------------- -// Program for pointing a telescope by Toshimi Taki -// -// Original published in Sky & Telescope, February 1989, pages 194-196. +// ----------------------------------------------------------------------------------- +// GEOMETRIC ALIGN FOR ALT/AZM AND EQ MOUNTS // -// Source here, with errors corrected: -// http://wwwcdn.skyandtelescope.com/wp-content/uploads/taki.bas +// by Howard Dutton // -// Background on equations is on Taki's site: -// http://www.geocities.jp/toshimi_taki/aim/aim.htm +// Copyright (C) 2012 to 2018 Howard Dutton // -// Conversion to C++/Arduino by Howard Dutton, 10/12/2016 #pragma once byte alignNumStars = 0; byte alignThisStar = 0; -#ifdef MOUNT_TYPE_ALTAZM -typedef struct { - double HA; - double Dec; - double Alt; - double Az; -} align_coord_t; - -class TAlign -{ - public: - TAlign(); - ~TAlign(); - void init(); - bool isReady(); - void addStar(int I, int N, double B, double D, double H, double F); - void EquToInstr(double B, double D, double *H, double *F); - void InstrToEqu(double H, double F, double *B, double *D); - - private: - double Z1; - double Z2; - double Z3; - boolean t_ready; - double W; - double Q[4][4]; - double V[4][4]; - double R[4][4]; - double X[4][4]; - double Y[4][4]; - - align_coord_t AlignStars[10]; - - void t_deter_sub(); - void t_angle_sub(double *F, double *H); - void t_sub1(double F, double H); - void t_sub2(double F, double H); - - void bestZ3(int I, double nrange, double range, double incr); -}; - -TAlign Align; -#endif - -#ifndef ALIGN_GOTOASSIST_ON // ----------------------------------------------------------------------------------- -// GEOMETRIC ALIGN FOR EQUATORIAL MOUNTS -// +// ADVANCED GEOMETRIC ALIGN FOR ALT/AZM MOUNTS (GOTO ASSIST) + +#ifdef MOUNT_TYPE_ALTAZM typedef struct { - double HA; - double Dec; - double HA1; - double Dec1; + double ha; + double dec; + double alt; + double azm; + int side; } align_coord2_t; -class TGeoAlign +class TGeoAlignH { public: + double ax1Cor; + double ax2Cor; double altCor; double azmCor; double doCor; double pdCor; double dfCor; double tfCor; + align_coord2_t mount[9]; + align_coord2_t actual[9]; + align_coord2_t delta[9]; - TGeoAlign(); - ~TGeoAlign(); void init(); void readCoe(); void writeCoe(); bool isReady(); bool addStar(int I, int N, double RA, double Dec); - void EquToInstr(double Lat, double HA, double Dec, double *HA1, double *Dec1); - void InstrToEqu(double Lat, double HA, double Dec, double *HA1, double *Dec1); + void HorToInstr(double Alt, double Azm, double *Alt1, double *Azm1, int PierSide); + void InstrToHor(double Alt, double Azm, double *Alt1, double *Azm1, int PierSide); + void autoModel(int n, bool start); private: boolean geo_ready; - double avgDec; - double avgHA; + double avgAlt; + double avgAzm; + + long num,l; + long Ff,Df; + double best_deo, best_pd, best_pz, best_pe, best_ohw, best_odw, best_ohe, best_ode, best_tf, best_df, best_ff; + double z1,a1; + double avg_azm,avg_alt; + double dist,sumd,rms; + double best_dist; + double ohe,ode,ohw,odw,dh; + double sa,sz,sum1; + double max_dist; - align_coord2_t AlignStars[4]; + void correct(double azm, double alt, double pierSide, double sf, double _deo, double _pd, double _pz, double _pe, double _da, double _ff, double _tf, double *z1, double *a1); + void do_search(double sf, int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9); }; -TGeoAlign GeoAlign; +TGeoAlignH Align; +#endif -#else // ----------------------------------------------------------------------------------- -// GEOMETRIC ALIGN FOR EQUATORIAL MOUNTS2 -// +// ADVANCED GEOMETRIC ALIGN FOR EQUATORIAL MOUNTS (GOTO ASSIST) + +#ifndef MOUNT_TYPE_ALTAZM typedef struct { double ha; @@ -116,22 +85,26 @@ typedef struct { class TGeoAlign { public: + double ax1Cor; + double ax2Cor; double altCor; double azmCor; double doCor; double pdCor; double dfCor; double tfCor; + align_coord2_t mount[9]; + align_coord2_t actual[9]; + align_coord2_t delta[9]; - TGeoAlign(); - ~TGeoAlign(); void init(); void readCoe(); void writeCoe(); bool isReady(); bool addStar(int I, int N, double RA, double Dec); - void EquToInstr(double Lat, double HA, double Dec, double *HA1, double *Dec1); - void InstrToEqu(double Lat, double HA, double Dec, double *HA1, double *Dec1); + void EquToInstr(double Lat, double HA, double Dec, double *HA1, double *Dec1, int PierSide); + void InstrToEqu(double Lat, double HA, double Dec, double *HA1, double *Dec1, int PierSide); + void autoModel(int n, bool start); private: boolean geo_ready; @@ -149,14 +122,10 @@ class TGeoAlign double sd,sh,sum1; double max_dist; - align_coord2_t mount[9]; - align_coord2_t actual[9]; - align_coord2_t delta[9]; - void correct(double ha, double dec, double pierSide, double sf, double _deo, double _pd, double _pz, double _pe, double _da, double _ff, double _tf, double *h1, double *d1); void do_search(double sf, int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9); - void autoModel(int n); }; -TGeoAlign GeoAlign; +TGeoAlign Align; #endif + diff --git a/AlignEq.ino b/AlignEq.ino new file mode 100644 index 000000000..1782a4976 --- /dev/null +++ b/AlignEq.ino @@ -0,0 +1,481 @@ +// ----------------------------------------------------------------------------------- +// GEOMETRIC ALIGN FOR EQ MOUNTS +// +// by Howard Dutton +// +// Copyright (C) 2012 to 2018 Howard Dutton +// + +// ----------------------------------------------------------------------------------- +// ADVANCED GEOMETRIC ALIGN FOR EQUATORIAL MOUNTS (GOTO ASSIST) + +#ifndef MOUNT_TYPE_ALTAZM +#define GOTO_ASSIST_DEBUG_OFF + +// Initialize +void TGeoAlign::init() { + avgDec=0.0; + avgHA =0.0; + + ax1Cor=0; // align internal index for Axis1 + ax2Cor=0; // align internal index for Axis2 + altCor=0; // for geometric coordinate correction/align, - is below the pole, + above + azmCor=0; // - is right of the pole, + is left + doCor =0; // declination/optics orthogonal correction + pdCor =0; // declination/polar orthogonal correction + dfCor =0; // fork or declination axis flex + tfCor =0; // tube flex + + geo_ready=false; +} + +// remember the alignment between sessions +void TGeoAlign::readCoe() { + ax1Cor=nv.readFloat(EE_ax1Cor); + ax2Cor=nv.readFloat(EE_ax2Cor); + dfCor=nv.readFloat(EE_dfCor); // dfCor is ffCor for fork mounts + tfCor=nv.readFloat(EE_tfCor); + doCor=nv.readFloat(EE_doCor); + pdCor=nv.readFloat(EE_pdCor); + altCor=nv.readFloat(EE_altCor); + azmCor=nv.readFloat(EE_azmCor); +} + +void TGeoAlign::writeCoe() { + nv.writeFloat(EE_ax1Cor,ax1Cor); + nv.writeFloat(EE_ax2Cor,ax2Cor); + nv.writeFloat(EE_dfCor,dfCor); // dfCor is ffCor for fork mounts + nv.writeFloat(EE_tfCor,tfCor); + nv.writeFloat(EE_doCor,doCor); + nv.writeFloat(EE_pdCor,pdCor); + nv.writeFloat(EE_altCor,altCor); + nv.writeFloat(EE_azmCor,azmCor); +} + +// Status +bool TGeoAlign::isReady() { + return geo_ready; +} + +/* +Alignment Logic: +Near the celestial equator (Dec=0, HA=0)... +the azmCor term is 0% in Dec +the altCor term is 100% in Dec +the doCor term is 100% in HA +the pdCor term is 0% in HA + +Near HA=6 and Dec=45... +the azmCor term is 100% in Dec +the altCor term is 0% in Dec +the doCor term is 0% in HA +the pdCor term is 100% in HA +*/ + +// I=1 for 1st star, I=2 for 2nd star, I=3 for 3rd star +// N=total number of stars for this align (1 to 9) +// RA, Dec (all in degrees) +bool TGeoAlign::addStar(int I, int N, double RA, double Dec) { + + // First star: + // Near the celestial equator (Dec=0, HA=0), telescope West of the pier if multi-star align + if (I==1) { + // set the indexAxis1/2 offset + if (syncEqu(RA,Dec)!=0) return true; + } + + mount[I-1].ha=getInstrAxis1()/Rad; + mount[I-1].dec=getInstrAxis2()/Rad; + actual[I-1].ha=haRange(LST()*15.0-RA)/Rad; + actual[I-1].dec=Dec/Rad; + if (getInstrPierSide()==PierSideWest) { actual[I-1].side=-1; mount[I-1].side=-1; } else + if (getInstrPierSide()==PierSideEast) { actual[I-1].side=1; mount[I-1].side=1; } else { actual[I-1].side=0; mount[I-1].side=0; } + + // two or more stars and finished + if ((I>=2) && (I==N)) { +#ifdef GOTO_ASSIST_DEBUG_ON + DL(""); +#endif + autoModel(N,true); + } + + return true; +} + +// returns the correction to be added to the requested RA,Dec to yield the actual RA,Dec that we will arrive at +void TGeoAlign::correct(double ha, double dec, double pierSide, double sf, double _deo, double _pd, double _pz, double _pe, double _da, double _ff, double _tf, double *h1, double *d1) { + double DO1,DOh; + double PD,PDh; + double PZ,PA; + double DF,DFd,TF,FF,FFd,TFh,TFd; + double lat; + + lat=latitude/Rad; + +// ------------------------------------------------------------ +// A. Misalignment due to tube/optics not being perp. to Dec axis +// negative numbers are further (S) from the NCP, swing to the +// equator and the effect on declination is 0. At the SCP it +// becomes a (N) offset. Unchanged with meridian flips. + DO1 =((_deo*sf)/3600.0)/Rad; +// works on HA. meridian flips effect this in HA + DOh = DO1*(1.0/cos(dec))*pierSide; + +// ------------------------------------------------------------ +// B. Misalignment, Declination axis relative to Polar axis +// expressed as a correction to where the Polar axis is pointing +// negative numbers are further (S) from the NCP, swing to the +// equator and the effect on declination is 0. +// At the SCP it is, again, a (S) offset + PD =((_pd*sf)/3600.0)/Rad; +// works on HA. + PDh = -PD*tan(dec)*pierSide; + +// ------------------------------------------------------------ +// Misalignment, relative to NCP +// negative numbers are east of the pole +// C. polar left-right misalignment + PZ =((_pz*sf)/3600.0)/Rad; +// D. negative numbers are below the pole +// polar below-above misalignment + PA =((_pe*sf)/3600.0)/Rad; + +// ------------------------------------------------------------ +// Axis flex + DF =((_da*sf)/3600.0)/Rad; + DFd =-DF*(cos(lat)*cos(ha)+sin(lat)*tan(dec)); + +// ------------------------------------------------------------ +// Fork flex + FF =((_ff*sf)/3600.0)/Rad; + FFd =FF*cos(ha); + +// ------------------------------------------------------------ +// Optical axis sag + TF =((_tf*sf)/3600.0)/Rad; + + TFh =TF*(cos(lat)*sin(ha)*(1.0/cos(dec))); + TFd =TF*(cos(lat)*cos(ha)-sin(lat)*cos(dec)); + +// ------------------------------------------------------------ + *h1 =(-PZ*cos(ha)*tan(dec) + PA*sin(ha)*tan(dec) + DOh + PDh + TFh); + *d1 =(+PZ*sin(ha) + PA*cos(ha) + DFd + FFd + TFd); +} + +void TGeoAlign::do_search(double sf, int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9) +{ + long l, + + _deo_m,_deo_p, + _pd_m,_pd_p, + _pz_m,_pz_p, + _pe_m,_pe_p, + _df_m,_df_p, + _tf_m,_tf_p, + _ff_m,_ff_p, + _oh_m,_oh_p, + _od_m,_od_p, + + _deo,_pd,_pz,_pe, _df,_tf,_ff, _ode,_ohe; + + // search + // set Parameter Space + _deo_m=-p1+round(best_deo/sf); _deo_p=p1+round(best_deo/sf); + _pd_m =-p2+round(best_pd/sf); _pd_p=p2+round(best_pd/sf); + _pz_m =-p3+round(best_pz/sf); _pz_p=p3+round(best_pz/sf); + _pe_m =-p4+round(best_pe/sf); _pe_p=p4+round(best_pe/sf); + _tf_m =-p5+round(best_tf/sf); _tf_p=p5+round(best_tf/sf); + _ff_m =-p6+round(best_ff/sf); _ff_p=p6+round(best_ff/sf); + _df_m =-p7+round(best_df/sf); _df_p=p7+round(best_df/sf); + _od_m =-p8+round(best_ode/sf); _od_p=p8+round(best_ode/sf); + _oh_m =-p9+round(best_ohe/sf); _oh_p=p9+round(best_ohe/sf); + + double md,mh; + for (_deo=_deo_m; _deo<=_deo_p; _deo++) + for (_pd=_pd_m; _pd<=_pd_p; _pd++) + for (_pz=_pz_m; _pz<=_pz_p; _pz++) + for (_pe=_pe_m; _pe<=_pe_p; _pe++) + for (_df=_df_m; _df<=_df_p; _df++) + for (_ff=_ff_m; _ff<=_ff_p; _ff++) + for (_tf=_tf_m; _tf<=_tf_p; _tf++) + for (_ohe=_oh_m; _ohe<=_oh_p; _ohe++) + for (_ode=_od_m; _ode<=_od_p; _ode++) { + ode=((((double)_ode)*sf)/(3600.0*Rad)); + odw=-ode; + ohe=((((double)_ohe)*sf)/(3600.0*Rad)); + ohw=ohe; + + // check the combinations for all samples + for (l=0; lPI) delta[l].ha=delta[l].ha-PI*2.0; + if (delta[l].ha<-PI) delta[l].ha=delta[l].ha+PI*2.0; + delta[l].dec=actual[l].dec-(md-d1); + delta[l].side=mount[l].side; + } + + // calculate the standard deviations + sum1=0.0; for (l=0; l50) return; + step++; + + if (step==1) { + num=n; // how many stars? + + best_dist =3600.0*180.0; + best_deo =0.0; + best_pd =0.0; + best_pz =0.0; + best_pe =0.0; + best_tf =0.0; + best_ff =0.0; + best_df =0.0; + best_ode =0.0; + best_ohe =0.0; + + // figure out the average HA offset as a starting point + ohe=0; + for (l=1; lPI) h1=h1-PI*2.0; + if (h1<-PI) h1=h1+PI*2.0; + ohe=ohe+h1; + } + ohe=ohe/num; best_ohe=round(ohe*Rad*3600.0); best_ohw=best_ohe; + +#if defined(MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) || defined(MOUNT_TYPE_ALTAZM) + Ff=1; Df=0; +#else + Ff=0; Df=1; +#endif + } + +#ifdef HAL_SLOW_PROCESSOR + // search, this can handle about 4.5 degrees of polar misalignment, and 1 degree of cone error + // DoPdPzPeTfFfDfOdOh + if (step==2) do_search( 8192,0,0,1,1,0,0,0,1,1); + if (step==4) do_search( 4096,0,0,1,1,0,0,0,1,1); + if (step==6) do_search( 2048,1,0,1,1,0,0,0,1,1); + if (step==20) do_search( 1024,1,0,1,1,0,0,0,1,1); + if (step==30) do_search( 512,1,0,1,1,0,0,0,1,1); + if (step==40) do_search( 256,1,0,1,1,0,0,0,1,1); +#elif HAL_FAST_PROCESSOR + // search, this can handle about 9 degrees of polar misalignment, and 2 degrees of cone error, 8' of FF/DF/PD + // DoPdPzPeTfFf Df OdOh + if (step==2) do_search(16384,0,0,1,1,0, 0, 0,1,1); + if (step==4) do_search( 8192,0,0,1,1,0, 0, 0,1,1); + if (step==6) do_search( 4096,1,0,1,1,0, 0, 0,1,1); + if (step==8) do_search( 2048,1,0,1,1,0, 0, 0,1,1); + if (step==10) do_search( 1024,1,0,1,1,0, 0, 0,1,1); + if (step==15) do_search( 512,1,0,1,1,0, 0, 0,1,1); + if (num>4) { + if (step==20) do_search( 256,1,1,1,1,0,Ff,Df,1,1); + if (step==30) do_search( 128,1,1,1,1,0,Ff,Df,1,1); + if (step==40) do_search( 64,1,1,1,1,0,Ff,Df,1,1); + } else { + if (step==20) do_search( 256,1,0,1,1,0, 0, 0,1,1); + if (step==30) do_search( 128,1,0,1,1,0, 0, 0,1,1); + if (step==40) do_search( 64,1,0,1,1,0, 0, 0,1,1); + } +#else + // search, this can handle about 9 degrees of polar misalignment, and 2 degrees of cone error + // DoPdPzPeTfFf Df OdOh + if (step==2) do_search(16384,0,0,1,1,0, 0, 0,1,1); + if (step==4) do_search( 8192,0,0,1,1,0, 0, 0,1,1); + if (step==6) do_search( 4096,1,0,1,1,0, 0, 0,1,1); + if (step==8) do_search( 2048,1,0,1,1,0, 0, 0,1,1); + if (step==10) do_search( 1024,1,0,1,1,0, 0, 0,1,1); + if (step==20) do_search( 512,1,0,1,1,0, 0, 0,1,1); + if (step==30) do_search( 256,1,0,1,1,0, 0, 0,1,1); + if (step==40) do_search( 128,1,0,1,1,0, 0, 0,1,1); +#endif + + if (step==50) { + // geometric corrections + doCor=best_deo/3600.0; + pdCor=best_pd/3600.0; + azmCor=best_pz/3600.0; + altCor=best_pe/3600.0; + + tfCor=best_tf/3600.0; +#if defined(MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) || defined(MOUNT_TYPE_ALTAZM) + dfCor=best_df/3600.0; +#else + dfCor=best_ff/3600.0; +#endif + + ax1Cor=best_ohw/3600.0; + ax2Cor=best_odw/3600.0; + + geo_ready=true; + } +} + +// takes the topocentric refracted coordinates and applies corrections to arrive at instrument equatorial coordinates +void TGeoAlign::EquToInstr(double Lat, double HA, double Dec, double *HA1, double *Dec1, int PierSide) { + double p=1.0; if (PierSide==PierSideWest) p=-1.0; + + if (Dec>90.0) Dec=90.0; + if (Dec<-90.0) Dec=-90.0; + + // breaks-down near the pole (limited to >1' from pole) + if (abs(Dec)<89.9833) { + + // initial rough guess at instrument HA,Dec + double h=HA/Rad; + double d=Dec/Rad; + + for (int pass=0; pass<3; pass++) { + double sinDec=sin(d); + double cosDec=cos(d); + double sinHA =sin(h); + double cosHA =cos(h); + + // ------------------------------------------------------------ + // misalignment due to tube/optics not being perp. to Dec axis + // negative numbers are further (S) from the NCP, swing to the + // equator and the effect on declination is 0. At the SCP it + // becomes a (N) offset. Unchanged with meridian flips. + // expressed as a correction to the Polar axis misalignment + double DOh=doCor*(1.0/cosDec)*p; + + // ------------------------------------------------------------ + // misalignment due to Dec axis being perp. to RA axis + double PDh=-pdCor*(sinDec/cosDec)*p; + + #if defined (MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) + // Fork flex + double DFd=dfCor*cosHA; + #else + // Axis flex + double DFd=-dfCor*(cosLat*cosHA+sinLat*(sinDec/cosDec)); + #endif + + // Tube flex + double TFh=tfCor*(cosLat*sinHA*(1.0/cosDec)); + double TFd=tfCor*(cosLat*cosHA-sinLat*cosDec); + + // polar misalignment + double h1=-azmCor*cosHA*(sinDec/cosDec) + altCor*sinHA*(sinDec/cosDec); + double d1=+azmCor*sinHA + altCor*cosHA; + *HA1 =HA +(h1+PDh+DOh+TFh); + *Dec1=Dec+(d1+DFd+TFd); + + // improved guess at instrument HA,Dec + h=*HA1/Rad; + d=*Dec1/Rad; + } + } else { + // just ignore the the correction if right on the pole + *HA1 =HA; + *Dec1=Dec; + } + + // finally, apply the index offsets + *HA1=*HA1-ax1Cor; + *Dec1=*Dec1-ax2Cor*-p; +} + +// takes the instrument equatorial coordinates and applies corrections to arrive at topocentric refracted coordinates +void TGeoAlign::InstrToEqu(double Lat, double HA, double Dec, double *HA1, double *Dec1, int PierSide) { + double p=1.0; if (PierSide==PierSideWest) p=-1.0; + + HA =HA +ax1Cor; + Dec=Dec+ax2Cor*-p; + if (Dec>90.0) Dec=90.0; + if (Dec<-90.0) Dec=-90.0; + + // breaks-down near the pole (limited to >1' from pole) + if (abs(Dec)<89.98333333) { + double h=HA/Rad; + double d=Dec/Rad; + double sinDec=sin(d); + double cosDec=cos(d); + double sinHA =sin(h); + double cosHA =cos(h); + + // ------------------------------------------------------------ + // misalignment due to tube/optics not being perp. to Dec axis + // negative numbers are further (S) from the NCP, swing to the + // equator and the effect on declination is 0. At the SCP it + // becomes a (N) offset. Unchanged with meridian flips. + // expressed as a correction to the Polar axis misalignment + double DOh=doCor*(1.0/cosDec)*p; + + // as the above offset becomes zero near the equator, the affect + // works on HA instead. meridian flips affect this in HA + double PDh=-pdCor*(sinDec/cosDec)*p; + +#if defined (MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) + // Fork flex + double DFd=dfCor*cosHA; +#else + // Axis flex + double DFd=-dfCor*(cosLat*cosHA+sinLat*(sinDec/cosDec)); +#endif + + // Tube flex + double TFh=tfCor*(cosLat*sinHA*(1.0/cosDec)); + double TFd=tfCor*(cosLat*cosHA-sinLat*cosDec); + + // ------------------------------------------------------------ + // polar misalignment + double h1=-azmCor*cosHA*(sinDec/cosDec) + altCor*sinHA*(sinDec/cosDec); + double d1=+azmCor*sinHA + altCor*cosHA; + + *HA1 =HA -(h1+PDh+DOh+TFh); + *Dec1=Dec-(d1+DFd+TFd); + } else { + // just ignore the the correction if right on the pole + *HA1=HA; + *Dec1=Dec; + } + + while (*HA1>180.0) *HA1-=360.0; + while (*HA1<-180.0) *HA1+=360.0; + if (*Dec1>90.0) *Dec1=90.0; + if (*Dec1<-90.0) *Dec1=-90.0; +} +#endif + diff --git a/AlignHor.ino b/AlignHor.ino new file mode 100644 index 000000000..e3279a828 --- /dev/null +++ b/AlignHor.ino @@ -0,0 +1,499 @@ +// ----------------------------------------------------------------------------------- +// GEOMETRIC ALIGN FOR ALT/AZ +// +// by Howard Dutton +// +// Copyright (C) 2012 to 2018 Howard Dutton +// + +// ----------------------------------------------------------------------------------- +// ADVANCED GEOMETRIC ALIGN FOR ALT/AZ MOUNTS (GOTO ASSIST) + +#ifdef MOUNT_TYPE_ALTAZM +#define GOTO_ASSIST_DEBUG_OFF + +// Initialize +void TGeoAlignH::init() { + avgAlt=0.0; + avgAzm=0.0; + + ax1Cor=0; // align internal index for Axis1 + ax2Cor=0; // align internal index for Axis2 + altCor=0; // for geometric coordinate correction/align, - is below the Zenith, + above + azmCor=0; // - is right of the Zenith, + is left + doCor =0; // altitude axis/optics orthogonal correction + pdCor =0; // altitude axis/Azimuth orthogonal correction + dfCor =0; // altitude axis axis flex + tfCor =0; // tube flex + + geo_ready=false; +} + +// remember the alignment between sessions +void TGeoAlignH::readCoe() { + ax1Cor=nv.readFloat(EE_ax1Cor); + ax2Cor=nv.readFloat(EE_ax2Cor); + dfCor=nv.readFloat(EE_dfCor); // dfCor is ffCor for fork mounts + tfCor=nv.readFloat(EE_tfCor); + doCor=nv.readFloat(EE_doCor); + pdCor=nv.readFloat(EE_pdCor); + altCor=nv.readFloat(EE_altCor); + azmCor=nv.readFloat(EE_azmCor); +} + +void TGeoAlignH::writeCoe() { + nv.writeFloat(EE_ax1Cor,ax1Cor); + nv.writeFloat(EE_ax2Cor,ax2Cor); + nv.writeFloat(EE_dfCor,dfCor); // dfCor is ffCor for fork mounts + nv.writeFloat(EE_tfCor,tfCor); + nv.writeFloat(EE_doCor,doCor); + nv.writeFloat(EE_pdCor,pdCor); + nv.writeFloat(EE_altCor,altCor); + nv.writeFloat(EE_azmCor,azmCor); +} + +// Status +bool TGeoAlignH::isReady() { + return geo_ready; +} + +/* +Alignment Logic: +Near the celestial equator (Dec=0, HA=0)... +the azmCor term is 0% in Dec +the altCor term is 100% in Dec +the doCor term is 100% in HA +the pdCor term is 0% in HA + +Near HA=6 and Dec=45... +the azmCor term is 100% in Dec +the altCor term is 0% in Dec +the doCor term is 0% in HA +the pdCor term is 100% in HA +*/ + +// I=1 for 1st star, I=2 for 2nd star, I=3 for 3rd star +// N=total number of stars for this align (1 to 9) +// RA, Dec (all in degrees) +bool TGeoAlignH::addStar(int I, int N, double RA, double Dec) { + double a,z; + EquToHor(haRange(LST()*15.0-RA),Dec,&a,&z); + + // First star: + // Near the celestial equator (Dec=0, HA=0), telescope West of the pier if multi-star align + if (I==1) { + // set the indexAxis1/2 offset + if (syncEqu(RA,Dec)!=0) return true; + } + + mount[I-1].azm=getInstrAxis1(); + mount[I-1].alt=getInstrAxis2(); + HorToEqu(mount[I-1].alt,mount[I-1].azm,&mount[I-1].ha,&mount[I-1].dec); + mount[I-1].azm=mount[I-1].azm/Rad; + mount[I-1].alt=mount[I-1].alt/Rad; + mount[I-1].ha=degRange(mount[I-1].ha)/Rad; + mount[I-1].dec=mount[I-1].dec/Rad; + + actual[I-1].ha =haRange(LST()*15.0-RA); + actual[I-1].dec=Dec; + EquToHor(actual[I-1].ha,actual[I-1].dec,&actual[I-1].alt,&actual[I-1].azm); + actual[I-1].alt=actual[I-1].alt/Rad; + actual[I-1].azm=actual[I-1].azm/Rad; + actual[I-1].ha =degRange(actual[I-1].ha)/Rad; + actual[I-1].dec=actual[I-1].dec/Rad; + + if (getInstrPierSide()==PierSideWest) { actual[I-1].side=-1; mount[I-1].side=-1; } else + if (getInstrPierSide()==PierSideEast) { actual[I-1].side=1; mount[I-1].side=1; } else { actual[I-1].side=0; mount[I-1].side=0; } + + // two or more stars and finished + if ((I>=2) && (I==N)) { +#ifdef GOTO_ASSIST_DEBUG_ON + DL(""); +#endif + autoModel(N,true); + } + + return true; +} + +// returns the correction to be added to the requested RA,Dec to yield the actual RA,Dec that we will arrive at +void TGeoAlignH::correct(double azm, double alt, double pierSide, double sf, double _deo, double _pd, double _pz, double _pe, double _da, double _ff, double _tf, double *z1, double *a1) { + double DO1,DOh; + double PD,PDh; + double PZ,PA; + double DF,DFd,TF,FF,FFd,TFh,TFd; + double lat; + + lat=90.0; // 90 deg. latitude for Alt/Azm + +// ------------------------------------------------------------ +// A. Misalignment due to tube/optics not being perp. to Dec axis +// negative numbers are further (S) from the NCP, swing to the +// equator and the effect on declination is 0. At the SCP it +// becomes a (N) offset. Unchanged with meridian flips. + DO1 =((_deo*sf)/3600.0)/Rad; +// works on HA. meridian flips effect this in HA + DOh = DO1*(1.0/cos(alt))*pierSide; + +// ------------------------------------------------------------ +// B. Misalignment, Declination axis relative to Polar axis +// expressed as a correction to where the Polar axis is pointing +// negative numbers are further (S) from the NCP, swing to the +// equator and the effect on declination is 0. +// At the SCP it is, again, a (S) offset + PD =((_pd*sf)/3600.0)/Rad; +// works on HA. + PDh = -PD*tan(alt)*pierSide; + +// ------------------------------------------------------------ +// Misalignment, relative to NCP +// negative numbers are east of the pole +// C. polar left-right misalignment + PZ =((_pz*sf)/3600.0)/Rad; +// D. negative numbers are below the pole +// polar below-above misalignment + PA =((_pe*sf)/3600.0)/Rad; + +// ------------------------------------------------------------ +// Axis flex + DF =((_da*sf)/3600.0)/Rad; + DFd =-DF*(cos(lat)*cos(azm)+sin(lat)*tan(alt)); + +// ------------------------------------------------------------ +// Fork flex + FF =((_ff*sf)/3600.0)/Rad; + FFd =FF*cos(azm); + +// ------------------------------------------------------------ +// Optical axis sag + TF =((_tf*sf)/3600.0)/Rad; + + TFh =TF*(cos(lat)*sin(azm)*(1.0/cos(alt))); + TFd =TF*(cos(lat)*cos(azm)-sin(lat)*cos(alt)); + +// ------------------------------------------------------------ + *z1 =(-PZ*cos(azm)*tan(alt) + PA*sin(azm)*tan(alt) + DOh + PDh + TFh); + *a1 =(+PZ*sin(azm) + PA*cos(azm) + DFd + FFd + TFd); +} + +void TGeoAlignH::do_search(double sf, int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9) +{ + long l, + + _deo_m,_deo_p, + _pd_m,_pd_p, + _pz_m,_pz_p, + _pe_m,_pe_p, + _df_m,_df_p, + _tf_m,_tf_p, + _ff_m,_ff_p, + _oh_m,_oh_p, + _od_m,_od_p, + + _deo,_pd,_pz,_pe, _df,_tf,_ff, _ode,_ohe; + + // search + // set Parameter Space + _deo_m=-p1+round(best_deo/sf); _deo_p=p1+round(best_deo/sf); + _pd_m =-p2+round(best_pd/sf); _pd_p=p2+round(best_pd/sf); + _pz_m =-p3+round(best_pz/sf); _pz_p=p3+round(best_pz/sf); + _pe_m =-p4+round(best_pe/sf); _pe_p=p4+round(best_pe/sf); + _tf_m =-p5+round(best_tf/sf); _tf_p=p5+round(best_tf/sf); + _ff_m =-p6+round(best_ff/sf); _ff_p=p6+round(best_ff/sf); + _df_m =-p7+round(best_df/sf); _df_p=p7+round(best_df/sf); + _od_m =-p8+round(best_ode/sf); _od_p=p8+round(best_ode/sf); + _oh_m =-p9+round(best_ohe/sf); _oh_p=p9+round(best_ohe/sf); + + double ma,mz; + for (_deo=_deo_m; _deo<=_deo_p; _deo++) + for (_pd=_pd_m; _pd<=_pd_p; _pd++) + for (_pz=_pz_m; _pz<=_pz_p; _pz++) + for (_pe=_pe_m; _pe<=_pe_p; _pe++) + for (_df=_df_m; _df<=_df_p; _df++) + for (_ff=_ff_m; _ff<=_ff_p; _ff++) + for (_tf=_tf_m; _tf<=_tf_p; _tf++) + for (_ohe=_oh_m; _ohe<=_oh_p; _ohe++) + for (_ode=_od_m; _ode<=_od_p; _ode++) { + ode=((((double)_ode)*sf)/(3600.0*Rad)); + odw=-ode; + ohe=((((double)_ohe)*sf)/(3600.0*Rad)); + ohw=ohe; + + // check the combinations for all samples + for (l=0; lPI) delta[l].azm=delta[l].azm-PI*2.0; + if (delta[l].azm<-PI) delta[l].azm=delta[l].azm+PI*2.0; + delta[l].alt=actual[l].alt-(ma-a1); + delta[l].side=mount[l].side; + } + + // calculate the standard deviations + sum1=0.0; for (l=0; l50) return; + step++; + + if (step==1) { + num=n; // how many stars? + + best_dist =3600.0*180.0; + best_deo =0.0; + best_pd =0.0; + best_pz =0.0; + best_pe =0.0; + best_tf =0.0; + best_ff =0.0; + best_df =0.0; + best_ode =0.0; + best_ohe =0.0; + + // figure out the average HA offset as a starting point + ohe=0; + for (l=1; lPI) z1=z1-PI*2.0; + if (z1<-PI) z1=z1+PI*2.0; + ohe=ohe+z1; + } + ohe=ohe/num; best_ohe=round(ohe*Rad*3600.0); best_ohw=best_ohe; + +#if defined(MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) || defined(MOUNT_TYPE_ALTAZM) + Ff=1; Df=0; +#else + Ff=0; Df=1; +#endif + } + +#ifdef HAL_SLOW_PROCESSOR + // search, this can handle about 4.5 degrees of polar misalignment, and 1 degree of cone error + // DoPdPzPeTfFfDfOdOh + if (step==2) do_search( 8192,0,0,1,1,0,0,0,1,1); + if (step==4) do_search( 4096,0,0,1,1,0,0,0,1,1); + if (step==6) do_search( 2048,1,0,1,1,0,0,0,1,1); + if (step==20) do_search( 1024,1,0,1,1,0,0,0,1,1); + if (step==30) do_search( 512,1,0,1,1,0,0,0,1,1); + if (step==40) do_search( 256,1,0,1,1,0,0,0,1,1); +#elif HAL_FAST_PROCESSOR + // search, this can handle about 9 degrees of polar misalignment, and 2 degrees of cone error, 8' of FF/DF/PD + // DoPdPzPeTfFf Df OdOh + if (step==2) do_search(16384,0,0,1,1,0, 0, 0,1,1); + if (step==4) do_search( 8192,0,0,1,1,0, 0, 0,1,1); + if (step==6) do_search( 4096,1,0,1,1,0, 0, 0,1,1); + if (step==8) do_search( 2048,1,0,1,1,0, 0, 0,1,1); + if (step==10) do_search( 1024,1,0,1,1,0, 0, 0,1,1); + if (step==15) do_search( 512,1,0,1,1,0, 0, 0,1,1); + if (num>4) { + if (step==20) do_search( 256,1,1,1,1,0,Ff,Df,1,1); + if (step==30) do_search( 128,1,1,1,1,0,Ff,Df,1,1); + if (step==40) do_search( 64,1,1,1,1,0,Ff,Df,1,1); + } else { + if (step==20) do_search( 256,1,0,1,1,0, 0, 0,1,1); + if (step==30) do_search( 128,1,0,1,1,0, 0, 0,1,1); + if (step==40) do_search( 64,1,0,1,1,0, 0, 0,1,1); + } +#else + // search, this can handle about 9 degrees of polar misalignment, and 2 degrees of cone error + // DoPdPzPeTfFf Df OdOh + if (step==2) do_search(16384,0,0,1,1,0, 0, 0,1,1); + if (step==4) do_search( 8192,0,0,1,1,0, 0, 0,1,1); + if (step==6) do_search( 4096,1,0,1,1,0, 0, 0,1,1); + if (step==8) do_search( 2048,1,0,1,1,0, 0, 0,1,1); + if (step==10) do_search( 1024,1,0,1,1,0, 0, 0,1,1); + if (step==20) do_search( 512,1,0,1,1,0, 0, 0,1,1); + if (step==30) do_search( 256,1,0,1,1,0, 0, 0,1,1); + if (step==40) do_search( 128,1,0,1,1,0, 0, 0,1,1); +#endif + + if (step==50) { + // geometric corrections + doCor=best_deo/3600.0; + pdCor=best_pd/3600.0; + azmCor=best_pz/3600.0; + altCor=best_pe/3600.0; + + tfCor=best_tf/3600.0; +#if defined(MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) || defined(MOUNT_TYPE_ALTAZM) + dfCor=best_df/3600.0; +#else + dfCor=best_ff/3600.0; +#endif + + ax1Cor=best_ohw/3600.0; + ax2Cor=best_odw/3600.0; + + geo_ready=true; + } +} + +void TGeoAlignH::HorToInstr(double Alt, double Azm, double *Alt1, double *Azm1, int PierSide) { + double p=1.0; if (PierSide==PierSideWest) p=-1.0; + + double cosLat=cos(90.0/Rad); double sinLat=sin(90.0/Rad); + + if (Alt>90.0) Alt=90.0; + if (Alt<-90.0) Alt=-90.0; + + // breaks-down near the Zenith (limited to >1' from Zenith) + if (abs(Alt)<89.98333333) { + + // initial rough guess at instrument HA,Dec + double z=Azm/Rad; + double a=Alt/Rad; + + for (int pass=0; pass<3; pass++) { + double sinAlt=sin(a); + double cosAlt=cos(a); + double sinAzm=sin(z); + double cosAzm=cos(z); + + // ------------------------------------------------------------ + // misalignment due to tube/optics not being perp. to Alt axis + // negative numbers are further (down) from the Zenith, swing to the + // horizon and the effect on Alt is 0. At the Nadir it + // becomes an (up) offset. Unchanged with meridian flips. + // expressed as a correction to the Zenith axis misalignment + double DOh=doCor*(1.0/cosAlt)*p; + + // ------------------------------------------------------------ + // misalignment due to Alt axis being perp. to Azm axis + double PDh=-pdCor*(sinAlt/cosAlt)*p; + + #if defined (MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) + // Fork flex + double DFd=dfCor*cosAzm; + #else + // Axis flex + double DFd=-dfCor*(cosLat*cosAzm+sinLat*(sinAlt/cosAlt)); + #endif + + // Tube flex + double TFh=tfCor*(cosLat*sinAzm*(1.0/cosAlt)); + double TFd=tfCor*(cosLat*cosAzm-sinLat*cosAlt); + + // polar misalignment + double z1=-azmCor*cosAzm*(sinAlt/cosAlt) + altCor*sinAzm*(sinAlt/cosAlt); + double a1=+azmCor*sinAzm + altCor*cosAzm; + *Azm1=Azm + (z1+PDh+DOh+TFh); + *Alt1=Alt + (a1+DFd+TFd); + + // improved guess at instrument Alt,Azm + z=*Azm1/Rad; + a=*Alt1/Rad; + } + } else { + // just ignore the the correction if right on the pole + *Azm1=Azm; + *Alt1=Alt; + } + + // finally, apply the index offsets + *Azm1=*Azm1-ax1Cor; + *Alt1=*Alt1-ax2Cor*-p; +} + +// takes the instrument equatorial coordinates and applies corrections to arrive at topocentric refracted coordinates +void TGeoAlignH::InstrToHor(double Alt, double Azm, double *Alt1, double *Azm1, int PierSide) { + double p=1.0; if (PierSide==PierSideWest) p=-1.0; + + double cosLat=cos(90.0/Rad); double sinLat=sin(90.0/Rad); + + Azm=Azm+ax1Cor; + Alt=Alt+ax2Cor*-p; + + if (Alt>90.0) Alt=90.0; + if (Alt<-90.0) Alt=-90.0; + + // breaks-down near the Zenith (limited to >1' from Zenith) + if (abs(Alt)<89.98333333) { + double z=Azm/Rad; + double a=Alt/Rad; + double sinAlt=sin(a); + double cosAlt=cos(a); + double sinAzm=sin(z); + double cosAzm=cos(z); + + // ------------------------------------------------------------ + // misalignment due to tube/optics not being perp. to Alt axis + // negative numbers are further (S) from the Zenith, swing to the + // horizon and the effect on Alt is 0. At the Nadir it + // becomes a (N) offset. Unchanged with meridian flips. + // expressed as a correction to the Azm axis misalignment + double DOh=doCor*(1.0/cosAlt)*p; + + // as the above offset becomes zero near the horizon, the affect + // works on Azm instead. meridian flips affect this in Azm + double PDh=-pdCor*(sinAlt/cosAlt)*p; + +#if defined (MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) + // Fork flex + double DFd=dfCor*cosAzm; +#else + // Axis flex + double DFd=-dfCor*(cosLat*cosAzm+sinLat*(sinAlt/cosAlt)); +#endif + + // Tube flex + double TFh=tfCor*(cosLat*sinAzm*(1.0/cosAlt)); + double TFd=tfCor*(cosLat*cosAzm-sinLat*cosAlt); + + // ------------------------------------------------------------ + // polar misalignment + double z1=-azmCor*cosAzm*(sinAlt/cosAlt) + altCor*sinAzm*(sinAlt/cosAlt); + double a1=+azmCor*sinAzm + altCor*cosAzm; + + *Azm1=Azm - (z1+PDh+DOh+TFh); + *Alt1=Alt - (a1+DFd+TFd); + } else { + // just ignore the the correction if right on the pole + *Azm1=Azm; + *Alt1=Alt; + } + + while (*Azm1>360.0) *Azm1-=360.0; + while (*Azm1<-360.0) *Azm1+=360.0; + if (*Alt1>90.0) *Alt1=90.0; + if (*Alt1<-90.0) *Alt1=-90.0; +} +#endif + diff --git a/Astro.ino b/Astro.ino index 7208899f2..8e486814e 100644 --- a/Astro.ino +++ b/Astro.ino @@ -42,7 +42,7 @@ boolean hmsToDouble(double *f, char *hms) { return true; } -boolean doubleToHms(char *reply, double *f) { +boolean doubleToHms(char *reply, double *f, boolean hp) { double h1,m1,f1,s1; f1=fabs(*f)+0.000139; // round to 1/2 arc-sec @@ -52,7 +52,7 @@ boolean doubleToHms(char *reply, double *f) { s1=(m1-floor(m1)); char s[]="%s%02d:%02d:%02d"; - if (highPrecision) { + if (hp) { s1=s1*60.0; } else { s1=s1*10.0; @@ -462,7 +462,7 @@ boolean do_refractionRate_calc() { // get the instrument coordinates if ((rr_step==10) || (rr_step==110)) { if (ot) { - GeoAlign.EquToInstr(latitude,rr_HA,rr_Dec,&rr_HA,&rr_Dec); + Align.EquToInstr(latitude,rr_HA,rr_Dec,&rr_HA,&rr_Dec,getInstrPierSide()); rr_HA+=indexAxis1; rr_Dec+=indexAxis2; } } @@ -523,7 +523,7 @@ boolean do_refractionRate_calc() { #ifdef MOUNT_TYPE_ALTAZM -#define AltAzTrackingRange 10 // distance in arc-min (20) ahead of and behind the current Equ position, used for rate calculation +#define AltAzTrackingRange 10 // distance in arc-min (10) ahead of and behind the current Equ position, used for rate calculation boolean do_altAzmRate_calc() { boolean done=false; @@ -661,7 +661,12 @@ double cot(double n) { // Acceleration rate calculation void SetAccelerationRates(double maxRate) { - // set the new acceleration rate + + // set the new guide acceleration rate +// slewRateX = (RateToXPerSec/(maxRate/16.0))*2.0; // double since exponential factor slows by about 1/2 +// accXPerSec = slewRateX/DegreesForAcceleration; +// guideRates[9]=RateToASPerSec/(maxRate/16.0); guideRates[8]=guideRates[9]/2.0; + // set the new goto acceleration rate cli(); StepsForRateChangeAxis1= (sqrt((double)DegreesForAcceleration*(double)StepsPerDegreeAxis1))*maxRate; @@ -707,3 +712,5 @@ void soundClick() { #endif } } + + diff --git a/Command.ino b/Command.ino index 61db6e2b6..d14aa5c4c 100644 --- a/Command.ino +++ b/Command.ino @@ -168,22 +168,9 @@ void processCommands() { // after last star turn meridian flips off when align is done if ((alignNumStars==alignThisStar) && (meridianFlip==MeridianFlipAlign)) meridianFlip=MeridianFlipNever; -#ifdef MOUNT_TYPE_ALTAZM - // AltAz Taki method - if ((alignNumStars>1) && (alignThisStar<=alignNumStars)) { - cli(); - // get the Azm/Alt - double F=(double)(posAxis1+indexAxis1Steps)/(double)StepsPerDegreeAxis1; - double H=(double)(posAxis2+indexAxis2Steps)/(double)StepsPerDegreeAxis2; - sei(); - // B=RA, D=Dec, H=Elevation (instr), F=Azimuth (instr), all in degrees - Align.addStar(alignThisStar,alignNumStars,haRange(LST()*15.0-newTargetRA),newTargetDec,H,F); - alignThisStar++; - } else -#endif if (alignThisStar<=alignNumStars) { - // RA, Dec (in degrees) - if (GeoAlign.addStar(alignThisStar,alignNumStars,newTargetRA,newTargetDec)) alignThisStar++; else commandError=true; + // AltAz or Equ mode + if (Align.addStar(alignThisStar,alignNumStars,newTargetRA,newTargetDec)) alignThisStar++; else commandError=true; } else commandError=true; if (commandError) { alignNumStars=0; alignThisStar=0; } @@ -437,7 +424,7 @@ void processCommands() { if (command[1]=='A') { getHor(&f,&f1); if (!doubleToDms(reply,&f,false,true)) commandError=true; else quietReply=true; } else // :Ga# Get Local Time in 12 hour format // Returns: HH:MM:SS# - if (command[1]=='a') { i=highPrecision; highPrecision=true; LMT=timeRange(UT1-timeZone); if (LMT>12.0) LMT-=12.0; if (!doubleToHms(reply,&LMT)) commandError=true; else quietReply=true; highPrecision=i; } else + if (command[1]=='a') { LMT=timeRange(UT1-timeZone); if (LMT>12.0) LMT-=12.0; if (!doubleToHms(reply,&LMT,true)) commandError=true; else quietReply=true; } else // :GC# Get the current date // Returns: MM/DD/YY# // The current local calendar date @@ -495,7 +482,7 @@ void processCommands() { // Returns: HH:MM:SS# // On devices with single precision fp several days up-time will cause loss of precision as additional mantissa digits are needed to represent hours // Devices with double precision fp are limitated by sidereal clock overflow which takes 249 days - if (command[1]=='L') { i=highPrecision; highPrecision=true; LMT=timeRange(UT1-timeZone); if (!doubleToHms(reply,&LMT)) commandError=true; else quietReply=true; highPrecision=i; } else + if (command[1]=='L') { LMT=timeRange(UT1-timeZone); if (!doubleToHms(reply,&LMT,true)) commandError=true; else quietReply=true; } else // :GM# Get Site 1 Name // :GN# Get Site 2 Name // :GO# Get Site 3 Name @@ -513,9 +500,9 @@ void processCommands() { // A # terminated string with the pier side. if (command[1]=='m') { reply[0]='?'; reply[1]=0; - if (pierSide==PierSideNone) reply[0]='N'; - if (pierSide==PierSideEast) reply[0]='E'; - if (pierSide==PierSideWest) reply[0]='W'; + if (getInstrPierSide()==PierSideNone) reply[0]='N'; + if (getInstrPierSide()==PierSideEast) reply[0]='E'; + if (getInstrPierSide()==PierSideWest) reply[0]='W'; quietReply=true; } else // :Go# Get Overhead Limit // Returns: DD*# @@ -533,15 +520,15 @@ void processCommands() { getEqu(&f,&f1,false); f/=15.0; _ra=f; _dec=f1; _coord_t=millis(); } - if (!doubleToHms(reply,&f)) commandError=true; else quietReply=true; + if (!doubleToHms(reply,&f,highPrecision)) commandError=true; else quietReply=true; } else // :Gr# Get current/target object RA // Returns: HH:MM.T# or HH:MM:SS (based on precision setting) - if (command[1]=='r') { f=newTargetRA; f/=15.0; if (!doubleToHms(reply,&f)) commandError=true; else quietReply=true; } else + if (command[1]=='r') { f=newTargetRA; f/=15.0; if (!doubleToHms(reply,&f,highPrecision)) commandError=true; else quietReply=true; } else // :GS# Get the Sidereal Time // Returns: HH:MM:SS# // The Sidereal Time as an ASCII Sexidecimal value in 24 hour format - if (command[1]=='S') { i=highPrecision; highPrecision=true; f=LST(); if (!doubleToHms(reply,&f)) commandError=true; else quietReply=true; highPrecision=i; } else + if (command[1]=='S') { f=LST(); if (!doubleToHms(reply,&f,true)) commandError=true; else quietReply=true; } else // :GT# Get tracking rate // Returns: dd.ddddd# (OnStep returns more decimal places than LX200 standard) // Returns the tracking rate if siderealTracking, 0.0 otherwise @@ -626,24 +613,32 @@ void processCommands() { } else // :GXnn# Get OnStep value // Returns: value - if (command[1]=='X') { + if (command[1]=='X') { if (parameter[2]==(char)0) { if (parameter[0]=='0') { // 0n: Align Model + static int star=0; switch (parameter[1]) { - case '0': sprintf(reply,"%ld",(long)(indexAxis1*3600.0)); quietReply=true; break; // indexAxis1 - case '1': sprintf(reply,"%ld",(long)(indexAxis2*3600.0)); quietReply=true; break; // indexAxis2 - case '2': sprintf(reply,"%ld",(long)(GeoAlign.altCor*3600.0)); quietReply=true; break; // altCor - case '3': sprintf(reply,"%ld",(long)(GeoAlign.azmCor*3600.0)); quietReply=true; break; // azmCor - case '4': sprintf(reply,"%ld",(long)(GeoAlign.doCor*3600.0)); quietReply=true; break; // doCor - case '5': sprintf(reply,"%ld",(long)(GeoAlign.pdCor*3600.0)); quietReply=true; break; // pdCor + case '0': sprintf(reply,"%ld",(long)(Align.ax1Cor*3600.0)); quietReply=true; break; // ax1Cor + case '1': sprintf(reply,"%ld",(long)(Align.ax2Cor*3600.0)); quietReply=true; break; // ax2Cor + case '2': sprintf(reply,"%ld",(long)(Align.altCor*3600.0)); quietReply=true; break; // altCor + case '3': sprintf(reply,"%ld",(long)(Align.azmCor*3600.0)); quietReply=true; break; // azmCor + case '4': sprintf(reply,"%ld",(long)(Align.doCor*3600.0)); quietReply=true; break; // doCor + case '5': sprintf(reply,"%ld",(long)(Align.pdCor*3600.0)); quietReply=true; break; // pdCor #if defined(MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) - case '6': sprintf(reply,"%ld",(long)(GeoAlign.dfCor*3600.0)); quietReply=true; break; // ffCor - case '7': sprintf(reply,"%ld",(long)(0)); quietReply=true; break; // dfCor + case '6': sprintf(reply,"%ld",(long)(Align.dfCor*3600.0)); quietReply=true; break; // ffCor + case '7': sprintf(reply,"%ld",(long)(0)); quietReply=true; break; // dfCor #else - case '6': sprintf(reply,"%ld",(long)(0)); quietReply=true; break; // ffCor - case '7': sprintf(reply,"%ld",(long)(GeoAlign.dfCor*3600.0)); quietReply=true; break; // dfCor + case '6': sprintf(reply,"%ld",(long)(0)); quietReply=true; break; // ffCor + case '7': sprintf(reply,"%ld",(long)(Align.dfCor*3600.0)); quietReply=true; break; // dfCor #endif - case '8': sprintf(reply,"%ld",(long)(GeoAlign.tfCor*3600.0)); quietReply=true; break; // tfCor + case '8': sprintf(reply,"%ld",(long)(Align.tfCor*3600.0)); quietReply=true; break; // tfCor + + case '9': { int n=0; if (alignThisStar>alignNumStars) n=alignNumStars; sprintf(reply,"%ld",(long)(n)); star=0; quietReply=true; } break; // Number of stars, reset to first star + case 'A': { double f=(Align.actual[star].ha*Rad)/15.0; doubleToHms(reply,&f,true); quietReply=true; } break; // Star #n HA + case 'B': { double f=(Align.actual[star].dec*Rad); doubleToDms(reply,&f,false,true); quietReply=true; } break; // Star #n Dec + case 'C': { double f=(Align.mount[star].ha*Rad)/15.0; doubleToHms(reply,&f,true); quietReply=true; } break; // Mount #n HA + case 'D': { double f=(Align.mount[star].dec*Rad); doubleToDms(reply,&f,false,true); quietReply=true; } break; // Mount #n Dec + case 'E': sprintf(reply,"%ld",(long)(Align.mount[star].side)); star++; quietReply=true; break; // Mount PierSide (and increment n) default: commandError=true; } } else @@ -658,7 +653,7 @@ void processCommands() { } else if (parameter[0]=='8') { // 8n: Date/Time switch (parameter[1]) { - case '0': i=highPrecision; highPrecision=true; f=timeRange(UT1); doubleToHms(reply,&f); highPrecision=i; quietReply=true; break; // UTC time + case '0': f=timeRange(UT1); doubleToHms(reply,&f,true); quietReply=true; break; // UTC time case '1': f1=JD; f=UT1; while (f>=24.0) { f-=24.0; f1+=1; } while (f<0.0) { f+=24.0; f1-=1; } greg(f1,&i2,&i,&i1); i2=(i2/99.99999-floor(i2/99.99999))*100; sprintf(reply,"%d/%d/%d",i,i1,i2); quietReply=true; break; // UTC date default: commandError=true; } @@ -669,7 +664,7 @@ void processCommands() { case '1': sprintf(reply,"%i",pecAnalogValue); quietReply=true; break; // pec analog value case '2': sprintf(reply,"%ld",(long)(maxRate/16L)); quietReply=true; break; // MaxRate case '3': sprintf(reply,"%ld",(long)(MaxRate)); quietReply=true; break; // MaxRate (default) - case '4': if (meridianFlip==MeridianFlipNever) { sprintf(reply,"%d N",(int)(pierSide)); } else { sprintf(reply,"%d",(int)(pierSide)); } quietReply=true; break; // pierSide (N if never) + case '4': if (meridianFlip==MeridianFlipNever) { sprintf(reply,"%d N",getInstrPierSide()); } else { sprintf(reply,"%d",getInstrPierSide()); } quietReply=true; break; // pierSide (N if never) case '5': sprintf(reply,"%i",(int)autoMeridianFlip); quietReply=true; break; // autoMeridianFlip case '6': // preferred pier side if (preferredPierSide==PPS_EAST) strcpy(reply,"E"); else @@ -888,7 +883,7 @@ void processCommands() { strcat(reply,","); strcat(reply,objType); if (strcmp(reply,",UNK")!=0) { - f=newTargetRA; f/=15.0; doubleToHms(ws,&f); strcat(reply,","); strcat(reply,ws); + f=newTargetRA; f/=15.0; doubleToHms(ws,&f,highPrecision); strcat(reply,","); strcat(reply,ws); doubleToDms(ws,&newTargetDec,false,true); strcat(reply,","); strcat(reply,ws); } @@ -1035,8 +1030,8 @@ void processCommands() { getEqu(&r,&d,false); i=validateGoToEqu(r,d); if (i==0) { - GeoAlign.altCor=0.0; - GeoAlign.azmCor=0.0; + Align.altCor=0.0; + Align.azmCor=0.0; i=goToEqu(r,d); } reply[0]=i+'0'; reply[1]=0; @@ -1414,7 +1409,7 @@ void processCommands() { nv.writeFloat(100+(currentSite)*25+0,latitude); #ifdef MOUNT_TYPE_ALTAZM celestialPoleAxis2=AltAzmDecStartPos; - if (latitude<0) celestialPoleAxis1=180L; else celestialPoleAxis1=0L; + if (latitude<0) celestialPoleAxis1=180.0; else celestialPoleAxis1=0.0; #else if (latitude<0) celestialPoleAxis2=-90.0; else celestialPoleAxis2=90.0; #endif @@ -1446,21 +1441,28 @@ void processCommands() { if (command[1]=='X') { if (parameter[2]!=',') { parameter[0]=0; commandError=true; } // make sure command format is correct if (parameter[0]=='0') { // 0n: Align Model + static int star; switch (parameter[1]) { - case '0': indexAxis1=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // indexAxis1 - case '1': indexAxis2=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // indexAxis2 - case '2': GeoAlign.altCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // altCor - case '3': GeoAlign.azmCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // azmCor - case '4': GeoAlign.doCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // doCor - case '5': GeoAlign.pdCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // pdCor + case '0': Align.ax1Cor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // ax1Cor + case '1': Align.ax2Cor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // ax2Cor + case '2': Align.altCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // altCor + case '3': Align.azmCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // azmCor + case '4': Align.doCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // doCor + case '5': Align.pdCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // pdCor #if defined(MOUNT_TYPE_FORK) || defined(MOUNT_TYPE_FORK_ALT) - case '6': GeoAlign.dfCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // ffCor + case '6': Align.dfCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // ffCor case '7': break; // dfCor #else case '6': break; // ffCor - case '7': GeoAlign.dfCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // dfCor -#endif - case '8': GeoAlign.tfCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // tfCor + case '7': Align.dfCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // dfCor +#endif + case '8': Align.tfCor=(double)strtol(¶meter[3],NULL,10)/3600.0; break; // tfCor + case '9': { i=strtol(¶meter[3],NULL,10); if (i==1) { alignNumStars=star; alignThisStar=star+1; Align.autoModel(star,true); } else star=0; } break; // use 0 to start upload of stars for align, use 1 to trigger align + case 'A': { i=highPrecision; highPrecision=true; if (!hmsToDouble(&Align.actual[star].ha,¶meter[3])) commandError=true; else Align.actual[star].ha=(Align.actual[star].ha*15.0)/Rad; highPrecision=i; } break; // Star #n HA + case 'B': { i=highPrecision; highPrecision=true; if (!dmsToDouble(&Align.actual[star].dec,¶meter[3],true)) commandError=true; else Align.actual[star].dec=Align.actual[star].dec/Rad; highPrecision=i; } break; // Star #n Dec + case 'C': { i=highPrecision; highPrecision=true; if (!hmsToDouble(&Align.mount[star].ha,¶meter[3])) commandError=true; else Align.mount[star].ha=(Align.mount[star].ha*15.0)/Rad; highPrecision=i; } break; // Mount #n HA + case 'D': { i=highPrecision; highPrecision=true; if (!dmsToDouble(&Align.mount[star].dec,¶meter[3],true)) commandError=true; else Align.mount[star].dec=Align.mount[star].dec/Rad; highPrecision=i; } break; // Star #n Dec + case 'E': Align.actual[star].side=Align.mount[star].side=strtol(¶meter[3],NULL,10); star++; break; // Mount PierSide (and increment n) default: commandError=true; } } else @@ -1984,3 +1986,4 @@ bool cmdReply(char *s) { strcpy(s,_replyX); _replyX[0]=0; return true; } + diff --git a/Config.Classic.h b/Config.Classic.h index 523cd5126..44fe9eb2e 100644 --- a/Config.Classic.h +++ b/Config.Classic.h @@ -16,10 +16,6 @@ // ------------------------------------------------------------------------------------------------------------------------- // ADJUST THE FOLLOWING TO CONFIGURE YOUR CONTROLLER FEATURES -------------------------------------------------------------- -// Enables internal goto assist mount modeling (for Eq mounts), default=_OFF (Experimental) -// Note that Goto Assist in Sky Planetarium works even if this is off -#define ALIGN_GOTOASSIST_OFF - // Default speed for Serial1 com port, Default=9600 #define SERIAL_B_BAUD_DEFAULT 9600 diff --git a/Config.MaxPCB.h b/Config.MaxPCB.h index fcd26b02e..e51ae81c7 100644 --- a/Config.MaxPCB.h +++ b/Config.MaxPCB.h @@ -15,10 +15,6 @@ // ------------------------------------------------------------------------------------------------------------------------- // ADJUST THE FOLLOWING TO CONFIGURE YOUR CONTROLLER FEATURES -------------------------------------------------------------- -// Enables internal goto assist mount modeling (for Eq mounts), default=_OFF (Experimental) -// Note that Goto Assist in Sky Planetarium works even if this is off -#define ALIGN_GOTOASSIST_OFF - // Default speed for Serial1 and Serial4 com ports, Default=9600 #define SERIAL_B_BAUD_DEFAULT 9600 #define SERIAL_C_BAUD_DEFAULT 9600 diff --git a/Config.Mega2560Alt.h b/Config.Mega2560Alt.h index a0a9f915f..40b8f2182 100644 --- a/Config.Mega2560Alt.h +++ b/Config.Mega2560Alt.h @@ -200,3 +200,4 @@ #define FileVersionConfig 2 #include "src/pinmaps/Pins.Mega2560Alt.h" #endif + diff --git a/Config.MiniPCB.h b/Config.MiniPCB.h index 41a2477df..0d026adae 100644 --- a/Config.MiniPCB.h +++ b/Config.MiniPCB.h @@ -15,10 +15,6 @@ // ------------------------------------------------------------------------------------------------------------------------- // ADJUST THE FOLLOWING TO CONFIGURE YOUR CONTROLLER FEATURES -------------------------------------------------------------- -// Enables internal goto assist mount modeling (for Eq mounts), default=_OFF (Experimental) -// Note that Goto Assist in Sky Planetarium works even if this is off -#define ALIGN_GOTOASSIST_OFF - // Default speed for Serial1 com port, Default=9600 #define SERIAL_B_BAUD_DEFAULT 9600 diff --git a/Config.Ramps14.h b/Config.Ramps14.h index dae4f4227..e30afaf2a 100644 --- a/Config.Ramps14.h +++ b/Config.Ramps14.h @@ -21,9 +21,6 @@ // ------------------------------------------------------------------------------------------------------------------------- // ADJUST THE FOLLOWING TO CONFIGURE YOUR CONTROLLER FEATURES -------------------------------------------------------------- -// Enables internal goto assist mount modeling (for Eq mounts), default=_OFF (Experimental) -// Goto Assist in Sky Planetarium works even if this is off -#define ALIGN_GOTOASSIST_OFF // Default speed for Serial1 com port, Default=9600 #define SERIAL_B_BAUD_DEFAULT 9600 diff --git a/Config.STM32.h b/Config.STM32.h index 6f683f7fb..3e9af0047 100644 --- a/Config.STM32.h +++ b/Config.STM32.h @@ -18,10 +18,6 @@ // ------------------------------------------------------------------------------------------------------------------------- // ADJUST THE FOLLOWING TO CONFIGURE YOUR CONTROLLER FEATURES -------------------------------------------------------------- -// Enables internal goto assist mount modeling (for Eq mounts), default=_OFF (Experimental) -// Note that Goto Assist in Sky Planetarium works even if this is off -#define ALIGN_GOTOASSIST_OFF - // Default speed for Serial1 and Serial4 com ports, Default=9600 #define SERIAL1_BAUD_DEFAULT 9600 #define SERIAL4_BAUD_DEFAULT 9600 diff --git a/Config.TM4C.h b/Config.TM4C.h index 872c996d5..6f96188e0 100644 --- a/Config.TM4C.h +++ b/Config.TM4C.h @@ -17,10 +17,6 @@ // ------------------------------------------------------------------------------------------------------------------------- // ADJUST THE FOLLOWING TO CONFIGURE YOUR CONTROLLER FEATURES -------------------------------------------------------------- -// Enables internal goto assist mount modeling (for Eq mounts), default=_OFF (Experimental) -// Note that Goto Assist in Sky Planetarium works even if this is off -#define ALIGN_GOTOASSIST_OFF - // Default speed for Serial1 and Serial4 com ports, Default=9600 #define SERIAL_B_BAUD_DEFAULT 9600 #define SERIAL_C_BAUD_DEFAULT 9600 diff --git a/Validate.h b/Validate.h index f38e92dcd..ba16a8534 100644 --- a/Validate.h +++ b/Validate.h @@ -226,26 +226,14 @@ #endif // figure out how many align star are allowed for the configuration -#ifndef ALIGN_GOTOASSIST_ON - #if defined(MOUNT_TYPE_GEM) - #define MAX_NUM_ALIGN_STARS '3' - #elif defined(MOUNT_TYPE_FORK) - #define MAX_NUM_ALIGN_STARS '3' - #elif defined(MOUNT_TYPE_FORK_ALT) - #define MAX_NUM_ALIGN_STARS '1' - #elif defined(MOUNT_TYPE_ALTAZM) - #define MAX_NUM_ALIGN_STARS '3' - #endif -#else - #if defined(MOUNT_TYPE_GEM) - #define MAX_NUM_ALIGN_STARS '6' - #elif defined(MOUNT_TYPE_FORK) - #define MAX_NUM_ALIGN_STARS '6' - #elif defined(MOUNT_TYPE_FORK_ALT) - #define MAX_NUM_ALIGN_STARS '1' - #elif defined(MOUNT_TYPE_ALTAZM) - #define MAX_NUM_ALIGN_STARS '3' - #endif +#if defined(MOUNT_TYPE_GEM) + #define MAX_NUM_ALIGN_STARS '6' +#elif defined(MOUNT_TYPE_FORK) + #define MAX_NUM_ALIGN_STARS '6' +#elif defined(MOUNT_TYPE_FORK_ALT) + #define MAX_NUM_ALIGN_STARS '6' +#elif defined(MOUNT_TYPE_ALTAZM) + #define MAX_NUM_ALIGN_STARS '6' #endif // make both enable and disable values