From 65de951b037a1fb31896a932f3f8184317dce6ed Mon Sep 17 00:00:00 2001 From: ozarchie Date: Fri, 23 Jul 2021 18:01:01 +1000 Subject: [PATCH] Delete Software/EQG2HBXE32/src directory --- Software/EQG2HBXE32/src/EQG2HBX.h | 209 ----- Software/EQG2HBXE32/src/EQG2HBXE32.ino | 256 ------ Software/EQG2HBXE32/src/EQGProtocol.h | 305 ------- Software/EQG2HBXE32/src/EQGProtocol.ino | 988 ---------------------- Software/EQG2HBXE32/src/ETXProtocol.h | 111 --- Software/EQG2HBXE32/src/ETXProtocol.ino | 903 -------------------- Software/EQG2HBXE32/src/HBXComms.h | 57 -- Software/EQG2HBXE32/src/HBXComms.ino | 334 -------- Software/EQG2HBXE32/src/HBXFileSystem.h | 12 - Software/EQG2HBXE32/src/HBXFileSystem.ino | 108 --- Software/EQG2HBXE32/src/HBXWiFiServer.h | 117 --- Software/EQG2HBXE32/src/HBXWiFiServer.ino | 509 ----------- Software/EQG2HBXE32/src/Hardware.h | 62 -- 13 files changed, 3971 deletions(-) delete mode 100644 Software/EQG2HBXE32/src/EQG2HBX.h delete mode 100644 Software/EQG2HBXE32/src/EQG2HBXE32.ino delete mode 100644 Software/EQG2HBXE32/src/EQGProtocol.h delete mode 100644 Software/EQG2HBXE32/src/EQGProtocol.ino delete mode 100644 Software/EQG2HBXE32/src/ETXProtocol.h delete mode 100644 Software/EQG2HBXE32/src/ETXProtocol.ino delete mode 100644 Software/EQG2HBXE32/src/HBXComms.h delete mode 100644 Software/EQG2HBXE32/src/HBXComms.ino delete mode 100644 Software/EQG2HBXE32/src/HBXFileSystem.h delete mode 100644 Software/EQG2HBXE32/src/HBXFileSystem.ino delete mode 100644 Software/EQG2HBXE32/src/HBXWiFiServer.h delete mode 100644 Software/EQG2HBXE32/src/HBXWiFiServer.ino delete mode 100644 Software/EQG2HBXE32/src/Hardware.h diff --git a/Software/EQG2HBXE32/src/EQG2HBX.h b/Software/EQG2HBXE32/src/EQG2HBX.h deleted file mode 100644 index 607f4fe..0000000 --- a/Software/EQG2HBXE32/src/EQG2HBX.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2017, 2018, 2020 John Archbold -*/ - -/******************************************************** - EQG2HBX program definitions - =========================== - *********************************************************/ - -#pragma once - -#include // Include the SPIFFS library -#include -#include "ESP32Ticker.h" - -void CheckETXState( unsigned char ); - -/************************************************************** - * Common variables - **************************************************************/ -String EQ2HBX_Version = "EQG2HBX V1.11"; - -Preferences preferences; -unsigned long DelayTime; // Delay timer -unsigned long StatusTime; // H2X interval time - -unsigned long StatusTimer; // H2X status delay timer -unsigned long StateTimer; // H2X state delay timer -bool StateSelect; -bool StatusSelect; -int StatusCount; - -Ticker AlarmCheckETX; - -long P1; -long P2; -float F1; -float F2; - -time_t epoch; // UTC seconds -time_t currentTime; // Local value - -/************************************************************** - * EQG protocol communications buffers and pointers - * EQG protocol variables - **************************************************************/ - -#define EQGLEN 256 // Communications buffers -#define EQGMASK EQGLEN-1 // Index wraps to 0 - -unsigned long EQGP1; -unsigned long EQGP2; -float EQGF1; - -unsigned char EQGRxBuffer[EQGLEN]; // Hold data from EQG -unsigned char EQGTxBuffer[EQGLEN]; // Hold responses to EQG -unsigned char EQGRxiPtr = 0; // Pointer for input from EQG -unsigned char EQGRxoPtr = 0; // Pointer for output from EQG Rx buffer -unsigned char EQGTxiPtr = 0; // Pointer for input to EQG buffer -unsigned char EQGTxoPtr = 0; // Pointer for output to EQG - -unsigned char EQGCmnd = 0; // EQG Command -unsigned char EQGErrorValue; // EQG Returned error value -unsigned char EQGDone = 0; // EQG Complete message -unsigned char EQGRADEC = 0; // EQG Motor Select (ASCII) -unsigned char EQGMOTOR = 0; // EQG Motor Select (binary) -unsigned char EQGRAAutoguide = 0; // EQG Autoguide rate -unsigned char EQGDECAutoguide = 0; // EQG Autoguide rate -unsigned char EQGRxState = 1; // EQG State -unsigned char EQGRxChar; // EQG Rx Character -unsigned char EQGRxCount; // EQG # parameters - float f; -unsigned long v; - -/************************************************************** - * HBX communications buffers and pointers - * HBX variables - **************************************************************/ - -unsigned long H2XStart = 0; // Used to count uS ticks -unsigned long H2XTimer = 0; // Used to count uS ticks -unsigned char EQGMotorStatus; // Current State of motor - -typedef struct { - unsigned char MotorType; // Current type of motor - unsigned char MotorFlag; // Flag to print motor positions - - unsigned long ETXMotorState; // ETX Motor State Nachine - unsigned long ETXMotorStatus; // Current ETX Motor Status - unsigned long EQGMotorStatus; // Current EQG Motor Status - unsigned long MotorControl; // Current HBX Motor Control bits - - unsigned char HBXBitCount; // #bits left to process - unsigned char Command; // Current command - unsigned char Flip; // Axis flipped - Alt for negative, Az probably never - unsigned char HBXData; // Data byte from HBX Bus - unsigned char HBXP1; // HBX status/data - MSB - unsigned char HBXP2; // HBX status/data - LSB - unsigned char HBXP3; // HBX status/data - PWM % related - unsigned char HBXP4; // HBX status/data - single flag bit related to battery alarm ( 0 = OK ) - unsigned char HBXCount; // HBX valid data count - unsigned char HBXLEDI; // LED current value from Motor - unsigned long DirnSpeed; // Speed, Direction for Motor to move - char HBXGuide; // Guide speed - char HBXSnapPort; // Snap port - char LEDValue; // Polar LED brightness - char ETXSpeedCommand; // Current ETX Speed command - long EQGSpeed; // EQG Move speed - long ETXSpeed; // ETX Move speed - long TargetSpeed; // Target Move speed - uint8_t SpeedState; // Slowdown/speedup state - long Position; // Current position - long Target; // Current target - long Increment; // Change in position for motor speed calcs - long SlowDown; // Point to change to lower speed - long Offset; // Current adjustment - -// MeadeRatio = ((Vanes * 4) * GbxRatio * XferRatio * WormTeeth) / 1,296,000 - float MeadeRatio; // Meade Ratio - float GbxRatio; // GearBox Ratio - unsigned long Vanes; // Number of photocoupler vanes - float XferRatio; // Gearbox Transfer Ratio (usually 1) - unsigned long WormTeeth; // Number of Worm teeth - -// a-Value = (Vanes * 4) * GbxRatio * XferRatio * WormTeeth -// b-Value = (6460.09 * MeadeRatio * a-Value * 15.041069) / 1,296,000 - unsigned long aVALUE; // For rate calculations - unsigned long bVALUE; // For rate calculations - unsigned long OneDegree; // For slew comparisons - -// SIDEREALRATE = 6460.09 * MeadeRatio -// SOLARRATE = (SOLARSECS/SIDEREALSECS) * SIDEREALRATE -// LUNARRATE = (SOLARSECS/SIDEREALSECS) * SIDEREALRATE -// DEGREERATE1 = SLEW7(240) * SIDEREALRATE -// BASERATE = (b * arcsec360) / a - - unsigned long SIDEREALRATE; // Constants - unsigned long SOLARRATE; - unsigned long LUNARRATE; - unsigned long BASERATE; - unsigned long DEGREERATE1; - -// PEC = a-VALUE / WormTeeth; - unsigned long PEC; // PEC period (period of worm tooth) - - unsigned char PrintStatus0; // Force print of no status change - unsigned long TimeDelta; // Used in HBX Monitor -} axis_type; - -axis_type axis[4]; // Az, Alt - -// Support other scopes with Meade interface -typedef struct { - unsigned long Vanes; // Number of photocoupler vanes - float GbxRatio; // GearBox Ratio - float XferRatio; // Gearbox Transfer Ratio (usually 1) - unsigned long WormTeeth; // Number of Worm teeth - char Telescope[16]; // name of scope -} axis_values; - -axis_values ratio[16][2] = // 16 scopes, Az, Alt - { - {{36, 91.1458333, 1, 94, "ETX60"}, {36, 157.5, 1, 58, "ETX60"}}, // ETX60/70/80 - {{36, 91.1458333, 1, 94, "ETX70"}, {36, 157.5, 1, 58, "ETX70"}}, // ETX60/70/80 - {{36, 91.1458333, 1, 94, "ETX80"}, {36, 157.5, 1, 58, "ETX80"}}, // ETX60/70/80 - {{108, 50, 1, 144, "LXD55"}, {108, 50, 1, 144, "LXD55"}}, // LXD55/75, LX70-GTS - {{108, 50, 1, 144, "LXD75"}, {108, 50, 1, 144, "LXD75"}}, // LXD55/75, LX70-GTS - {{108, 50, 1, 144, "LXD70"}, {108, 50, 1, 144, "LXD70"}}, // LXD55/75, LX70-GTS - {{108, 53.5859375, 1, 154, "LX90"}, {108, 53.5859375, 1, 154, "LX90"}}, // LX90, LT, LX80AltAz - {{108, 53.5859375, 1, 154, "LT"}, {108, 53.5859375, 1, 154, "LT"}}, // LX90, LT, LX80AltAz - {{108, 53.5859375, 1, 154, "LX80"}, {108, 53.5859375, 1, 154, "LX80"}}, // LX90, LT, LX80AltAz - {{256, 50, 1, 350, "LX200"}, {256, 50, 1, 350, "LX200"}}, // LX200 - {{500, 36, 1, 225, "LX850"}, {500, 36, 1, 225, "LX850"}}, // LX850 - {{256, 50, 1, 180, "LX400"}, {256, 50, 1, 180, "LX400"}}, // LX400/500 - {{36, 205.3330000, 1, 144, "DSEXT"}, {36, 205.3330000, 1, 144, "DSEXT"}}, // DS external - {{36, 410.6660000, 1, 100, "DHEXT"}, {36, 157.5, 1, 58, "DHEXT"}}, // DH external/114EQs/4504s - - {{36, 205.3330000, 1, 60, "ETXnn"}, {36, 205.3330000, 1, 60, "ETXnn"}}, // ETX-xxx, DS-xxx - {{36, 91.1458333, 1, 83, "ETX??"}, {36, 144.7362076, 1, 66, "ETX??"}} // ?? - }; - -unsigned char telescope = 0; // Default telescope (ETX60) -unsigned char protocol = 0; // Default protocol (UDP) -unsigned char station = 0; // Default station (AP) -char scope[16] = "ETX60"; - -char* an0 = (char*)"Bad"; -char* an1 = (char*)"Az "; -char* an2 = (char*)"Alt"; -char * axis_name[3] = { an0, an1, an2 }; - -char SpeedStateDesc[4][16] = {"ChangeToStep", "Slowing1", "Slowing2", "Stopped"}; - - -// Testing only - -Ticker AlarmDebugPrint; -#define dbgLEN 256 // Communications buffers -#define dbgMASK dbgLEN-1 // Index wraps to 0 -unsigned char dbgRxBuffer[dbgLEN]; // Hold data from EQG - char dbgCommand[dbgLEN]; // Hold data from EQG -unsigned char dbgRxiPtr = 0; // Pointer for input from EQG -unsigned char dbgRxoPtr = 0; // Pointer for output from EQG Rx buffer -unsigned char dbgFlag = 0; // Received a command -unsigned char dbgIndex = 0; // Index into command - -unsigned char TestCount; -unsigned long TestLoopTime; -unsigned long PreviousTime; // Used in HBX Monitor, Testing diff --git a/Software/EQG2HBXE32/src/EQG2HBXE32.ino b/Software/EQG2HBXE32/src/EQG2HBXE32.ino deleted file mode 100644 index 11b3193..0000000 --- a/Software/EQG2HBXE32/src/EQG2HBXE32.ino +++ /dev/null @@ -1,256 +0,0 @@ -/**@file*/ -/* - Name: EQG2HBXE32.ino - Created: 2018-09-01 10:07:17 AM - Author: JOHNWIN10PRO\John -*/ -#include -#include -#include -#include "Hardware.h" - -#include // Include the SPIFFS library -#include -#include "ESP32Ticker.h" -//#include - -#include "EQG2HBX.h" -#include "EQGProtocol.h" -#include "ETXProtocol.h" -#include "HBXComms.h" -#include "HBXWiFiServer.h" -#include "HBXFileSystem.h" - - -// Functions -// -/************************************************************************************************** - * Read / Update ETX - Timer Driven - **************************************************************************************************/ -void UpdateETX(void) { -} - -/************************************************************************************************** - * Get ETXStatus - **************************************************************************************************/ -void CheckETXStatus(unsigned char Motor) { - HBXGetStatus(Motor); -} - -/************************************************************************************************** - * Check ETXState - **************************************************************************************************/ -void CheckETXState(unsigned char Motor) { - ETXState(Motor); // Check the motor state -} - -/******************************************************** - Initialize HBX, translate EQG to HBX - ==================================== - *********************************************************/ - -// ======================================================================================================= -void setup() -{ -// int i, j, k; -// bool b; - -#ifdef mESP32 - dbgSerial.begin(115200); // debug - EQGSerial.begin(9600, SERIAL_8N1, 18, 19); // EQG via serial, bluetooth or WiFi - #ifdef BTSerial - EQGBluetooth.begin("EQ6Blue"); - #endif - delay(10); -#endif - - dbgSerial.println(EQ2HBX_Version); - DelayTime = micros(); // Initialize timers, counts - StatusTime = DelayTime; - EQGErrorValue = 0; - -#ifdef mESP32 - HBXWiFiSetup(); -#endif - - pinMode(ETXLED, OUTPUT); // Operation indicators - pinMode(EQGLED, OUTPUT); - digitalWrite(ETXLED, LOW); - digitalWrite(EQGLED, LOW); - - axis[AzMotor].PrintStatus0 = 0; // Disable printing "status polls" with no change - axis[AltMotor].PrintStatus0 = 0; // Disable printing "status polls" with no change - - // Initialize EQG communications - dbgSerial.println("HBX Initialization"); - - // Read Motor Type to determine telescope type - // ------------------------------------------- - preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace - telescope = 0; // Default ETX60 - if (!(preferences.getUChar("TELESCOPE", 0) == 0)) { // If it exists check telescope table for a match - telescope = (preferences.getUChar("TELESCOPE", 0)); - } - dbgSerial.print("Telescope: "); - dbgSerial.print(telescope); - dbgSerial.print(", "); - dbgSerial.println(ratio[telescope][0].Telescope); - if (!(preferences.getUChar("PROTOCOL", 0) == 0)) { // If it exists get protocol type (UDP, NOW) - protocol = (preferences.getUChar("PROTOCOL", 0)); - } - dbgSerial.print("Protocol: "); - dbgSerial.print(protocol); - dbgSerial.print(", "); - if (!(preferences.getUChar("STATION", 0) == 0)) { // If it exists get station type (AP, STA) - protocol = (preferences.getUChar("STATION", 0)); - } - dbgSerial.print("Station: "); - dbgSerial.println(station); - preferences.end(); - - AzInitialise(telescope); - AltInitialise(telescope); - //PrintRatioValues(telescope); - PrintHbxValues(AzMotor); - PrintHbxValues(AltMotor); - - // Initialize HBX communications as outputs - // It will use H2X communications - HBXReset(); - - // Reset the motors (RA and DEC) - // and wait until both respond to a command - dbgSerial.println("Waiting for both motors to start up .."); - WaitForMotors(); - - // Get Motor Type from Az MC ( assume both same type of motor) - - do { - axis[AzMotor].MotorType = 0x00; - if (HBXSendCommand(GetMotorType, AzMotor)) - axis[AzMotor].MotorType = HBXGetByte(AzMotor); - } while (!axis[AzMotor].MotorType); - axis[AltMotor].MotorType = axis[AzMotor].MotorType; - dbgSerial.println(""); dbgSerial.print("Motor Type: "); dbgSerial.print(axis[AltMotor].MotorType); - - // Handle position sensors LED current - // ----------------------------------- - dbgSerial.println(""); dbgSerial.print("Check Calibrate LEDs"); - preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace - if (preferences.getUChar("AzLEDI", 0) == 0) { // If it does not exist, calibrate the LEDs - CalibrateLEDs(); - } -// Read stored LED currents - axis[AzMotor].HBXLEDI = preferences.getUChar("AzLEDI", 0); - axis[AltMotor].HBXLEDI = preferences.getUChar("AltLEDI", 0); - preferences.end(); - -// Set the MC LED values - dbgSerial.println(""); dbgSerial.print("Set MC LED values"); - if (HBXSendCommand(SetLEDI, AzMotor)) - HBXSendByte(axis[AzMotor].HBXLEDI, AzMotor); - axis[AzMotor].HBXP1 = axis[AzMotor].HBXLEDI; - HBXPrintStatus(AzMotor); - - if (HBXSendCommand(SetLEDI, AltMotor)) - HBXSendByte(axis[AltMotor].HBXLEDI, AltMotor); - axis[AltMotor].HBXP1 = axis[AltMotor].HBXLEDI; - HBXPrintStatus(AltMotor); - - // Set the Offset Clear Command - // Send HBXP1, HBXP2 - dbgSerial.println(""); dbgSerial.print("Reset any ETX offset bytes"); - axis[AzMotor].HBXP1 = 0; - axis[AzMotor].HBXP2 = 0; - axis[AltMotor].HBXP1 = 0; - axis[AltMotor].HBXP2 = 0; - if (HBXSendCommand(SetOffset, AzMotor)) - HBXSend2Bytes(AzMotor); - TimerDelaymS(CMNDTIME); - if (HBXSendCommand(SetOffset, AltMotor)) - HBXSend2Bytes(AltMotor); - TimerDelaymS(CMNDTIME); - - // Stop the motors (RA and DEC) - dbgSerial.println(""); dbgSerial.print("Stop motors"); - do { - P1 = 0; - if (HBXSendCommand(Stop, AzMotor)) P1 += 1; - if (HBXSendCommand(Stop, AltMotor)) P1 += 1; - } while (P1 < 2); - - // Read status - dbgSerial.println(""); dbgSerial.println("Read Status"); - HBXGet2Status(); // Check and read both motor states - - dbgSerial.println("Setup Complete. Listening for commands .."); - - // Print debug info every 10 s - // --------------------------- - - // HBXTestLoop(); - -// AlarmDebugPrint.attach(10, debugEQG); // Print debug info every 10 s -// AlarmCheckETX.attach_ms(6, CheckETXState); // Check motor status (position), every 6mS -} - - -// ======================================================================================================= -void loop() -{ - /************************************************************************************************** - * Process EQG comms - Rx, Tx Comms are interrupt driven - **************************************************************************************************/ - - // dbgRx(); // Check for comms from debug port for telescope values - - // Check ETX motor status and state - if ((micros() - StateTimer) > (STATEDELAY * 1000)) { // ~6.55mS - if (StateSelect) StateSelect = false; - else StateSelect = true; - StateTimer = micros(); - if (StateSelect) CheckETXState(AzMotor); - else CheckETXState(AltMotor); - } - -//jma CheckAltFlipReqd(); - - if ((micros() - StatusTimer) > (STATUSDELAY * 1000)) { // ~50mS - StatusTimer = micros(); -/* if (StatusSelect) StatusSelect = false; - else StatusSelect = true; - if (StatusSelect) CheckETXStatus(AzMotor); - else CheckETXStatus(AltMotor); -*/ - CheckETXStatus(AzMotor); - CheckETXStatus(AltMotor); - } - - // Check any incoming characters from the EQMOD serial interface - if (HBXCheckRx()) - EQGState(); // Check command state if data received - if (EQGDone) { // EQG Rx complete, see what it is - if (EQGErrorValue == 0) { - EQGAction(); // and do it - } - else { - EQGError(EQGErrorValue); // EQGAction() may set an error - } - } - - // Check for any characters that are ready to go to the WiFi interface - while (EQGTxoPtr != EQGTxiPtr) { - - // Send any characters that are ready to go to the WiFi interface - digitalWrite(EQGLED, HIGH); - HBXCheckTx(); - EQGTxoPtr &= EQGMASK; - digitalWrite(EQGLED, LOW); - } -// TimerDelaymS(1); -// yield(); - // HandleOTA(); -} - -// End loop() - diff --git a/Software/EQG2HBXE32/src/EQGProtocol.h b/Software/EQG2HBXE32/src/EQGProtocol.h deleted file mode 100644 index 07846f1..0000000 --- a/Software/EQG2HBXE32/src/EQGProtocol.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright 2017, 2018, 2020 John Archbold -*/ - -/******************************************************** - EQG Protocol function definitions - ================================= - *********************************************************/ - -#pragma once - -#define CR 0x0d -#define LF 0x0a - -float SIDEREALSECS = 86164.098903691; // Some astronomical constants -float SOLARSECS = 86400; -float LUNARSECS = 89309; - -#define SKYWATCHER_SIDEREAL_DAY 86164.09053083288 -#define SKYWATCHER_SIDEREAL_SPEED 15.04106864 -#define SKYWATCHER_STELLAR_DAY 86164.098903691 -#define SKYWATCHER_STELLAR_SPEED 15.041067179 - -#define EQG_CMNDSTART 0x01 -#define EQG_WAITFORCR 0x77 -#define EQG_INTERPRET 0x78 - -/* - tmpMCVersion = Revu24str2long(response + 1); - MCVersion = ((tmpMCVersion & 0xFF) << 16) | ((tmpMCVersion & 0xFF00)) | ((tmpMCVersion & 0xFF0000) >> 16); - MountCode = MCVersion & 0xFF; -*/ - -/* -// Get Motor Controller Version -// :em[0D] -// ="llhhMM"[0D] (6 bytes - hex encoded) -// Revu24str2long = MMhhll (3 bytes - binary encoded) -// MCVersion = llhhMM (3 bytes - binary encoded) -// MountCode = MM (1 byte - binary encoded) -// ================================================================================= -// e 0 6 Get Motor Controller Version ="llhhMM"[0D] MM = mount code, -// x00 = "EQ6Pro" -// x01 = "HEQ5" -// x02 = "EQ5" -// x03 = "EQ3" -// x04 = "EQ8" -// x05 = "AZEQ6" -// x06 = "AZEQ5" -// x80 = "GT" -// x81 = "MF" -// x82 = "114GT" -// x90 = "DOB" -// hh.ll = board firmware version -// hh=x00..x07 -> equatorial -// =x08..xFF -> altaz -*/ -// Get Axis Features -// :qm[0D] -// ="EFCDAB"[0D] (6 bytes - hex encoded) -// AxisFeatures = EFCDAB (3 bytes - binary encoded) -// A 8 -// 4 -// 2 in PPEC -// 1 in PPECTraining - -// B 8 is AZEQ -// 4 has HomeIndexer -// 2 has PPEC -// 1 has Encoder - -// C 8 has Wifi -// 4 hasHalfCurrentTracking // ref :Wx06.... -// 2 has CommonSlewStart // Supports ":J3" -// 1 has PolarLed -/* -// AxisFeatures = EFCDAB (3 bytes - binary encoded) -// A -AxisFeatures[Axis1].inPPECTraining = rafeatures & 0x00000010; -AxisFeatures[Axis1].inPPEC = rafeatures & 0x00000020; -// B -AxisFeatures[Axis1].hasEncoder = rafeatures & 0x00000001; -AxisFeatures[Axis1].hasPPEC = rafeatures & 0x00000002; -AxisFeatures[Axis1].hasHomeIndexer = rafeatures & 0x00000004; -AxisFeatures[Axis1].isAZEQ = rafeatures & 0x00000008; -// C -AxisFeatures[Axis1].hasPolarLed = rafeatures & 0x00001000; -AxisFeatures[Axis1].hasCommonSlewStart = rafeatures & 0x00002000; // supports :J3 -AxisFeatures[Axis1].hasHalfCurrentTracking = rafeatures & 0x00004000; -AxisFeatures[Axis1].hasWifi = rafeatures & 0x00008000; -*/ -// Types -enum SkywatcherCommand -{ - Initialize = 'F', - InquireMotorBoardVersion = 'e', - InquireGridPerRevolution = 'a', - InquireTimerInterruptFreq = 'b', - InquireHighSpeedRatio = 'g', - InquirePECPeriod = 's', - InstantAxisStop = 'L', - NotInstantAxisStop = 'K', - SetAxisPositionCmd = 'E', - GetAxisPosition = 'j', - GetAxisStatus = 'f', - SetSwitch = 'O', - SetMotionMode = 'G', - SetGotoTargetIncrement = 'H', - SetBreakPointIncrement = 'M', - SetGotoTarget = 'S', - SetBreakStep = 'U', - SetStepPeriod = 'I', - StartMotion = 'J', - GetStepPeriod = 'D', - ActivateMotor = 'B', // See eq6direct implementation http://pierre.nerzic.free.fr/INDI/ - SetST4GuideRateCmd = 'P', - GetHomePosition = 'd', // Get Home position encoder count (default at startup) - SetFeatureCmd = 'W', // EQ8/AZEQ6/AZEQ5 only - GetFeatureCmd = 'q', // EQ8/AZEQ6/AZEQ5 only - InquireAuxEncoder = 'd', // EQ8/AZEQ6/AZEQ5 only - NUMBER_OF_SkywatcherCommand -}; - -enum SkywatcherAxis -{ - Axis1 = 0, // RA/AZ - Axis2 = 1, // DE/ALT - NUMBER_OF_SKYWATCHERAXIS -}; -char AxisCmd[2]{ '1', '2' }; - -enum SkywatcherDirection -{ - BACKWARD = 0, - FORWARD = 1 -}; -enum SkywatcherSlewMode -{ - SLEW = 0, - GOTO = 1 -}; -enum SkywatcherSpeedMode -{ - LOWSPEED = 0, - HIGHSPEED = 1 -}; - -typedef struct SkyWatcherFeatures -{ - bool inPPECTraining = false; - bool inPPEC = false; - bool hasEncoder = false; - bool hasPPEC = false; - bool hasHomeIndexer = false; - bool isAZEQ = false; - bool hasPolarLed = false; - bool hasCommonSlewStart = false; // supports :J3 - bool hasHalfCurrentTracking = false; - bool hasWifi = false; -} SkyWatcherFeatures; - -enum SkywatcherGetFeatureCmd -{ - GET_INDEXER_CMD = 0x00, - GET_FEATURES_CMD = 0x01 -}; - -enum SkywatcherSetFeatureCmd -{ - START_PPEC_TRAINING_CMD = 0x00, - STOP_PPEC_TRAINING_CMD = 0x01, - TURN_PPEC_ON_CMD = 0x02, - TURN_PPEC_OFF_CMD = 0X03, - ENCODER_ON_CMD = 0x04, - ENCODER_OFF_CMD = 0x05, - DISABLE_FULL_CURRENT_LOW_SPEED_CMD = 0x0006, - ENABLE_FULL_CURRENT_LOW_SPEED_CMD = 0x0106, - RESET_HOME_INDEXER_CMD = 0x08 -}; - -// Get Motor Controller Assets -// :qm010000[0D] -// =ABCDEF[0D] -// ============ -// A 8 not defined -// 4 not defined -// 2 PPEC ON -// 1 PPEC training in progress, -// B 8 supports AZ/EQ -// 4 has Home Sensors -// 2 supports PPEC -// 1 supports dual encoders -// C 8 has WIFI -// 4 supports half current tracking // ref :Wx06.... -// 2 axes slews must start independently // ie cant use :J3 -// 1 has polar LED -// D 0000 -// E 0000 -// F 0000 -// EQ6 returns !0 -// ABCDEF -// AZEQ5 =0B6000 at boot -// AZEQ6 =0B3000 -// EQ8 =076000 -// ABCDEF - -// Mount Assets -// EFCDAB -#define AEQ6 0x003000 // !:J3, PolarLED ; Real EQ6Pro -#define AAEQ6 0x003008 // !:J3, PolarLED ; Pretend Az-EQ6 -#define AEQ5 0x003008 // !:J3, PolarLED ; AZ/EQ -#define AEQ3 0x003000 // !:J3, PolarLED -#define AAZEQ5 0x00B008 // WiFi, !:J3, PolarLED ; AZ/EQ -#define AAZEQ6 0x00B008 // WiFi, !:J3, PolarLED ; AZ/EQ - -// Motor firmware versions -/* -// Get Motor Controller Version -// :e1[0D] -// ="llhhMM"[0D] (6 bytes - hex encoded) -// MountCode = MM (1 byte - binary encoded) -// x00 = "EQ6Pro", x01 = "HEQ5", x02 = "EQ5", x03 = "EQ3", x04 = "EQ8", x05 = "AZEQ6", "AZEQ5" -// x80 = "GT", x81 = "MF" , x82 = "114GT", x90 = "DOB" -// hh.ll = board firmware version -// hh = x00..x07 : equatorial -// = x08..xFF : altaz -*/ -#define VEQ6 0x000402 // Pretend EQ6 V 2.04 yyyy.mm.dd -#define VAEQ6 0x050902 // Pretend Az-EQ6 V 2.09 yyyy.mm.dd -#define VHEQ5 0x010204 // Pretend HEQ5 V 2.04 yyyy.mm.dd -#define VEQ5 0x020207 // Pretend EQ5 V 2.07 yyyy.mm.dd -#define VEQ3 0x030207 // Pretend EQ3 V 2.07 yyyy.mm.dd -#define VEQ8 0x040211 // Pretend EQ8 V 2.11 2014.11.10 -#define VAZEQ6 0x050211 // Pretend AZEQ6 V 2.11 2014.11.10 -#define VAZEQ5 0x060301 // Pretend AZEQ5 V 3.01 2015.08.10 - -#define EQGVERSION VAEQ6 // For ETX, pretend to be an AltAz mount based on EQ6 -#define EQGASSETS AAEQ6 // For ETX, pretend to be an AltAz mount based on EQ6 - - -// :I := ( :b * (360*60*60) / :a ) / Speed ( where Speed is in arcsec/sec ) -// If :I is greater than about 10, then the slew will need to use :G = LoSpeed mode -// If :I is less than 10, then the slew will need :G = HiRate, and :I := I * :g -// a-AxxValue (Ticks/rev) := AxxVanes * 4 * AxxGbxRatio * ( Axx Transfer ) * AxxWormTeeth -// b-AxxValue := 6460.09 * AxxRatio * a-AxxValue * 15.041069 / (360*60*60) - -// Speed = g*(b*(360*60*60)/a)/I -// ============================== -// IVALUE = (axis[EQGMOTOR].bVALUE * (360*60*60)) / axis[EQGMOTOR].STEPSPER360) - -#define EQG_gVALUE 0x000010 -#define EQGMAXIMUMSPEED 12 - -// EQG 'G' Command - SET move parameters -#define DIRECTION 0x00000001 // Increasing(0) Decreasing(1) -#define HEMISPHERE 0x00000002 // North(0) South(1) - -// Get axis tracking/slewing "status" -// EQG 'f' Command - GET Motor status bit definitions -// =ABC[0D] -// A xxx0 0 means GOTO, 1 means SLEW *** these are diff to :G usage -// 0 means "actually doing" the goto. On stopping, it reverts to Slew Mode -// xx0x 0 means +ve, 1 means -ve -// x0xx 0 means LoRate, 1 means HiSpeed *** -// B xxx0 0 means stopped, 1 means moving, -// xx0x 0 means OK, 1 means blocked ( For DC motors only ) -// C xxx0 1 means axis is Initialised/Energised -// xx0x 1 means level switch ON ( AltAz mounts and DEC only ) - -// MotorState bit definitions -// A nibble1 -#define MOVESLEW 0x0001 // Step(0) Slew(1) -#define MOVEDECR 0x0002 // Increasing(0) Decreasing(1) -#define MOVEHIGH 0x0004 // Low(0) High(1) -// B nibble2 -#define MOVEAXIS 0x0010 // Stopped(0) Moving(1) -#define MOVEFACE 0x0020 // Front(0) Rear(1) -// C nibble3 -#define MOVEACTIVE 0x0100 // Inactive(0) Active(1) - -#define RATESLEWHI RATE2DEGREES -#define RATESLEWLO RATESLEWHI >> 3 -#define RATEGOTOHI RATE1DEGREE -#define RATEGOTOLO RATEGOTOHI >> 3 - -void EQGState(void); -void EQGError(unsigned char); -void EQGAction(void); - -bool EQGRx(void); -void EQGTx(unsigned char); -void EQGTxHex(unsigned char); -void EQGTxHex2(unsigned char); -void EQGTxHex3(unsigned int); -void EQGTxHex6(unsigned long); - -// debug -void putbyte(unsigned char); -void putbyte(unsigned char); -void puthexb(unsigned char); -void puthexw(unsigned int); -void puthexl(unsigned long); -void putdecb(unsigned char); -void putdecw(unsigned int); -void putdecl(unsigned long); diff --git a/Software/EQG2HBXE32/src/EQGProtocol.ino b/Software/EQG2HBXE32/src/EQGProtocol.ino deleted file mode 100644 index 4e3e8f9..0000000 --- a/Software/EQG2HBXE32/src/EQGProtocol.ino +++ /dev/null @@ -1,988 +0,0 @@ -/**@file*/ -/* - * Copyright 2017, 2018, 2020 John Archbold -*/ -#include "Hardware.h" -#include "ETXProtocol.h" -#include "EQGProtocol.h" -#include "EQG2HBX.h" -#include "HBXComms.h" -#include "HBXFileSystem.h" -#include "HBXWiFiServer.h" -/* -// EQG Protocol description -// Courtesy Andrew Johansen - Yahoo Roboscope Group - -// Transmit to EQG -================== - :CbDDDDDD[0D] - C = command ( a..z, A..Z ) - b = controller ( 1 = Az, 2 = Alt, 3 = both ) - DDDDDD = data ( little endian ) uses 24bit little endian ( unless its a bitmapped command like :G ) -//------------------------------------------------------------------------------------------------- - -// Receive from EQG -=================== - "=DDDDDD[0D]" // Data - "!E[0D]" // Error - = means success - DDDDDD = data ( little endian ) uses 24bit little endian ( unless its a bitmapped command like :f, :q ) - ! means error - E is reason code - Error E = 0 Invalid Command // the command doesn't apply to the model - 1 Invalid Paramcount // a valid command was passed with invalid parameter count - 2 Motor not Stopped // a valid command failed to run ( e.g. sending :G whilst motor is running ) - 3 NonHex Param // the parameter contains a non uppercase Hex Char // Note! It doesn't mean an invalid parameter - 4 Not energised // motor is not energised - 5 Driver Asleep // controller is in sleep mode - 6 - 7 - 8 Invalid PPEC model -//------------------------------------------------------------------------------------------------- - -Values for Bytes sent -:C DDDDDD bytes - -Command, Bytes Sent, Nibbles Received, Description, // Example - - sent rcvd -a 0 6 Get microsteps per 360deg // =llhhLL[0D] -b 0 6 Get timer interrupt freq // =llhhLL[0D] -c 0 6 Get current ":U" value // =llhhLL[0D] -d 0 6 Get Current Encoder count // =llhhLL[0D] default #x800000 = home ( this is synched somehow with :j Data ) -e 0 6 Get Motor Controller Version // =llhhMM[0D] MM = mount type, - // x00 = "EQ6Pro" - // x01 = "HEQ5" - // x02 = "EQ5" - // x03 = "EQ3" - // x04 = "EQ8" - // x05 = "AZEQ6" - // x06 = "AZEQ5" - // hh.ll = board version hh=x00..x07 = equatorial - // =x08..xFF = altaz -f 0 3 Get axis tracking/slewing "status" // =ABC[0D] - // A xxx0 0 means GOTO, 1 means SLEW *** these are diff to :G usage - // 0 means "actually doing" the goto. On stopping, it reverts to Slew Mode - // xx0x 0 means +ve, 1 means -ve - // x0xx 0 means LoSpeed, 1 means HiSpeed *** - // B xxx0 0 means stopped, 1 means moving, - // xx0x 0 means OK, 1 means blocked ( For DC motors only ) - // C xxx0 1 means axis is Initialised/Energised - // xx0x 1 means level switch ON ( AltAz mounts and DEC only ) -g 0 2 Get HiSpeed multiplier // =llhhLL[0D] EQ6Pro, AZEQ5, EQ8 = 16 AZEQ6 = 32 -h 0 6 Get Current "goto" target // =llhhLL[0D] last value as set by :S or ( :j +/- :H ) -i 0 6 Get Current "slew" speed // =llhhLL[0D] must use with :f Hi/Lo and :g multiplier for correct value - // Note! this value gets changed as a goto is done, ie a goto trumps any prev :I data - // AZEQ5 changes as we do a goto, EQ6 only returns one value. -j 0 6 Get Current Axis position. // =llhhLL[0D] Cardinal encoder count with #x800000 = 0 as a centre datum - // DEC #x800000 = 0, pointing at West Horizon in Sth Hemi - // DEC #xA26C80 = -90, pointing at Polar South in Sth Hemi - // RA #x800000 = 0, CW shaft down -k 1 6 :kx0[0D]=llhhLL[0D] gets running microstep count since last start/reset - :kx1[0D]=llhhLL[0D] gets running microstep count since last start/reset then resets count - // :k works on EQ6Pro, but not AZEQ5, AZEQ6, EQ8 -l *** -m 0 6 Appears to be ramp up for a goto // =llhhLL[0D] ( ie :j +/- :M ) ) - // :J processing for EQ6Pro converts data to :h +/- :c if above low distance limit - // to :h if below low distance limit -n 0 2 Read EEProm Addr // =DD[0D] used with :C for peek ??? #### -o *** -p *** -q 6 6 :qx000000[0D]=000000[0D] if axis is CW from home ( ie -ve ) just after home sensor trip has been reset - =FFFFFF[0D] CCW from home ( ie +ve ) just after home sensor trip has been reset - =llhhLL[0D] if sensor has tripped since reset ( use :W to clear data first ) - // AZEQ5 returns =000080 for Az and Alt -:qx010000[0D]=ABCDEF[0D] ie the bitmapped nibbles for current status - // A 8 not defined - // 4 not defined - // 2 PPEC ON - // 1 PPEC training in progress, - // B 8 supports AZ/EQ - // 4 has Home Sensors - // 2 supports PPEC - // 1 supports dual encoders - // C 8 has WIFI - // 4 supports half current tracking // ref :Wx06.... - // 2 axes slews must start independently // ie cant use :J3 - // 1 has polar LED - // D - // E - // F - // EQ6 returns !0 - // AZEQ5 =0B6000 at boot - // AZEQ6 =0B3000 - // EQ8 =076000 -r 0 2 Read Register Addr // =DD[0D] or =DDDD or =DDDDDD used with :A for peek ??? - // result appears to vary based on length of last valid data return ref test data done lower - // AZEQ5 returns =[0D] ie no data if used directly after :A - // must use :A then :g then :r ( ie the :g fake sets the return length to 2 ) -s 0 6 Get microsteps per worm rev // =llhhLL[0D] Used for wormwheel teeth calcs and PPEC -t *** -u *** -v *** -w *** -x *** -y *** -z 0 0 Set Debug Flag // EQ6Pro returns !0[0D], AZEQ5/AZEQ6/EQ8 returns =[0D] - -A 2 0 :AxHH[0D] Set Register Addr // used with :R and :r for Register poke/peek -B *** -C 4 0 :CxLLHH[0D] Set EEProm Addr // used with :N and :n for EEProm poke/peek -D 0 6 :Dx[0D] Get 1x Track Rate // =llhhLL[0D] This is the :I rate used to give sidereal tracking -E 6 0 :ExllhhLL[0D] Reset Axis datum to // used to synch encoder posn against a known HA/DEC ) -F 0 0 :Fx[0D] Initialise Target Axis ( energises motor ) -G 2 0 :GxAB[0D] Prepare slew parameters using bitmapped nybbles xAB - // ( Note: ":f" is used to read the "current" actual status ) - // A = '0' high speed GOTO slewing, doesnt make "bitmapped" sense, but it is as coded by SkyWatcher????? ????? - // '1' low speed slewing mode, all other bytes use bitmapping ( incl :f ), this doesnt - // '2' low speed GOTO mode, - // '3' high speed slewing mode - // xxx0 0 means AutoGoto, 1 means manual slew or stopped - // xx0x 0 means HiRate if Goto else LoRate if Slew - // speed mode for AutoGoto is ignored for EQ6Pro - // B = '0' +CW and Nth Hemi - // '1' -CCW and Nth Hemi - // '2' +CW and Sth Hemi - // '3' -CCW and Sth Hemi - // xxx0 0 means +ve, 1 = -ve "motor" direction, ie code takes care of whats N/S/E/W etc - // +ve speed in RA is Axle moves CW when viewed from pole - // +ve speed in DEC is Axle moves CCW when viewed from above - // xx0x 0 means Nth Hemi else Sth Hemi ( ST4 guiding related ) ????? - // Note! when using :S type gotos, the direction bit here "appears" to be ignored - -H 6 0 :HxllhhLL[0D] Set goto target ( as a delta to current ) increment. Direction set by :G, -I 6 0 :IxllhhLL[0D] Set Manual slewing rate ( read in conjunction with Hi/Lo rate as set by :G ) -J 0 0 :Jx[0D] Start moving -K 0 0 :Kx[0D] Stop moving normal ( ramp if reqd ) -L 0 0 :Lx[0D] Stop moving Immediately -M 6 0 :MxllhhLL[0D] Set break point increment // Doesnt appear to do anything ????? But possibly Ramp UP related - // EQASCOM uses if H > 80000 then H - 80000 else H / 2 - // Indi uses HiSpeed if H > 3200 then 3200 else H/10 based on skywatcher code ( that also sets I ) - // LoSpeed if H > 200 then 200 else H/10 - // no values of :M appear to affect my EQ6 behaviour -N 2 0 :NxHH[0D] Set EEProm Value to xHH // used with :C for poke?? NOT TESTED -O 1 0 :OxA[0D] Toggle "Trigger/Snap Port" A = '1' = On, '0' = Off // EQ6 fires both at same time via Hbx, ie :O11 :O21 - // AZEQ5 can fire independently, EQ8 uses :O2x[0D] to fire its only port. -P 1 0 :PxA[0D] set ST4 guiderate A = 0..4 = 1.0, 0.75, 0.50, 0.25, 0.125 -Q *** Set Bootloader Mode // Always uses :Qx55AA[0D] and has no response. 55AA looks like a flash unlock code ???? -R 2 0 :RxHH[0D] Set Register Value to xHH // used with :A for poke?? NOT TESTED -S 6 0 :SxllhhLL[0D] Set absolute goto target // EQ8 also uses :M with this, but :M is absolute in EQ8 ????? - // :S appears to ignore direction data set via :G -T 6 0 :TxllhhLL[0D] Set LSB of speed // hhLL must be 0000. ie equivalent to :I = ll0000[0D] but works in HiSpeed mode ????? - // Set Long Goto Step Period ( as per Synta ) -U 6 0 :UxllhhLL[0D] Set rampdown range // sets the microsteps from target where the rampdown process begins -V 2 0 :VxHH[0D] Set Polar LED brightness // HH := x00 to xFF -W 6 0 :Wx000000[0D] Start PPEC train - :Wx010000[0D] Stop PPEC train - :Wx020000[0D] Turn PPEC ON - :Wx030000[0D] Turn PPEC OFF ( also sent when synch encoder used in EQ6 in 3.36. Not in 3.37 ??? - :Wx040000[0D] Encoder ON - :Wx050000[0D] Encoder OFF - :Wx060000[0D] Disable Full Current Low speed - :Wx060100[0D] Enable Full Current Low speed - :Wx07vvvv[0D] Set Stride for Slewing // need to test - :Wx080000[0D] Reset Home Sensor datum -X *** -Y *** -Z *** -//================================================================================================= -When setting "GOTO" data, it appears to require a correct sequence -ie :G then :H then :M or - :G then :S then :M for gotos. -Mount must be stopped before sending :G here, or it chucks a fault. -:M appears to have no function anymore???? - -:U appears to be standalone, and can be set at any time and is totally "sticky" - Only appears to work so far with the EQ6Pro - -When getting data we also need to get current status -:j gets current offset -:f is used first to check for current mode ie slew/goto, Hi/Lo, Fwd/Bwd so we know/can check signs for :h and :m -:h gets current target ( should be ( :j + :H ) for Fwds, ( :j - :H ) for Bwds ) // ie same as :S -:m gets ??? target ( should be ( :j + :M ) for Fwds, ( :j - :M ) for Bwds ) -:d gets the current quadrature encoder count ( if encoders are fitted ). Result is always true - ie even if encoders are OFF, :d returns the true count. -// *** WARNING *** :f always responds correctly to the latest :G -// however, :h and :m do not. The :M and :H/:S must be sent AFTER :G -// if you want to correctly reverse engineer settings from :h, :m - -When setting "Slew" data, it also requires a set procedure -Again :G sets direction and speed "range", and must be sent when stopped. -:I is used to set the speed. -The value used is basically the no of timer interrupts per microstep -:I := ( :b * 86164 / :a ) / Speed ( where Speed is in arcsec/sec ) -Speed = g*(b*86164/9024000)/I -If :I is greater than about 10, then the slew will need to use :G = LoSpeed mode -If :I is less than 10, then the slew will need :G = HiRate, and :I := I * :g -In LoSpeed mode, once moving, simply resending a new :I will cause the speed to change. -In HiSpeed mode, you must issue a stop, resend :G, reset :I then restart. -:b = :I * Speed/g * :a / 86164 -*/ - -/******************************************************** - EQG Protocol related functions - ============================== - *********************************************************/ - -// Process received EQG characters -// =============================== -void EQGState(void) { - while ((EQGRxiPtr != EQGRxoPtr) && (EQGDone == 0)) { - if (dbgFlag == 1) { - if (EQGRxBuffer[EQGRxoPtr] == 'j') - dbgFlag = 0; - } - if (EQGRxBuffer[EQGRxoPtr] == ':') { - dbgSerial.println(""); - dbgSerial.print(">>> "); - dbgFlag++; - } - if (dbgFlag) { - if ((EQGRxBuffer[EQGRxoPtr] != CR) && (EQGRxBuffer[EQGRxoPtr] != LF)) - dbgSerial.write(EQGRxBuffer[EQGRxoPtr]); - else dbgSerial.write('.'); -// dbgSerial.write(EQGRxBuffer[EQGRxoPtr]); - } - - EQGRxChar = EQGRxBuffer[EQGRxoPtr++]; // Get a character - if ((EQGRxState < EQG_WAITFORCR) && (EQGRxChar < ' ')) { - EQGRxState = EQG_INTERPRET; // Terminate on non-alpha - } - -// Convert hex parameters to binary nibble -// --------------------------------------- - if ((EQGRxState > 0x03) && (EQGRxState < EQG_WAITFORCR)) { - EQGRxChar = toupper(EQGRxChar); - if ((EQGRxChar <= 'F') && (EQGRxChar >= '0')) { - EQGRxChar -= '0'; - if (EQGRxChar > 9) EQGRxChar -= 0x07; - } - else EQGRxState = EQG_INTERPRET; // terminate on non-hex - } - -// Rx State machine -// ---------------- - - switch (EQGRxState) { - - case EQG_WAITFORCR: // Waiting for CR - if (EQGRxChar == CR) { - EQGRxState = EQG_CMNDSTART; - EQGDone++; - } - break; - - case EQG_CMNDSTART: // Waiting for ':' - if (EQGRxChar == ':') { - EQGRxCount = 1; // Count for # parameters - EQGRxState++; - } - break; - - case 0x02: // Waiting for command - EQGCmnd = EQGRxChar; - EQGRxCount++; - EQGRxState++; - break; - - case 0x03: // Which motor? - EQGRADEC = EQGRxChar; - EQGMOTOR = EQGRADEC - '0'; - if ((EQGRADEC > '0') && (EQGRADEC < '3')) { - EQGRxCount++; - switch (EQGCmnd) { // Commands that have additional bytes - case 'q': // Get mount assets - case 'A': // Not used - Set Register Addr - case 'B': // Unknown - case 'C': // Not done - Set EEPROM Addr - case 'E': // Set Current Position - case 'G': // Set Move direction and speed multiplier - case 'H': // Set GoTo Target Increment - case 'I': // Set Speed - case 'M': // Set BreakPoint Increment - case 'N': // Not done - Set EEPROM - case 'O': // Not done - Set trigger (0-off,1-on) - case 'P': // Set AutoGuide Speed - case 'R': // Not done - Set Register - case 'S': // Not done - Set GoTo Target - case 'T': // Unknown - case 'U': // Not done - Set Break Step - case 'V': // Set Polar LED brightness - EQGRxState++; // Yes, so next state - break; - - default: - EQGRxState = EQG_INTERPRET; // No, so command complete - break; - } - } - else { - if (EQGRxChar != 0x0d) EQGRxState = EQG_WAITFORCR; - else EQGDone++; - EQGErrorValue = '3'; // Failure - Bad Parameters - } - break; - - case 0x04: // First nibble - EQGP1 = EQGRxChar; // EQGRxChar already converted to binary nibble - EQGRxCount++; // Increase character count - switch (EQGCmnd) { // Commands that send one nibble - case 'B': // Not done - Unknown - case 'O': // Set trigger (0-off,1-on) - case 'P': // Set ST4 Guiderate - EQGRxState = EQG_INTERPRET; - break; - default: - EQGRxState++; - break; - } - break; - - case 0x05: // Second nibble - first byte (B1 = N1N2) - EQGP2 = EQGRxChar; // EQGRxChar already converted to binary nibble - EQGP1 = ((EQGP1 << 4) | EQGP2); // First byte - EQGRxCount++; - switch (EQGCmnd) { // Commands that send one byte - case 'A': // Set register address - case 'G': // Set direction, range - case 'N': // Set EEPROM (:C) to xHH - case 'R': // Set Register (:A) to xHH - case 'V': // Set Polar LED brightness ro xHH - EQGRxState = EQG_INTERPRET; - break; - default: - EQGRxState++; // All the rest send 3 bytes - break; - } - break; - - case 0x06: // Third nibble - N3N1N2 - EQGP2 = EQGRxChar; // EQGRxChar already converted to binary nibble - EQGP1 |= (EQGP2 << 8); - EQGRxCount++; - EQGRxState++; - break; - - case 0x07: // Fourth nibble - N3N4N1N2 - EQGP1 &= 0xFF; // Clear all bar low byte - EQGP1 |= (EQGP2 << 12); // Get N3 into correct position - EQGP2 = EQGRxChar; // EQGRxChar already converted to binary nibble - EQGP1 |= (EQGP2 << 8); // Get N4 into correct position - EQGRxCount++; - switch (EQGCmnd) { // Commands that send two bytes - case 'C': // Set EEPROM address - EQGRxState = EQG_INTERPRET; - break; - default: - EQGRxState++; // All the rest send 3 bytes - break; - } - break; - - case 0x08: // Fifth nibble - N5xxN3N4N1N2 - - EQGP2 = EQGRxChar; - EQGP1 |= (EQGP2 << 20); - EQGRxCount++; - EQGRxState++; // Get next data - break; - - case 0x09: // Sixth nibble - N5N6N3N4N1N2 - - - EQGP2 = EQGRxChar; - EQGP1 |= (EQGP2 << 16); - EQGRxCount++; - EQGRxState = EQG_INTERPRET; // All done - break; - - case EQG_INTERPRET: - if ((EQGRxChar == 0x0d) && (EQGRxCount >= 3)) { - EQGRxState = EQG_CMNDSTART; // Reset state machine - switch (EQGCmnd) { - // Commands that have no data - case 'a': // Read steps per rotation - case 'b': // Read tracking scale - case 'c': // Read Motor Speed Change - case 'd': // Read Current Encoder count - case 'e': // Read firmware version - case 'f': // Read motor status - case 'g': // Read speed divisor - case 'j': // Read position - case 'm': // Read motor slowdown point - case 'n': // Read EEPROM data - case 'r': // Read register data - case 's': // Read steps per arcsec - case 'D': // Read track rate - case 'F': // Energise motors - case 'J': // GoTo position, track - case 'K': // Stop movement - EQGDone++; - break; - - // Commands that have three bytes - // ============================== - case 'q': // Read mount assets - case 'E': // Set current position - case 'H': // Set target position - case 'I': // Set GoTo speed - case 'M': // Set motor slowdown position ?? - case 'U': // Set motor slowdown speed ?? - if (EQGRxCount == (3 + 6)) { - EQGDone++; - } - else { - if (EQGRxChar != 0x0d) EQGRxState = EQG_WAITFORCR; - else EQGDone++; - EQGErrorValue = '3'; // Failure - Bad Parameters - } - break; - - // Commands that have two bytes - case 'C': // Set EEPROM address - if (EQGRxCount == (3 + 4)) { - EQGDone++; - } - else { - if (EQGRxChar != 0x0d) EQGRxState = EQG_WAITFORCR; - else EQGDone++; - EQGErrorValue = '3'; // Failure - Bad Parameters - } - break; - - // Commands that have one byte - case 'A': // Set register address - case 'G': // Set direction, range - case 'N': // Set EEPROM (:C) to xHH - case 'R': // Set Register (:A) to xHH - case 'V': // Set LED Brightness to xHH - if (EQGRxCount == (3 + 2)) { - EQGDone++; - } - else { - if (EQGRxChar != 0x0d) EQGRxState = EQG_WAITFORCR; - else EQGDone++; - EQGErrorValue = '3'; // Failure - Bad Parameters - } - break; - - // Commands that have one nibble - case 'P': // Set autoguide speed - case 'O': // Set Snap Port - if (EQGRxCount == (3 + 1)) { - EQGDone++; - } - else { - if (EQGRxChar != 0x0d) EQGRxState = EQG_WAITFORCR; - else EQGDone++; - EQGErrorValue = '3'; // Failure - Bad Parameters - } - break; - - default: - if (EQGRxChar != 0x0d) EQGRxState = EQG_WAITFORCR; - else EQGDone++; - EQGErrorValue = '0'; // Failure - Bad Command - break; - } // End - switch (EQGCmnd) - } - else { - if (EQGRxChar != 0x0d) EQGRxState = EQG_WAITFORCR; - else EQGDone++; - EQGErrorValue = '0'; // Failure - Bad Command - } - break; // End - if (((EQGRxChar == 0x0d) || (EQGRxChar == 0x0a)) && (EQGRxCount >= 3)) - - default: - EQGRxState = EQG_CMNDSTART; - } // End - switch (EQGRxState) - } // END - while ((EQGRxiPtr != EQGRxoPtr) && (EQGDone == 0)) -} - -void EQGError(unsigned char errorbyte) { - EQGTx('!') ; // Failure - Bad Parameters - EQGTx(errorbyte); - EQGTx(CR); - EQGDone = 0; // Process errors - EQGRxState = EQG_CMNDSTART; - EQGRxCount = 0; // Count for # parameters - EQGErrorValue = 0; -} - -// Received a valid command so execute it, if supported -// ==================================================== -void EQGAction(void) { - - EQGDone = 0; // Reset flag - EQGRxState = EQG_CMNDSTART; - EQGTx('='); // Answer (with parameters) - - switch (EQGCmnd) { - - case 'a': // Request total number of steps per revolution - EQGTxHex6(axis[EQGMOTOR].aVALUE); - break; - - case 'b': // Request step interrupt frequency - EQGTxHex6(axis[EQGMOTOR].bVALUE); // Let EQMOD calculate SIDEREAL, etc - break; - - case 'c': - EQGTxHex6(0x00D800); // Return same as EQ6 to keep the speed commands consistent - break; - - case 'd': // Request Mount center point -// EQGTxHex6(EQG_CENTRE); // Return same as EQ6 to keep the speed commands consistent - EQGTxHex6(axis[EQGMOTOR].Position); - break; - - case 'e': // Request version - EQGTxHex6(EQGVERSION); // - break; - - case 'f': // Request motor status - -// EQGMotorStatus bit definitions -// A nibble1 -// MOVESLEW 0x0001 // Step(0) Slew(1) -// MOVEDECR 0x0002 // Increasing(0) Decreasing(1) -// MOVEHIGH 0x0004 // Low(0) High(1) -// B nibble2 -// MOVEAXIS 0x0010 // Stopped(0) Moving(1) -// MOVEFACE 0x0020 // Front(0) Rear(1) -// C nibble3 -// MOVEACTIVE 0x0100 // Inactive(0) Active(1) - - EQGTxHex3(axis[EQGMOTOR].EQGMotorStatus); - - break; - - case 'g': // Request speed multiplier - EQGTxHex2(EQG_gVALUE); // Return same as EQ6 to keep the speed commands consistent - break; - - case 'j': // Request axis position - EQGTxHex6(axis[EQGMOTOR].Position); - break; - - case 'm': // GET Point at which to change from fast to slow - EQGTxHex6(axis[EQGMOTOR].SlowDown); - break; - - case 'q': // GET mount capabilities - EQGTxHex6(EQGASSETS); // Say EQ and AZ - break; - - case 's': // PEC period - EQGTxHex6(axis[EQGMOTOR].PEC); - break; - - case 'E': // Set current motor position - if ((EQGP1 == 0x800000) || (EQGP1 == 0x85049c)) - break; - else axis[EQGMOTOR].Position = EQGP1; - break; - - case 'F': // Initialize and activate motors - axis[EQGMOTOR].EQGMotorStatus |= MOVEACTIVE; - axis[EQGMOTOR].ETXMotorStatus |= MOVEACTIVE; - break; - - case 'G': // EQG 'G' Command :GxAB[0D] - -// See below for A -// =============== -// B nibble -// -------- - // B = '0' +CW and Nthn Hemi - // '1' -CCW and Nthn Hemi - // '2' +CW and Sthn Hemi - // '3' -CCW and Sthn Hemi - // xxx0 0 means +ve, 1 = -ve "motor" direction, ie code takes care of whats N/S/E/W etc - // +ve speed in RA is Axis moves CW when viewed from pole - // +ve speed in DEC is Axis moves CCW when viewed from above (OTA horizontal, facing E->W ?) - // xx0x 0 means Nthn Hemi else Sthn Hemi ( ST4 guiding related ) ????? - // Note! when using :S type gotos, the direction bit here "appears" to be ignored - // Also note that EQMOD does not appear to send the Hemisphere bit - // - // xxx0 CW(0) CCW(1) DIRECTION - // xx0x North(0) South(1) HEMISPHERE - - axis[EQGMOTOR].DirnSpeed = (int)EQGP1; // Save the command value - switch (axis[EQGMOTOR].DirnSpeed & 0x03) { - case 0x00: - case 0x02: - axis[EQGMOTOR].EQGMotorStatus &= ~MOVEDECR; -dbgSerial.print(" +CW "); - break; - case 0x01: - case 0x03: - axis[EQGMOTOR].EQGMotorStatus |= MOVEDECR; -dbgSerial.print(" -CCW "); - break; - default: - break; - } - -// When setting "Slew" data, it also requires a set procedure -// G sets direction and speed "range", and must be sent when stopped. -// A nibble - // A = '0' high speed GOTO slewing, doesnt make "bitmapped" sense, but it is as coded by SkyWatcher - // '1' low speed slewing mode, all other bytes use bitmapping ( incl :f ), this doesnt - // '2' low speed GOTO mode, - // '3' high speed slewing mode - // xxx0 0 means AutoGoto, 1 means manual slew or stopped - // xx0x 0 means HiRate if Goto else LoRate if Slew - // speed mode for AutoGoto is ignored for EQ6Pro - -// A - switch ((EQGP1 >> 4) & 0x03) { - case 00: // 0 HIGH SPEED GOTO - axis[EQGMOTOR].EQGMotorStatus &= ~MOVESLEW; // GoTo target - axis[EQGMOTOR].EQGMotorStatus |= MOVEHIGH; // Enable high speed multiplier - axis[EQGMOTOR].TargetSpeed = axis[EQGMOTOR].DEGREERATE1; -dbgSerial.print("HIGH SPEED GOTO "); - break; - case 01: // 1 LOW SPEED SLEW - axis[EQGMOTOR].EQGMotorStatus |= MOVESLEW; // Just move the axis - axis[EQGMOTOR].EQGMotorStatus &= ~MOVEHIGH; // Disable high speed multiplier - axis[EQGMOTOR].TargetSpeed = (axis[EQGMOTOR].SIDEREALRATE); -dbgSerial.print("LOW SPEED SLEW "); - break; - case 02: // 2 LOW SPEED GOTO - axis[EQGMOTOR].EQGMotorStatus &= ~MOVESLEW; // GoTo target - axis[EQGMOTOR].EQGMotorStatus &= ~MOVEHIGH; // Disable high speed multiplier - axis[EQGMOTOR].TargetSpeed = (axis[EQGMOTOR].DEGREERATE1 << 3); -dbgSerial.print("LOW SPEED GOTO "); - break; - case 03: // 3 HIGH SPEED SLEW - axis[EQGMOTOR].EQGMotorStatus |= MOVESLEW; // Just move the axis - axis[EQGMOTOR].EQGMotorStatus |= MOVEHIGH; // Enable high speed multiplier - axis[EQGMOTOR].TargetSpeed = axis[EQGMOTOR].DEGREERATE1; -dbgSerial.print("HIGH SPEED SLEW "); - break; - } -dbgSerial.print(axis[EQGMOTOR].TargetSpeed); - - axis[EQGMOTOR].ETXMotorStatus = axis[EQGMOTOR].EQGMotorStatus; // Copy the status for ETXProtocol - break; - - case 'H': // Set the goto target increment - axis[EQGMOTOR].Increment = EQGP1; - if (axis[EQGMOTOR].EQGMotorStatus & MOVEDECR) - axis[EQGMOTOR].Target = axis[EQGMOTOR].Position - axis[EQGMOTOR].Increment; // subtract the relative target - else - axis[EQGMOTOR].Target = axis[EQGMOTOR].Position + axis[EQGMOTOR].Increment; // add the relative target - axis[EQGMOTOR].MotorControl |= GoToHBX; - break; - - case 'I': // Set motor speed -/* - :I is used to set the speed. - The value used is basically the number of timer interrupts per microstep - ------------------------------------------------------------------------ - I = (b * SiderealSecs / a) / Speed (where Speed is in arcsec/sec, SiderealSecs=86164.nn) - Speed = g * (b * SiderealSecs / a) / I - ====================================== - If I is greater than about 10, then the slew will need to use :G = LoSpeed mode - If I is less than 10, then the slew will need :G = HiRate, and :I = :I * :g - In LoSpeed mode, once moving, simply resending a new :I will cause the speed to change. - In HiSpeed mode, you must issue a stop, resend :G, reset :I then restart. - b = I * Speed / g * a / SiderealSecs -*/ - - axis[EQGMOTOR].EQGSpeed = EQGP1; // Set EQG speed value (I) - axis[EQGMOTOR].TargetSpeed = EQGP1; // Set ETX target speed - axis[EQGMOTOR].TargetSpeed = axis[EQGMOTOR].SIDEREALRATE * ((axis[EQGMOTOR].bVALUE*SIDEREALSECS)/axis[EQGMOTOR].aVALUE) / EQGP1; - if (axis[EQGMOTOR].EQGMotorStatus & MOVEHIGH) - axis[EQGMOTOR].TargetSpeed *= EQG_gVALUE; - if (axis[EQGMOTOR].ETXMotorStatus & MOVEAXIS) // If already moving - axis[EQGMOTOR].ETXMotorState = ETXStepMotor; // update speed - break; - - case 'J': // Tell motor to Go - axis[EQGMOTOR].ETXMotorStatus |= MOVEAXIS; // Signal moving - axis[EQGMOTOR].ETXMotorState = ETXCheckStartup; // General entry - - break; - - case 'K': // Tell motor to stop - axis[EQGMOTOR].EQGMotorStatus |= MOVESLEW; // Set slew as default - axis[EQGMOTOR].ETXMotorStatus |= MOVESLEW; // Set slew as default - axis[EQGMOTOR].TargetSpeed = 0; - axis[EQGMOTOR].ETXMotorState = ETXCheckSpeed; // to enable motor slowdown - break; - - case 'L': // Tell motor to stop immediately - axis[EQGMOTOR].EQGMotorStatus |= MOVESLEW; // Clear speed change - axis[EQGMOTOR].ETXMotorStatus |= MOVESLEW; // Set slew as default - axis[EQGMOTOR].TargetSpeed = 0; - axis[EQGMOTOR].ETXMotorState = ETXStopMotor; // Immediate stop - break; - - case 'M': // Set the break point increment - axis[EQGMOTOR].SlowDown = EQGP1; - if ((axis[EQGMOTOR].EQGMotorStatus & MOVEDECR) == 0) - axis[EQGMOTOR].SlowDown = axis[EQGMOTOR].Position + axis[EQGMOTOR].SlowDown; // add the relative target - else - axis[EQGMOTOR].SlowDown = axis[EQGMOTOR].Position - axis[EQGMOTOR].SlowDown; // subtract the relative target - axis[EQGMOTOR].MotorControl |= GoToHBX; // Signal pending GoTo - break; - - case 'O': - axis[EQGMOTOR].HBXSnapPort = (char)EQGP1; - break; - - case 'P': - axis[EQGMOTOR].HBXGuide = (char)EQGP1; - break; - - case 'U': // Set the break point steps -// JMA TODO axis[EQGMOTOR].SlowDown = EQGP1; - break; - - case 'V': // Set the LED brightness - axis[EQGMOTOR].LEDValue = EQGP1; - break; - - default: - EQGErrorValue = '0'; // Failure - Bad Command - break; - } - EQGTx(CR); -} - -void EQGTxHex(unsigned char data) { - if ((data & 0x0f) < 0x0a) EQGTx((data & 0x0f) + 0x30); - else EQGTx((data & 0x0f) + 0x37); -} - -void EQGTxHex2(unsigned char data) { - EQGTxHex(data >> 4); - EQGTxHex(data); -} - -void EQGTxHex3(unsigned int data) { - EQGTxHex((unsigned char)data); - EQGTxHex((unsigned char)(data >> 4)); - EQGTxHex((unsigned char)(data >> 8)); -} - -void EQGTxHex6(unsigned long data) { - EQGTxHex2((unsigned char)data); - EQGTxHex2((unsigned char)(data >> 8)); - EQGTxHex2((unsigned char)(data >> 16)); -} - -/********************************************** - Debug routines -***********************************************/ -void dbgRx(void) { - while (dbgSerial.available() > 0) { - dbgRxBuffer[dbgRxiPtr++] = dbgSerial.read(); - dbgRxiPtr &= dbgMASK; - } -} - -void putbyte(unsigned char data) { - dbgSerial.write(data); -} - -void puthexb(unsigned char data) { - if (((data >> 4) & 0x0f) < 0x0a) putbyte(((data >> 4) & 0x0f) + 0x30); - else putbyte(((data >> 4) & 0x0f) + 0x37); - if ((data & 0x0f) < 0x0a) putbyte((data & 0x0f) + 0x30); - else putbyte((data & 0x0f) + 0x37); -} - -void putdecb(unsigned char data) { - dbgSerial.print(data); -} - -void puthexw(unsigned int data) { - puthexb((data >> 8) & 0xFF); - puthexb(data & 0xFF); -} - -void putdecw(unsigned int data) { - dbgSerial.print(data); -} - -void puthex6(unsigned long data) { - puthexb((data >> 16) & 0xFF); - puthexw(data & 0xFFFF); -} - -void puthexl(unsigned long data) { - puthexw((data >> 16) & 0xFFFF); - puthexw(data & 0xFFFF); -} - -void putdecl(unsigned long data) { - dbgSerial.print(data); -} - -void EQGSend(unsigned char data) { - dbgSerial.write(data); -} - -void EQGSendHex(unsigned char data) { - if ((data & 0x0f) < 0x0a) EQGSend((data & 0x0f) + 0x30); - else EQGSend((data & 0x0f) + 0x37); -} - -void EQGSendHex2(unsigned char data) { - EQGSendHex(data >> 4); - EQGSendHex(data); -} - -void EQGSendHex6(unsigned long data) { - EQGSendHex2((unsigned char)data); - EQGSendHex2((unsigned char)(data >> 8)); - EQGSendHex2((unsigned char)(data >> 16)); -} - -void debugEQG() { - dbgSerial.println(""); - dbgSerial.print("Az:<"); - dbgSerial.print(axis[AzMotor].EQGMotorStatus, HEX); - dbgSerial.print("> Pos: "); - dbgSerial.print(axis[AzMotor].Position, HEX); - dbgSerial.print(" SD: "); - dbgSerial.print(axis[AzMotor].SlowDown, HEX); - dbgSerial.print(" Tgt: "); - dbgSerial.print(axis[AzMotor].Target, HEX); - dbgSerial.print(" Speed: "); - dbgSerial.print(axis[AzMotor].ETXSpeed, HEX); - - dbgSerial.print(", Alt:<"); - dbgSerial.print(axis[AltMotor].EQGMotorStatus, HEX); - dbgSerial.print(">Pos: "); - dbgSerial.print(axis[AltMotor].Position, HEX); - dbgSerial.print(" SD: "); - dbgSerial.print(axis[AltMotor].SlowDown, HEX); - dbgSerial.print(" Tgt: "); - dbgSerial.print(axis[AltMotor].Target, HEX); - dbgSerial.print(" Speed: "); - dbgSerial.print(axis[AltMotor].ETXSpeed, HEX); -/* - while (dbgRxoPtr != dbgRxiPtr) { - dbgCommand[dbgIndex] = dbgRxBuffer[dbgRxoPtr]; // Copy character - dbgSerial.write(dbgCommand[dbgIndex]); - if ((dbgCommand[dbgIndex] != ':') && (dbgFlag == 0)) { // Wait for start of command string - dbgSerial.write(dbgCommand[dbgIndex]); // Output to debug and skip - } - else { - if (dbgCommand[dbgIndex] == CR) { - dbgCommand[dbgIndex + 1] = 0; - processdbgCommand(); - dbgFlag = 0; - dbgIndex = 0; - } - else { - dbgFlag |= 1; - dbgIndex += 1; - } - } - dbgRxoPtr += 1; - dbgRxoPtr &= dbgMASK; - } - -} - -// Format - ":","Motor","Command","Paramters" -// Motor 1, 2 -// Command t, w, g, v, x - -void processdbgCommand(void) { - unsigned char m, t; - char argStr[256]; - - dbgSerial.println(""); dbgSerial.print("Scope: "); dbgSerial.println(telescope); - dbgSerial.println(dbgCommand); - - strcpy(argStr, &dbgCommand[3]); - m = dbgCommand[2] - '1'; - if ((m == 0) || (m == 1)) { - switch (dbgCommand[1]) { - - case 't': - t = dbgCommand[3] - '0'; - if (t > 9) t -= 7; - if ((t >= 0) & (t < 16)) - telescope = t; - dbgSerial.println(""); dbgSerial.print("Scope: "); dbgSerial.println(telescope); - break; - - case 'w': // Number of Worm teeth - sscanf(argStr, "%ld", &v); - dbgSerial.println(""); - dbgSerial.print("WormTeeth: "); - dbgSerial.print(argStr); - dbgSerial.print(" "); - dbgSerial.println(f); - ratio[telescope][m].WormTeeth = v; - break; - - case 'g': // Gearbox Ratio (float) - sscanf(argStr, "%f", &f); // Warning: you need the float libraries for this - dbgSerial.println(""); - dbgSerial.print("GearBox: "); // "-Wl,-u,vfscanf -lscanf_flt -lm" in platform.local.txt - dbgSerial.print(argStr); - dbgSerial.print(" "); - dbgSerial.println(f); - ratio[telescope][m].GbxRatio = f; - break; - - case 'v': // Number of optical vanes per revolution - sscanf(argStr, "%ld", &v); - dbgSerial.println(""); - dbgSerial.print("Vanes: "); - dbgSerial.print(argStr); - dbgSerial.print(" "); - dbgSerial.println(v); - ratio[telescope][m].Vanes = v; - break; - - case 'x': // Gear transfer ratio - sscanf(argStr, "%f", &f); // Warning: you need the float libraries for this - dbgSerial.println(""); - dbgSerial.print("XferRatio: "); // "-Wl,-u,vfscanf -lscanf_flt -lm" in platform.local.txt - dbgSerial.print(argStr); - dbgSerial.print(" "); - dbgSerial.println(f); - ratio[telescope][m].XferRatio = f; - break; - - default: - break; - - } - PrintRatioValues(telescope); - } - */ -} - - -/********************************************** - Handle EQG communications -***********************************************/ -bool EQGRx(void) { - if (EQGSerial.available() == 0) - return false; - digitalWrite(EQGLED, HIGH); - while (EQGSerial.available() > 0) { - EQGRxBuffer[EQGRxiPtr++] = EQGSerial.read(); - EQGRxiPtr &= EQGMASK; - } - digitalWrite(EQGLED, LOW); - return true; -} - -// Just put it in the output buffer -// Main loop handles transmission -void EQGTx(unsigned char data) { - EQGTxBuffer[EQGTxiPtr++] = data; - EQGTxiPtr &= EQGMASK; -} - diff --git a/Software/EQG2HBXE32/src/ETXProtocol.h b/Software/EQG2HBXE32/src/ETXProtocol.h deleted file mode 100644 index 26389d2..0000000 --- a/Software/EQG2HBXE32/src/ETXProtocol.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2017, 2018, 2020 John Archbold -*/ - -/******************************************************** - EQG Protocol function definitions - ================================= - *********************************************************/ -#pragma once - -// Function Prototypes -// -void UpdateETX(void); -void CheckETXStatus(unsigned char); -void CheckETXState(unsigned char); - -bool HBXGetStatus( unsigned char ); -bool ETXState( unsigned char ); -void AzInitialise( unsigned char ); -void AltInitialise( unsigned char ); -void WaitForMotors( void ); -void CalibrateLEDs( void); -void HBXPrintStatus( unsigned char ); -bool HBXReset( void ); - -void PrintHbxValues( unsigned char ); -void PrintHbxValues( unsigned char ); -void dbgRx(void); - -#define HBXAux 0x00 // The HBX interface port (Aux) -#define MotorAz 0x01 // Pin7 on HBX interface -#define MotorAlt 0x02 // Pin5 on HBX interface - -uint8_t AuxHBX = HBXAux; -uint8_t AzMotor = MotorAz; -uint8_t AltMotor = MotorAlt; - -// ETX Bit Definitions -// Variable - axis[Motor].MotorControl -// nibble 4 -#define StartHBX 0x8000 // Motor start bit -#define StopHBX 0x4000 // Motor stop bit -#define SlewHBX 0x2000 // Move in progress -#define SpeedHBX 0x1000 // Speed change pending -#define GoToHBX 0x0800 // GoTo in process - -// ETX Known Commands -#define SpeedChnge 0x00 // Update "8.16" speed -#define SpeedStart 0x01 // Begin "8.16" speed -#define SetOffset 0x02 // Output "16" correction offset -#define SetLEDI 0x03 // Output "8" LED current -#define CalibrateLED 0x04 // None -#define Stop 0x05 // None -#define SlewReverse 0x06 // None -#define SlewForward 0x07 // None -#define GetStatus 0x08 // Input "16.8.1" ticks.pwm.error -#define GetLEDI 0x09 // Input "8" LED current -#define GetMotorType 0x0B // Input "8" Motor type -#define SleepHBX 0xE4 // None - -#define OffsetMax 0x0020 // Maximum for a SetOffset command -// ETX State Machine -#define ETXIdle 0 -#define ETXCheckStartup 1 -#define ETXSlewMotor 2 -#define ETXStepMotor 3 -#define ETXCheckSlowDown 4 -#define ETXCheckSpeed 5 -#define ETXCheckPosition 6 -#define ETXCheckStop 7 -#define ETXStopMotor 8 -#define ETXMotorEnd 9 -// ETX axis State Machine -#define NORMAL 0 -#define FLIP 1 -#define FLIPPED 2 -#define UNFLIP 3 -#define FLIPPING 4 -#define UNFLIPPING 5 - -const float ETX60PERIOD = 152.587891; // (1/6.5536mS) -const unsigned long ETX_CENTRE = 0x00800000; // RA, DEC; - -const float MeadeSidereal = 6460.0900; // Refer Andrew Johansen - Roboscope -const float SiderealArcSecs = 15.041069; // Sidereal arcsecs/sec (ArcSec360/Sidereal secs) -const float ArcSecs360 = 1296000; // Arcsecs / 360 - - -//#define ETXSlew0 .5 // .5 x sidereal (0.125 arc-min/sec or 0.0021°/sec) -#define ETXSlew1 1 // 1 x sidereal (0.25 arc-min/sec or 0.0042°/sec) -#define ETXSlew2 2 // 2 x sidereal (0.50 arc-min/sec or 0.0084°/sec) -#define ETXSlew3 8 // 8 x sidereal ( 2 arc-min/sec or 0.0334°/sec) -#define ETXSlew4 16 // 16 x sidereal ( 4 arc-min/sec or 0.0669°/sec) -#define ETXSlew5 64 // 64 x sidereal ( 16 arc-min/sec or 0.2674°/sec) -#define ETXSlew6 120 // 30 arc-min/sec or 0.5°/sec -#define ETXSlew7 240 // 60 arc-min/sec or 1.0°/sec -#define ETXSlew8 600 // 150 arc-min/sec or 2.5°/sec -#define ETXSlew9 1080 // 270 arc-min/sec or 4.5°/sec - -#define ETXSLOWPOSN 0x00000800 // Point at which to start slowdown - -// bool HBXGetStatus(unsigned char); - -/* -bool HBXSetMotorState(unsigned char); -bool HBXCheckTargetStatus(unsigned char); -bool HBXUpdatePosn(void); -bool HBXStartMotor(unsigned char); -bool HBXStopMotor(unsigned char); -void PositionPoll(unsigned char); -*/ diff --git a/Software/EQG2HBXE32/src/ETXProtocol.ino b/Software/EQG2HBXE32/src/ETXProtocol.ino deleted file mode 100644 index 95efd60..0000000 --- a/Software/EQG2HBXE32/src/ETXProtocol.ino +++ /dev/null @@ -1,903 +0,0 @@ -/**@file*/ -/* - * Copyright 2017, 2018, 2020 John Archbold -*/ -#include "Hardware.h" -#include "ETXProtocol.h" -#include "EQGProtocol.h" -#include "EQG2HBX.h" -#include "HBXComms.h" -#include "HBXFileSystem.h" -#include "HBXWiFiServer.h" - -/******************************************************** - ETX Protocol related functions - ============================== - *********************************************************/ - -bool ETXState(unsigned char Motor) { - long distance; - - switch(axis[Motor].ETXMotorState) { - - case ETXIdle: - break; - - case ETXCheckStartup: - if (axis[Motor].ETXMotorStatus & MOVEAXIS) { // Start moving -//jma CheckAltFlip(Motor); - - dbgSerial.println(""); dbgSerial.print("ETXCheckStartup - Motor: "); dbgSerial.print(axis_name[Motor]); dbgSerial.print(" MOVING"); - - if (axis[Motor].ETXMotorStatus & MOVESLEW) { - axis[Motor].MotorControl |= SlewHBX; - axis[Motor].ETXMotorState = ETXSlewMotor; - if (axis[Motor].ETXMotorStatus & MOVEHIGH) { // Use high speed multiplier? - dbgSerial.print(" HIGH SLEW"); // Ramp up to HIGH SPEED - } - else { - axis[Motor].ETXMotorState = ETXStepMotor; - axis[Motor].MotorControl |= SpeedHBX; // Use 0x01 command for next speed - dbgSerial.print(" LOW SLEW"); - } - } - else { // GoTo or Low Speed Slew - axis[Motor].MotorControl &= ~SlewHBX; - axis[Motor].ETXMotorState = ETXCheckSpeed; // so just check speed - dbgSerial.print(" GOTO"); - } - - if (axis[Motor].MotorControl & GoToHBX) { // Check GoTo? - distance = axis[Motor].Target - axis[Motor].Position; // Distance to target - if (axis[Motor].ETXMotorStatus & MOVEDECR) // If it is decreasing - distance = TwosComplement(distance); - dbgSerial.printf(" Distance: %6lX, Tgt: %6lX, Pos: %6lX", distance, axis[Motor].Target, axis[Motor].Position); - if (axis[Motor].MotorControl & SlewHBX) { // May need to slew for large changes - axis[Motor].ETXMotorState = ETXSlewMotor; // Slew to M-point - } - else { - axis[Motor].ETXMotorState = ETXCheckSpeed; - axis[Motor].TargetSpeed = axis[Motor].DEGREERATE1; // Set initial speed for 'HIGH SPEED GOTO' - if (distance < axis[Motor].OneDegree) // Scale target speed depending on distance to target - axis[Motor].TargetSpeed = (axis[Motor].TargetSpeed >> 1); // 1/2 - if (distance < (axis[Motor].OneDegree >> 2)) - axis[Motor].TargetSpeed = (axis[Motor].TargetSpeed >> 1); // 1/4 - axis[Motor].ETXSpeed = 0; // Starting from 0 - dbgSerial.print(" GoTo-STEP"); - } - if (distance < OffsetMax) { // Check for really small moves (< 16 steps) - axis[Motor].ETXMotorState = ETXMotorEnd; // Use Adjust offset - dbgSerial.print(" GoTo-OFFSET"); - } - if (distance > (axis[Motor].OneDegree << 3)) { // Always slew for > 8 degrees - axis[Motor].ETXMotorState = ETXSlewMotor; - dbgSerial.print(" GoTo-SLEW"); - } - } - } - break; - - case ETXSlewMotor: -//dbgSerial.println(""); dbgSerial.print("ETXSlewMotor Motor: "); dbgSerial.print(axis_name[Motor]); dbgSerial.print(" SLEW Cmd: "); -/* Andrew Johansen Melbourne Australia -All gotos are done in 2 phases -In the first phase, it calcs distance to "target minus a set time" -( ie it aims for a spot "behind" the target ) -It then starts slewing, at Max speed first if longer than a set distance. -It checks distance intermittently and recalcs speed based on distance to go. -When within a radius of about 40 arcsec it stops. -It then recalcs for a position a few clock seconds ahead of target -and does a second slew to finalise. -It also sets a timer when starting the second slew. -Once within about 10 arcsec of target, it stops until the timer trips -then restarts tracking. ie no hunting around etc at the end, -it just assumes it is correct. -JMA -In the ETX-arduino code, I do similar to what you have said previously. -1. send a high speed command to get somewhere close (originally the breakpoint location) -2. change to a low speed command to get closer (the maximum value of the offset command) -3. read the current position from the ETX and issue an offset command to get to the target - -0x06/0x07 Move at fastest rate (reverse/forward) -0x01 Start moving, set speed and direction to the value specified in command -0x00 While moving, adjust speed (but not direction) to the value specified in command -0x02 Adjust position, while moving -0x05 Stop moving - -0x08 Return change in position - -When, moving the speed set by subsequent 0x00 commands, appears to be ~0.8 of the previous speed. -So the motor asymptotes down to a very low speed. And, at the end the 0x02 command adjusts the final position. - -*/ - digitalWrite(ETXLED, HIGH); // Turn on the ETX telescope LED - HBXSendCommand(Stop, Motor); // Stop the motor - if (axis[Motor].ETXMotorStatus & MOVEDECR) // -ve i.e. -CCW - axis[Motor].Command = SlewReverse; - else - axis[Motor].Command = SlewForward; - HBXSendCommand(axis[Motor].Command, Motor); // SLEW - - axis[Motor].EQGMotorStatus |= MOVEAXIS; // Tell EQx - axis[Motor].ETXSpeed = axis[Motor].DEGREERATE1; // Set ETXSpeed as approx (SLEW=DEGREERATE1) for later speed checks - axis[Motor].ETXMotorState = ETXCheckPosition; // Preset position check - - if (axis[Motor].MotorControl & GoToHBX) { // Check if slew was caused by a high speed long distance GoTo - distance = axis[Motor].Target - axis[Motor].Position; // Check Distance to target - if (axis[Motor].ETXMotorStatus & MOVEDECR) // If it is decreasing - distance = TwosComplement(distance); - if (distance < axis[Motor].OneDegree) { // Change to GoTo if within one degree - while(!(HBXSendCommand(Stop, Motor))); // Stop the motor command - axis[Motor].ETXMotorState = ETXStepMotor; - axis[Motor].MotorControl |= SpeedHBX; // Use 0x01 command for next speed - axis[Motor].TargetSpeed = axis[Motor].DEGREERATE1; // Set initial speed - axis[Motor].ETXSpeed = axis[Motor].DEGREERATE1; - axis[Motor].SpeedState = 0; - } - } - if (axis[Motor].MotorControl & SlewHBX) { // Slewing to M-point - axis[Motor].ETXSpeed = axis[Motor].DEGREERATE1; // Indicate current speed (approx) - axis[Motor].ETXMotorState = ETXCheckSlowDown; // Slew until SlowDown - } - -//* -dbgSerial.println(""); dbgSerial.print("ETXSlewMotor Motor: "); dbgSerial.print(axis_name[Motor]); -dbgSerial.print(" "); -dbgSerial.print(", Cmd: "); dbgSerial.print(axis[Motor].Command, HEX); -dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX); -dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX); -dbgSerial.print(" Chg: "); dbgSerial.print(axis[Motor].Position-axis[Motor].Target, HEX); -dbgSerial.print(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX); -dbgSerial.print(", ETXSpeed: "); dbgSerial.print(axis[Motor].ETXSpeed, HEX); -dbgSerial.print(" TgtSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX); -dbgSerial.print(" SpeedState: "); dbgSerial.println(SpeedStateDesc[(axis[Motor].SpeedState)]); -//*/ - break; - - case ETXStepMotor: -//* -dbgSerial.println(""); dbgSerial.print("ETXStepMotor Motor: "); dbgSerial.print(axis_name[Motor]); -dbgSerial.print(" "); -dbgSerial.print(", Cmd: "); dbgSerial.print(axis[Motor].Command, HEX); -dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX); -dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX); -dbgSerial.print(" Chg: "); dbgSerial.print(axis[Motor].Position-axis[Motor].Target, HEX); -dbgSerial.print(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX); -dbgSerial.print(" Speed: "); dbgSerial.print(axis[Motor].ETXSpeed, HEX); -dbgSerial.print(" TargetSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX); -dbgSerial.print(" SpeedState: "); dbgSerial.println(SpeedStateDesc[(axis[Motor].SpeedState)]); -//*/ - - digitalWrite(ETXLED, HIGH); // Turn on the LED - if (axis[Motor].MotorControl & SpeedHBX) { // Stepping, High or Low speed - axis[Motor].Command = SpeedStart; // Use SpeedStart to start motion - axis[Motor].MotorControl &= ~SpeedHBX; // Clear flag - } - else - axis[Motor].Command = SpeedChnge; // Use SpeedChnge once started - - // Set the speed, and direction - // ---------------------------- - P1 = axis[Motor].TargetSpeed; - if (axis[Motor].ETXMotorStatus & MOVEDECR) // If negative, change P - P1 = TwosComplement(P1); // to 2's complement - axis[Motor].HBXP1 = (P1 >> 16) & 0xFF; // Initialize command bytes - axis[Motor].HBXP2 = (P1 >> 8) & 0xFF; - axis[Motor].HBXP3 = P1 & 0xFF; - if (HBXSendCommand(axis[Motor].Command, Motor)) { // Send Command, check OK? - HBXSend3Bytes(Motor); // Send the speed - axis[Motor].EQGMotorStatus |= MOVEAXIS; // Tell EQx - axis[Motor].ETXSpeed = axis[Motor].TargetSpeed; - } - else break; - - axis[Motor].ETXMotorState = ETXCheckSpeed; // Preset Checkspeed, & if needed, make sure we are up to target speed - if (axis[Motor].MotorControl & GoToHBX) { // If it is a GoTo and up to speed, check position - if (axis[Motor].ETXSpeed == axis[Motor].TargetSpeed) - axis[Motor].ETXMotorState = ETXCheckPosition; - } - else if (axis[Motor].ETXSpeed == 0) { // Stop issued - axis[Motor].ETXMotorState = ETXStopMotor; - } - else if ((axis[Motor].MotorControl & SlewHBX) && - !(axis[Motor].MotorControl & GoToHBX)) { // SLEW without GoTo = speed change - axis[Motor].ETXMotorState = ETXIdle; - } - else if (axis[Motor].ETXSpeed == axis[Motor].TargetSpeed) { // Else slewing at speed - axis[Motor].ETXMotorState = ETXCheckPosition; - } - - break; - - case ETXCheckSlowDown: - // Check if Slowdown reached - // Calculate absolute distance to slowdown - // --------------------------------------- - -///* -dbgSerial.println(""); dbgSerial.print("ETXCheckSlowDown Motor: "); dbgSerial.print(axis_name[Motor]); -dbgSerial.print(" "); -dbgSerial.print(", Cmd: "); dbgSerial.print(axis[Motor].Command, HEX); -dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX); -dbgSerial.print(" Tgt: "); dbgSerial.print(axis[Motor].Target, HEX); -dbgSerial.print(" Chg: "); dbgSerial.print(axis[Motor].Position-axis[Motor].Target, HEX); -dbgSerial.print(", SD: "); dbgSerial.print(axis[Motor].SlowDown, HEX); -dbgSerial.print(", ETXSpeed: "); dbgSerial.print(axis[Motor].ETXSpeed, HEX); -dbgSerial.print(" TgtSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX); -//*/ -// distance = axis[Motor].SlowDown - axis[Motor].Position; - distance = (axis[Motor].Target - 0x1000) - axis[Motor].Position; // Distance to target - if (axis[Motor].Target < axis[Motor].Position) // If it is decreasing - distance = TwosComplement(distance); - -//dbgSerial.print(" distance: "); -//dbgSerial.print(distance, HEX); - - if (distance <= 0) { - while(!(HBXSendCommand(Stop, Motor))); // Stop the motor -// HBXSendCommand(Stop, Motor); // Stop the motor - axis[Motor].TargetSpeed = (axis[Motor].SIDEREALRATE << 7); // target is 128xSidereal - axis[Motor].ETXMotorState = ETXCheckSpeed; - axis[Motor].MotorControl &= ~SlewHBX; // Clear slew bit (if it was set) - axis[Motor].MotorControl |= SpeedHBX; // Use 0x01 command for first slow-down - } - break; - - case ETXCheckSpeed: - -/* -ETXSlew1 1 // 1 x sidereal (0.25 arc-min/sec or 0.0042°/sec) -ETXSlew2 2 // 2 x sidereal (0.50 arc-min/sec or 0.0084°/sec) -ETXSlew3 8 // 8 x sidereal ( 2 arc-min/sec or 0.0334°/sec) -ETXSlew4 16 // 16 x sidereal ( 4 arc-min/sec or 0.0669°/sec) -ETXSlew5 64 // 64 x sidereal ( 16 arc-min/sec or 0.2674°/sec) -ETXSlew6 120 // 30 arc-min/sec or 0.5°/sec -ETXSlew7 240 // 60 arc-min/sec or 1.0°/sec -ETXSlew8 600 // 150 arc-min/sec or 2.5°/sec -ETXSlew9 1080 // 270 arc-min/sec or 4.5°/sec -*/ - -///* -dbgSerial.println(""); dbgSerial.print("ETXCheckSpeed Motor: "); dbgSerial.print(axis_name[Motor]); -dbgSerial.print(" "); -dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX); -dbgSerial.print(" Tgt: "); dbgSerial.print(axis[Motor].Target, HEX); -dbgSerial.print(" Chg: "); dbgSerial.print(axis[Motor].Position-axis[Motor].Target, HEX); -dbgSerial.print(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX); -dbgSerial.print(", ETXSpeed: "); dbgSerial.print(axis[Motor].ETXSpeed, HEX); -dbgSerial.print(" TgtSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX); -//*/ -// Speeding Up -// =========== - axis[Motor].ETXMotorState = ETXStepMotor; // Preset set speed as next action -// Ramp up to speed - if ((axis[Motor].TargetSpeed != 0) && (axis[Motor].TargetSpeed > axis[Motor].ETXSpeed)) { - if ((axis[Motor].TargetSpeed - axis[Motor].ETXSpeed) > (axis[Motor].SIDEREALRATE << 6)) { // 64x sidereal - axis[Motor].ETXSpeed += ((axis[Motor].TargetSpeed - axis[Motor].ETXSpeed) >> 1); // Ramp up approx .5 difference - axis[Motor].MotorControl &= ~SpeedHBX; // Use 0x00 command (changes speed, but not direction) - } - else { - axis[Motor].ETXSpeed = axis[Motor].TargetSpeed; - while(!(HBXSendCommand(Stop, Motor))); // Stop the motor command - axis[Motor].MotorControl |= SpeedHBX; // Use 0x01 command (changes speed and direction) - } - } -// Ramp down to speed - else if ((axis[Motor].TargetSpeed != 0) && (axis[Motor].ETXSpeed > axis[Motor].TargetSpeed)) { - axis[Motor].ETXSpeed -= ((axis[Motor].ETXSpeed - axis[Motor].TargetSpeed) >> 2); // Approx .75 - if ((axis[Motor].ETXSpeed - axis[Motor].TargetSpeed) <= (axis[Motor].SIDEREALRATE << 7)) { - axis[Motor].ETXSpeed = axis[Motor].TargetSpeed; // Close enough at 128x sidereal, so set the speed -// while(!(HBXSendCommand(Stop, Motor))); // Stop the motor command - axis[Motor].MotorControl &= ~SpeedHBX; // Use 0x00 command (changes speed, but not direction) - } - } -// Ramp down to stop - else if ((axis[Motor].TargetSpeed == 0) && (axis[Motor].ETXSpeed != 0)) { - if (axis[Motor].ETXMotorStatus & MOVESLEW) { - axis[Motor].ETXMotorState = ETXStopMotor; - } - else if (axis[Motor].ETXSpeed >= (axis[Motor].SIDEREALRATE << 7)) { // Ramp down to 128 sidereal - axis[Motor].ETXSpeed -= (axis[Motor].ETXSpeed >> 2); // Approximately .75 - while(!(HBXSendCommand(Stop, Motor))); // Stop the motor command - axis[Motor].MotorControl |= SpeedHBX; // Use 0x01 command (changes speed and direction) - } - else - axis[Motor].ETXMotorState = ETXStopMotor; // OK, Stop the motor - } -// Already stopped - else if ((axis[Motor].TargetSpeed == 0) && (axis[Motor].ETXSpeed == 0)) { - axis[Motor].ETXMotorStatus |= MOVESLEW; // ETX Set slewing mode - axis[Motor].ETXMotorStatus &= ~MOVEHIGH; // and speed - axis[Motor].ETXMotorStatus &= ~MOVEAXIS; // Clear the motor moving flag - axis[Motor].MotorControl &= ~GoToHBX; // Clear the GoTo flag - axis[Motor].MotorControl &= ~SlewHBX; // and the slew flag - axis[Motor].EQGMotorStatus |= MOVESLEW; // EQG Set slewing mode - axis[Motor].EQGMotorStatus &= ~MOVEHIGH; // and speed - axis[Motor].EQGMotorStatus &= ~MOVEAXIS; // Clear the motor moving flag - axis[Motor].EQGMotorStatus &= ~MOVEDECR; // Clear the direction flag - axis[Motor].ETXMotorState = ETXCheckStartup; - } -// Switch to position check, when we are at speed - check done in ETXStepMotor - -//dbgSerial.print(" oSpeed: "); dbgSerial.print(axis[Motor].ETXSpeed, HEX); -//dbgSerial.print(" oTargetSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX); - - break; - - case ETXCheckPosition: - // Check if Target acquired - // ------------------------ - - // Calculate absolute distance to target - // ------------------------------------- - -///* -if ( ((Motor == MotorAlt) && ((pAltCount % 10) == 0)) || - ((Motor == MotorAz) && ((pAzCount % 10) == 0)) ) { - dbgSerial.println(""); dbgSerial.print("ETXCheckPosition Motor: "); dbgSerial.print(axis_name[Motor]); - dbgSerial.print(" "); - dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX); - dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX); - dbgSerial.print(" Chg: "); dbgSerial.print(axis[Motor].Position-axis[Motor].Target, HEX); - dbgSerial.print(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX); - dbgSerial.print(", ETXSpeed: "); dbgSerial.print(axis[Motor].ETXSpeed, HEX); - dbgSerial.print(" TgtSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX); - } - pAzCount++; - pAltCount++; -//*/ - if ( (axis[Motor].MotorControl & SlewHBX) && - !(axis[Motor].MotorControl & GoToHBX) ) // SLEW without GoTo = speed change - break; - - - distance = axis[Motor].Target - axis[Motor].Position; // Distance to target - if (axis[Motor].ETXMotorStatus & MOVEDECR) // If it is decreasing - distance = TwosComplement(distance); - - if (distance == 0) - axis[Motor].ETXMotorState = ETXMotorEnd; - else if (distance > 0) { - // Start to slow motor if getting near target - // ------------------------------------------ - if (distance <= OffsetMax) { - axis[Motor].ETXMotorState = ETXMotorEnd; // Stop motor, set offset - axis[Motor].SpeedState = 0; - } - else if (axis[Motor].SpeedState == 3) { - axis[Motor].TargetSpeed = (axis[Motor].SIDEREALRATE) << 2; - axis[Motor].MotorControl &= ~SpeedHBX; // Use 0x00 command - axis[Motor].ETXMotorState = ETXStepMotor; // Change speed - axis[Motor].SpeedState += 1; - } - else if ((distance <= 0x200) && (axis[Motor].SpeedState == 2)) { - axis[Motor].TargetSpeed = axis[Motor].ETXSpeed >> 2; // 1/16 - axis[Motor].MotorControl &= ~SpeedHBX; // Use 0x00 command - axis[Motor].ETXMotorState = ETXStepMotor; // Change speed - axis[Motor].SpeedState += 1; - } - else if ((distance <= 0x400) && (axis[Motor].SpeedState == 1)) { - axis[Motor].TargetSpeed = axis[Motor].ETXSpeed >> 1; // 1/4 - axis[Motor].MotorControl &= ~SpeedHBX; // Use 0x00 command - axis[Motor].ETXMotorState = ETXStepMotor; // Change speed - axis[Motor].SpeedState += 1; - } - else if ((distance <= 0x800) && (axis[Motor].SpeedState == 0)) { - axis[Motor].TargetSpeed = axis[Motor].ETXSpeed >> 1; // 1/2 - while(!(HBXSendCommand(Stop, Motor))); // Stop the motor command - axis[Motor].MotorControl |= SpeedHBX; // Use 0x01 command - axis[Motor].ETXMotorState = ETXStepMotor; // Change speed - axis[Motor].SpeedState += 1; - } - } - else { - if ((TwosComplement(distance)) > OffsetMax) { // Not sure how good offset is! - // Motor has over-shot the target - // ------------------------------ - if (axis[Motor].ETXMotorStatus & MOVEDECR) // ETX -> change direction - axis[Motor].ETXMotorStatus &= ~MOVEDECR; - else - axis[Motor].ETXMotorStatus |= MOVEDECR; - while(!(HBXSendCommand(Stop, Motor))); // Stop the motor command - axis[Motor].MotorControl |= SpeedHBX; // Use 0x01 command - axis[Motor].TargetSpeed = (axis[Motor].SIDEREALRATE) << 2; - axis[Motor].ETXMotorState = ETXStepMotor; // Change ETX speed - } - else{ - axis[Motor].ETXMotorState = ETXMotorEnd; // Stop motor, set offset - axis[Motor].SpeedState = 0; - } - } - - break; - - case ETXStopMotor: - - while(!(HBXSendCommand(Stop, Motor))); // Stop the motor - axis[Motor].ETXMotorStatus |= MOVESLEW; // ETX Set slewing mode - axis[Motor].ETXMotorStatus &= ~MOVEHIGH; // and speed - axis[Motor].ETXMotorStatus &= ~MOVEAXIS; // Clear the motor moving flag - axis[Motor].MotorControl &= ~GoToHBX; // Clear the GoTo flag - axis[Motor].MotorControl &= ~SlewHBX; // and the slew flag - axis[Motor].EQGMotorStatus |= MOVESLEW; // EQG Set slewing mode - axis[Motor].EQGMotorStatus &= ~MOVEHIGH; // and speed - axis[Motor].EQGMotorStatus &= ~MOVEAXIS; // Clear the motor moving flag - axis[Motor].EQGMotorStatus &= ~MOVEDECR; // Clear the direction flag - axis[Motor].TargetSpeed = 0; - axis[Motor].ETXSpeed = 0; - axis[Motor].ETXMotorState = ETXCheckStartup; - -//jma CheckAltFlipState(); - dbgSerial.println(""); dbgSerial.print("ETXStopMotor Motor: "); dbgSerial.print(axis_name[Motor]); - dbgSerial.print(" "); - dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX); - dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX); - dbgSerial.print(" Chg: "); dbgSerial.print(axis[Motor].Position-axis[Motor].Target, HEX); - dbgSerial.print(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX); - dbgSerial.print(", ETXSpeed: "); dbgSerial.print(axis[Motor].ETXSpeed, HEX); - dbgSerial.print(" TgtSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX); - - break; - - case ETXMotorEnd: -///* -dbgSerial.println(""); dbgSerial.print("ETXMotorEnd Motor: "); dbgSerial.print(axis_name[Motor]); -dbgSerial.print(" "); -dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX); -dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX); -dbgSerial.print(" Chg: "); dbgSerial.print(axis[Motor].Position-axis[Motor].Target, HEX); -dbgSerial.print(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX); -//*/ - digitalWrite(ETXLED, LOW); // Turn off the ETX LED - distance = axis[Motor].Target - axis[Motor].Position; // Distance to target - if (axis[Motor].Target < axis[Motor].Position) // If it is decreasing - distance = TwosComplement(distance); - - if (distance == 0) { - axis[Motor].ETXMotorState = ETXStopMotor; // Stop the motor - } - else { - axis[Motor].HBXP1 = (distance >> 8) & 0xFF; // Initialize offset bytes - axis[Motor].HBXP2 = distance & 0xFF; - axis[Motor].Command = SetOffset; - if (HBXSendCommand(axis[Motor].Command, Motor)) // Command OK? - HBXSend2Bytes(Motor); // Send the offset - -///* -dbgSerial.print(" OFFSET"); -dbgSerial.print(" "); dbgSerial.print(axis[Motor].Command, HEX); -dbgSerial.print(" "); dbgSerial.print(axis[Motor].HBXP1, HEX); -dbgSerial.print(" "); dbgSerial.print(axis[Motor].HBXP2, HEX); -dbgSerial.print(" "); dbgSerial.print(axis[Motor].HBXP3, HEX); -//*/ - } - axis[Motor].Position = axis[Motor].Target; - axis[Motor].MotorControl &= ~GoToHBX; // Clear the flag - axis[Motor].ETXMotorState = ETXStopMotor; - break; - - default: - break; - } - return(true); -} - -// Motor functions - -bool HBXGetStatus(unsigned char Motor) { - if (!HBXSendCommand(GetStatus, Motor)) { - dbgSerial.println(""); dbgSerial.print("HBXGetStatus Motor: "); dbgSerial.print(axis_name[Motor]); dbgSerial.println(" Cmd Fail"); - return(false); - } - HBXGet3Bytes(Motor); - P1 = (axis[Motor].HBXP1 << 8); // Update calculated position - P1 |= axis[Motor].HBXP2; // Convert to 16bits - if (axis[Motor].HBXP1 & 0x80) - P1 |= 0xffff0000; // Sign extend HBXP1 for 2s complement - axis[Motor].Position += P1; - - // Wrap the position if above (+12H or +90deg) - if (axis[Motor].Position >= (ETX_CENTRE + (axis[Motor].aVALUE >> 1))) - axis[Motor].Position -= axis[Motor].aVALUE; - // Wrap the position if below (-12H or -90deg) - if (axis[Motor].Position <= (ETX_CENTRE - (axis[Motor].aVALUE >> 1))) - axis[Motor].Position += axis[Motor].aVALUE; - - if (StatusCount++ > 51) { - StatusCount = 0; - dbgSerial.print(axis_name[MotorAlt]); dbgSerial.print(": "); dbgSerial.print(axis[MotorAlt].Position, HEX); dbgSerial.print(", "); - dbgSerial.print(axis_name[MotorAz]); dbgSerial.print(": "); dbgSerial.println(axis[MotorAz].Position, HEX); - } - return(true); -} - -bool HBXGet2Status(void) { - int i; - do { - i = 0; - if (HBXGetStatus(AzMotor)) i += 1; - TimerDelayuS(HBXBitTime << 2); - - if (HBXGetStatus(AltMotor)) i += 1; - TimerDelayuS(HBXBitTime << 2); - - } while (i < 2); - return(true); -} - -// Calibrate motor LED -// =================== -void CalibrateLEDs(void) { - - - while (!(HBXSendCommand(Stop, AzMotor))); // Stop both motors - TimerDelaymS(100); - while (!(HBXSendCommand(Stop, AltMotor))); - TimerDelaymS(100); - - while (!(HBXGetStatus(AzMotor))) - TimerDelaymS(100); - while (!(HBXGetStatus(AltMotor))) - TimerDelaymS(100); - - HBXSendCommand(SleepHBX, AzMotor); // Issue Sleep - TimerDelaymS(100); - HBXSendCommand(CalibrateLED, AzMotor); // Issue Calibrate LED - TimerDelaymS(4000); - - HBXSendCommand(SleepHBX, AltMotor); - TimerDelaymS(100); - HBXSendCommand(CalibrateLED, AltMotor); - TimerDelaymS(4000); - - HBXSendCommand(GetLEDI, AzMotor); HBXGetByte(AzMotor); - HBXSendCommand(GetLEDI, AltMotor); HBXGetByte(AltMotor); - - while (!(HBXGetStatus(AzMotor))) - TimerDelaymS(100); - while (!(HBXGetStatus(AltMotor))) - TimerDelaymS(100); - - // Read the calibration - dbgSerial.println(""); dbgSerial.print("Read LEDs - AzMotor: "); - if (HBXSendCommand(GetLEDI, AzMotor)) - axis[AzMotor].HBXLEDI = HBXGetByte(AzMotor); - dbgSerial.print(axis[AzMotor].HBXLEDI); - dbgSerial.print(", AltMotor: "); - if (HBXSendCommand(GetLEDI, AltMotor)) - axis[AltMotor].HBXLEDI = HBXGetByte(AltMotor); - dbgSerial.print(axis[AltMotor].HBXLEDI); - - // Save it to preferences - // Prefences.begin must be set by the caller - preferences.putUChar("AzLEDI", axis[AzMotor].HBXLEDI); - preferences.putUChar("AltLEDI", axis[AltMotor].HBXLEDI); -} - -void WaitForMotors(void) { -// GetLED commands always return a vaild value - motors not online until this happens -// "Valid" values are not 0 and not 0xFF for Az, Alt. (exception here is if LEDRA || LEDAlt == 0xff) -// - bool PAz = false; - bool PAlt = false; - do { - if (!PAz) { - if (HBXSendCommand(GetLEDI, AzMotor)) - axis[AzMotor].HBXLEDI = HBXGetByte(AzMotor); - dbgSerial.print("Az HBXLEDI: "); dbgSerial.println(axis[AzMotor].HBXLEDI); - TimerDelaymS(CMNDTIME); - if ((axis[AzMotor].HBXLEDI != 0) && (axis[AzMotor].HBXLEDI != 0xFF)) - PAz = true; - } - if (!PAlt) { - if (HBXSendCommand(GetLEDI, AltMotor)) - axis[AltMotor].HBXLEDI = HBXGetByte(AltMotor); - TimerDelaymS(CMNDTIME); - dbgSerial.print("Alt HBXLEDI: "); dbgSerial.println(axis[AltMotor].HBXLEDI); - if ((axis[AltMotor].HBXLEDI != 0) && (axis[AltMotor].HBXLEDI != 0xFF)) - PAlt = true; - } - // Attempt to reset Motor Controller - if (!PAz) { - HBXMotorReset(AzMotor); - } - if (!PAlt) { - HBXMotorReset(AltMotor); - } - } while ((!PAz) || (!PAlt)); -} - -void AzInitialise(unsigned char scope) { -// Telescope specific -// telescope steps - axis[AzMotor].Vanes = ratio[scope][AzMotor-1].Vanes; - axis[AzMotor].GbxRatio = ratio[scope][AzMotor-1].GbxRatio; - axis[AzMotor].XferRatio = ratio[scope][AzMotor-1].XferRatio; - axis[AzMotor].WormTeeth = ratio[scope][AzMotor-1].WormTeeth; -// EQMOD - axis[AzMotor].aVALUE = axis[AzMotor].Vanes * (float)4 * axis[AzMotor].GbxRatio * axis[AzMotor].XferRatio * axis[AzMotor].WormTeeth; - axis[AzMotor].MeadeRatio = (float)axis[AzMotor].aVALUE / ArcSecs360; // Count for one arcsec - axis[AzMotor].bVALUE = (MeadeSidereal * axis[AzMotor].MeadeRatio) * ((float)axis[AzMotor].aVALUE / SIDEREALSECS) * SiderealArcSecs; - axis[AzMotor].BASERATE = axis[AzMotor].bVALUE / axis[AzMotor].MeadeRatio; - axis[AzMotor].SIDEREALRATE = MeadeSidereal * axis[AzMotor].MeadeRatio; - axis[AzMotor].SOLARRATE = axis[AzMotor].SIDEREALRATE * SOLARSECS / SIDEREALSECS; - axis[AzMotor].LUNARRATE = axis[AzMotor].SIDEREALRATE * LUNARSECS / SIDEREALSECS; - axis[AzMotor].DEGREERATE1 = axis[AzMotor].SIDEREALRATE * ETXSlew7; - axis[AzMotor].PEC = axis[AzMotor].aVALUE / axis[AzMotor].WormTeeth; - -// ETX - axis[AzMotor].HBXP1 = 0x00; - axis[AzMotor].HBXP2 = 0x00; - axis[AzMotor].HBXP3 = 0x00; - axis[AzMotor].HBXP4 = 0x00; - axis[AzMotor].ETXSpeed = 0x00; - axis[AzMotor].SpeedState = 0x00; - axis[AzMotor].TargetSpeed = axis[AzMotor].SIDEREALRATE; - axis[AzMotor].Position = ETX_CENTRE; // ETX RA initially at 0 hours - axis[AzMotor].OneDegree = axis[AzMotor].aVALUE / (float)360; // Distance for one degree - axis[AzMotor].Target = axis[AzMotor].Position; - axis[AzMotor].DirnSpeed = 0x000; - axis[AzMotor].ETXMotorStatus = MOVESLEW; - axis[AzMotor].EQGMotorStatus = MOVESLEW; - axis[AzMotor].ETXMotorState = ETXCheckStartup; -} - -void AltInitialise(unsigned char scope) { -// Telescope specific -// telescope steps - axis[AltMotor].Vanes = ratio[scope][AltMotor-1].Vanes; - axis[AltMotor].GbxRatio = ratio[scope][AltMotor-1].GbxRatio; - axis[AltMotor].XferRatio = ratio[scope][AltMotor-1].XferRatio; - axis[AltMotor].WormTeeth = ratio[scope][AltMotor-1].WormTeeth; -// EQMOD - axis[AltMotor].aVALUE = axis[AltMotor].Vanes * (float)4 * axis[AltMotor].GbxRatio * axis[AltMotor].XferRatio * axis[AltMotor].WormTeeth; - axis[AltMotor].MeadeRatio = axis[AltMotor].aVALUE / ArcSecs360; // Count for one arcsec - axis[AltMotor].bVALUE = (MeadeSidereal * axis[AltMotor].MeadeRatio) * (axis[AltMotor].aVALUE / SIDEREALSECS) * SiderealArcSecs; - axis[AltMotor].BASERATE = axis[AltMotor].bVALUE / axis[AltMotor].MeadeRatio; - axis[AltMotor].SIDEREALRATE = MeadeSidereal * axis[AltMotor].MeadeRatio; - axis[AltMotor].SOLARRATE = axis[AltMotor].SIDEREALRATE * SOLARSECS / SIDEREALSECS; - axis[AltMotor].LUNARRATE = axis[AltMotor].SIDEREALRATE * LUNARSECS / SIDEREALSECS; - axis[AltMotor].DEGREERATE1 = axis[AltMotor].SIDEREALRATE * ETXSlew7; - axis[AltMotor].PEC = axis[AltMotor].aVALUE / axis[AltMotor].WormTeeth; - axis[AltMotor].EQGMotorStatus = MOVESLEW; -// ETX - axis[AltMotor].HBXP1 = 0x00; - axis[AltMotor].HBXP2 = 0x00; - axis[AltMotor].HBXP3 = 0x00; - axis[AltMotor].HBXP4 = 0x00; - axis[AltMotor].ETXSpeed = 0x00; - axis[AltMotor].SpeedState = 0x00; - axis[AltMotor].TargetSpeed = axis[AzMotor].SIDEREALRATE; - axis[AltMotor].Position = ETX_CENTRE; // + (axis[AltMotor].aVALUE >> 2); // Initially at +90 degrees - axis[AltMotor].OneDegree = axis[AltMotor].aVALUE / (float)360; // Distance for one degree - axis[AltMotor].Target = axis[AltMotor].Position; - axis[AltMotor].DirnSpeed = 0x000; - axis[AltMotor].ETXMotorStatus = MOVESLEW; - - axis[AltMotor].ETXMotorState = ETXCheckStartup; -} - -/* -// Check if ETX mount will hit fork physical limits -// When used as GEM, ETX mounts cannot go past vertical -// This means E in Sthn, W in Nthn, for East side pointing West -// So rotate 180 degrees in Az and flip the Alt destination -*/ -void CheckAltFlip(unsigned char Motor) { - long distance; - distance = axis[Motor].Target - axis[Motor].Position; // Distance to target - if ((telescope < 3) && (Motor == AltMotor)) { // ETXn0 series - long p; - if (distance > 0) { - // GoTo - if (axis[AltMotor].Target >= (ETX_CENTRE + (axis[AltMotor].aVALUE >> 2))) { // E[Sthn] (or W[Nthn]) - dbgSerial.println(""); dbgSerial.print("Flip: target "); dbgSerial.print(axis[AltMotor].Target); // Set Target - p = axis[AltMotor].Target - (ETX_CENTRE + (axis[AltMotor].aVALUE >> 2)); // Offset from EQG midpoint - axis[AltMotor].Target -= (p << 1); // Swap to other side - distance = axis[Motor].Target - axis[Motor].Position; // Distance to target - dbgSerial.print(", new "); dbgSerial.print(axis[AltMotor].Target); - // Flip direction - if (axis[AltMotor].ETXMotorStatus & MOVEDECR) axis[AltMotor].ETXMotorStatus &= ~MOVEDECR; - else axis[AltMotor].ETXMotorStatus |= MOVEDECR; - // Set SlowDown - p = axis[AltMotor].SlowDown - (ETX_CENTRE + (axis[AltMotor].aVALUE >> 2)); - axis[AltMotor].SlowDown -= (p << 1); - dbgSerial.print(", Slowdown "); dbgSerial.print(p); - if (axis[AltMotor].Flip == NORMAL) { - axis[AltMotor].Flip = FLIP; - dbgSerial.print(", Type "); dbgSerial.print("ALREADY FLIPPED"); - } - else { - dbgSerial.print(", Type "); dbgSerial.print("NORMAL"); - } - } - else { - if (axis[AltMotor].Flip == FLIPPED) { - axis[AltMotor].Flip = UNFLIP; - dbgSerial.print(", Action "); dbgSerial.print("UNFLIP"); - } - else { - dbgSerial.print(", Action "); dbgSerial.print("NOTHING"); - } - } - } - else { - // SLEW - if (axis[AltMotor].ETXMotorStatus & MOVEDECR) { - axis[AltMotor].ETXMotorStatus &= ~MOVEDECR; - if (axis[AltMotor].Flip == NORMAL) { - axis[AltMotor].Flip = FLIP; - dbgSerial.print(", Action "); dbgSerial.print("FLIP"); - } - else { - dbgSerial.print(", Action "); dbgSerial.print("NOTHING"); - } - } - if (axis[AltMotor].Flip == FLIPPED) { - axis[AltMotor].Flip = UNFLIP; - dbgSerial.print(", Action "); dbgSerial.print("FLIP"); - } - else { - dbgSerial.print(", Action "); dbgSerial.print("NOTHING"); - } - } - } -} - -void CheckAltFlipState(void) { - if ((axis[AltMotor].Flip == FLIPPING) || (axis[AltMotor].Flip == UNFLIPPING)) { - dbgSerial.println(""); dbgSerial.print("Stop Motor: "); - if (axis[AltMotor].Flip == FLIPPING) { - axis[AltMotor].Flip = FLIPPED; dbgSerial.print("FLIPPING"); - } - else { - axis[AltMotor].Flip = NORMAL; dbgSerial.print("NORMAl"); - } - } -} - -void CheckAltFlipReqd(void) { - if (axis[AltMotor].ETXMotorState == ETXIdle) { - if ((axis[AltMotor].Flip == FLIP) || (axis[AltMotor].Flip == UNFLIP)) { - if (axis[AltMotor].Flip == FLIP) axis[AltMotor].Flip = FLIPPING; - else axis[AltMotor].Flip = UNFLIPPING; - // Rotate 180 degrees in RA - if (axis[AzMotor].Target > ETX_CENTRE) axis[AzMotor].Target -= (axis[AzMotor].aVALUE >> 1); - else axis[AzMotor].Target += (axis[AzMotor].aVALUE >> 1); - axis[AzMotor].ETXMotorStatus |= (MOVEAXIS || MOVEHIGH); - axis[AzMotor].ETXMotorStatus &= ~MOVESLEW; - axis[AzMotor].MotorControl |= GoToHBX; - CheckETXState(AzMotor); - } - } -} - -void PrintHbxValues(unsigned char Motor) { - if (Motor == AzMotor) - dbgSerial.println("AzMotor"); - else - dbgSerial.println("AltMotor"); - - dbgSerial.print("Vanes "); dbgSerial.print(axis[Motor].Vanes); - dbgSerial.print(", GbxRatio "); dbgSerial.print(axis[Motor].GbxRatio,4); - dbgSerial.print(", XferRatio "); dbgSerial.print(axis[Motor].XferRatio,4); - dbgSerial.print(", WormTeeth "); dbgSerial.println(axis[Motor].WormTeeth); - dbgSerial.print("MeadeRatio "); dbgSerial.print(axis[Motor].MeadeRatio,6); - dbgSerial.print(", MeadeSidereal "); dbgSerial.println(MeadeSidereal,4); - - dbgSerial.print("aVALUE 0x"); dbgSerial.print(axis[Motor].aVALUE, HEX); - dbgSerial.print(", bVALUE 0x"); dbgSerial.print(axis[Motor].bVALUE, HEX); - dbgSerial.print(", PEC 0x"); dbgSerial.println(axis[Motor].PEC, HEX); - - dbgSerial.print("BASERATE 0x"); dbgSerial.print(axis[Motor].BASERATE, HEX); - dbgSerial.print(", SIDEREALRATE 0x"); dbgSerial.print(axis[Motor].SIDEREALRATE, HEX); - dbgSerial.print(", SOLARRATE 0x"); dbgSerial.print(axis[Motor].SOLARRATE, HEX); - dbgSerial.print(", LUNARRATE 0x"); dbgSerial.print(axis[Motor].LUNARRATE, HEX); - dbgSerial.print(", DEGREERATE1 0x"); dbgSerial.println(axis[Motor].DEGREERATE1, HEX); - - dbgSerial.print("One DEGREE 0x"); dbgSerial.println(axis[Motor].OneDegree, HEX); - dbgSerial.println(""); -} - -void PrintRatioValues(unsigned char scope) { - int j; - for (j = 0; j < 2; j++) { - if (j == 0) - dbgSerial.print("AzMotor: "); - else - dbgSerial.print("AltMotor: "); - dbgSerial.print("Vanes "); dbgSerial.print(ratio[scope][j].Vanes); - dbgSerial.print(", GbxRatio "); dbgSerial.print(ratio[scope][j].GbxRatio,4); - dbgSerial.print(", XferRatio "); dbgSerial.print(ratio[scope][j].XferRatio,4); - dbgSerial.print(", WormTeeth "); dbgSerial.print(ratio[scope][j].WormTeeth); - float r = (ratio[scope][j].Vanes * (float) 4 * ratio[scope][j].GbxRatio * ratio[scope][j].XferRatio * ratio[scope][j].WormTeeth) / (float) 1296000; - dbgSerial.print(", MeadeRatio "); dbgSerial.println(r, 6); - } -} - -void HBXPrintStatus(unsigned char Motor) { - axis[Motor].HBXCount = 0; - if ((axis[Motor].Command != GetStatus) || (axis[Motor].HBXP1 | axis[Motor].HBXP2 | axis[Motor].HBXP3 | axis[Motor].HBXP4) || axis[Motor].PrintStatus0) { - - /* dbgSerial.println(""); - dbgSerial.print("Motor: "); - dbgSerial.print(axis_name[Motor]); - dbgSerial.print(", Cmnd: "); - dbgSerial.print(axis[Motor].Command, HEX); - dbgSerial.print(" - "); - */ - switch (axis[Motor].Command) { - case SpeedChnge: - // dbgSerial.print("SpeedChnge "); - axis[Motor].HBXCount = 3; - break; - case SpeedStart: - // dbgSerial.print("SpeedStart "); - axis[Motor].HBXCount = 3; - break; - case SetOffset: - // dbgSerial.print("SetOffset "); - axis[Motor].HBXCount = 4; - break; - case SetLEDI: - // dbgSerial.print("SetLEDI "); - axis[Motor].HBXCount = 1; - break; - case CalibrateLED: - // dbgSerial.print("CalibrateLED "); - break; - case Stop: - // dbgSerial.print("Stop "); - break; - case SlewReverse: - // dbgSerial.print("SlewReverse "); - break; - case SlewForward: - // dbgSerial.print("SlewForward "); - break; - case GetStatus: - // dbgSerial.print("GetStatus "); - axis[Motor].HBXCount = 4; - break; - case GetLEDI: - // dbgSerial.print("GetLEDI "); - axis[Motor].HBXCount = 1; - break; - case GetMotorType: - // dbgSerial.print("GetMotorType "); - axis[Motor].HBXP1 = axis[Motor].MotorType; - axis[Motor].HBXCount = 1; - break; - case SleepHBX: - // dbgSerial.print("SleepHBX "); - break; - default: - dbgSerial.print("UNKNOWN "); - break; - } - - /* - if (axis[Motor].HBXCount != 0) { - dbgSerial.print(", Data: "); - dbgSerial.print(axis[Motor].HBXP1, HEX); - if (axis[Motor].HBXCount >= 2) dbgSerial.print(", "); - axis[Motor].HBXCount -= 1; - } - if (axis[Motor].HBXCount != 0) { - dbgSerial.print(axis[Motor].HBXP2, HEX); - if (axis[Motor].HBXCount >= 2) dbgSerial.print(", "); - axis[Motor].HBXCount -= 1; - } - if (axis[Motor].HBXCount != 0) { - dbgSerial.print(axis[Motor].HBXP3, HEX); - if (axis[Motor].HBXCount >= 2) dbgSerial.print(", "); - axis[Motor].HBXCount -= 1; - } - if (axis[Motor].HBXCount > 0) { - dbgSerial.print(axis[Motor].HBXP4, HEX); - axis[Motor].HBXCount -= 1; - } - dbgSerial.println(""); - */ - } -} diff --git a/Software/EQG2HBXE32/src/HBXComms.h b/Software/EQG2HBXE32/src/HBXComms.h deleted file mode 100644 index bf6da6a..0000000 --- a/Software/EQG2HBXE32/src/HBXComms.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2017, 2018, 2020 John Archbold -*/ - -/******************************************************** - EQG Protocol function definitions - ================================= - *********************************************************/ -#pragma once - -#define CR 0x0d -#define LF 0x0a - -#define HBXLEN 16 -#define HBXMASK HBXLEN-1 - -#define HCLRESETTIME 5 // Reset H2X Clock (mS) -#define H2XRESETTIME 25 // Reset H2X bus -#define BITTIME 100 // H2X clock ~200uS i.e 100us Low/High - -#define STATUSDELAY 50 // H2X ETX status poll delay (mS) -#define STATEDELAY 6.55 // H2X ETX state poll delay (mS) -#define CMNDTIME 1 // H2X command delay (mS) -#define STARTTIME 50 // H2X startup time for motors (mS) -#define CLOCKTIMEOUT 50 // H2X Clock transition timeout (uS) (for monitor mode) -#define MOTORDETECT 500 // H2X Detect Motor controller (mS) - -uint8_t HDA = HDAAz; // Default -uint8_t HCL = HCLAz; // Default - -uint8_t pCommand; -uint16_t pAzCount; -uint16_t pAltCount; - -unsigned char HBXBitTime = BITTIME; -void TimerDelayuS(unsigned int); -void TimerDelaymS(unsigned long); - -bool HBXSendCommand(unsigned char, unsigned char); -void HBXMotorReset(unsigned char); -bool HBXStartSequence(unsigned char); -void HBXSendByte(unsigned char, unsigned char); -unsigned char HBXGetByte(unsigned char); -void HBXSend2Bytes(unsigned char); -void HBXSend3Bytes(unsigned char); -void HBXGet3Bytes(unsigned char); - -void HDAListen(uint8_t); -void HDATalk(uint8_t); -bool HBXReset(void); - -long TwosComplement(long); - -// Testing -void HBXTestLoop(void); -void HBXTest(void); -bool HBXGet2Status(void); diff --git a/Software/EQG2HBXE32/src/HBXComms.ino b/Software/EQG2HBXE32/src/HBXComms.ino deleted file mode 100644 index 9144335..0000000 --- a/Software/EQG2HBXE32/src/HBXComms.ino +++ /dev/null @@ -1,334 +0,0 @@ -/**@file*/ -/* - * Copyright 2017, 2018, 2020 John Archbold -*/ -#include "Hardware.h" -#include "ETXProtocol.h" -#include "EQGProtocol.h" -#include "EQG2HBX.h" -#include "HBXComms.h" -#include "HBXFileSystem.h" -#include "HBXWiFiServer.h" - -/******************************************************** - HBX Comms related functions - =========================== - *********************************************************/ -/********************************************** - Multiple 1mS delay -***********************************************/ - -void TimerDelaymS(unsigned long d) { - delay(d); -} - -/********************************************** - Multiple 1uS delay -***********************************************/ - -void TimerDelayuS(unsigned int d) { - delayMicroseconds(d); -} - - // HBX Attempt to reset - // -------------------- -void HBXMotorReset(unsigned char Motor) -{ - if (Motor == AzMotor) {HCL = HCLAz; HDA = HDAAz;} - else {HCL = HCLAlt; HDA = HDAAlt;} - /* - int i; - - // Write LOW - HDATalk(Motor); - digitalWrite(HDA1, LOW); - TimerDelayuS(HBXBitTime); - for (i = 0; i < 8; i++) - { - if (Motor == MotorAz) digitalWrite(HCL1, LOW); - else digitalWrite(HCL2, LOW); - TimerDelayuS(HBXBitTime); - if (Motor == MotorAz) digitalWrite(HCL1, HIGH); - else digitalWrite(HCL2, HIGH); - TimerDelayuS(HBXBitTime); - } - - // Write HIGH - digitalWrite(HDA1, HIGH); - TimerDelayuS(HBXBitTime); - for (i = 0; i < 8; i++) - { - if (Motor == MotorAz) digitalWrite(HCL1, LOW); - else digitalWrite(HCL2, LOW); - TimerDelayuS(HBXBitTime); - if (Motor == MotorAz) digitalWrite(HCL1, HIGH); - else digitalWrite(HCL2, HIGH); - TimerDelayuS(HBXBitTime); - } - - // Read, and discard, a byte - HDAListen(HDA); - for (i = 0; i < 8; i++) { - if (Motor == MotorAz) digitalWrite(HCL1, LOW); - else digitalWrite(HCL2, LOW); - TimerDelayuS(HBXBitTime); - if (Motor == MotorAz) digitalWrite(HCL1, HIGH); - else digitalWrite(HCL2, HIGH); - TimerDelayuS(HBXBitTime); - } - */ - - // Force Clock High, Low, High for reset, time ~1.25s - HCLTalk(Motor); - digitalWrite(HCL, HIGH); - TimerDelaymS(MOTORDETECT); - digitalWrite(HCL, LOW); - TimerDelaymS(MOTORDETECT); - digitalWrite(HCL, HIGH); - TimerDelaymS(MOTORDETECT >> 1); -} - -// HBX transmission functions -// ========================== - -// HBX Send a command -// ------------------ -bool HBXSendCommand(unsigned char Command, unsigned char Motor) { - - pCommand = Command; - if (Command != GetStatus){ - dbgSerial.println("");dbgSerial.print("+++ ");dbgSerial.print(Motor); - } - axis[Motor].Command = Command; - - // Select the interface - if (Motor == MotorAz) {HDA = HDAAz;HCL = HCLAz;} - else {HDA = HDAAlt;HCL = HCLAlt;} - -// Send the start sequence -// ----------------------- - if (HBXStartSequence(Motor)) { -// Send the command byte -// --------------------- - HBXSendByte(Command, Motor); - return(true); - } - else { - HDAListen(HDA); // Set data inbound - return(false); - } -} - -// HBX Initiate start sequence -// --------------------------- -bool HBXStartSequence(unsigned char Motor) { - if (Motor == AzMotor) {HCL = HCLAz; HDA = HDAAz;} - else if (Motor == AltMotor) {HCL = HCLAlt; HDA = HDAAlt;} - else {HCL = HCLAux; HDA = HDAAux;} - -// 1. HDA as input, Clock as output - HDAListen(HDA); - HCLTalk(HCL); -// 2. Set clock low - digitalWrite(HCL, LOW); - TimerDelayuS(HBXBitTime >> 1); // 1/2 bit-time -// 3. Wait for data low (HDA = 0) by MC, or timeout - H2XStart = micros(); - do { - H2XTimer = micros() - H2XStart; - } while ((digitalRead(HDA) == 1) && (H2XTimer < (HBXBitTime << 3))); - TimerDelayuS((HBXBitTime >> 5)); // 1/32 bit-time delay, in case of data line glitch -// 4. Re-read data line, check if (data low) or (MC timeout) - if ((digitalRead(HDA) == 1) || (H2XTimer >= (HBXBitTime << 3))) { - digitalWrite(HCL, HIGH); - return(false); // error exit if no response from Motor - } -// 5. Set clock high if data low occurred (i.e. MC acknowledged clock low) - digitalWrite(HCL, HIGH); - TimerDelayuS(HBXBitTime >> 1); -// 6. Wait for data line release (HDA = 1) by MC, or timeout - H2XStart = micros(); - do { - H2XTimer = micros() - H2XStart; - } while ((digitalRead(HDA) == 0) && (H2XTimer < (HBXBitTime << 3))); - TimerDelayuS(HBXBitTime); // Wait one bit-time, in case of success -// 7. Check timeout for data line released or no response from MC - if (H2XTimer >= (HBXBitTime << 3)) { - return(false); // Error Exit if no response from MC - } - return(true); // Success -} - -// HBX Send a single byte -// ---------------------- -void HBXSendByte(unsigned char databyte, unsigned char Motor) { - - unsigned char mask; - if (Motor == AzMotor) {HCL = HCLAz; HDA = HDAAz;} - else if (Motor == AltMotor) {HCL = HCLAlt; HDA = HDAAlt;} - else {HCL = HCLAux; HDA = HDAAux;} - - if (axis[Motor].Command != GetStatus) { - dbgSerial.print("-> "); dbgSerial.print(databyte, HEX); - } - - HDATalk(HDA); // HDA as output - axis[Motor].HBXBitCount = 8; // 8bits to go - mask = 0x80; // MSB first -// Clock was set high before entry - TimerDelayuS(HBXBitTime); - do { - axis[Motor].HBXBitCount -= 1; -// Set data bit - if (databyte & mask) digitalWrite(HDA, HIGH); - else digitalWrite(HDA, LOW); - TimerDelayuS(HBXBitTime >> 1); // Let data stabilise - mask = mask >> 1; // Next data bit -// Set clock low - digitalWrite(HCL, LOW); - TimerDelayuS(HBXBitTime); -// Set clock high - digitalWrite(HCL, HIGH); - TimerDelayuS(HBXBitTime-(HBXBitTime >> 1)); // Data is written DSTABLE before clock low -// for 8 bits - } while (axis[Motor].HBXBitCount); - TimerDelayuS(HBXBitTime >> 1); // Last high clock - HDAListen(HDA); // Release data pin - TimerDelayuS(HBXBitTime); -} - -// HBX Send two bytes in sequence -// ------------------------------ -void HBXSend2Bytes(unsigned char Motor) { - HBXSendByte(axis[Motor].HBXP1, Motor); - HBXSendByte(axis[Motor].HBXP2, Motor); - if (pCommand != GetStatus) dbgSerial.println(""); -} - -// HBX Send three bytes in sequence -// -------------------------------- -void HBXSend3Bytes(unsigned char Motor) { - HBXSendByte(axis[Motor].HBXP1, Motor); - HBXSendByte(axis[Motor].HBXP2, Motor); - HBXSendByte(axis[Motor].HBXP3, Motor); - if (pCommand != GetStatus) dbgSerial.println(""); -} - -// HBX Get a single byte -// ---------------------- -unsigned char HBXGetByte(unsigned char Motor) { - - if (Motor == AzMotor) {HCL = HCLAz; HDA = HDAAz;} - else if (Motor == AltMotor) {HCL = HCLAlt; HDA = HDAAlt;} - else {HCL = HCLAux; HDA = HDAAux;} - -// HDA as input - HDAListen(HDA); - axis[Motor].HBXBitCount = 8; - axis[Motor].HBXData = 0; -// Clock was set high before entry - while (axis[Motor].HBXBitCount) { -// Set clock low - digitalWrite(HCL, LOW); - TimerDelayuS(HBXBitTime >> 1); -// Read data bit - axis[Motor].HBXData = axis[Motor].HBXData << 1; // Shift previous bit - if (digitalRead(HDA)) axis[Motor].HBXData |= 0x01; // Read next bit - axis[Motor].HBXBitCount--; // Need eight bits - TimerDelayuS(HBXBitTime-(HBXBitTime >> 1)); // Wait for low time -// Set clock high - digitalWrite(HCL, HIGH); - TimerDelayuS(HBXBitTime); - } - TimerDelayuS(HBXBitTime); - if (axis[Motor].Command != GetStatus) { - dbgSerial.print("<- "); dbgSerial.print(axis[Motor].HBXData, HEX); - } -// Return data byte - axis[Motor].HBXCount = 1; - return (axis[Motor].HBXData); -} - -// HBX Get the status bytes (25 bits) -// ---------------------------------- -void HBXGet3Bytes(unsigned char Motor) { - - axis[Motor].HBXP1 = HBXGetByte(Motor); - TimerDelayuS(HBXBitTime); - axis[Motor].HBXP2 = HBXGetByte(Motor); - TimerDelayuS(HBXBitTime); - axis[Motor].HBXP3 = HBXGetByte(Motor); - TimerDelayuS(HBXBitTime); - axis[Motor].HBXP4 = 0; - -// Read 'byte4' = error bit -// ------------------------ - digitalWrite(HCL, LOW); - TimerDelayuS(HBXBitTime >> 1); - axis[Motor].HBXP4 |= digitalRead(HDA); // Read the battery error bit - TimerDelayuS(HBXBitTime-(HBXBitTime >> 1)); - digitalWrite(HCL, HIGH); - TimerDelayuS(HBXBitTime); - if (axis[Motor].Command != GetStatus) { - dbgSerial.print("- "); dbgSerial.print(axis[Motor].HBXP4, HEX); - } - axis[Motor].HBXCount = 4; - if (pCommand != GetStatus) dbgSerial.println(""); -} - -// H2X Low level Functions -// ----------------------- -void HDAListen(uint8_t HDA) { -// digitalWrite(HDA, HIGH); - pinMode(HDA, H2C_INPUT); -} -void HDAFloat(uint8_t HDA) { - pinMode(HDA, H2C_INPUT); -} -void HDATalk(uint8_t HDA) { - digitalWrite(HDA, HIGH); - pinMode(HDA, H2C_OUTPUT); -} -void HCLListen(uint8_t HCL) { -// digitalWrite(HCL, HIGH); - pinMode(HCL, H2C_INPUTPU); -} -void HCLFloat(uint8_t HCL) { - pinMode(HCL, H2C_INPUT); -} -void HCLTalk(uint8_t HCL) { - digitalWrite(HCL, HIGH); - pinMode(HCL, H2C_OUTPUT); -} - -bool HBXReset(void) { - int ClockCount = 0; - - HCLTalk(HCLAz); // Set clock high - HCLTalk(HCLAlt); // Set clock high - HCLTalk(HCLAux); // Set clock high - HDAListen(HDAAz); // Set common data inbound - TimerDelayuS(HBXBitTime); - - // Data should be high - while ((!digitalRead(HDA)) && (ClockCount < 25)) { - digitalWrite(HCLAux, LOW); - digitalWrite(HCLAz, LOW); - digitalWrite(HCLAlt, LOW); - TimerDelaymS(HCLRESETTIME); - digitalWrite(HCLAux, HIGH); - digitalWrite(HCLAz, HIGH); - digitalWrite(HCLAlt, HIGH); - TimerDelayuS(HBXBitTime); - ClockCount += 1; - } - if (ClockCount >= 25) return(false); - else return(true); -} - -long TwosComplement(long p) { // Calculate 2s complement - long q; - q = ~p; // Bitwise invert - q = q + 1; // +1 - return q; -} diff --git a/Software/EQG2HBXE32/src/HBXFileSystem.h b/Software/EQG2HBXE32/src/HBXFileSystem.h deleted file mode 100644 index 5ae76d8..0000000 --- a/Software/EQG2HBXE32/src/HBXFileSystem.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -/************************************************************** - * SPIFFS filesystem - * Only invoked in STA mode -*/ - -#include -#include -#include -#include - -#define FORMAT_SPIFFS_IF_FAILED true diff --git a/Software/EQG2HBXE32/src/HBXFileSystem.ino b/Software/EQG2HBXE32/src/HBXFileSystem.ino deleted file mode 100644 index 78ddf12..0000000 --- a/Software/EQG2HBXE32/src/HBXFileSystem.ino +++ /dev/null @@ -1,108 +0,0 @@ -/**@file*/ -// SPIFFS file system -#include "Hardware.h" -#include "ETXProtocol.h" -#include "EQGProtocol.h" -#include "EQG2HBX.h" -#include "HBXComms.h" -#include "HBXFileSystem.h" -#include "HBXWiFiServer.h" - -void listDir(fs::FS &fs, const char * dirname, uint8_t levels) { - Serial.printf("Listing directory: %s\r\n", dirname); - - File root = fs.open(dirname); - if (!root) { - Serial.println("- failed to open directory"); - return; - } - if (!root.isDirectory()) { - Serial.println(" - not a directory"); - return; - } - - File file = root.openNextFile(); - while (file) { - if (file.isDirectory()) { - Serial.print(" DIR : "); - Serial.println(file.name()); - if (levels) { - listDir(fs, file.name(), levels - 1); - } - } - else { - Serial.print(" FILE: "); - Serial.print(file.name()); - Serial.print("\tSIZE: "); - Serial.println(file.size()); - } - file = root.openNextFile(); - } -} - -void readFile(fs::FS &fs, const char * path) { - Serial.printf("Reading file: %s\r\n", path); - - File file = fs.open(path); - if (!file || file.isDirectory()) { - Serial.println("- failed to open file for reading"); - return; - } - - Serial.println("- read from file:"); - while (file.available()) { - Serial.write(file.read()); - } -} - -void writeFile(fs::FS &fs, const char * path, const char * message) { - Serial.printf("Writing file: %s\r\n", path); - - File file = fs.open(path, FILE_WRITE); - if (!file) { - Serial.println("- failed to open file for writing"); - return; - } - if (file.print(message)) { - Serial.println("- file written"); - } - else { - Serial.println("- frite failed"); - } -} - -void appendFile(fs::FS &fs, const char * path, const char * message) { - Serial.printf("Appending to file: %s\r\n", path); - - File file = fs.open(path, FILE_APPEND); - if (!file) { - Serial.println("- failed to open file for appending"); - return; - } - if (file.print(message)) { - Serial.println("- message appended"); - } - else { - Serial.println("- append failed"); - } -} - -void renameFile(fs::FS &fs, const char * path1, const char * path2) { - Serial.printf("Renaming file %s to %s\r\n", path1, path2); - if (fs.rename(path1, path2)) { - Serial.println("- file renamed"); - } - else { - Serial.println("- rename failed"); - } -} - -void deleteFile(fs::FS &fs, const char * path) { - Serial.printf("Deleting file: %s\r\n", path); - if (fs.remove(path)) { - Serial.println("- file deleted"); - } - else { - Serial.println("- delete failed"); - } -} diff --git a/Software/EQG2HBXE32/src/HBXWiFiServer.h b/Software/EQG2HBXE32/src/HBXWiFiServer.h deleted file mode 100644 index 64e59a3..0000000 --- a/Software/EQG2HBXE32/src/HBXWiFiServer.h +++ /dev/null @@ -1,117 +0,0 @@ - - -/* - * Copyright 2017, 2018, 2020 John Archbold -*/ - -/******************************************************** - EQG Serial WiFi - =============== - *********************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -/************************************************************** - * WiFi communications buffers and pointers - * WiFi variables - **************************************************************/ - -uint8_t smac[] = { 0x5C, 0xCF, 0x7F, 0x88, 0x88, 0x88 }; // Hopefully :) Unique Espressif mac -uint8_t mmac[] = { 0x5C, 0xCF, 0x7F, 0x00, 0x00, 0x00 }; // Master mac address -const uint8_t WIFI_CHANNEL = 4; - -String ssid; // char ssid[64] = "EQMODWiFi"; -String pass; // char pass[64] = "CShillit0"; - -const char* http_username = "admin"; -const char* http_password = "eqmod"; -// flag to use from web update to reboot the ESP -bool shouldReboot = false; -bool loginValid = false; - -IPAddress ip(192, 168, 88, 1); -IPAddress gateway(192, 168, 88, 1); -IPAddress netmask(255, 255, 255, 0); - -/************************************************************** - * WiFi WebServer - * Only invoked in STA mode -*/ - -AsyncWebServer server(80); -AsyncWebSocket ws("/ws"); // access at ws://[esp ip]/ws -AsyncEventSource events("/events"); // event source (Server-Sent events) - -/************************************************************** - * WiFi ESP_NOW -*/ -esp_now_peer_info serial_peer; - -/************************************************************** - * WiFi UDP -*/ -WiFiUDP udp; -IPAddress remoteIp; -const int localUdpPort = 11880; - -/************************************************************** - * WiFi Data Buffers -*/ -struct __attribute__((packed)) DataStruct { - char text[ESP_NOW_MAX_DATA_LEN]; - uint8_t len; -}; - -DataStruct sendWiFi; -DataStruct recvWiFi; -uint8_t sendWiFi8[sizeof(sendWiFi)]; -uint8_t recvWiFi8[sizeof(recvWiFi)]; - -/************************************************************** - * WiFi EQMOD virtualization -*/ -#define EQxTimeout 10 -#define EQxSize ESP_NOW_MAX_DATA_LEN-1 - -uint8_t RxD; -uint8_t TxD; -uint8_t TxDIndex; - -unsigned long RxTimeout; -unsigned long WiFiTimeout; -unsigned long LastmS; -unsigned long CheckmS = 1000; -bool Connected = false; -bool dataSending = false; -bool waitingForReply = false; - -unsigned long TxDuS; -unsigned long AckuS; -unsigned long RxDuS; - -unsigned long LastLEDmS; -unsigned long FastLEDmS = 200; -unsigned long SlowLEDmS = 800; -unsigned long BlinkmS = SlowLEDmS; -unsigned long SavedBlinkmS = SlowLEDmS; - -bool UDPFlag = false; -bool APFlag = false; -bool SerialFlag = false; - -void HBXWiFiSetup(); -bool HBXCheckRx(); -void HBXCheckTx(); -void InitESPNow(); -void recvCallBack(const uint8_t*, const uint8_t* , int ); -void sendData(const esp_now_peer_info_t* ); -void sendCallBack(const uint8_t* , esp_now_send_status_t ); -void putRxDataIntoMountInputBuffer(void); -void getTxDataFromMountOutputBuffer(void); diff --git a/Software/EQG2HBXE32/src/HBXWiFiServer.ino b/Software/EQG2HBXE32/src/HBXWiFiServer.ino deleted file mode 100644 index e01a0da..0000000 --- a/Software/EQG2HBXE32/src/HBXWiFiServer.ino +++ /dev/null @@ -1,509 +0,0 @@ -/**@file*/ -// HBXSerialServer.ino -// https://esp-idf.readthedocs.io/en/latest/api-reference/wifi/esp_now.html -#include "Hardware.h" -#include "ETXProtocol.h" -#include "EQGProtocol.h" -#include "EQG2HBX.h" -#include "HBXComms.h" -#include "HBXFileSystem.h" -#include "HBXWiFiServer.h" -#include // Include the SPIFFS library - -// Init ESP Now with fallback -void InitESPNow() { - WiFi.disconnect(); - if (esp_now_init() == ESP_OK) { - dbgSerial.println("ESPNow Init Success"); - } - else { - dbgSerial.println("ESPNow Init Failed"); - // Retry InitESPNow, add a counter and then restart? - // InitESPNow(); - // or Simply Restart - ESP.restart(); - } -} - -// Handle ESP_NOW WiFi data -// Data in recvWiFi.text, length recvWiFi.len -void recvCallBack(const uint8_t *senderMac, const uint8_t *incomingData, int len) { - -// Get data from WiFi buffer - memcpy(&recvWiFi.text, incomingData, len); // Receive data from EQMOD Tx - recvWiFi.text[len] = 0; // Null terminate - recvWiFi.len = len; - -// Check if serial device is requesting restart - if ((len == 20) && ((strncmp(recvWiFi.text, "Mount, please reply", 15) == 0))) { - // Capture the serial device mac address - for (byte n = 0; n < ESP_NOW_ETH_ALEN; n++) { - serial_peer.peer_addr[n] = senderMac[n]; - } - // Discard data from reconnect request, clear flags - recvWiFi.len = 0; - Connected = false; - dataSending = false; - // Reply to reconnect request - strcpy(sendWiFi.text, "EQMOD WiFi Mount V1.0\n"); - sendWiFi.len = sizeof("EQMOD WiFi Mount V1.0\n"); - dbgSerial.println("Reconnecting"); - sendData(&serial_peer); - return; - } -} - -// Send data to ESP_NOW -void sendData(const esp_now_peer_info_t* s_peer) { - // If first time, create a peer2peer connection with the sender mac address - if (!Connected) { - esp_now_add_peer(s_peer); // Only one paired device - the first one to respond - } - - // Send data, if not waiting for previous send to complete - if (!dataSending) { - memcpy(sendWiFi8, &sendWiFi, sendWiFi.len); // Need to satisfy esp_now - esp_now_send(serial_peer.peer_addr, sendWiFi8, sendWiFi.len); - dataSending = true; - } -} - -// Get Send data status -void sendCallBack(const uint8_t* mac, esp_now_send_status_t sendStatus) { - if (sendStatus == 0) { - sendWiFi.len = 0; // Data successfully sent - Connected = true; - dataSending = false; - } - // Do some error checking? -} - -// Put received WiFi (UDP/ESP_NOW) data into the mount input data buffer for processing -// Data in recvWiFi.text, length recvWiFi.len -void putRxDataIntoMountInputBuffer(void) { - uint8_t n; - n = 0; - while (n < recvWiFi.len) { - EQGRxBuffer[EQGRxiPtr++] = recvWiFi.text[n]; - EQGRxiPtr &= EQGMASK; - n += 1; - } - recvWiFi.len = 0; -} - -// Get mount data to send to WiFi (UDP/NOW) into WiFi buffer -// Data in sendWiFi.text, length sendWiFi.len -void getTxDataFromMountOutputBuffer(void) { - while (EQGTxoPtr != EQGTxiPtr) { - if ((EQGTxBuffer[EQGTxoPtr] != CR) && (EQGTxBuffer[EQGTxoPtr] != LF)) - dbgSerial.write(EQGTxBuffer[EQGTxoPtr]); - else dbgSerial.write('.'); - sendWiFi.text[TxDIndex++] = EQGTxBuffer[EQGTxoPtr++]; - EQGTxoPtr &= EQGMASK; - } - // Send when a CR is detected - if (sendWiFi.text[TxDIndex - 1] == 0x0d) { - sendWiFi.text[TxDIndex] = 0; - sendWiFi.len = TxDIndex; - } -} - -// Webserver functions for ssid, pass, telescope etc -// ================================================= - -void onRequest(AsyncWebServerRequest *request){ - //Handle Unknown Request - request->send(404, "text/plain", "The content you are looking for was not found."); -} - -void onBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ - if (!index) { - dbgSerial.printf("BodyStart: %u B\n", total); - } - for (size_t i = 0; i < len; i++) { - dbgSerial.write(data[i]); - } - if (index + len == total) { - dbgSerial.printf("BodyEnd: %u B\n", total); - } -} - -void onUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ - if (!index) { - dbgSerial.printf("UploadStart: %s\n", filename.c_str()); - } - for (size_t i = 0; i < len; i++) { - dbgSerial.write(data[i]); - } - if (final) { - dbgSerial.printf("UploadEnd: %s, %u B\n", filename.c_str(), index + len); - } -} - -void AsyncServerResponseSetup(void) { - - // respond to GET requests on URL /scan - //First request will return 0 results unless you start scan from somewhere else (loop/setup) - //Do not request more often than 3-5 seconds - - server.on("/scan", HTTP_GET, [](AsyncWebServerRequest *request){ - String json = "["; - int n = WiFi.scanComplete(); - if(n == -2){ - WiFi.scanNetworks(true); - } else if(n){ - for (int i = 0; i < n; ++i) { - if(i) json += ","; - json += "{"; - json += "\"rssi\":"+String(WiFi.RSSI(i)); - json += ",\"ssid\":\""+WiFi.SSID(i)+"\""; - json += ",\"bssid\":\""+WiFi.BSSIDstr(i)+"\""; - json += ",\"channel\":"+String(WiFi.channel(i)); - json += ",\"secure\":"+String(WiFi.encryptionType(i)); -// json += ",\"hidden\":"+String(WiFi.isHidden(i)?"true":"false"); - json += "}\r\n"; - } - WiFi.scanDelete(); - if(WiFi.scanComplete() == -2){ - WiFi.scanNetworks(true); - } - } - json += "]"; - request->send(200, "application/json", json); - json = String(); - }); - - // upload a file to /upload - server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){ - request->send(200); - }, onUpload); - - // send /index.htm file when /index is requested - server.on("/index", HTTP_ANY, [](AsyncWebServerRequest *request){ - request->send(SPIFFS, "/www/index.htm"); - }); - - // send /settings.htm file when /settings is requested - server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(SPIFFS, "/www/settings.htm"); - int paramsNr = request->params(); - dbgSerial.print("Number of settings parameters: "); dbgSerial.println(paramsNr); - if (paramsNr) { - for (int i = 0; i < paramsNr; i++) { - AsyncWebParameter* p = request->getParam(i); - dbgSerial.print("Param name: "); dbgSerial.print(p->name()); - dbgSerial.print(", value: "); dbgSerial.println(p->value()); - if ((p->name()) == "ssid") - ssid = (p->value()); - if ((p->name()) == "pass") - pass = (p->value()); - if ((p->name()) == "scope") - strcpy(scope, (p->value()).c_str()); - } - - preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace - - dbgSerial.print("Original - ssid: "); dbgSerial.print(preferences.getString("STA_SSID")); - dbgSerial.print(", pass: "); dbgSerial.print(preferences.getString("STA_PASS")); - dbgSerial.print(", Telescope: "); dbgSerial.println(preferences.getString("TELESCOPE")); - - if (strlen(ssid.c_str()) != 0) preferences.putString("STA_SSID", ssid); - if (strlen(pass.c_str()) != 0) preferences.putString("STA_PASS", pass); - if (strlen(scope) != 0) preferences.putString("TELESCOPE", scope); - - dbgSerial.print("Updated - ssid: "); dbgSerial.print(preferences.getString("STA_SSID")); - dbgSerial.print(", pass: "); dbgSerial.print(preferences.getString("STA_PASS")); - dbgSerial.print(", Telescope: "); dbgSerial.println(preferences.getString("TELESCOPE")); - preferences.end(); - } - }); - - // HTTP basic authentication - server.on("/login", HTTP_GET, [](AsyncWebServerRequest *request){ - dbgSerial.print("B4 http_username: "); - dbgSerial.print(http_username); - dbgSerial.print(", http_password: "); - dbgSerial.println(http_password); - - if(!request->authenticate(http_username, http_password)) - return request->requestAuthentication(); - else { - dbgSerial.print("http_username: "); - dbgSerial.print(http_username); - dbgSerial.print(", http_password: "); - dbgSerial.println(http_password); - } - request->send(200, "text/plain", "Login Success!"); - loginValid = true; - }); - - // Simple Firmware Update Form - // send /update.htm file when /index is requested - server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request) { - if (loginValid == true) { - request->send(SPIFFS, "/update.htm"); - } - else { - request->send(200, "text/plain", "Before you can update firmware, Please Login"); - } - }); - - // Process POST from Update Form - server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){ - shouldReboot = !Update.hasError(); - AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", shouldReboot?"OK":"FAIL"); - response->addHeader("Connection", "close"); - request->send(response); - },[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ - if(!index){ - dbgSerial.printf("Update Start: %s\n", filename.c_str()); - -// Update.runAsync(true); -// if (!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000)) { - if (!Update.begin(0x140000)) { - Update.printError(dbgSerial); - } - } - if(!Update.hasError()){ - if(Update.write(data, len) != len){ - Update.printError(dbgSerial); - } - } - if(final){ - if(Update.end(true)){ - dbgSerial.printf("Update Success: %uB\n", index+len); - } else { - Update.printError(dbgSerial); - } - } - }); -} - -void browseService(const char * service, const char * proto) { - Serial.printf("Browsing for service _%s._%s.local. ... ", service, proto); - int n = MDNS.queryService(service, proto); - if (n == 0) { - Serial.println("no services found"); - } - else { - Serial.print(n); - Serial.println(" service(s) found"); - for (int i = 0; i < n; ++i) { - // Print details for each service found - Serial.print(" "); - Serial.print(i + 1); - Serial.print(": "); - Serial.print(MDNS.hostname(i)); - Serial.print(" ("); - Serial.print(MDNS.IP(i)); - Serial.print(":"); - Serial.print(MDNS.port(i)); - Serial.println(")"); - } - } - Serial.println(); -} - -// ================================================================================================ - -void HBXWiFiSetup() { - - // TODO - // Read from EEPROM - // ESPNOW - - UDPFlag = false; -#ifdef SelectUDP - UDPFlag = true; // Either UDP or ESPNOW -#endif - APFlag = false; -#ifdef SelectAP - APFlag = true; // Either AP or STA -#endif - - if (APFlag) { - // AP mode device connects directly to EQMODWiFi (no router) - // For AP mode: UDP2Serial: This ESP assigns IP addresses - // For AP mode: ESP IP is always 192.168.88.1 (set above) - - dbgSerial.println("EQMODWiFi Access Point Mode"); - // Check preferences for ssid, pass - preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace - if (preferences.getString("AP_SSID", "none") == "none") - preferences.putString("AP_SSID", "EQGWiFi"); // Default - if (preferences.getString("AP_PASS", "none") == "none") - preferences.putString("AP_PASS", "EQG2HBXPcl"); // Default - ssid = preferences.getString("AP_SSID", "none"); - pass = preferences.getString("AP_PASS", "none"); - preferences.end(); - - WiFi.persistent(false); - WiFi.mode(WIFI_AP); - WiFi.softAP(ssid.c_str(), pass.c_str()); // softAP ssid, pass - delay(2000); // Espressif wifi bug needs this - WiFi.softAPConfig(ip, gateway, netmask); // softAP ip - dbgSerial.print("SoftAP IP address: "); dbgSerial.println(WiFi.softAPIP()); - } - else { - // STA mode EQMODWiFi connects to network router and gets an IP - // For STA mode: Host software must detect that IP - // For STA mode: UDP2Serial router network assigns IP address - // For STA mode: Start webserver, mDNS and accept changes to ssid, pass, Telescope etc - - dbgSerial.println("EQMODWiFi Station Mode"); - // Check preferences for ssid, pass - preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace - preferences.putString("STA_SSID", "bunyas_g"); - preferences.putString("STA_PASS", "WindyRidge137"); - if (preferences.getString("STA_SSID", "none") == "none") - preferences.putString("STA_SSID", "EQGnet"); // Default Home Network - if (preferences.getString("STA_PASS", "none") == "none") - preferences.putString("STA_PASS", "EQGconnect"); - ssid = preferences.getString("STA_SSID", "none"); - pass = preferences.getString("STA_PASS", "none"); - preferences.end(); - - WiFi.mode(WIFI_STA); - WiFi.disconnect(); - WiFi.begin(ssid.c_str(), pass.c_str()); - int i = 0; - while ((WiFi.status() != WL_CONNECTED) && (i++ < 50)) { - delay(1000); - dbgSerial.print(i); dbgSerial.print(", ssid: "); dbgSerial.print(ssid.c_str()); dbgSerial.print(", pass: "); dbgSerial.println(pass.c_str()); - } - if (i >= 50) { - WiFi.begin("EQGnet", "EQGconnect"); - while (WiFi.status() != WL_CONNECTED) { - delay(100); - dbgSerial.print("!"); - } - } - dbgSerial.print("ssid: "); dbgSerial.println(ssid.c_str()); - dbgSerial.print("pass: "); dbgSerial.println(pass.c_str()); - dbgSerial.print("IP: "); dbgSerial.println(WiFi.localIP().toString().c_str()); - dbgSerial.println(" connected"); - if (!MDNS.begin("eqmodwifi")) { - Serial.println("Error setting up MDNS responder!"); - while (1) { - delay(1000); - } - } - Serial.println("mDNS responder started"); - dbgSerial.print("ssid: "); dbgSerial.println(ssid.c_str()); - dbgSerial.print("pass: "); dbgSerial.println(pass.c_str()); - dbgSerial.print("IP: "); dbgSerial.println(WiFi.softAPIP().toString().c_str()); - // Load 'server.on' responses - AsyncServerResponseSetup(); - WiFi.scanNetworks(); - dbgSerial.print("ssid: "); dbgSerial.println(ssid.c_str()); - dbgSerial.print("pass: "); dbgSerial.println(pass.c_str()); - dbgSerial.print("IP: "); dbgSerial.println(WiFi.softAPIP().toString().c_str()); - // attach filesystem root at URL /fs - if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) { - dbgSerial.println("SPIFFS Mount Failed, SPIFF formatted"); - } - else - dbgSerial.println("SPIFFS Mounted .. "); - writeFile(SPIFFS, "/www/index.htm", EQ2HBX_Version.c_str()); - listDir(SPIFFS, "/", 0); - - server.serveStatic("/", SPIFFS, "/www/").setDefaultFile("index.htm"); - - // Catch-All Handlers - // Any request that can not find a Handler that canHandle it - // ends in the callbacks below. - server.onNotFound(onRequest); - server.onFileUpload(onUpload); - server.onRequestBody(onBody); - - server.begin(); - // Add service to MDNS-SD - MDNS.addService("_http", "_tcp", 80); - MDNS.addService("_osc", "_udp", localUdpPort); - //browseService("http", "tcp"); - } - - if (!UDPFlag) { - // ESP_NOW mode (EQMODWiFi responds to MAC protocol) - dbgSerial.println("ESP_NOW Mode"); - InitESPNow(); - dbgSerial.println("ESPNOW2SerialServer"); - dbgSerial.print("Mount soft mac: "); dbgSerial.println(WiFi.softAPmacAddress()); - dbgSerial.print("Mount hard mac: "); dbgSerial.println(WiFi.macAddress()); -// esp_now_set_self_role(ESP_NOW_ROLE_COMBO); - esp_now_register_recv_cb(recvCallBack); - esp_now_register_send_cb(sendCallBack); - } - else { - dbgSerial.println("UDP Mode"); - udp.begin(localUdpPort); - dbgSerial.println("UDP2SerialServer"); - if (APFlag) - dbgSerial.printf("AP : "); - else - dbgSerial.printf("STA: "); - dbgSerial.printf("Now listening at IP %s, UDP port %d\n", WiFi.softAPIP().toString().c_str(), localUdpPort); - } - - TxDIndex = 0; - sendWiFi.len = 0; - recvWiFi.len = 0; -} - -// ------------------------------------------------------------------------------------------- - -bool HBXCheckRx() { - if (UDPFlag) { -// UDP - SynScanPro UDP - recvWiFi.len = udp.parsePacket(); - if (recvWiFi.len > 0) { - // receive incoming UDP packets - recvWiFi.len = udp.read(recvWiFi.text, 250); - if (recvWiFi.len > 0) { - recvWiFi.text[recvWiFi.len] = 0; // Null terminate - -// dbgSerial.print("RxUDP - len: "); -// dbgSerial.print(recvWiFi.len); -// dbgSerial.print(", data: "); - // dbgSerial.println(recvWiFi.text); - - } - } - } - if (recvWiFi.len > 0) { // Send data to mount Input data buffer for processing - putRxDataIntoMountInputBuffer(); - return true; // Data received from UDP or ESP_NOW callback - } - else - return false; // No Data received -} - -void HBXCheckTx() { - if (UDPFlag) { - // Get data to send to SynScanPro via UDP into WiFi buffer - getTxDataFromMountOutputBuffer(); - // send back a reply, to the IP address and port we got the packet from - if (sendWiFi.len > 0) { - -// dbgSerial.print("TxUDP - len: "); -// dbgSerial.print(sendWiFi.len); -// dbgSerial.print(", data: "); -// dbgSerial.println(sendWiFi.text); - - udp.beginPacket(udp.remoteIP(), udp.remotePort()); - memcpy(sendWiFi8, &sendWiFi.text, sendWiFi.len); - udp.write(sendWiFi8, sendWiFi.len); - udp.endPacket(); - } - sendWiFi.len = 0; - TxDIndex = 0; - } - else { - // Get data to send to ESP_NOW - EQMOD/SynScanPro Serial WiFi - if (Connected) { - getTxDataFromMountOutputBuffer(); - if (sendWiFi.len > 0) - sendData(&serial_peer); - } - } -} diff --git a/Software/EQG2HBXE32/src/Hardware.h b/Software/EQG2HBXE32/src/Hardware.h deleted file mode 100644 index 2bc407e..0000000 --- a/Software/EQG2HBXE32/src/Hardware.h +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************** - Hardware Definitions - ==================== - *********************************************************/ -#pragma once - -#define mESP32 - - // Configuration for WiFi interface - // ================================ - - // UDP allows communications with the Skywatcher SynScan app on Laptop, Tablet or phone - // ESPNOW is alocal area wifi net .. TODO - // AP provides a n access point in absence of Telscope wifi network - // STA enables use of wifi credentials to log on to Telescope wifi network - -#define SelectUDP // Either UDP or ESPNOW -#undef SelectAP // Either AP or STA - - // Serial port definitions for HBX interface - // ========================================= - -#ifdef mESP32 -#define dbgSerial Serial -#define EQGSerial Serial2 - -#ifdef BTSerial - #define EQGBluetooth SerialBT -#endif -#endif -// Pin definitions for ESP32-HBX interface -// ======================================= - -#ifdef mESP32 - // 8Pin RJ - // ======= - // Pin8 Gnd -#define HDAAz 25 // Pin7 on HBX interface -#define HCLAz 26 // Pin6 on HBX interface -#define HDAAlt 14 // Pin5 on HBX interface -#define HCLAlt 27 // Pin4 on HBX interface -#define HDAAux 18 // Pin3 on HBX interface -#define HCLAux 19 // Pin2 on HBX interface - // Pin1 Vbat - - // 4Pin RJ - // ======= - // Pin1 Gnd -#define HDAAux 18 // Pin2 on HBX interface -#define HCLAux 19 // Pin3 on HBX interface - // Pin4 Vbat - -#define H2C_INPUTPU INPUT_PULLUP // Set pin data input mode -#define H2C_INPUT INPUT // Set pin data input mode -#define H2C_OUTPUT OUTPUT // Set pin data output - -// Pin definitions for LED indicators -// ================================== -#define EQGLED 21 -#define ETXLED 22 - -#endif