牧夫天文网

找回密码
加入牧夫(请注明天文爱好者,否则无法通过审核)

QQ登录

只需一步,快速开始

发新帖

0

收听

42

听众

25

主题
发表于 2016-4-5 19:22 | 查看: 3776| 回复: 14来自: 香港 城市电讯有限公司
    看看对大家有什么帮助。思路还挺有意思的。通过算GOTO的距离。来调细分。举个例。如果要转100秒 80秒前是1细分 98秒时用32细 直到GOTO到目标。用这种方法来加减速。
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. ARDUINO CODE:
  3. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  4. /**************************************************************************
  5. * MEqM1DriverControl Arduino File
  6. *
  7. * My German Equatorial Mount Controller with Arduino Due that implements
  8. * LX200 Protocol Resumed and control the stepper motor driver DRV8825.
  9. *
  10. * Created: 29 de julho de 2014
  11. *
  12. * Author: Luiz Antonio Gabriel
  13. *
  14. **************************************************************************/
  15. #include "Wire.h"
  16. #include <MEqM1DriverControl.h>
  17. MEqM1DriverControl Driver;
  18. void setup() {
  19.   Wire.begin();
  20.   SerialUSB.begin(9600);
  21.   Driver.initializeDateTime();
  22. }
  23. void loop() {
  24.   if (SerialUSB.available()) {
  25.     Driver.answerSerialRequest();
  26.   }
  27.   Driver.shaftDecController();
  28.   Driver.shaftRAController();
  29.   Driver.slewController();
  30. }

  31. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  32. C++ HEADER:
  33. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  34. /**************************************************************************
  35. * MEqM1DriverControl Class Header File
  36. *
  37. * My German Equatorial Mount Controller with Arduino Due that implements
  38. * LX200 Protocol Resumed and control the stepper motor driver DRV8825.
  39. *
  40. * Created: 29 de julho de 2014
  41. *
  42. * Author: Luiz Antonio Gabriel
  43. *
  44. **************************************************************************/
  45. #ifndef MEqM1DriverControl_h
  46. #define MEqM1DriverControl_h
  47. // Arduino Driver Pins Configuration.
  48. #define DecDRV8825Dir   2
  49. #define DecDRV8825Step  3
  50. #define DecDRV8825M2    4
  51. #define DecDRV8825M1    5
  52. #define DecDRV8825M0    6
  53. #define DecDRV8825En    7
  54. #define RADRV8825Dir    8
  55. #define RADRV8825Step   9
  56. #define RADRV8825M2     10
  57. #define RADRV8825M1     11
  58. #define RADRV8825M0     12
  59. #define RADRV8825En     13
  60. #define SLEWALLOWED     31
  61. #define JOYSTICKVER     A9
  62. #define JOYSTICKHOR     A10
  63. #define JOYSTICKSEL     A11
  64. // Define minimum semi-period of stepper motors (maximum frequency).
  65. #define GOTO_RATE       625
  66. // The Earth spend 23.9344698888889 h to complete one rotation relative
  67. // to a fixed star, this implies in a frequency of
  68. // 2.37686020007898e-5 µS/µs that result in a half period of 21036 µs.
  69. #define TRACKING_RATE   21036
  70. #define SLEW_RATE       1775
  71. // Define the PCF8563 address.
  72. #define PCF8563ADDRESS  0x51
  73. #define PCF8563TIMEADD  0x02
  74. #define PCF8563DATEADD  0x05
  75. // library interface description
  76. class MEqM1DriverControl {
  77.   public:
  78.     // MEqM1DriverControl Constructor.
  79.     MEqM1DriverControl();
  80.     // Translates serial input in accordance of LX200 protocol and answer it.
  81.     void answerSerialRequest(void);
  82.     // Initializes date and time;
  83.     void initializeDateTime(void);
  84.     // Controls the Thumb Joystick and slew.
  85.     void slewController(void);
  86.     // Controls the DEC shafts.
  87.     void shaftDecController(void);
  88.     // Controls the RA shafts.
  89.     void shaftRAController(void);
  90.   private:
  91.     /*******
  92.      * Private Members Variables.
  93.      *****************************/
  94.    
  95.     // Holds the state of button.
  96.     bool buttonState;
  97.     // The variable is TRUE if target is check and is OK otherwise is FALSE.
  98.     bool gotoDecAllowed;
  99.     // The variable is TRUE if target is check and is OK otherwise is FALSE.
  100.     bool gotoRAAllowed;
  101.     // Holds the time elapsed since initial time.
  102.     unsigned long initialMicrosecond;
  103.     // Holds the initial time.
  104.     double initialTime;
  105.     // Holds the high limit that is allowing to point the telescope.
  106.     double highLimit;
  107.     // Holds the initialJD0.
  108.     double initialJD0;
  109.     // Holds the last micros() to calculate the delay for step pulse.
  110.     unsigned long lastDecMicro;
  111.     // Holds the last micros() to calculate the delay for step pulse.
  112.     unsigned long lastRAMicro;
  113.     // Holds the last micros() to calculate the delay for step pulse.
  114.     unsigned long lastSlewMicro;
  115.     // Local latitude in decimal format.
  116.     double latitude;
  117.     // Local longitude in decimal format.
  118.     double longitude;
  119.     // Holds the microsteps for DEC DRV8825 driver.
  120.     short microstepModeDec;
  121.     // Holds the microsteps for RA DRV8825 driver.
  122.     short microstepModeRA;
  123.     // Holds the all response for serial communications.
  124.     char *response;
  125.     // Current position of Dec Shaft given in microsteps (mode 5 = 1/32).
  126.     long shaftDecPosition;
  127.     // Current position of RA Shaft given in microsteps (mode 5 = 1/32).
  128.     long shaftRAPosition;
  129.     // Holds the state of slew.
  130.     bool slewEnabled;
  131.     // Steps to go to reach the Dec target given in microsteps (mode 5 = 1/32).
  132.     long microStepsTogoDec;
  133.     // Steps to go to reach the RA target given in microsteps (mode 5 = 1/32).
  134.     long microStepsTogoRA;
  135.     // Target Dec Coordinate in decimal degrees.
  136.     double targetDec;
  137.     // Target RA Coordinate in decimal degrees.
  138.     double targetRA;
  139.     // Controls the Dec, RA and Slew clocks.
  140.     bool tictacDec;
  141.     bool tictacRA;
  142.     // Turn on/off the syncronization of RA.
  143.     bool tracking;
  144.    
  145.     /*******
  146.      * Private Members Functions.
  147.      *****************************/
  148.    
  149.     // Transforms bcd format to decimal.
  150.     int BCDToDecimal(byte bcd);
  151.     // Verify if the telescope is allowable to reach the target.
  152.     short checkTarget(void);
  153.     // Transforms decimal format to bcd.
  154.     byte decimalToBCD(int decimal);
  155.     // Translate decimal format into HMS.
  156.     void decimalToHMS(double value, bool sign);
  157.     // Disables the DEC Driver.
  158.     void disableDecDriver(void);
  159.     // Disables the RA Driver.
  160.     void disableRADriver(void);
  161.     // Enables the DEC Driver.
  162.     void enableDecDriver(void);
  163.     // Enables the RA Driver.
  164.     void enableRADriver(void);
  165.     // Enables tracking.
  166.     void enableTracking(void);
  167.     // Selects the best mode to reach the target.
  168.     short getBestMode(long microStepsToGo);
  169.     // Returns Dec current coordinate in decimal degrees.
  170.     double getCurrentDec(void);
  171.     // Returns RA current coordinate in decimal degrees.
  172.     double getCurrentRA(void);
  173.     // Returns the current date on the standard buffer (response).
  174.     void getDate(void);
  175.     // Returns HA in decimal degrees with range correction.
  176.     double getHA(double RA);
  177.     // Gets the Julian Date.
  178.     double getJD0(void);
  179.     // Returns the Local Sidereal Time in decimal degrees.
  180.     double getLST(void);
  181.     // Gets the microsteps to go.
  182.     void getMicrostepsTogo(void);
  183.     // Gets the precise time.
  184.     double getPreciseTime(void);
  185.     // Gets the coordinate of shaft position for RA/Dec.
  186.     void getTargetShaftPosition(double RA, double Dec,
  187.                 long &tgShRA, long &tgShDec);
  188.     // Gets the local time in decimal format.
  189.     double getTime(void);
  190.     // Transform the coordinates RA/Dec to Alt/Az.
  191.     void RADecToAltAz(double RA, double Dec, double &Alt, double &Az);
  192.     // Sets the Greenwich julian date from date passed in format (DD, MM, AAAA).
  193.     bool setDate(int day, int mo, int yr);
  194.     // Sets the high limit.
  195.     bool setHighLimit(double highLimit);
  196.     // Sets the local latitude.
  197.     void setLatitude(double latitude);
  198.     // Sets the local longitude.
  199.     void setLongitude(double longitude);
  200.     // Sets the two drivers to the mode of microstep chosed.
  201.     void setMicrostepDecMode(short mode);
  202.     // Sets the two drivers to the mode of microstep chosed.
  203.     void setMicrostepRAMode(short mode);
  204.     // Sets target Dec Coordinate in decimal degrees.
  205.     void setTargetDec(int d, int m, int s);
  206.     // Sets target RA Coordinate in decimal degrees.
  207.     void setTargetRA(int h, int m, int s);
  208.     // Sets the real time clock on PCF8563 and updated initial local time.
  209.     void setTime(int h, int m, int s);
  210.     // Return the sign of x.
  211.     int sign(double x);
  212.     // Translate HMS format into decimal.
  213.     double translateHMSToDec(char *value);
  214. };

  215. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  216. C++ CODE:
  217. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  218. /**************************************************************************
  219. * MEqM1DriverControl Class Implementation File
  220. *
  221. * My German Equatorial Mount Controller with Arduino Due that implements
  222. * LX200 Protocol Resumed and control the stepper motor driver DRV8825.
  223. *
  224. * Created: 29 de julho de 2014
  225. *
  226. * Author: Luiz Antonio Gabriel
  227. *
  228. **************************************************************************/
  229. #include "Arduino.h"
  230. #include "Wire.h"
  231. #include "MEqM1DriverControl.h"
  232. /*****************************************************************
  233. *
  234. *  MEqM1DriverControl Constructor
  235. *
  236. *****************************************************************/
  237. MEqM1DriverControl::MEqM1DriverControl() {
  238.   // Initially puts the state of button to HIGH (true).
  239.   this->buttonState = true;
  240.   // Initially make the goto function not allowed.
  241.   this->gotoDecAllowed = false;
  242.   this->gotoRAAllowed = false;
  243.   // Initializes high limit as 90º.
  244.   this->highLimit = 90.0;
  245.   // Initializes with the latitude of Guarulhos by default.
  246.   this->latitude = -23.4600000;
  247.   // Initializes with the longitude of Guarulhos by default.
  248.   this->longitude = -46.4900028;
  249.   // Put the full step mode for both shafts.
  250.   this->microstepModeDec = 0;
  251.   this->microstepModeRA = 0;
  252.   // Initialize microsteps to go with zero for both shafts.
  253.   this->microStepsTogoDec = 0L;
  254.   this->microStepsTogoRA = 0L;
  255.   // Create the standard buffer to responses.
  256.   this->response = new char[30];
  257.   // Initially points to south (-90º,0h) or north (+90º,0h) celestial pole.
  258.   this->shaftDecPosition = 0L;
  259.   this->shaftRAPosition = 0L;
  260.   // Initially sets the slew mode to off (false).
  261.   this->slewEnabled = false;
  262.   // Puts the target at the South sidereal pole.
  263.   this->targetDec = -90.0;
  264.   this->targetRA = 0.0;
  265.   // Puts the initial tictac to HIGH for both shafts.
  266.   this->tictacDec = true;
  267.   this->tictacRA = true;
  268.   // Turn off the tracking initially.
  269.   this->tracking = false;

  270. // setup the pins on the microcontroller:
  271.   pinMode(DecDRV8825Dir,  OUTPUT);
  272.   pinMode(DecDRV8825Step, OUTPUT);
  273.   pinMode(DecDRV8825M2,   OUTPUT);
  274.   pinMode(DecDRV8825M1,   OUTPUT);
  275.   pinMode(DecDRV8825M0,   OUTPUT);
  276.   pinMode(RADRV8825Dir,   OUTPUT);
  277.   pinMode(RADRV8825Step,  OUTPUT);
  278.   pinMode(RADRV8825M2,    OUTPUT);
  279.   pinMode(RADRV8825M1,    OUTPUT);
  280.   pinMode(RADRV8825M0,    OUTPUT);
  281.   pinMode(SLEWALLOWED,    OUTPUT);
  282.   pinMode(JOYSTICKSEL,    INPUT);
  283.   pinMode(JOYSTICKHOR,    INPUT);
  284.   pinMode(JOYSTICKVER,    INPUT);
  285. }
  286. /*****************************************************************
  287. *
  288. *  Public Function Members
  289. *
  290. *****************************************************************/
  291. void MEqM1DriverControl::answerSerialRequest(void) {
  292.   int delayRead = 60;
  293.   char request = 0;
  294.   int d, h, m, s, y;
  295.   double Alt, Az;
  296.   short checkResult;

  297.   while (SerialUSB.available() > 0 && request != ':') {
  298.     request=SerialUSB.read();
  299.     delayMicroseconds(delayRead);
  300.   }
  301.   // Get the first character after beginning of command symbol ':'.
  302.   request=SerialUSB.read();
  303.   switch(request) {
  304.     case 'G': // Get Telescope Information.
  305.       // Get next character.
  306.       request=SerialUSB.read();
  307.       if (request == 'A') { // Telescope Altitude. Returns: sDD:MM:SS#
  308.         RADecToAltAz(getCurrentRA(), getCurrentDec(),Alt, Az);
  309.         decimalToHMS(Alt, false);
  310.         SerialUSB.print(this->response);
  311.       } else if (request == 'C') { // Current date. Returns: MM/DD/YY#
  312.         getDate();
  313.         SerialUSB.println(this->response);
  314.       } else if (request == 'd') { // Currently Target DEC. Returns: sDD:MM:SS#
  315.         decimalToHMS(this->targetDec, true);
  316.         SerialUSB.print(this->response);
  317.       } else if (request == 'D') { // Telescope DEC. Returns: sDD:MM:SS#
  318.         decimalToHMS(getCurrentDec(), true);
  319.         SerialUSB.print(this->response);
  320.       } else if (request == 'g') { // Current Site Longitude. Returns: sDDD:MM#
  321.         decimalToHMS(this->longitude, true);
  322.         SerialUSB.print(this->response);
  323.       } else if (request == 'G') { // UTC offset time. Returns: sHH# or sHH.H#
  324.         sprintf(this->response, "%+02i#", int(this->longitude/15));
  325.         SerialUSB.print(this->response);
  326.       } else if (request == 'h') { // High Limit. Returns: sDD#
  327.         SerialUSB.println(this->highLimit);
  328.       } else if (request == 'H') { // Daylight Saving Time Setting.
  329.                                  // Returns: 0# if daylight savings is disabled
  330.                                  // Returns: 1# if daylight savings is enabled
  331.       } else if (request == 'K') { // Microsteps to go Extended Command.
  332.         getMicrostepsTogo();
  333.         sprintf(this->response,"RA: %d, DEC: %d",
  334.           this->microStepsTogoRA, this->microStepsTogoDec);
  335.         SerialUSB.println(this->response);
  336.       } else if (request == 'L') { // Local Time (24h). Returns: HH:MM:SS#
  337.         decimalToHMS(getTime(), false);
  338.         SerialUSB.println(this->response);
  339.       } else if (request == 'o') { // Lower Limit. Returns: DD#
  340.         SerialUSB.println("00#");
  341.       } else if (request == 'r') { // Current Target RA. Returns: HH:MM:SS#
  342.         decimalToHMS(this->targetRA, false);
  343.         SerialUSB.print(this->response);
  344.       } else if (request == 'R') { // Current Telescope RA. Returns: HH:MM:SS#
  345.         decimalToHMS(getCurrentRA()/15.0, false);
  346.         SerialUSB.print(this->response);
  347.       } else if (request == 'S') { // Sidereal Time. Returns: HH:MM:SS#
  348.         decimalToHMS(getLST()/15.0, false);
  349.         SerialUSB.print(this->response);
  350.       } else if (request == 't') { // Current Site Latitude. Returns: sDD:MM#
  351.         decimalToHMS(this->latitude, true);
  352.         SerialUSB.print(this->response);
  353.       } else if (request == 'T') { // Tracking Rate. Returns: TT.T#
  354.         SerialUSB.print("23.768602#"); // microsteps/s (mode 5).
  355.       } else if (request == 'V') {
  356.         // Get next character.
  357.         request=SerialUSB.read();
  358.         if (request == 'D') {        // EM1 Firmware Date. Returns: mmm dd yyyy#
  359.           SerialUSB.print("jul 29 2014#");
  360.         } else if (request == 'N') { // EM1 Firmware Version. Returns: dd.d#
  361.           SerialUSB.print("1.0#");
  362.         }         
  363.       } else if (request == 'Z') { // Telescope Azimuth. Returns: DDD:MM:SS#
  364.         RADecToAltAz(getCurrentRA(), getCurrentDec(), Alt, Az);
  365.         decimalToHMS(Az, false);
  366.         SerialUSB.print(this->response);
  367.       }
  368.       break;
  369.     case 'M': // Telescope Movement Commands.
  370.       // Get next character.
  371.       request=SerialUSB.read();
  372.       if (request == 'A') { // Slew Alt/Az. Format: MA#
  373.         // Returns: 0 - no fault, 1 - fault.
  374.       } else if (request == 'e') { // Move to East at current rate. Format: Me#
  375.         // Returns: Nothing.
  376.       } else if (request == 'g') { // Move to direction for milliseconds.
  377.         // Get next character.
  378.         request=SerialUSB.read();
  379.         if (request == 'e') {        // East. Format: MgeDDDD#
  380.           // Returns: Nothing.
  381.         } else if (request == 'n') { // North. Format: MgnDDDD#
  382.           // Returns: Nothing.
  383.         } else if (request == 's') { // South. Format: MgsDDDD#
  384.           // Returns: Nothing.
  385.         } else if (request == 'w') { // West. Format: MgwDDDD#
  386.           // Returns: Nothing.
  387.         }
  388.       } else if (request == 'n') { // Move to North at current rate. Format: Mn#
  389.         // Returns: Nothing.
  390.       } else if (request == 's') { // Move to South at current rate. Format: Ms#
  391.         // Returns: Nothing.
  392.       } else if (request == 'S') { // Slew to Target. Format: MS#
  393.         // Returns: 0 - possible, 1<str># - below horizont w/ string,
  394.         // 2<str># - Over higher w/ string.
  395.         // Verify if target position is above the horizon.
  396.         checkResult = checkTarget();
  397.         if (checkResult == 0) {
  398.           SerialUSB.print("0#"); // If OK send '0'.
  399.         } else if (checkResult == 1) {
  400.           // If it's below the horizon respond with '1'.
  401.           SerialUSB.print("1Object below low limit.#");
  402.         } else {
  403.           // If it's over higher respond with '2'.
  404.           SerialUSB.print("2Object over high limit.#");
  405.         }
  406.       }
  407.       break;
  408.     case 'Q': // Movement Commands.
  409.       // Get next character.
  410.       request=SerialUSB.read();
  411.       if (request != '#') {
  412.         if (request == 'e') {        // Halt Eastward slew. Format: Qe#
  413.           // Returns: Nothing.
  414.         } else if (request == 'n') { // Halt Northward slew. Format: Qn#
  415.           // Returns: Nothing.
  416.         } else if (request == 's') { // Halt Southward slew. Format: Qs#
  417.           // Returns: Nothing.
  418.         } else if (request == 'w') { // Halt Westward slew. Format: Qw#
  419.           // Returns: Nothing.
  420.         }
  421.       } else { // Halt all current slewing. Format: Q#
  422.         disableDecDriver();
  423.         disableRADriver();
  424.         // Returns: Nothing.
  425.       }
  426.       break;
  427.     case 'S': // Telescope Set Commands.
  428.       // Get next character.
  429.       request=SerialUSB.read();
  430.       if (request == 'C') { // Date. Format: SCMM/DD/YY.
  431.         d = SerialUSB.parseInt();   // Initial day.
  432.         m = SerialUSB.parseInt();   // Initial month.
  433.         y = SerialUSB.parseInt();   // Initial year.
  434.         // Returns: '0' if date is invalid. '1' if valid + "Date updated!#"
  435.         if (setDate(d, m, y)) SerialUSB.println("1Date updated!#");
  436.         else SerialUSB.println("0#");
  437.       } else if (request == 'd') {  // Target DEC. Format: Sdsdd:mm:ss.
  438.         d = SerialUSB.parseInt();   // Target DEC degrees.
  439.         m = SerialUSB.parseInt();   // Target DEC minutes of arc.
  440.         s = SerialUSB.parseInt();   // Target DEC seconds of arc.
  441.         // Returns: 0 - invalid, 1 - valid.
  442.         setTargetDec(d, m, s);
  443.         SerialUSB.print("1#");
  444.       } else if (request == 'g') {  // Current site's long. Format: SgDDD:MM#
  445.         // Returns: 0 - invalid, 1 - valid.
  446.       } else if (request == 'G') {  // Number of hours to UTC. Format: SGsHH.H#
  447.         // Returns: 0 - invalid, 1 - valid.
  448.       } else if (request == 'h') {  // Maximum elevation limit. Format: ShDD#
  449.         // Returns: 0 - invalid, 1 - valid.
  450.         h = SerialUSB.parseInt();   // Take the high limit.
  451.         if (setHighLimit(h)) SerialUSB.print("1#");
  452.         else SerialUSB.print("0#");
  453.       } else if (request == 'H') {  // Daylight saving. Format: SH1# or SH0#
  454.         // Returns: nothing.
  455.       } else if (request == 'L') {  // Local time. Format: SLHH:MM:SS#
  456.         h = SerialUSB.parseInt();   // Initial hour.
  457.         m = SerialUSB.parseInt();   // Initial minute.
  458.         s = SerialUSB.parseInt();   // Initial second.
  459.         // Returns: 0 - invalid, 1 - valid.
  460.         setTime(h, m, s);
  461.         SerialUSB.print("1#");
  462.       } else if (request == 'o') { // Lowest elevation. Format: SoDD#
  463.         // Returns: 0 - invalid, 1 - valid.
  464.       } else if (request == 'r') {  // Target RA. Format: SrHH:MM:SS#.
  465.         h = SerialUSB.parseInt();   // Target RA hour of arc.
  466.         m = SerialUSB.parseInt(); // Target RA minutes of arc.
  467.         s = SerialUSB.parseInt(); // Target Ra seconds of arc.
  468.         // Returns: 0 - invalid, 1 - valid.
  469.         setTargetRA(h, m, s);
  470.         SerialUSB.print("1#");
  471.       } else if (request == 'S') { // LST. Format: SSHH:MM:SS#
  472.         // Returns: 0 - invalid, 1 - valid.
  473.       } else if (request == 't') { // Current site latitude. Format: StsDD:MM#
  474.         // Returns: 0 - invalid, 1 - valid.
  475.       } else if (request == 'T') { // Tracking rate. Format: STdd.ddddddd#
  476.         // Tracking rate (microsteps/s). One shaft revolution = 2048000 µS.
  477.         // Sidereal rate: 23.7686019 µS/s or one microstep every 42072 µs with
  478.         // an error of 1 arc-sec every 2,5 h.
  479.         // Returns: 0 - invalid, 1 - valid.
  480.       } else if (request == 'w') { // Slew rate. Format: SwN#
  481.         // Returns: 0 - invalid, 1 - valid.
  482.       } else if (request == 'z') { // Target Azimuth. Format: SzDDD:MM#
  483.         // Returns: 0 - invalid, 1 - valid.
  484.       }
  485.       break;
  486.     case 'T': // Tracking Commands.
  487.       // Get next character.
  488.       request=SerialUSB.read();
  489.       if (request == '+') {        // Increment Manual rate. Format: T+#
  490.         // Return nothing.
  491.       } else if (request == '-') { // Decrement Manual rate. Format: T-#
  492.         // Return nothing.
  493.       } else if (request == 'L') { // Lunar Tracking rate. Format: TL#
  494.         // Return nothing.
  495.       } else if (request == 'M') { // Custom tracking rate. Format: TM#
  496.         // Return nothing.
  497.       } else if (request == 'Q') { // Sidereal tracking rate. Format: TQ#
  498.         // Return nothing.
  499.       } else if (request == 'S') { // Solar tracking rate. Format: TS#
  500.         // Return nothing.
  501.       }
  502.       break;
  503.     default:
  504.       break;
  505.   }
  506. }
  507. void MEqM1DriverControl::initializeDateTime(void) {
  508.   int day, dow, month, year;
  509.   Wire.beginTransmission(PCF8563ADDRESS);
  510.   Wire.write(PCF8563DATEADD);
  511.   Wire.endTransmission();
  512.   Wire.requestFrom(PCF8563ADDRESS, 4);
  513.   day   = BCDToDecimal(Wire.read() & 0x3f);
  514.   dow   = BCDToDecimal(Wire.read() & 0x07);
  515.   month = BCDToDecimal(Wire.read() & 0x1f);
  516.   year  = 2000 + BCDToDecimal(Wire.read());

  517.   // Calculate the JD0 (Julian Day without hours calculation) and return it.
  518.   this->initialJD0 = double(367.0 * year -
  519.     int(7 * (year + int((month + 9) / 12.0)) / 4.0) +
  520.     int(275.0 * month / 9.0) + day + 1721013.5);
  521.   // Gets initial time.
  522.   this->initialTime = getTime();
  523.   // Holds the microseconds of initial time.
  524.   this->initialMicrosecond = micros();
  525. }
  526. void MEqM1DriverControl::slewController(void) {
  527.   long timeElapsed = 0L;
  528.   long microsNow = 0L;
  529.   int button, horizontal, vertical;
  530.   // Read the state of joystick.
  531.   button  = analogRead(JOYSTICKSEL);
  532.   // Verify if joystick button was pressed.
  533.   if ((button == 0) && buttonState) { // If it is transition to down.
  534.     buttonState = false;
  535.     // Wait 0.1 s to stop bouncing.
  536.     delay(100);
  537.   } else if ((button != 0) && !buttonState) { // If it is transition to up.
  538.     buttonState = true;
  539.     // Wait 0.1 s to stop bouncing.
  540.     delay(100);
  541.     // Do not allow the RA shaft exceeds the limit of ± 90° (512000 microsteps)
  542.     // and the DEC shaft exceeds the limit of ± 180° (1024000 microsteps).
  543.     if ((abs(this->shaftDecPosition) < 1024000) &&
  544.           (abs(this->shaftRAPosition) < 512000)) {
  545.       // Change the state of slew mode.
  546.       this->slewEnabled = !this->slewEnabled;
  547.     }
  548.     // Run the Once Time Routine.
  549.     if (this->slewEnabled) {
  550.       // Turn on the slew indicator led.
  551.       digitalWrite(SLEWALLOWED, HIGH);
  552.       // Disable all moviment of the telescope.
  553.       disableDecDriver();
  554.       disableRADriver();
  555.       // Enables the movement of the drivers.
  556.       digitalWrite(DecDRV8825En, LOW);
  557.       digitalWrite(RADRV8825En, LOW);
  558.       // Sets the microstep to mode 5 in both axis.
  559.       setMicrostepDecMode(5);
  560.       setMicrostepRAMode(5);
  561.     } else {
  562.       // Turn off the slew indicator led.
  563.       digitalWrite(SLEWALLOWED, LOW);
  564.       // Disable all moviment of DEC shaft.
  565.       disableDecDriver();
  566.       // Restart the tracking.
  567.       enableTracking();
  568.     }
  569.   }
  570.   if (this->slewEnabled) {
  571.     vertical = analogRead(JOYSTICKVER);
  572.     horizontal = analogRead(JOYSTICKHOR);
  573.     if (!((horizontal >= 700) && (horizontal <= 800)) ||
  574.         !((vertical >= 700) && (vertical <= 800))) {
  575.       microsNow = micros();
  576.       // Corrects, if necessary, timeElapsed for micros() overflow.
  577.       if (microsNow < this->lastSlewMicro) {
  578.         timeElapsed = (4294967295 - this->lastSlewMicro) + microsNow;
  579.       } else {
  580.         timeElapsed = microsNow - this->lastSlewMicro;
  581.       }
  582.       if (timeElapsed > SLEW_RATE) {
  583.         // Update the clock holder.
  584.         this->lastSlewMicro = microsNow;
  585.         if (horizontal < 700) { // slew to the WEST.
  586.           // Increment exactly one microstep by cycle.
  587.           this->shaftRAPosition++;
  588.           digitalWrite(RADRV8825Dir, LOW);
  589.           digitalWrite(RADRV8825Step, LOW);
  590.           delayMicroseconds(100);
  591.           digitalWrite(RADRV8825Step, HIGH);
  592.         } else if (horizontal > 800) { // slew to the EAST.
  593.           // Decrement exactly one microstep by cycle.
  594.           this->shaftRAPosition--;
  595.           digitalWrite(RADRV8825Dir, HIGH);
  596.           digitalWrite(RADRV8825Step, LOW);
  597.           delayMicroseconds(100);
  598.           digitalWrite(RADRV8825Step, HIGH);
  599.         }
  600.         if (vertical < 700) { // slew to the NORTH.
  601.           // Increment exactly one microstep by cycle.
  602.           this->shaftDecPosition++;
  603.           digitalWrite(DecDRV8825Dir, LOW);
  604.           digitalWrite(DecDRV8825Step, LOW);
  605.           delayMicroseconds(100);
  606.           digitalWrite(DecDRV8825Step, HIGH);
  607.         } else if (vertical > 800) { // slew to the EAST.
  608.           // Decrement exactly one microstep by cycle.
  609.           this->shaftDecPosition--;
  610.           digitalWrite(DecDRV8825Dir, HIGH);
  611.           digitalWrite(DecDRV8825Step, LOW);
  612.           delayMicroseconds(100);
  613.           digitalWrite(DecDRV8825Step, HIGH);
  614.         }
  615.       }
  616.     }
  617.   }
  618. }
  619. void MEqM1DriverControl::shaftDecController(void) {
  620.   long timeElapsed = 0L;
  621.   long microsNow = 0L;
  622.   int advance = 0;
  623.   if (this->gotoDecAllowed) {
  624.     microsNow = micros();
  625.     // Corrects, if necessary, timeElapsed for micros() overflow.
  626.     if (microsNow < this->lastDecMicro) {
  627.       timeElapsed = (4294967295 - this->lastDecMicro) + microsNow;
  628.     } else {
  629.       timeElapsed = microsNow - this->lastDecMicro;
  630.     }
  631.     if (timeElapsed > GOTO_RATE){
  632.       // Update the clock holder.
  633.       this->lastDecMicro = microsNow;
  634.       if (this->tictacDec) {
  635.         this->tictacDec = false;
  636.         // Get the best mode for Dec.
  637.         setMicrostepDecMode(getBestMode(this->microStepsTogoDec));
  638.         advance = sign(this->microStepsTogoDec) * pow(2,5-microstepModeDec);
  639.         // Do not allow the DEC shaft exceeds the
  640.         // limit of ± 180° (1024000 microsteps).
  641.         if (abs(this->shaftDecPosition + advance) >= 1024000) {
  642.           this->gotoDecAllowed = false;
  643.         } else {
  644.           this->shaftDecPosition += advance;
  645.           // Update the stepsTogo in acordance to the how many microsteps the
  646.           // correspondent shaft slewed.
  647.           this->microStepsTogoDec -= advance;
  648.           // Verify if the target was achieved.
  649.           if (this->microStepsTogoDec == 0) {
  650.             disableDecDriver();
  651.           } else {
  652.             // Change the output of wire to HIGH
  653.             digitalWrite(DecDRV8825Step, HIGH);
  654.           }
  655.         }
  656.       } else {
  657.         this->tictacDec = true;
  658.         // Change the output of wire to LOW.
  659.         digitalWrite(DecDRV8825Step, LOW);
  660.       }
  661.     }
  662.   }
  663. }
  664. void MEqM1DriverControl::shaftRAController(void) {
  665.   long timeElapsed = 0L;
  666.   long microsNow = 0L;
  667.   long tgShRA  = 0L;
  668.   long tgShDec = 0L;
  669.   int advance = 0;
  670.   if (this->gotoRAAllowed) {
  671.     microsNow = micros();
  672.     // Corrects, if necessary, timeElapsed for micros() overflow.
  673.     if (microsNow < this->lastRAMicro) {
  674.       timeElapsed = (4294967295 - this->lastRAMicro) + microsNow;
  675.     } else {
  676.       timeElapsed = microsNow - this->lastRAMicro;
  677.     }
  678.     if (timeElapsed > GOTO_RATE){
  679.       // Update the clock holder.
  680.       this->lastRAMicro = microsNow;
  681.       if (this->tictacRA) {
  682.         this->tictacRA = false;
  683.         // Get the best mode for RA.
  684.         setMicrostepRAMode(getBestMode(this->microStepsTogoRA));
  685.         advance = sign(this->microStepsTogoRA) * pow(2,5-microstepModeRA);
  686.         // Do not allow the RA shaft exceeds the
  687.         // limit of ± 90° (512000 microsteps).
  688.         if (abs(this->shaftRAPosition + advance)>= 512000) {
  689.           disableRADriver();
  690.         } else {
  691.           this->shaftRAPosition += advance;
  692.           // Gets the new position of target in microsteps.
  693.           getTargetShaftPosition(targetRA, targetDec, tgShRA, tgShDec);
  694.           // Gets the microsteps to go from current position
  695.           // to the new target position.
  696.           this->microStepsTogoRA  = tgShRA - this->shaftRAPosition;
  697.           if (this->microStepsTogoRA == 0) {
  698.             enableTracking();
  699.           } else {
  700.             // Change the output of wire to HIGH
  701.             digitalWrite(RADRV8825Step, HIGH);
  702.           }
  703.         }
  704.       } else {
  705.         this->tictacRA = true;
  706.         // Change the output of wire to LOW.
  707.         digitalWrite(RADRV8825Step, LOW);
  708.       }
  709.     } // If tracking is enable and slew is disable.
  710.   } else if (this->tracking) {
  711.     microsNow = micros();
  712.     // Corrects, if necessary, timeElapsed for micros() overflow.
  713.     if (microsNow < this->lastRAMicro) {
  714.       timeElapsed = (4294967295 - this->lastRAMicro) + microsNow;
  715.     } else {
  716.       timeElapsed = microsNow - this->lastRAMicro;
  717.     }
  718.     if (timeElapsed > TRACKING_RATE){
  719.       // Update the clock holder.
  720.       this->lastRAMicro = microsNow;
  721.       if (this->tictacRA) {
  722.         this->tictacRA = false;
  723.         // Do not allow the RA shaft exceeds the
  724.         // limit of ± 90° (512000 microsteps).
  725.         if (abs(this->shaftRAPosition) >= 512000) {
  726.           disableRADriver();
  727.         } else {
  728.           // Increment exactly one microstep by cycle.
  729.           this->shaftRAPosition++;
  730.           // Change the output of wire to HIGH
  731.           digitalWrite(RADRV8825Step, HIGH);
  732.         }
  733.       } else {
  734.         this->tictacRA = true;
  735.         // Change the output of wire to LOW.
  736.         digitalWrite(RADRV8825Step, LOW);
  737.       }
  738.     }
  739.   }
  740. }
  741. /*****************************************************************
  742. *
  743. *  Private Function Members
  744. *
  745. *****************************************************************/
  746. int MEqM1DriverControl::BCDToDecimal(byte bcd) {
  747.   return ((bcd / 16) * 10 + bcd % 16);
  748. }
  749. short MEqM1DriverControl::checkTarget(void) {
  750.   double Alt = 0.0;
  751.   double Az = 0.0;
  752.   short AltCheck = 1;
  753.   RADecToAltAz(this->targetRA, this->targetDec, Alt, Az);
  754.   // If future position is above the horizon then allow goes to the target.
  755.   if (Alt > 0) {
  756.     if (Alt > this->highLimit) {
  757.       disableDecDriver();
  758.       disableRADriver();
  759.       AltCheck = 2;
  760.     } else {
  761.       AltCheck = 0;
  762.       // Gets the microsteps to go to the target.
  763.       getMicrostepsTogo();
  764.       // Enables both drivers.
  765.       enableDecDriver();
  766.       enableRADriver();
  767.       // Initialize lastMicro by the first time before goto start.
  768.       this->lastRAMicro = this->lastDecMicro = micros();
  769.     }
  770.   } else {
  771.     disableDecDriver();
  772.     disableRADriver();
  773.     AltCheck = 1;
  774.   }

  775.   return AltCheck;
  776. }
  777. byte MEqM1DriverControl::decimalToBCD(int decimal) {
  778.   return byte(decimal / 10 * 16 + decimal % 10);
  779. }
  780. void MEqM1DriverControl::decimalToHMS(double value, bool sign) {
  781.   int h = 0;
  782.   int m = 0;
  783.   int s = 0;
  784.   h = int(value);
  785.   m = int(abs(value - h) * 60);
  786.   s = round((abs(value) - abs(h) - m/60.0) * 3600);
  787.   // Put the symbol 'ß' instead ':' for numbers with sign
  788.   // and increase the number of character to write.
  789.   if (sign) {
  790.     sprintf(this->response, "%+03d%c%02d:%02d#", h, char(223), m, s);
  791.   } else {
  792.     sprintf(this->response, "%02d:%02d:%02d#", h, m, s);
  793.   }
  794. }
  795. void MEqM1DriverControl::disableDecDriver(void) {
  796.   // Stop the motion in DEC shaft.
  797.   this->gotoDecAllowed = false;
  798.   // Change all currents LOW to save energy.
  799.   setMicrostepDecMode(0);
  800.   digitalWrite(DecDRV8825Step, LOW);
  801.   digitalWrite(DecDRV8825Dir, LOW);
  802.   // Disables the driver.
  803.   digitalWrite(DecDRV8825En, HIGH);
  804. }
  805. void MEqM1DriverControl::disableRADriver(void) {
  806.   this->gotoRAAllowed = false;
  807.   this->tracking = false;
  808.   // Change all currents LOW to save energy.
  809.   setMicrostepRAMode(0);
  810.   digitalWrite(RADRV8825Step, LOW);
  811.   digitalWrite(RADRV8825Dir, LOW);
  812.   // Disables the driver.
  813.   digitalWrite(RADRV8825En, HIGH);
  814. }
  815. void MEqM1DriverControl::enableDecDriver(void) {
  816.   // Go to is allowed.
  817.   this->gotoDecAllowed = true;
  818.   // Set the direction of rotation.
  819.   if (this->microStepsTogoRA > 0) {
  820.     digitalWrite(RADRV8825Dir, LOW);
  821.   } else {
  822.     digitalWrite(RADRV8825Dir, HIGH);
  823.   }
  824.   setMicrostepDecMode(0);
  825.   // Enables the driver.
  826.   digitalWrite(DecDRV8825En, LOW);
  827. }
  828. void MEqM1DriverControl::enableRADriver(void) {
  829.   // Go to is allowed.
  830.   this->gotoRAAllowed = true;
  831.   // When enable the goto disable, initially, the tracking.
  832.   this->tracking = false;
  833.   // Set the direction of rotation.
  834.   if (this->microStepsTogoDec > 0) {
  835.     digitalWrite(DecDRV8825Dir, LOW);
  836.   } else {
  837.     digitalWrite(DecDRV8825Dir, HIGH);
  838.   }
  839.   // Enables the driver.
  840.   digitalWrite(RADRV8825En, LOW);
  841. }
  842. void MEqM1DriverControl::enableTracking(void) {
  843.   this->gotoRAAllowed = false;
  844.   // Prepares to track.
  845.   this->tictacRA = false;
  846.   this->tracking = true;
  847.   // Sets the microstep to mode 5.
  848.   setMicrostepRAMode(5);
  849.   // Sets the correct direction of rotation. Clockwise in South.
  850.   if (this->latitude < 0) {
  851.     digitalWrite(RADRV8825Dir, LOW);
  852.   } else {
  853.     digitalWrite(RADRV8825Dir, HIGH);
  854.   }
  855. }
  856. short MEqM1DriverControl::getBestMode(long microStepsToGo) {
  857.   short mode = 0;
  858.   long limit = abs(microStepsToGo);
  859.   // Control the distance of final position where the slew rate slowing down.
  860.   if (limit > 25600) {
  861.     mode = 0;
  862.   } else if (limit > 12800) {
  863.     mode = 1;
  864.   } else if (limit > 6400) {
  865.     mode = 2;
  866.   } else if (limit > 3200) {
  867.     mode = 3;
  868.   } else if (limit > 1600) {
  869.     mode = 4;
  870.   } else {
  871.     mode = 5;
  872.   }
  873.   return mode;
  874. }
  875. double MEqM1DriverControl::getCurrentDec(void) {
  876.   double dec = 0.0;
  877.   double shaftDec = 0.0;
  878.   double shaftRA = 0.0;
  879.   int signLAT = sign(this->latitude);
  880.   // Transform from microsteps (1/32 of full step) into degrees.
  881.   // 360° of shaft = 320*200*32 = 2.048.000 microsteps.
  882.   shaftDec = this->shaftDecPosition * 360.0 / 2048000.0;
  883.   shaftRA = this->shaftRAPosition * 360.0 / 2048000.0;

  884.   // Calculation of RA/DEC from shaft position and its respectives signal.
  885.   // HA Quadrant <- signals for South(shaftRA, shaftDec): 1:-+ 2:++ 3:-- 4:+-
  886.   // HA Quadrant <- signals for North(shaftRA, shaftDec): 1:+- 2:-- 3:++ 4:-+
  887.   // Range of HA(0,360). Range of Dec(-90,90).

  888.   // (-+): 1st Quadrant in South. 4th Quadrant in North.
  889.   if (shaftRA <= 0 && shaftDec >= 0) {
  890.     dec = (90.0 - shaftDec) * signLAT;         // South and North: (0,180).
  891.   // (++): 2nd in Quadrant South. 3rd in Quadrant North.
  892.   } else if (shaftRA >= 0 && shaftDec >= 0) {
  893.     dec = (90.0 - shaftDec) * signLAT;         // South and North: (0,180).
  894.   // (--): 3rd Quadrant in South. 2nd Quadrant in North.
  895.   } else if (shaftRA <= 0 && shaftDec <= 0) {
  896.     dec = (shaftDec + 90) * signLAT;           // South and North: (0,180).
  897.   // (+-): 4th Quadrant in South. 1st Quadrant in North.
  898.   } else {
  899.     dec = (shaftDec + 90) * signLAT;           // South and North: (0,180).
  900.   }
  901.   return dec;
  902. }
  903. double MEqM1DriverControl::getCurrentRA(void) {
  904.   double ha = 0.0;
  905.   double ra = 0.0;
  906.   double shaftDec = 0.0;
  907.   double shaftRA = 0.0;
  908.   int signLAT = sign(this->latitude);
  909.   // Transform from microsteps (1/32 of full step) into degrees.
  910.   // 360° of shaft = 320*200*32 = 2.048.000 microsteps.
  911.   shaftDec = this->shaftDecPosition * 360.0 / 2048000.0;
  912.   shaftRA = this->shaftRAPosition * 360.0 / 2048000.0;

  913.   // Calculation of RA/DEC from shaft position and its respectives signal.
  914.   // HA Quadrant <- signals for South(shaftRA, shaftDec): 1:-+ 2:++ 3:-- 4:+-
  915.   // HA Quadrant <- signals for North(shaftRA, shaftDec): 1:+- 2:-- 3:++ 4:-+
  916.   // Range of HA(0,360). Range of Dec(-90,90).

  917.   // (-+): 1st Quadrant in South. 4th Quadrant in North.
  918.   if (shaftRA <= 0 && shaftDec >= 0) {
  919.     if (signLAT < 0) {
  920.       ha  = shaftRA + 90.0;      // South: HA(0,90).
  921.     } else {
  922.       ha  = 270.0 - shaftRA;     // North: HA(270,360).
  923.       if (ha == 360.0) ha = 0.0;
  924.     }
  925.   // (++): 2nd Quadrant in South. 3rd Quadrant in North.
  926.   } else if (shaftRA >= 0 && shaftDec >= 0) {
  927.     if (signLAT < 0) {
  928.       ha  = shaftRA + 90.0;      // South: HA(90,180).
  929.     } else {
  930.       ha  = 270.0 - shaftRA;     // North: HA(180,270).
  931.     }
  932.   // (--): 3rd Quadrant in South. 2nd Quadrant in North.
  933.   } else if (shaftRA <= 0 && shaftDec <= 0) {
  934.     if (signLAT < 0) {
  935.       ha  = 270.0 + shaftRA;     // South: HA(180,270).
  936.     } else {
  937.       ha  = 180.0 + shaftRA;     // North: HA(90,180).
  938.     }
  939.   // (+-): 4th Quadrant in South. 1st Quadrant in North.
  940.   } else {
  941.     if (signLAT < 0) {
  942.       ha  = 270.0 + shaftRA;     // South: HA(270,360).
  943.       if (ha == 360.0) ha = 0.0;
  944.     } else {
  945.       ha  = 90.0 - shaftRA;      // North: HA(0,90).
  946.     }
  947.   }
  948.   // HA = LST - RA
  949.   ra = getLST() - ha;
  950.   if (ra < 0) ra = 360 + ra;     // Correct the range of RA (from 0° to 360°);
  951.   return ra;
  952. }
  953. void MEqM1DriverControl::getDate(void) {
  954.   int day, dow, month, year;
  955.   Wire.beginTransmission(PCF8563ADDRESS);
  956.   Wire.write(PCF8563DATEADD);
  957.   Wire.endTransmission();
  958.   Wire.requestFrom(PCF8563ADDRESS, 4);
  959.   day   = BCDToDecimal(Wire.read() & 0x3f);
  960.   dow   = BCDToDecimal(Wire.read() & 0x07);
  961.   month = BCDToDecimal(Wire.read() & 0x1f);
  962.   year  = BCDToDecimal(Wire.read());
  963.   sprintf(this->response, "%02d/%02d/%02d#", day, month, year);
  964. }
  965. double MEqM1DriverControl::getHA(double RA) {
  966.   double HA = 0.0;
  967.   HA = getLST() - RA;
  968.   if (HA < 0) HA = 360 + HA;     // Correct the range of HA (from 0° to 360°);
  969.   return HA;
  970. }
  971. double MEqM1DriverControl::getLST(void) {
  972.   double GST, GST0, JC, LST;
  973.   JC = (this->initialJD0 - 2451545.0) / 36525.0;
  974.   GST0 = 100.4606184 + 36000.77005361 * JC + 0.00038793 * JC * JC;
  975.   GST = GST0 + 15.041068640247729 * (getPreciseTime() -
  976.     int(this->longitude/15.0));
  977.   // Puts the value into the range of 0º to 360º;
  978.   GST = GST - int(GST / 360.0) * 360.0;
  979.   LST = GST + this->longitude;

  980.   return LST;
  981. }
  982. void MEqM1DriverControl::getMicrostepsTogo(void){
  983.   long tgShRA  = 0L;
  984.   long tgShDec = 0L;

  985.   // Gets the position of target in microsteps.
  986.   getTargetShaftPosition(targetRA, targetDec, tgShRA, tgShDec);
  987.   // Gets the microsteps to go from current position to the target position.
  988.   this->microStepsTogoRA  = tgShRA  - this->shaftRAPosition;
  989.   this->microStepsTogoDec = tgShDec - this->shaftDecPosition;
  990. }
  991. double MEqM1DriverControl::getPreciseTime(void) {
  992.   unsigned long timeElapsed, microsNow;

  993.     microsNow = micros();
  994.     // Corrects, if necessary, for micros() overflow.
  995.     if (microsNow < this->initialMicrosecond) {
  996.       timeElapsed = (4294967295 - this->initialMicrosecond) + microsNow;
  997.       this->initialTime += (this->initialMicrosecond/3.6e9);
  998.       this->initialMicrosecond = microsNow;
  999.     } else {
  1000.       timeElapsed = microsNow - this->initialMicrosecond;
  1001.     }
  1002.   return this->initialTime + timeElapsed/3.6e9;
  1003. }
  1004. void MEqM1DriverControl::getTargetShaftPosition(double RA, double Dec,
  1005.                 long &tgShRA, long &tgShDec) {
  1006.   double HA = 0.0;
  1007.   double shaftDec = 0.0;
  1008.   double shaftRA = 0.0;
  1009.   int signLAT = sign(this->latitude);
  1010.   HA = getHA(RA);
  1011.   // Calculation of shaftRa and shaftDec from HA quadrant.
  1012.   // Quadrant signals for South(RA, Dec): 1:-+ 2:++ 3:-- 4:+-
  1013.   // Quadrant signals for North(RA, Dec): 1:+- 2:-- 3:++ 4:-+
  1014.   // Range of shaftRA(-90,90). Range of shaftDec(-180,180).
  1015.   if (HA >= 0 && HA < 90) {            // First Quadrant.
  1016.     shaftRA  = (90.0 - HA) * signLAT;   // Sinal - in South, + in North.
  1017.     shaftDec = Dec - 90 * signLAT;      // Sinal + in South, - in North.
  1018.   } else if (HA >= 90 && HA < 180) {   // Second Quadrant.
  1019.     shaftRA  = (90.0 - HA) * signLAT;   // Sinal + in South, - in North.
  1020.     shaftDec = Dec - 90 * signLAT;      // Sinal + in South, - in North.
  1021.   } else if (HA >= 180 && HA < 270) {  // Third Quadrant.
  1022.     shaftRA  = (270.0 - HA) * signLAT;  // Sinal - in South, + in North.
  1023.     shaftDec = -(Dec - 90 * signLAT);   // Sinal - in South, + in North.
  1024.   } else {                              // Fourth Quadrant.
  1025.     shaftRA  = (270.0 - HA) * signLAT;  // Sinal + in South, - in North.
  1026.     shaftDec = -(Dec - 90 * signLAT);   // Sinal - in South, + in North.
  1027.   }
  1028.   // Transform from degrees into microsteps (1/32 of full step).
  1029.   // 360° of shaft = 320*200*32 = 2.048.000 microsteps.
  1030.   tgShRA = long(shaftRA / 360.0 * 2048000);
  1031.   tgShDec = long(shaftDec / 360.0 * 2048000);
  1032. }
  1033. double MEqM1DriverControl::getTime(void) {
  1034.   byte h, m, s;

  1035.   Wire.beginTransmission(PCF8563ADDRESS);
  1036.   Wire.write(PCF8563TIMEADD);
  1037.   Wire.endTransmission();
  1038.   Wire.requestFrom(PCF8563ADDRESS, 3);
  1039.   s = BCDToDecimal(Wire.read() & 0x7f);
  1040.   m = BCDToDecimal(Wire.read() & 0x7f);
  1041.   h = BCDToDecimal(Wire.read() & 0x3f);

  1042.   return double(h + m/60.0 + s/3600.0);
  1043. }
  1044. void MEqM1DriverControl::RADecToAltAz(double RA, double Dec,
  1045.         double &Alt, double &Az) {
  1046.   double D2R = 3.1415926535897 / 180.0; // º -> radians transformation factor.
  1047.   double DE = 0.0;
  1048.   double HA = 0.0;
  1049.   double LAT = 0.0;
  1050.   // Transform degree in radians.
  1051.   HA = getHA(RA)*D2R;
  1052.   DE = Dec*D2R;
  1053.   LAT = this->latitude*D2R;
  1054.   // Coordinates transformation.
  1055.   Alt = asin(sin(DE)*sin(LAT) + cos(DE)*cos(LAT)*cos(HA));
  1056.   Az = acos((sin(DE) - sin(LAT)*sin(Alt))/(cos(Alt)*cos(LAT)));
  1057.   // Transform radians back to the degree.
  1058.   Alt /= D2R;
  1059.   Az /= D2R;
  1060.   // Correction for the range of the azimute (Az).
  1061.   if (HA > 0) Az = 360 - Az;
  1062. }
  1063. bool MEqM1DriverControl::setDate(int day, int mo, int yr) {
  1064.   bool validDate = false;

  1065.   // Make a basic verification of date. Because of use of J2000
  1066.   // and PCF8563 the year must be greater than 2000 -> 00.
  1067.   // Pay attention to the more common errors.
  1068.   if ((mo == 2) && (day > 28)) {
  1069.     // If is leap year allow the 29th day.
  1070.     if ((yr / 4.0 == 0) && (day == 29)) {
  1071.       validDate = true;
  1072.     } else {
  1073.       validDate = false;
  1074.     }
  1075.   } else if ((mo == 4) || (mo == 6) || (mo == 9) || (mo == 11) && (day > 30)) {
  1076.     validDate = false;     
  1077.   } else if ((day > 0) && (day <= 31) && (mo > 0) && (mo <=12)) {
  1078.     validDate = true;
  1079.     // Update the time on PCF8563.
  1080.     Wire.beginTransmission(PCF8563ADDRESS);
  1081.     Wire.write(PCF8563DATEADD);
  1082.     Wire.write(decimalToBCD(day));
  1083.     Wire.write(decimalToBCD(1)); // Not used. Don't worry about.
  1084.     Wire.write(decimalToBCD(mo));
  1085.     Wire.write(decimalToBCD(yr));
  1086.     Wire.endTransmission();
  1087.   }
  1088.   return validDate;
  1089. }
  1090. bool MEqM1DriverControl::setHighLimit(double highLimit) {
  1091.   if (highLimit >= 0.0 && highLimit <= 90.0) {
  1092.     this->highLimit = highLimit;
  1093.     return 1;
  1094.   } else {
  1095.     return 0;
  1096.   }
  1097. }
  1098. void MEqM1DriverControl::setLatitude(double latitude) {
  1099.   this->latitude = latitude;
  1100. }
  1101. void MEqM1DriverControl::setLongitude(double longitude) {
  1102.   this->longitude = longitude;
  1103. }
  1104. void MEqM1DriverControl::setMicrostepDecMode(short mode) {
  1105.   switch (mode) {
  1106.     case 0:
  1107.       digitalWrite(DecDRV8825M2, LOW);
  1108.       digitalWrite(DecDRV8825M1, LOW);
  1109.       digitalWrite(DecDRV8825M0, LOW);
  1110.       break;
  1111.     case 1:
  1112.       digitalWrite(DecDRV8825M2, LOW);
  1113.       digitalWrite(DecDRV8825M1, LOW);
  1114.       digitalWrite(DecDRV8825M0, HIGH);
  1115.       break;
  1116.     case 2:
  1117.       digitalWrite(DecDRV8825M2, LOW);
  1118.       digitalWrite(DecDRV8825M1, HIGH);
  1119.       digitalWrite(DecDRV8825M0, LOW);
  1120.       break;
  1121.     case 3:
  1122.       digitalWrite(DecDRV8825M2, LOW);
  1123.       digitalWrite(DecDRV8825M1, HIGH);
  1124.       digitalWrite(DecDRV8825M0, HIGH);
  1125.       break;
  1126.     case 4:
  1127.       digitalWrite(DecDRV8825M2, HIGH);
  1128.       digitalWrite(DecDRV8825M1, LOW);
  1129.       digitalWrite(DecDRV8825M0, LOW);
  1130.       break;
  1131.     case 5:
  1132.       digitalWrite(DecDRV8825M2, HIGH);
  1133.       digitalWrite(DecDRV8825M1, LOW);
  1134.       digitalWrite(DecDRV8825M0, HIGH);
  1135.       break;
  1136.     default:
  1137.       digitalWrite(DecDRV8825M2, LOW);
  1138.       digitalWrite(DecDRV8825M1, LOW);
  1139.       digitalWrite(DecDRV8825M0, LOW);
  1140.       break;
  1141.   }
  1142.   // Update the microstep mode for the Dec shaft.
  1143.   this->microstepModeDec = mode;
  1144. }
  1145. void MEqM1DriverControl::setMicrostepRAMode(short mode) {
  1146.   switch (mode) {
  1147.     case 0:
  1148.       digitalWrite(RADRV8825M2, LOW);
  1149.       digitalWrite(RADRV8825M1, LOW);
  1150.       digitalWrite(RADRV8825M0, LOW);
  1151.       break;
  1152.     case 1:
  1153.       digitalWrite(RADRV8825M2, LOW);
  1154.       digitalWrite(RADRV8825M1, LOW);
  1155.       digitalWrite(RADRV8825M0, HIGH);
  1156.       break;
  1157.     case 2:
  1158.       digitalWrite(RADRV8825M2, LOW);
  1159.       digitalWrite(RADRV8825M1, HIGH);
  1160.       digitalWrite(RADRV8825M0, LOW);
  1161.       break;
  1162.     case 3:
  1163.       digitalWrite(RADRV8825M2, LOW);
  1164.       digitalWrite(RADRV8825M1, HIGH);
  1165.       digitalWrite(RADRV8825M0, HIGH);
  1166.       break;
  1167.     case 4:
  1168.       digitalWrite(RADRV8825M2, HIGH);
  1169.       digitalWrite(RADRV8825M1, LOW);
  1170.       digitalWrite(RADRV8825M0, LOW);
  1171.       break;
  1172.     case 5:
  1173.       digitalWrite(RADRV8825M2, HIGH);
  1174.       digitalWrite(RADRV8825M1, LOW);
  1175.       digitalWrite(RADRV8825M0, HIGH);
  1176.       break;
  1177.     default:
  1178.       digitalWrite(RADRV8825M2, LOW);
  1179.       digitalWrite(RADRV8825M1, LOW);
  1180.       digitalWrite(RADRV8825M0, LOW);
  1181.       break;
  1182.   }
  1183.   // Update the microstep mode for the RA shaft.
  1184.   this->microstepModeRA = mode;
  1185. }
  1186. void MEqM1DriverControl::setTargetDec(int d, int m, int s) {
  1187.   this->targetDec = sign(d)*(abs(d) + float(m) / 60.0 + float(s) / 3600.0);
  1188. }
  1189. void MEqM1DriverControl::setTargetRA(int h, int m, int s) {
  1190.   this->targetRA = (h + float(m) / 60.0 + float(s) / 3600.0) * 15;
  1191. }
  1192. void MEqM1DriverControl::setTime(int h, int m, int s) {
  1193.   // Update the time on PCF8563.
  1194.   Wire.beginTransmission(PCF8563ADDRESS);
  1195.   Wire.write(PCF8563TIMEADD);
  1196.   Wire.write(decimalToBCD(s));
  1197.   Wire.write(decimalToBCD(m));
  1198.   Wire.write(decimalToBCD(h));
  1199.   Wire.endTransmission();
  1200. }
  1201. int MEqM1DriverControl::sign(double x) {
  1202.   int sign = 1;
  1203.   // Verify if x is zero because of the denominator in the expression below.
  1204.   if (x == 0) sign = 0;
  1205.   else sign = int (x / abs(x));
  1206.   return sign;
  1207. }
  1208. double MEqM1DriverControl::translateHMSToDec(char *value) {
  1209.   char buffer[5];
  1210.   int number[3];
  1211.   int j = 0;
  1212.   int k = 0;
  1213.   for (int i = 0; i < strlen(value); i++) {
  1214.     if (value[i] == ':' or value[i] == char(223)) {
  1215.       buffer[j] = 0;            // Close the string.
  1216.       number[k] = atoi(buffer); // Convert from string to integer.
  1217.       j = 0;                    // Points to the first place of the buffer.
  1218.       ++k;                      // Points to the next integer of array.
  1219.     } else {
  1220.       buffer[j] = value[i];     // Copy the value to buffer.
  1221.       ++j;
  1222.     }
  1223.   }
  1224.   buffer[j] = 0;                // Close the last string.
  1225.   number[2] = atoi(buffer);     // Gets the last number.
  1226.   return double(abs(number[0]) + number[1] / 60.0 +
  1227.           number[2] / 3600.0) * sign(number[0]);
  1228. }
复制代码


发表于 2016-4-5 19:49 来自手机 来自: 广东省肇庆市端州区 电信
求原网址

点评 回复 显示全部楼层 道具 举报

open 发表于 2016-4-6 10:05 详情  回复
出处在翻视频老外在评论里直贴出来的。视频地址:https://www.youtube.com/watch?v=mvmumsAvjLM
v2500 该用户已被删除
发表于 2016-4-5 21:14 来自: 广东省深圳市 天威视讯
提示: 作者被禁止或删除 内容自动屏蔽

回复 显示全部楼层 道具 举报

发表于 2016-4-5 21:15 来自: 北京市 教育信息网

回复 显示全部楼层 道具 举报

发表于 2016-4-5 23:20 来自: 江苏省苏州市 电信
一直想学但一直想不起来要学

回复 显示全部楼层 道具 举报

发表于 2016-4-6 07:18 来自: 河南省郑州市 电信
本帖最后由 optical 于 2016-4-6 07:20 编辑

楼主好人,MARK下,正好我用的驱动芯片也是DRV8825,以后用到就来拿了

点评 回复 显示全部楼层 道具 举报

v2500 发表于 2016-4-6 12:41 详情  回复
用好后,有啥好的经验,给大家分享一下吧
发表于 2016-4-6 10:05 来自: 香港 城市电讯有限公司

出处在翻视频老外在评论里直贴出来的。视频地址:https://www.youtube.com/watch?v=mvmumsAvjLM

点评 回复 显示全部楼层 道具 举报

弼马温1984 发表于 2016-4-6 12:31 详情  回复
感谢分享,祝早日成功
发表于 2016-4-6 12:31 来自: 广东省肇庆市端州区 电信
open 发表于 2016-4-6 10:05
出处在翻视频老外在评论里直贴出来的。视频地址:https://www.youtube.com/watch?v=mvmumsAvjLM
...

感谢分享,祝早日成功

点评 回复 显示全部楼层 道具 举报

open 发表于 2016-4-6 16:00 详情  回复
我没整经纬仪.dob的可以拿来参考.通过看变量名。用的模块有 DRV8825 最高32细分驱动、PCF8563时钟模块、JOYSTICK手柄
v2500 该用户已被删除
发表于 2016-4-6 12:41 来自: 广东省深圳市 电信
提示: 作者被禁止或删除 内容自动屏蔽

回复 显示全部楼层 道具 举报

发表于 2016-4-6 16:00 来自: 广东省广州市 电信
弼马温1984 发表于 2016-4-6 12:31
感谢分享,祝早日成功

我没整经纬仪.dob的可以拿来参考.通过看变量名。用的模块有 DRV8825 最高32细分驱动、PCF8563时钟模块、JOYSTICK手柄

点评 回复 显示全部楼层 道具 举报

弼马温1984 发表于 2016-4-6 16:44 详情  回复
好像有面向对象的“类”,可惜没学过C++,只会一些C的皮毛,搞不懂。
发表于 2016-4-6 16:44 来自: 广东省肇庆市端州区 电信
open 发表于 2016-4-6 16:00
我没整经纬仪.dob的可以拿来参考.通过看变量名。用的模块有 DRV8825 最高32细分驱动、PCF8563时钟模块、J ...

好像有面向对象的“类”,可惜没学过C++,只会一些C的皮毛,搞不懂。

回复 显示全部楼层 道具 举报

发表于 2016-4-10 20:22 来自: 浙江省宁波市 电信
学汇编的路过。。。

回复 显示全部楼层 道具 举报

发表于 2016-4-11 16:36 来自: 浙江省宁波市 鄞州畅联信息技术有限公司
汇编路过

回复 显示全部楼层 道具 举报

发表于 2016-4-15 15:30 来自: 上海市 东方有线
不错。

回复 显示全部楼层 道具 举报

发表于 2016-4-16 18:18 来自手机 来自: 广东省深圳市 电信
学c++的路过

回复 显示全部楼层 道具 举报

APP下載|爱牧夫天文淘宝店|牧夫天文网 ( 公安备案号21021102000967 )|网站地图|辽ICP备19018387号

GMT+8, 2024-7-6 07:24 , Processed in 0.071788 second(s), 32 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表