Delete Software/EQG2HBXE32/src directory

pull/5/head
ozarchie 2021-07-23 18:01:01 +10:00 zatwierdzone przez GitHub
rodzic 63eaf9a14a
commit 65de951b03
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
13 zmienionych plików z 0 dodań i 3971 usunięć

Wyświetl plik

@ -1,209 +0,0 @@
/*
* Copyright 2017, 2018, 2020 John Archbold
*/
/********************************************************
EQG2HBX program definitions
===========================
*********************************************************/
#pragma once
#include <FS.h> // Include the SPIFFS library
#include <Preferences.h>
#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

Wyświetl plik

@ -1,256 +0,0 @@
/**@file*/
/*
Name: EQG2HBXE32.ino
Created: 2018-09-01 10:07:17 AM
Author: JOHNWIN10PRO\John
*/
#include <Arduino.h>
#include <stdio.h>
#include <dummy.h>
#include "Hardware.h"
#include <FS.h> // Include the SPIFFS library
#include <Preferences.h>
#include "ESP32Ticker.h"
//#include <BluetoothSerial.h>
#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()

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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);
*/

Wyświetl plik

@ -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(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); 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(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); 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(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); 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(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); 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(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); 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(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); 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(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); 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("");
*/
}
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -1,12 +0,0 @@
#pragma once
/**************************************************************
* SPIFFS filesystem
* Only invoked in STA mode
*/
#include <EEPROM.h>
#include <FS.h>
#include <SPIFFS.h>
#include <SPIFFSEditor.h>
#define FORMAT_SPIFFS_IF_FAILED true

Wyświetl plik

@ -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");
}
}

Wyświetl plik

@ -1,117 +0,0 @@
/*
* Copyright 2017, 2018, 2020 John Archbold
*/
/********************************************************
EQG Serial WiFi
===============
*********************************************************/
#pragma once
#include <WiFi.h>
#include <AsyncUDP.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Update.h>
#include <esp_now.h>
#include <ESPmDNS.h>
/**************************************************************
* 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);

Wyświetl plik

@ -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 <FS.h> // 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);
}
}
}

Wyświetl plik

@ -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