kopia lustrzana https://github.com/ozarchie/EQMOD-ETX
INITIAL RELEASE
rodzic
c9ff98157f
commit
0bc6cba53c
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright 2017, 2018 John Archbold
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
/********************************************************
|
||||
EQG2HBX program definitions
|
||||
===========================
|
||||
*********************************************************/
|
||||
|
||||
#ifndef EQG2HBX
|
||||
#define EQG2HBX
|
||||
|
||||
// Time related libararies
|
||||
#include <Ticker.h>
|
||||
#include <TimeLord.h> //https://github.com/probonopd/TimeLord
|
||||
//#include <TimeLib.h> //https://github.com/PaulStoffregen/Time
|
||||
//#include <TimeAlarms.h> //https://github.com/PaulStoffregen/TimeAlarms
|
||||
|
||||
|
||||
// Pin definitions for LED indicators
|
||||
// ==================================
|
||||
#ifdef m2560
|
||||
#define AzLED 7 // Mega2560 D7
|
||||
#define AltLED 6 // Mega2560 D6
|
||||
#endif
|
||||
#ifdef mESP32
|
||||
#define AzLED 22
|
||||
#define AltLED 21
|
||||
#endif
|
||||
|
||||
// Jumpers to run test
|
||||
// ==============================
|
||||
#ifdef m2560
|
||||
#define TESTHBX 9 // Mega2560 D2
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
#define TESTHBX 13 // GPI35
|
||||
#endif
|
||||
|
||||
// Pin definitions for ESP_NOW interface
|
||||
// =====================================
|
||||
|
||||
#ifdef mESP32
|
||||
#define PROTOCOL 32 // GPIO32
|
||||
#define MODE 33 // GPIO33
|
||||
#define SERIAL 14 // GPI34
|
||||
#endif
|
||||
|
||||
/**************************************************************
|
||||
* Common variables
|
||||
**************************************************************/
|
||||
Preferences preferences;
|
||||
unsigned long DelayTimer; // Delay timer
|
||||
unsigned long StatusTimer; // H2X delay timer
|
||||
unsigned long StatusTime; // H2X interval time
|
||||
Ticker AlarmDebugPrint;
|
||||
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
|
||||
|
||||
#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
|
||||
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 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 ETXSpeedCommand; // Current ETX Speed command
|
||||
long Speed; // Move speed
|
||||
long TargetSpeed; // Target Move speed
|
||||
char SpeedState; // Slowdown/speedup state
|
||||
long Position; // Current position
|
||||
long Target; // Current target delta
|
||||
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 = 240 * SIDEREALRATE
|
||||
|
||||
unsigned long SIDEREALRATE; // Constants
|
||||
unsigned long SOLARRATE;
|
||||
unsigned long LUNARRATE;
|
||||
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
|
||||
} axis_values;
|
||||
|
||||
unsigned char telescope = 0; // Default telescope (ETX60)
|
||||
|
||||
axis_values ratio[16][2] = // 16 scopes, Az, Alt
|
||||
{
|
||||
{{36, 91.1458333, 1, 94}, {36, 157.5, 1, 58}}, // ETX60/70/80
|
||||
{{256, 50, 1, 350}, {256, 50, 1, 350}}, // LX200
|
||||
{{500, 36, 1, 225}, {500, 36, 1, 225}}, // LX850
|
||||
{{256, 50, 1, 180}, {256, 50, 1, 180}}, // LX200/400/500
|
||||
|
||||
{{108, 53.5859375, 1, 154}, {108, 53.5859375, 1, 154}}, // LX90, LT, LX80AltAz
|
||||
{{108, 50, 1, 144}, {108, 50, 1, 144}}, // LXD55/75, LX70-GTS
|
||||
{{36, 205.3330000, 1, 60}, {36, 205.3330000, 1, 60}}, // ETX-xxx, DS-xxx
|
||||
{{36, 91.1458333, 1, 83}, {36, 144.7362076, 1, 66}}, // ??
|
||||
|
||||
{{36, 205.3330000, 1, 144}, {36, 205.3330000, 1, 144}}, // DS external
|
||||
{{36, 410.6660000, 1, 100}, {36, 157.5, 1, 58}}, // DH external/114EQs/4504s
|
||||
{{36, 91.1458333, 1, 94}, {36, 157.5, 1, 58}}, // ETX60/70/80
|
||||
{{36, 91.1458333, 1, 94}, {36, 157.5, 1, 58}}, // ETX60/70/80
|
||||
|
||||
{{36, 91.1458333, 1, 94}, {36, 157.5, 1, 58}}, // ETX60/70/80
|
||||
{{36, 91.1458333, 1, 94}, {36, 157.5, 1, 58}}, // ETX60/70/80
|
||||
{{36, 91.1458333, 1, 94}, {36, 157.5, 1, 58}}, // ETX60/70/80
|
||||
{{36, 91.1458333, 1, 94}, {36, 157.5, 1, 58}} // ETX60/70/80
|
||||
};
|
||||
|
||||
unsigned long PreviousTime; // Used in HBX Monitor, Testing
|
||||
|
||||
// Testing only
|
||||
unsigned char TestCount;
|
||||
unsigned long TestLoopTime;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
// Visual Micro is in vMicro>General>Tutorial Mode
|
||||
//
|
||||
/*
|
||||
Name: EQG2HBXE32.ino
|
||||
Created: 2018-09-01 10:07:17 AM
|
||||
Author: JOHNWIN10PRO\John
|
||||
*/
|
||||
|
||||
/********************************************************
|
||||
Initialize HBX, translate EQG to HBX
|
||||
====================================
|
||||
*********************************************************/
|
||||
#undef m2560
|
||||
|
||||
|
||||
|
||||
|
||||
#include <Preferences.h>
|
||||
#include <dummy.h>
|
||||
#define mESP32
|
||||
#define mTEST
|
||||
|
||||
#include "HBXWiFiServer.h"
|
||||
#include "EQGProtocol.h"
|
||||
#include "ETXProtocol.h"
|
||||
#include "HBXComms.h"
|
||||
#include "EQG2HBX.h" // All the declared variables
|
||||
|
||||
|
||||
// Define User Types below here or use a .h file
|
||||
//
|
||||
|
||||
|
||||
// Function Prototypes
|
||||
//
|
||||
void UpdateETX(void);
|
||||
void CheckETXState(void);
|
||||
void TimerDelaymS(unsigned long );
|
||||
void TimerDelayuS(unsigned int);
|
||||
|
||||
|
||||
// Functions
|
||||
//
|
||||
/**************************************************************************************************
|
||||
* Read / Update ETX - Timer Driven
|
||||
**************************************************************************************************/
|
||||
void UpdateETX(void) {
|
||||
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
Multiple 1mS delay
|
||||
***********************************************/
|
||||
|
||||
void TimerDelaymS(unsigned long d) {
|
||||
delay(d);
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
Multiple 1uS delay
|
||||
***********************************************/
|
||||
|
||||
void TimerDelayuS(unsigned int d) {
|
||||
delayMicroseconds(d);
|
||||
}
|
||||
|
||||
void CheckETXState(void) {
|
||||
/**************************************************************************************************
|
||||
* Check ETXState
|
||||
**************************************************************************************************/
|
||||
HBXGetStatus(AzMotor);
|
||||
HBXGetStatus(AltMotor);
|
||||
|
||||
ETXState(AzMotor); // Check the Az motor state
|
||||
ETXState(AltMotor); // Check the Alt motor state
|
||||
}
|
||||
|
||||
// =======================================================================================================
|
||||
void setup()
|
||||
{
|
||||
int i, j, k;
|
||||
bool b;
|
||||
|
||||
#ifdef mESP32
|
||||
dbgSerial.begin(115200); // debug
|
||||
EQGSerial.begin(9600, SERIAL_8N1, 18, 19); // EQG via serial or WiFi
|
||||
delay(10);
|
||||
#endif
|
||||
|
||||
dbgSerial.println("ETX V2.04, ETX-EQMOD V1.03");
|
||||
DelayTimer = micros(); // Initialize timers, counts
|
||||
StatusTimer = DelayTimer;
|
||||
StatusTime = DelayTimer;
|
||||
EQGErrorValue = 0;
|
||||
|
||||
#ifdef mESP32
|
||||
HBXWiFiSetup();
|
||||
#endif
|
||||
|
||||
pinMode(AzLED, OUTPUT);
|
||||
pinMode(AltLED, OUTPUT);
|
||||
digitalWrite(AzLED, LOW);
|
||||
digitalWrite(AltLED, LOW);
|
||||
pinMode(TESTHBX, INPUT_PULLUP); // Initialize Mode jumpers
|
||||
digitalWrite(TESTHBX, HIGH); // Use internal PUR, write 1 to O/P
|
||||
|
||||
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
|
||||
|
||||
// **************************
|
||||
// Check for HBX Testing Mode
|
||||
// ==========================
|
||||
dbgSerial.print("digitalRead(TESTHBX) : ");
|
||||
dbgSerial.println(digitalRead(TESTHBX));
|
||||
while (digitalRead(TESTHBX) == 0) { // Check if test jumper installed
|
||||
dbgSerial.print("digitalRead(TESTHBX) : ");
|
||||
dbgSerial.println(digitalRead(TESTHBX));
|
||||
HBXTestLoop(); // Execute test code until jumper removed
|
||||
};
|
||||
|
||||
dbgSerial.println("HBX Initialization");
|
||||
AzInitialise();
|
||||
AltInitialise();
|
||||
PrintRatioValues(telescope);
|
||||
PrintHbxValues(AzMotor);
|
||||
PrintHbxValues(AltMotor);
|
||||
|
||||
// Initialize HBX communications as outputs
|
||||
// It will use H2X communications
|
||||
HCL1Talk(); // Set for Talking on RAClk
|
||||
HCL2Talk(); // Set for Talking on DECClk
|
||||
HDAListen();
|
||||
TimerDelaymS(STARTTIME);
|
||||
|
||||
// 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)
|
||||
|
||||
dbgSerial.print("Get Motor Type: ");
|
||||
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(axis[AltMotor].MotorType);
|
||||
|
||||
dbgSerial.println("Check Calibrate LEDs");
|
||||
|
||||
preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace
|
||||
|
||||
// Handle position sensors LED current
|
||||
// -----------------------------------
|
||||
if (preferences.getUChar("AzLEDI", 0) == 0) { // If it does not exist, return 0
|
||||
// Calibrate motors
|
||||
if (HBXSendCommand(CalibrateLED, AzMotor));
|
||||
TimerDelaymS(2500);
|
||||
if (HBXSendCommand(CalibrateLED, AltMotor))
|
||||
TimerDelaymS(2500);
|
||||
// Read the calibration
|
||||
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.println(axis[AltMotor].HBXLEDI);
|
||||
// Save it to preferences
|
||||
preferences.putUChar("AzLEDI", axis[AzMotor].HBXLEDI);
|
||||
preferences.putUChar("AltLEDI", axis[AltMotor].HBXLEDI);
|
||||
}
|
||||
// Read stored LED currents
|
||||
axis[AzMotor].HBXLEDI = preferences.getUChar("AzLEDI", 0);
|
||||
axis[AltMotor].HBXLEDI = preferences.getUChar("AltLEDI", 0);
|
||||
preferences.end();
|
||||
|
||||
// Set the MC 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 - which were initialised to 0
|
||||
dbgSerial.println("Reset any ETX offset bytes");
|
||||
if (HBXSendCommand(SetOffset, AzMotor))
|
||||
HBXSend2Bytes(AzMotor);
|
||||
TimerDelaymS(CMNDTIME);
|
||||
if (HBXSendCommand(SetOffset, AltMotor))
|
||||
HBXSend2Bytes(AltMotor);
|
||||
TimerDelaymS(CMNDTIME);
|
||||
|
||||
// Stop the motors (RA and DEC)
|
||||
dbgSerial.println("Stop motors");
|
||||
do {
|
||||
P1 = 0;
|
||||
if (HBXSendCommand(Stop, AzMotor)) P1 += 1;
|
||||
if (HBXSendCommand(Stop, AltMotor)) P1 += 1;
|
||||
} while (P1 < 2);
|
||||
|
||||
// Read status
|
||||
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 motors status and state
|
||||
if ((micros() - StatusTimer) > (ETXDELAY * 1000)) { // ~6.55mS
|
||||
StatusTimer = micros();
|
||||
CheckETXState();
|
||||
}
|
||||
|
||||
// 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
|
||||
HBXCheckTx();
|
||||
EQGTxoPtr &= EQGMASK;
|
||||
}
|
||||
// TimerDelaymS(1);
|
||||
// yield();
|
||||
}
|
||||
|
||||
// End loop()
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28010.2003
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EQG2HBXE32", "EQG2HBXE32.vcxproj", "{C5F80730-F44F-4478-BDAE-6634EFC2CA88}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ESPAsyncWebServer-master", "..\libraries\ESPAsyncWebServer-master\ESPAsyncWebServer-master.vcxitems", "{C275F5BA-F9BA-4E60-AB38-E2C1239F937C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {41E70D0C-14E5-42F0-A4A9-88EE3BDA9362}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="EQG2HBXE32.ino" />
|
||||
<None Include="EQGProtocol.ino">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="ETXProtocol.ino">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="HBXComms.ino">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="HBXWiFiServer.ino">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="HBXzTest.ino">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="__vm\.EQG2HBXE32.vsarduino.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EQG2HBX.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EQGProtocol.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ETXProtocol.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HBXComms.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HBXWiFiServer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright 2017, 2018 John Archbold
|
||||
*/
|
||||
|
||||
/********************************************************
|
||||
EQG Protocol function definitions
|
||||
=================================
|
||||
*********************************************************/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifndef EQGProtocol
|
||||
#define EQGProtocol
|
||||
|
||||
#define CR 0x0d
|
||||
#define LF 0x0a
|
||||
|
||||
float SIDEREALSECS = 86164.091; // Some astronomical constants
|
||||
float SOLARSECS = 86400;
|
||||
float LUNARSECS = 89309;
|
||||
|
||||
|
||||
#define EQG_CMNDSTART 0x01
|
||||
#define EQG_WAITFORCR 0x77
|
||||
#define EQG_INTERPRET 0x78
|
||||
|
||||
/*
|
||||
// Get Motor Controller Version
|
||||
// :e1[0D]
|
||||
// =llhhMM[0D]
|
||||
// ============
|
||||
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
|
||||
*/
|
||||
// :qm
|
||||
|
||||
// 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
|
||||
/*
|
||||
// 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;
|
||||
*/
|
||||
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
|
||||
// E
|
||||
// F
|
||||
// EQ6 returns !0
|
||||
// ABCDEF
|
||||
// AZEQ5 =0B6000 at boot
|
||||
// AZEQ6 =0B3000
|
||||
// EQ8 =076000
|
||||
|
||||
//#define EQGVERSION 0x020400 // Pretend EQ6/5
|
||||
//#define EQGVERSION 0x030100 // Pretend EQ3-AzEq
|
||||
#define EQGVERSION 0x020600 // Pretend EQ5-AzEq
|
||||
// EFCDAB
|
||||
#define EQGASSETS 0x008008 // AZ/EQ and Polar LED
|
||||
|
||||
// :I := ( :b * 1296000 / :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 / 1,296,000
|
||||
|
||||
// Speed = g*(b*129600/a)/I
|
||||
// ==============================
|
||||
// IVALUE = (axis[EQGMOTOR].bVALUE * 1296000) / axis[EQGMOTOR].STEPSPER360)
|
||||
|
||||
#define EQG_AzCENTRE ETX_AzCENTRE
|
||||
#define EQG_AltCENTRE ETX_AltCENTRE
|
||||
#define EQG_gVALUE 0x000010
|
||||
|
||||
|
||||
#define EQGMAXIMUMSPEED 12 // 0x0C
|
||||
|
||||
// EQG 'G' Command - SET move parameters
|
||||
#define DIRECTION 0x00000001 // Increasing(0) Decreasing(1)
|
||||
#define HEMISPHERE 0x00000002 // North(0) South(1)
|
||||
|
||||
// EQG 'f' Command - GET Motor status bit definitions
|
||||
// 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 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: nibble 1
|
||||
#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)
|
||||
|
||||
void EQGState(void);
|
||||
void EQGError(unsigned char);
|
||||
void EQGAction(void);
|
||||
|
||||
void TimerDelaymS(unsigned long);
|
||||
|
||||
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 puthexn(unsigned char);
|
||||
void puthexb(unsigned char);
|
||||
void puthexw(unsigned int);
|
||||
void puthexl(unsigned long);
|
||||
void putdecn(unsigned char);
|
||||
void putdecb(unsigned char);
|
||||
void putdecw(unsigned int);
|
||||
void putdecl(unsigned long);
|
||||
#endif
|
||||
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright 2017, 2018 John Archbold
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
|
||||
/********************************************************
|
||||
EQG Protocol function definitions
|
||||
=================================
|
||||
*********************************************************/
|
||||
#ifndef ETXProtocol
|
||||
#define ETXProtocol
|
||||
|
||||
#define MotorAz 0x01 // Pin3 on HBX interface
|
||||
#define MotorAlt 0x02 // Pin5 on HBX interface
|
||||
|
||||
#define AzMotor MotorAz
|
||||
#define 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 ResetH2X 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
|
||||
|
||||
#define EEPROMAzLEDI 0x01 // EEPROM Storage
|
||||
#define EEPROMAltLEDI 0x02
|
||||
#define EEPROMMotor 0x03 // MOTOR TYPE
|
||||
|
||||
const float ETX60PERIOD = 152.587891; // (1/6.5536mS)
|
||||
|
||||
#define ETX_AzCENTRE 0x00800000 // HA
|
||||
#define ETX_AltCENTRE 0x00800000 // DEC
|
||||
|
||||
const float MeadeSidereal = 6460.0900; // Refer Andrew Johansen
|
||||
const float SiderealArcSecs = 15.041069; // Sidereal arcsecs/sec
|
||||
const float ArcSecs360 = 1296000; // Arcsecs / 360
|
||||
|
||||
|
||||
#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
|
||||
|
||||
#define H2X_INPUTPU INPUT_PULLUP // Set pin data input mode
|
||||
#define H2X_INPUT INPUT // Set pin data input mode
|
||||
#define H2X_OUTPUT OUTPUT // Set pin data output
|
||||
|
||||
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);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,606 @@
|
|||
/*
|
||||
* Copyright 2017, 2018 John Archbold
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
|
||||
/********************************************************
|
||||
ETX Protocol related functions
|
||||
==============================
|
||||
*********************************************************/
|
||||
|
||||
bool ETXState(unsigned char Motor) {
|
||||
long distance;
|
||||
int s1;
|
||||
|
||||
switch(axis[Motor].ETXMotorState) {
|
||||
|
||||
case ETXIdle:
|
||||
break;
|
||||
|
||||
case ETXCheckStartup:
|
||||
if (axis[Motor].ETXMotorStatus & MOVEAXIS) { // Start moving
|
||||
|
||||
dbgSerial.println(""); dbgSerial.print("ETXCheckStartup - Motor: "); dbgSerial.print(Motor); dbgSerial.print(" MOVE");
|
||||
|
||||
distance = axis[Motor].Target - axis[Motor].Position; // Distance to target
|
||||
if (axis[Motor].ETXMotorStatus & MOVEDECR) // If it is decreasing
|
||||
distance = TwosComplement(distance);
|
||||
dbgSerial.print(" Distance: "); dbgSerial.print(distance);
|
||||
|
||||
if (axis[Motor].ETXMotorStatus & MOVEHIGH) { // High Speed Slew ?
|
||||
if (axis[Motor].ETXMotorStatus & MOVESLEW) {
|
||||
axis[Motor].ETXMotorState = ETXSlewMotor; // Move axis using high speed multiplier
|
||||
|
||||
dbgSerial.print(" HIGH SLEW");
|
||||
|
||||
}
|
||||
}
|
||||
else { // GoTo or Low Speed Slew
|
||||
axis[Motor].ETXMotorState = ETXCheckSpeed;
|
||||
|
||||
dbgSerial.print(" GOTO");
|
||||
|
||||
}
|
||||
|
||||
if (axis[Motor].MotorControl & GoToHBX) { // Check GoTo?
|
||||
if (axis[Motor].MotorControl & SlewHBX) { // May need to slew for large changes
|
||||
axis[Motor].ETXMotorState = ETXSlewMotor; // Slew to M-point
|
||||
|
||||
dbgSerial.print(" SLEW");
|
||||
|
||||
}
|
||||
else {
|
||||
axis[Motor].ETXMotorState = ETXCheckSpeed;
|
||||
axis[Motor].TargetSpeed = axis[Motor].DEGREERATE1; // Set initial speed for 'HIGH SPEED GOTO'
|
||||
if (distance < axis[Motor].OneDegree)
|
||||
axis[Motor].TargetSpeed = (axis[Motor].TargetSpeed >> 1);
|
||||
if (distance < (axis[Motor].OneDegree >> 2))
|
||||
axis[Motor].TargetSpeed = (axis[Motor].TargetSpeed >> 1);
|
||||
axis[Motor].Speed = 0; // Starting from 0
|
||||
|
||||
dbgSerial.print(" STEP");
|
||||
}
|
||||
if (distance < OffsetMax) { // Check for really small moves (< 16 steps)
|
||||
axis[Motor].ETXMotorState = ETXMotorEnd; // Use Adjust offset
|
||||
|
||||
dbgSerial.print(" OFFSET");
|
||||
}
|
||||
if (distance > (axis[Motor].OneDegree << 3)) { // Always slew for > 8 degrees
|
||||
axis[Motor].ETXMotorState = ETXSlewMotor;
|
||||
dbgSerial.print(" GoToSLEW");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ETXSlewMotor:
|
||||
|
||||
dbgSerial.println(""); dbgSerial.print("ETXSlewMotor Motor: "); dbgSerial.print(Motor); dbgSerial.print(" SLEW Cmd: ");
|
||||
|
||||
if (Motor == MotorAz) digitalWrite(AzLED, HIGH); // Turn on the LED
|
||||
else digitalWrite(AltLED, HIGH);
|
||||
|
||||
HBXSendCommand(Stop, Motor); // Stop the motor
|
||||
|
||||
if (axis[Motor].ETXMotorStatus & MOVEDECR) // -ve
|
||||
axis[Motor].Command = SlewReverse;
|
||||
else
|
||||
axis[Motor].Command = SlewForward;
|
||||
dbgSerial.print(axis[Motor].Command, HEX);
|
||||
|
||||
// Send the command to the ETX
|
||||
HBXSendCommand(axis[Motor].Command, Motor); // SLEW
|
||||
|
||||
axis[Motor].EQGMotorStatus |= MOVEAXIS; // Tell EQx
|
||||
axis[Motor].Speed = axis[Motor].DEGREERATE1; // Set "current speed" for later speed checks
|
||||
|
||||
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].Speed = axis[Motor].DEGREERATE1;
|
||||
axis[Motor].SpeedState = 0;
|
||||
dbgSerial.print(" GoToSLEW END");
|
||||
}
|
||||
}
|
||||
if (axis[Motor].MotorControl & SlewHBX) { // Slewing to M-point
|
||||
axis[Motor].Speed = axis[Motor].DEGREERATE1; // Indicate current speed (approx)
|
||||
axis[Motor].ETXMotorState = ETXCheckSlowDown; // Slew until SlowDown
|
||||
}
|
||||
|
||||
dbgSerial.println(""); dbgSerial.print("ETXSlewMotor Motor: "); dbgSerial.print(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(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX);
|
||||
dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX);
|
||||
dbgSerial.print(" Speed: "); dbgSerial.print(axis[Motor].Speed, HEX);
|
||||
dbgSerial.print(" TargetSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX);
|
||||
dbgSerial.print(" SpeedState: "); dbgSerial.println(axis[Motor].SpeedState, HEX);
|
||||
break;
|
||||
|
||||
case ETXStepMotor:
|
||||
|
||||
dbgSerial.println(""); dbgSerial.print("ETXStepMotor Motor: "); dbgSerial.print(Motor); dbgSerial.print(" STEP Cmd: ");
|
||||
|
||||
if (Motor == MotorAz) digitalWrite(AzLED, HIGH); // Turn on the LED
|
||||
else digitalWrite(AltLED, HIGH);
|
||||
|
||||
if (axis[Motor].MotorControl & SpeedHBX) // Stepping, High or Low speed
|
||||
axis[Motor].Command = SpeedStart; // Use SpeedStart to start motion
|
||||
else {
|
||||
axis[Motor].Command = SpeedChnge; // Use SpeedChnge once started
|
||||
}
|
||||
axis[Motor].MotorControl &= ~SpeedHBX; // Clear flag
|
||||
// Set the speed, and direction
|
||||
// ----------------------------
|
||||
P1 = axis[Motor].Speed;
|
||||
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;
|
||||
|
||||
dbgSerial.print(axis[Motor].Command, HEX);
|
||||
|
||||
// Send the command
|
||||
// ----------------
|
||||
if (HBXSendCommand(axis[Motor].Command, Motor)) // Command OK?
|
||||
HBXSend3Bytes(Motor); // Send the speed
|
||||
axis[Motor].EQGMotorStatus |= MOVEAXIS; // Tell EQx
|
||||
|
||||
axis[Motor].ETXMotorState = ETXCheckSpeed; // 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].Speed == axis[Motor].TargetSpeed)
|
||||
axis[Motor].ETXMotorState = ETXCheckPosition;
|
||||
}
|
||||
else if (axis[Motor].Speed == 0) { // Stop issued
|
||||
axis[Motor].ETXMotorState = ETXStopMotor;
|
||||
}
|
||||
else if (axis[Motor].Speed == axis[Motor].TargetSpeed) { // Else slewing at speed
|
||||
axis[Motor].ETXMotorState = ETXIdle;
|
||||
}
|
||||
break;
|
||||
|
||||
case ETXCheckSlowDown:
|
||||
// Check if Slowdown reached
|
||||
// Calculate absolute distance to slowdown
|
||||
// ---------------------------------------
|
||||
|
||||
dbgSerial.println(""); dbgSerial.print("ETXCheckSlowDown Motor: "); dbgSerial.print(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(", SD: "); dbgSerial.print(axis[Motor].SlowDown, HEX);
|
||||
dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX);
|
||||
dbgSerial.print(" Speed: "); dbgSerial.print(axis[Motor].Speed, HEX);
|
||||
dbgSerial.print(" TargetSpeed: "); 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:
|
||||
// Speeding Up
|
||||
// ===========
|
||||
/*
|
||||
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(Motor);
|
||||
dbgSerial.print(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); dbgSerial.print("> ");
|
||||
dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX);
|
||||
dbgSerial.print(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX);
|
||||
dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX);
|
||||
dbgSerial.print(" iSpeed: "); dbgSerial.print(axis[Motor].Speed, HEX);
|
||||
dbgSerial.print(" iTargetSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX);
|
||||
|
||||
axis[Motor].ETXMotorState = ETXStepMotor; // Preset set speed as next action
|
||||
|
||||
// Ramp up to speed
|
||||
if ((axis[Motor].TargetSpeed != 0) && (axis[Motor].TargetSpeed > axis[Motor].Speed)) {
|
||||
if ((axis[Motor].TargetSpeed - axis[Motor].Speed) > (axis[Motor].SIDEREALRATE << 6)) { // 64x sidereal
|
||||
axis[Motor].Speed += ((axis[Motor].TargetSpeed - axis[Motor].Speed) >> 1); // Ramp up approx .5 difference
|
||||
// while(!(HBXSendCommand(Stop, Motor))); // Stop the motor command
|
||||
axis[Motor].MotorControl &= ~SpeedHBX; // Use 0x00 command
|
||||
}
|
||||
else {
|
||||
axis[Motor].Speed = axis[Motor].TargetSpeed;
|
||||
while(!(HBXSendCommand(Stop, Motor))); // Stop the motor command
|
||||
axis[Motor].MotorControl |= SpeedHBX; // Use 0x01 command
|
||||
}
|
||||
}
|
||||
// Ramp down to speed
|
||||
else if ((axis[Motor].TargetSpeed != 0) && (axis[Motor].Speed > axis[Motor].TargetSpeed)) {
|
||||
axis[Motor].Speed -= ((axis[Motor].Speed - axis[Motor].TargetSpeed) >> 2); // Approx .75
|
||||
if ((axis[Motor].Speed - axis[Motor].TargetSpeed) <= (axis[Motor].SIDEREALRATE << 7)) {
|
||||
axis[Motor].Speed = 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
|
||||
}
|
||||
}
|
||||
// Ramp down to stop
|
||||
else if ((axis[Motor].TargetSpeed == 0) && (axis[Motor].Speed != 0)) {
|
||||
if (axis[Motor].ETXMotorStatus & MOVESLEW) {
|
||||
axis[Motor].ETXMotorState = ETXStopMotor;
|
||||
}
|
||||
else if (axis[Motor].Speed >= (axis[Motor].SIDEREALRATE << 7)) { // Ramp down to 128x sidereal
|
||||
axis[Motor].Speed -= (axis[Motor].Speed >> 2); // Approximately .75
|
||||
while(!(HBXSendCommand(Stop, Motor))); // Stop the motor command
|
||||
axis[Motor].MotorControl |= SpeedHBX; // Use 0x01 command
|
||||
}
|
||||
else
|
||||
axis[Motor].ETXMotorState = ETXStopMotor; // OK, Stop the motor
|
||||
}
|
||||
|
||||
// Switch to position check, when we are at speed - check done in ETXStepMotor
|
||||
|
||||
dbgSerial.print(" oSpeed: "); dbgSerial.print(axis[Motor].Speed, HEX);
|
||||
dbgSerial.print(" oTargetSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX);
|
||||
|
||||
break;
|
||||
|
||||
case ETXCheckPosition:
|
||||
// Check if Target acquired
|
||||
// ------------------------
|
||||
|
||||
// Calculate absolute distance to target
|
||||
// -------------------------------------
|
||||
|
||||
dbgSerial.println(""); dbgSerial.print("ETXCheckPosition Motor: "); dbgSerial.print(Motor);
|
||||
dbgSerial.print(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); dbgSerial.print("> ");
|
||||
dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX);
|
||||
dbgSerial.print(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX);
|
||||
dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX);
|
||||
dbgSerial.print(" Speed: "); dbgSerial.print(axis[Motor].Speed, HEX);
|
||||
dbgSerial.print(" TargetSpeed: "); dbgSerial.print(axis[Motor].TargetSpeed, HEX);
|
||||
dbgSerial.print(" SpeedState: "); dbgSerial.print(axis[Motor].SpeedState, HEX);
|
||||
|
||||
if (!(axis[Motor].MotorControl & GoToHBX)) { // Slewing so update position
|
||||
break;
|
||||
}
|
||||
|
||||
distance = axis[Motor].Target - axis[Motor].Position; // Distance to target
|
||||
dbgSerial.print(" distance0: ");
|
||||
dbgSerial.print(distance, HEX);
|
||||
|
||||
if (axis[Motor].ETXMotorStatus & MOVEDECR) // If it is decreasing
|
||||
distance = TwosComplement(distance);
|
||||
|
||||
dbgSerial.print(" distance1: ");
|
||||
dbgSerial.print(distance, HEX);
|
||||
|
||||
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 <= 0x100) && (axis[Motor].SpeedState == 2)) {
|
||||
axis[Motor].TargetSpeed = axis[Motor].Speed >> 2; // 1/16
|
||||
axis[Motor].MotorControl &= ~SpeedHBX; // Use 0x00 command
|
||||
axis[Motor].ETXMotorState = ETXStepMotor; // Change speed
|
||||
axis[Motor].SpeedState += 1;
|
||||
}
|
||||
else if ((distance <= 0x200) && (axis[Motor].SpeedState == 1)) {
|
||||
axis[Motor].TargetSpeed = axis[Motor].Speed >> 1; // 1/4
|
||||
axis[Motor].MotorControl &= ~SpeedHBX; // Use 0x00 command
|
||||
axis[Motor].ETXMotorState = ETXStepMotor; // Change speed
|
||||
axis[Motor].SpeedState += 1;
|
||||
}
|
||||
else if ((distance <= 0x400) && (axis[Motor].SpeedState == 0)) {
|
||||
axis[Motor].TargetSpeed = axis[Motor].Speed >> 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) // EQG -> 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:
|
||||
|
||||
dbgSerial.println(""); dbgSerial.print("ETXStopMotor Motor: "); dbgSerial.print(Motor);
|
||||
|
||||
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].ETXMotorState = ETXCheckStartup;
|
||||
axis[Motor].TargetSpeed = axis[Motor].Speed; // For any subsequent move
|
||||
axis[Motor].Speed = 0;
|
||||
break;
|
||||
|
||||
case ETXMotorEnd:
|
||||
|
||||
dbgSerial.println(""); dbgSerial.print("ETXMotorEnd Motor: "); dbgSerial.print(Motor);
|
||||
dbgSerial.print(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); dbgSerial.print("> ");
|
||||
dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX);
|
||||
dbgSerial.print(", Inc: "); dbgSerial.print(axis[Motor].Increment, HEX);
|
||||
dbgSerial.print("->Tgt: "); dbgSerial.print(axis[Motor].Target, HEX);
|
||||
|
||||
if (Motor == MotorAz) digitalWrite(AzLED, LOW); // Turn off the LED
|
||||
else digitalWrite(AltLED, LOW);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Motor functions
|
||||
|
||||
bool HBXGetStatus(unsigned char Motor) {
|
||||
axis[Motor].HBXP4 = 0xFF; // Preset error
|
||||
|
||||
if (!HBXSendCommand(GetStatus, Motor)) {
|
||||
dbgSerial.println(""); dbgSerial.print("HBXGetStatus Motor: "); dbgSerial.print(Motor); dbgSerial.println(" Cmd Fail");
|
||||
return(false);
|
||||
}
|
||||
HBXGet3Bytes(Motor);
|
||||
if (axis[Motor].HBXP4 == 0) { // If no error, update position
|
||||
P1 = (axis[Motor].HBXP1 << 8);
|
||||
P1 |= axis[Motor].HBXP2; // Convert to 16bits
|
||||
if (axis[Motor].HBXP1 & 0x80)
|
||||
P1 |= 0xffff0000; // Sign extend HBXP1 for 2s complement
|
||||
axis[Motor].Position += P1;
|
||||
axis[Motor].Position &= 0x00FFFFFF;
|
||||
|
||||
if ((axis[Motor].ETXMotorStatus & MOVEAXIS) && (axis[Motor].Speed != axis[Motor].SIDEREALRATE)) {
|
||||
dbgSerial.println(""); dbgSerial.print("HBXGetStatus Motor: "); dbgSerial.print(Motor);
|
||||
dbgSerial.print(" <sts: "); dbgSerial.print(axis[Motor].ETXMotorStatus, HEX); dbgSerial.print("> ");
|
||||
dbgSerial.print(", time: "); dbgSerial.print(StatusTimer / 1000);
|
||||
dbgSerial.print(", P1: "); dbgSerial.print(P1, HEX);
|
||||
dbgSerial.print(", P4: "); dbgSerial.print(axis[Motor].HBXP4, HEX);
|
||||
dbgSerial.print(", Pos: "); dbgSerial.print(axis[Motor].Position, HEX);
|
||||
dbgSerial.print(", Dir: "); dbgSerial.print(axis[Motor].ETXMotorStatus & MOVEDECR, HEX);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
else return(false);
|
||||
}
|
||||
|
||||
bool HBXGet2Status(void) {
|
||||
int i;
|
||||
do {
|
||||
i = 0;
|
||||
if (HBXGetStatus(AzMotor))
|
||||
i += 1;
|
||||
if (HBXGetStatus(AltMotor))
|
||||
i += 1;
|
||||
} while (i < 2);
|
||||
return(true);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Wait ~.5s between loops
|
||||
TimerDelaymS(MOTORDETECT);
|
||||
// Reset Clocks to high
|
||||
digitalWrite(HCL1, HIGH);
|
||||
digitalWrite(HCL2, HIGH);
|
||||
TimerDelaymS(CMNDTIME);
|
||||
} while ((!PAz) || (!PAlt));
|
||||
}
|
||||
|
||||
void AzInitialise(void) {
|
||||
// Telescope specific
|
||||
// telescope steps
|
||||
axis[AzMotor].Vanes = ratio[telescope][AzMotor-1].Vanes;
|
||||
axis[AzMotor].GbxRatio = ratio[telescope][AzMotor-1].GbxRatio;
|
||||
axis[AzMotor].XferRatio = ratio[telescope][AzMotor-1].XferRatio;
|
||||
axis[AzMotor].WormTeeth = ratio[telescope][AzMotor-1].WormTeeth;
|
||||
// EQMOD values
|
||||
axis[AzMotor].aVALUE = axis[AzMotor].Vanes * (float)4 * axis[AzMotor].GbxRatio * axis[AzMotor].XferRatio * axis[AzMotor].WormTeeth;
|
||||
axis[AzMotor].MeadeRatio = axis[AzMotor].aVALUE / ArcSecs360; // Distance for one arcsec
|
||||
axis[AzMotor].bVALUE = (MeadeSidereal * axis[AzMotor].MeadeRatio * axis[AzMotor].aVALUE * SiderealArcSecs) / ArcSecs360;
|
||||
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].Position = ETX_AzCENTRE; // 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(void) {
|
||||
// Telescope specific
|
||||
// telescope steps
|
||||
axis[AltMotor].Vanes = ratio[telescope][AltMotor-1].Vanes;
|
||||
axis[AltMotor].GbxRatio = ratio[telescope][AltMotor-1].GbxRatio;
|
||||
axis[AltMotor].XferRatio = ratio[telescope][AltMotor-1].XferRatio;
|
||||
axis[AltMotor].WormTeeth = ratio[telescope][AltMotor-1].WormTeeth;
|
||||
// EQMOD values
|
||||
axis[AltMotor].aVALUE = axis[AltMotor].Vanes * (float)4 * axis[AltMotor].GbxRatio * axis[AltMotor].XferRatio * axis[AltMotor].WormTeeth;
|
||||
axis[AltMotor].MeadeRatio = axis[AltMotor].aVALUE / ArcSecs360; // Distance for one arcsec
|
||||
axis[AltMotor].bVALUE = MeadeSidereal * axis[AltMotor].MeadeRatio * axis[AltMotor].aVALUE * SiderealArcSecs / ArcSecs360;
|
||||
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;
|
||||
|
||||
// ETX
|
||||
axis[AltMotor].HBXP1 = 0x00;
|
||||
axis[AltMotor].HBXP2 = 0x00;
|
||||
axis[AltMotor].HBXP3 = 0x00;
|
||||
axis[AltMotor].HBXP4 = 0x00;
|
||||
axis[AltMotor].Position = ETX_AltCENTRE + (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].EQGMotorStatus = MOVESLEW;
|
||||
axis[AltMotor].ETXMotorState = ETXCheckStartup;
|
||||
}
|
||||
|
||||
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("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 telescope) {
|
||||
int j;
|
||||
float r;
|
||||
for (j = 0; j < 2; j++) {
|
||||
if (j == 0)
|
||||
dbgSerial.print("AzMotor: ");
|
||||
else
|
||||
dbgSerial.print("AltMotor: ");
|
||||
dbgSerial.print("Vanes "); dbgSerial.print(ratio[telescope][j].Vanes);
|
||||
dbgSerial.print(", GbxRatio "); dbgSerial.print(ratio[telescope][j].GbxRatio,4);
|
||||
dbgSerial.print(", XferRatio "); dbgSerial.print(ratio[telescope][j].XferRatio,4);
|
||||
dbgSerial.print(", WormTeeth "); dbgSerial.print(ratio[telescope][j].WormTeeth);
|
||||
r = (ratio[telescope][j].Vanes * (float) 4 * ratio[telescope][j].GbxRatio * ratio[telescope][j].XferRatio * ratio[telescope][j].WormTeeth) / (float) 1296000;
|
||||
dbgSerial.print(", MeadeRatio "); dbgSerial.println(r,6);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2017, 2018 John Archbold
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
|
||||
/********************************************************
|
||||
EQG Protocol function definitions
|
||||
=================================
|
||||
*********************************************************/
|
||||
#ifndef HBXComms
|
||||
#define HBXComms
|
||||
|
||||
#include <EEPROM.h>
|
||||
|
||||
// Serial port definitions for HBX interface
|
||||
// =========================================
|
||||
|
||||
#ifdef m2560
|
||||
#define dbgSerial Serial
|
||||
#define EQGSerial Serial1
|
||||
#endif
|
||||
|
||||
#ifdef mESP32
|
||||
#define dbgSerial Serial
|
||||
#define EQGSerial Serial2
|
||||
#endif
|
||||
|
||||
// Pin definitions for HBX interface
|
||||
// =================================
|
||||
#ifdef m2560
|
||||
#define HDA1 8 // Pin2, 4, 6 on HBX interface
|
||||
#define HCL1 2 // Pin3 on HBX interface
|
||||
#define HDA2 10 // Not used
|
||||
#define HCL2 3 // Pin5 on HBX interface
|
||||
#endif
|
||||
|
||||
#ifdef mESP32
|
||||
#define HDA1 27 // Pin2, 4, 6 on HBX interface
|
||||
#define HCL1 26 // Pin3 on HBX interface
|
||||
#define HCL2 25 // Pin5 on HBX interface
|
||||
#endif
|
||||
|
||||
#define CR 0x0d
|
||||
#define LF 0x0a
|
||||
|
||||
#define HBXLEN 16
|
||||
#define HBXMASK HBXLEN-1
|
||||
|
||||
#define H2XRESETTIME 25 // Reset H2X bus
|
||||
#define BITTIME 120 // H2X clock ~200uS i.e 100us Low/High
|
||||
#define HIGHTIME 120 // H2X clock ~200uS i.e 100us Low/High
|
||||
#define LOWTIME 120 // H2X clock ~200uS i.e 100us Low/High
|
||||
#define DSTABLE 60 // H2X data write delay ~ 50uS
|
||||
#define DGLITCH 5 // H2X data glitch sample
|
||||
#define ETXDELAY 6.55 // H2X ETX poll delay (mS)
|
||||
#define CMNDTIME 1 // H2X command delay (mS)
|
||||
#define STARTTIME 50 // H2X startup time for motors
|
||||
#define CLOCKTIMEOUT 50 // H2X Clock transition timeout (uS) (for monitor mode)
|
||||
#define MOTORDETECT 500 // H2X Detect Motor controller
|
||||
|
||||
unsigned char HBXBitTime = 128;
|
||||
void TimerDelayuS(unsigned int);
|
||||
|
||||
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(void);
|
||||
void HDATalk(void);
|
||||
void HCL1Listen(void);
|
||||
void HCL1Talk(void);
|
||||
void HCL2Listen(void);
|
||||
void HCL2Talk(void);
|
||||
void H2XReset(void);
|
||||
//bool ResetMotor(unsigned char);
|
||||
|
||||
long TwosComplement(long);
|
||||
|
||||
unsigned long eeprom_crc(void);
|
||||
unsigned long get_eeprom_crc(void);
|
||||
bool set_eeprom_crc(void);
|
||||
bool check_eeprom_crc(void);
|
||||
|
||||
// Testing
|
||||
void HBXTestLoop(void);
|
||||
void HBXTest(void);
|
||||
bool HBXGet2Status(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* Copyright 2017, 2018 John Archbold
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
|
||||
/********************************************************
|
||||
HBX Comms related functions
|
||||
===========================
|
||||
*********************************************************/
|
||||
|
||||
// HBX Attempt to reset
|
||||
// --------------------
|
||||
void HBXMotorReset(unsigned char Motor)
|
||||
{
|
||||
int i;
|
||||
/*
|
||||
// Write LOW
|
||||
HDATalk();
|
||||
digitalWrite(HDA1, HIGH);
|
||||
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, LOW);
|
||||
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();
|
||||
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 Low for reset
|
||||
if (Motor == MotorAz) digitalWrite(HCL1, LOW);
|
||||
else digitalWrite(HCL2, LOW);
|
||||
}
|
||||
|
||||
// HBX transmission functions
|
||||
// ==========================
|
||||
|
||||
// HBX Send a command
|
||||
// ------------------
|
||||
bool HBXSendCommand(unsigned char Command, unsigned char Motor) {
|
||||
|
||||
unsigned long i;
|
||||
axis[Motor].Command = Command;
|
||||
|
||||
// Send the start sequence
|
||||
// -----------------------
|
||||
if (HBXStartSequence(Motor)) {
|
||||
// Send the command byte
|
||||
// ---------------------
|
||||
HBXSendByte(Command, Motor);
|
||||
return(true);
|
||||
}
|
||||
else {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
// HBX Initiate start sequence
|
||||
// ---------------------------
|
||||
bool HBXStartSequence(unsigned char Motor) {
|
||||
// 1. HDA as input
|
||||
HDAListen();
|
||||
// 2. Set clock low
|
||||
if (Motor == MotorAz) digitalWrite(HCL1, LOW);
|
||||
else digitalWrite(HCL2, LOW);
|
||||
TimerDelayuS(HBXBitTime >> 1); // 1/2 bit-time
|
||||
// 3. Wait for data low (HDA1 = 0) by MC, or timeout
|
||||
H2XStart = micros();
|
||||
do {
|
||||
H2XTimer = micros() - H2XStart;
|
||||
} while ((digitalRead(HDA1) == 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(HDA1) == 1) || (H2XTimer >= (HBXBitTime << 3))) {
|
||||
if (Motor == MotorAz) digitalWrite(HCL1, HIGH);
|
||||
else digitalWrite(HCL2, HIGH); // Set clock high, and
|
||||
return(false); // error exit if no response from Motor
|
||||
}
|
||||
// 5. Set clock high if data low occurred (i.e. MC acknowledged clock low)
|
||||
if (Motor == MotorAz) digitalWrite(HCL1, HIGH);
|
||||
else digitalWrite(HCL2, HIGH);
|
||||
TimerDelayuS(HBXBitTime >> 1);
|
||||
// 6. Wait for data line release (HDA1 = 1) by MC, or timeout
|
||||
H2XStart = micros();
|
||||
do {
|
||||
H2XTimer = micros() - H2XStart;
|
||||
} while ((digitalRead(HDA1) == 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 b, mask;
|
||||
|
||||
HDATalk(); // HDA as output
|
||||
axis[Motor].HBXBitCount = 8; // 8bits to go
|
||||
mask = 0x80; // MSB first
|
||||
// Clock was set high before entry
|
||||
TimerDelayuS(HIGHTIME);
|
||||
do {
|
||||
axis[Motor].HBXBitCount -= 1;
|
||||
// Set data bit
|
||||
if (databyte & mask) digitalWrite(HDA1, HIGH);
|
||||
else digitalWrite(HDA1, LOW);
|
||||
TimerDelayuS(HBXBitTime >> 1); // Let data stabilise
|
||||
mask = mask >> 1; // Next data bit
|
||||
// Set clock low
|
||||
if (Motor == MotorAz) digitalWrite(HCL1, LOW);
|
||||
else digitalWrite(HCL2, LOW);
|
||||
TimerDelayuS(HBXBitTime);
|
||||
if (!(axis[Motor].HBXBitCount)) { // Last bit -> force float on data
|
||||
digitalWrite(HDA1, LOW);
|
||||
HDAListen();
|
||||
}
|
||||
// Set clock high
|
||||
if (Motor == MotorAz) digitalWrite(HCL1, HIGH);
|
||||
else digitalWrite(HCL2, 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
|
||||
}
|
||||
|
||||
// HBX Send two bytes in sequence
|
||||
// ------------------------------
|
||||
void HBXSend2Bytes(unsigned char Motor) {
|
||||
HBXSendByte(axis[Motor].HBXP1, Motor);
|
||||
HBXSendByte(axis[Motor].HBXP2, Motor);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// HBX Get a single byte
|
||||
// ----------------------
|
||||
unsigned char HBXGetByte(unsigned char Motor) {
|
||||
|
||||
unsigned long i;
|
||||
unsigned char b;
|
||||
// HDA as input
|
||||
HDAListen();
|
||||
axis[Motor].HBXBitCount = 8;
|
||||
axis[Motor].HBXData = 0;
|
||||
// Clock was set high before entry
|
||||
while (axis[Motor].HBXBitCount) {
|
||||
// Set clock low
|
||||
if (Motor == MotorAz) digitalWrite(HCL1, LOW);
|
||||
else digitalWrite(HCL2, LOW);
|
||||
TimerDelayuS(HBXBitTime >> 1);
|
||||
// Read data bit
|
||||
axis[Motor].HBXData = axis[Motor].HBXData << 1; // Shift previous bit
|
||||
if (digitalRead(HDA1)) axis[Motor].HBXData |= 0x01; // Read next bit
|
||||
axis[Motor].HBXBitCount--; // Need eight bits
|
||||
TimerDelayuS(HBXBitTime-(HBXBitTime >> 1)); // Wait for low time
|
||||
// Set clock high
|
||||
if (Motor == MotorAz) digitalWrite(HCL1, HIGH);
|
||||
else digitalWrite(HCL2, HIGH);
|
||||
TimerDelayuS(HBXBitTime);
|
||||
}
|
||||
// Return data byte
|
||||
axis[Motor].HBXCount = 1;
|
||||
return (axis[Motor].HBXData);
|
||||
}
|
||||
|
||||
// HBX Get the status bytes (25 bits)
|
||||
// ----------------------------------
|
||||
void HBXGet3Bytes(unsigned char Motor) {
|
||||
unsigned char b;
|
||||
|
||||
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
|
||||
// ------------------------
|
||||
if (Motor == MotorAz) digitalWrite(HCL1, LOW);
|
||||
else digitalWrite(HCL2, LOW);
|
||||
TimerDelayuS(HBXBitTime >> 1);
|
||||
axis[Motor].HBXP4 |= digitalRead(HDA1); // Read the battery error bit
|
||||
TimerDelayuS(HBXBitTime-(HBXBitTime >> 1));
|
||||
if (Motor == MotorAz)digitalWrite(HCL1, HIGH);
|
||||
else digitalWrite(HCL2, HIGH);
|
||||
TimerDelayuS(HBXBitTime);
|
||||
|
||||
axis[Motor].HBXCount = 4;
|
||||
}
|
||||
|
||||
// H2X Low level Functions
|
||||
// -----------------------
|
||||
void HDAListen() {
|
||||
pinMode(HDA1, H2X_INPUT);
|
||||
// digitalWrite(HDA1, HIGH);
|
||||
}
|
||||
void HDAFloat() {
|
||||
pinMode(HDA1, H2X_INPUT);
|
||||
}
|
||||
void HDATalk() {
|
||||
digitalWrite(HDA1, HIGH);
|
||||
pinMode(HDA1, H2X_OUTPUT);
|
||||
}
|
||||
void HCL1Listen() {
|
||||
pinMode(HCL1, H2X_INPUT);
|
||||
}
|
||||
void HCL1Talk() {
|
||||
digitalWrite(HCL1, HIGH);
|
||||
pinMode(HCL1, H2X_OUTPUT);
|
||||
}
|
||||
void HCL2Listen() {
|
||||
pinMode(HCL2, H2X_INPUT);
|
||||
}
|
||||
void HCL2Talk() {
|
||||
digitalWrite(HCL2, HIGH);
|
||||
pinMode(HCL2, H2X_OUTPUT);
|
||||
}
|
||||
|
||||
void H2XReset() {
|
||||
HCL1Talk();
|
||||
HCL2Talk();
|
||||
HDATalk();
|
||||
digitalWrite(HDA1, LOW);
|
||||
TimerDelayuS(H2XRESETTIME);
|
||||
digitalWrite(HDA1, HIGH);
|
||||
TimerDelayuS(H2XRESETTIME);
|
||||
HDAListen();
|
||||
}
|
||||
|
||||
long TwosComplement(long p) { // Calculate 2s complement
|
||||
long q;
|
||||
q = ~p; // Bitwise invert
|
||||
q = q + 1; // +1
|
||||
return q;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
#include <ArduinoOTA.h>
|
||||
bool ota_started;
|
||||
|
||||
const char* ssid = "YOUR_ROUTER_SSID";
|
||||
const char* password = "YOUR_ROUTER_WIFI_PASSWORD";
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
ConnectToWiFi();
|
||||
StartOTAIfRequired();
|
||||
PrintWifiStatus();
|
||||
Serial.println("Connected to wifi");
|
||||
}
|
||||
void loop()
|
||||
{
|
||||
//Serial.println("Hello world");
|
||||
HandleOTA();
|
||||
}
|
||||
|
||||
void ConnectToWiFi()
|
||||
{
|
||||
|
||||
Serial.println("Booting");
|
||||
WiFi.mode(WIFI_STA);
|
||||
Serial.println("Mode set");
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("Begin complete");
|
||||
}
|
||||
void HandleOTA()
|
||||
{
|
||||
StartOTAIfRequired();
|
||||
ArduinoOTA.handle();
|
||||
}
|
||||
void StartOTAIfRequired()
|
||||
{
|
||||
if (ota_started)
|
||||
return;
|
||||
// Port defaults to 8266
|
||||
// ArduinoOTA.setPort(8266);
|
||||
// Hostname defaults to esp8266-[ChipID]
|
||||
//if (ArduinoOTA.getHostname() && ArduinoOTA.getHostname().length())
|
||||
|
||||
// No authentication by default
|
||||
ArduinoOTA.setPassword((const char *)"123");
|
||||
ArduinoOTA.onStart([]() {
|
||||
Serial.println("OTA Start");
|
||||
});
|
||||
ArduinoOTA.onEnd([]() {
|
||||
Serial.println("\nOTA End");
|
||||
});
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||
Serial.printf("Progress: %u%%\r\n", (progress / (total / 100)));
|
||||
});
|
||||
ArduinoOTA.onError([](ota_error_t error) {
|
||||
Serial.printf("Error[%u]: ", error);
|
||||
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
||||
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
||||
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
||||
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
||||
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
ota_started = true;
|
||||
delay(500);
|
||||
|
||||
}
|
||||
void PrintWifiStatus()
|
||||
{
|
||||
// print the SSID of the network you're attached to:
|
||||
Serial.print("SSID: ");
|
||||
Serial.println(WiFi.SSID());
|
||||
//using dhcp? wait for ip or ip not set!
|
||||
if (WiFi.localIP()[0] == 0)
|
||||
{
|
||||
Serial.println("DHCP: Waiting for IP Address ...");
|
||||
while (WiFi.localIP()[0] == 0)
|
||||
{
|
||||
yield();
|
||||
}
|
||||
}
|
||||
// print your WiFi shield's IP address:
|
||||
IPAddress ip = WiFi.localIP();
|
||||
Serial.print("IP Address: ");
|
||||
Serial.println(ip);
|
||||
//Serial.println(WiFi.status());
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright 2017, 2018 John Archbold
|
||||
*/
|
||||
|
||||
|
||||
/********************************************************
|
||||
EQG Serial WiFi
|
||||
===============
|
||||
*********************************************************/
|
||||
#ifndef HBXWiFiServer
|
||||
#define HBXWiFiServer
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include <AsyncUdp.h>
|
||||
#include <AsyncTCP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <esp_now.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;
|
||||
|
||||
// char ssid[64] = "EQMODWiFi";
|
||||
// char pass[64] = "CShillit0";
|
||||
String ssid;
|
||||
String pass;
|
||||
|
||||
IPAddress ip(192, 168, 88, 1);
|
||||
IPAddress netmask(255, 255, 255, 0);
|
||||
|
||||
/**************************************************************
|
||||
* WiFi WebServer
|
||||
*/
|
||||
AsyncWebServer server(80);
|
||||
|
||||
/**************************************************************
|
||||
* 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);
|
||||
|
||||
#endif // HBXWiFiServer
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
// HBXSerialServer.ino
|
||||
// https://esp-idf.readthedocs.io/en/latest/api-reference/wifi/esp_now.html
|
||||
|
||||
// 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 TxD, 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) {
|
||||
dbgSerial.write(EQGTxBuffer[EQGTxoPtr]);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
|
||||
void HBXWiFiSetup() {
|
||||
|
||||
pinMode(PROTOCOL, INPUT_PULLUP); // ESP_NOW(1), UDP(0)
|
||||
pinMode(MODE, INPUT_PULLUP); // AP(1), STA(0)
|
||||
pinMode(SERIAL, INPUT_PULLUP);
|
||||
|
||||
digitalWrite(SERIAL, HIGH);
|
||||
digitalWrite(PROTOCOL, HIGH);
|
||||
digitalWrite(MODE, HIGH);
|
||||
|
||||
dbgSerial.println("");
|
||||
dbgSerial.print("digitalRead(PROTOCOL): ");
|
||||
dbgSerial.println(digitalRead(PROTOCOL));
|
||||
dbgSerial.print("digitalRead(MODE) : ");
|
||||
dbgSerial.println(digitalRead(MODE));
|
||||
dbgSerial.print("digitalRead(SERIAL) : ");
|
||||
dbgSerial.println(digitalRead(SERIAL));
|
||||
|
||||
if (digitalRead(PROTOCOL))
|
||||
UDPFlag = false;
|
||||
else
|
||||
UDPFlag = true;
|
||||
|
||||
if (digitalRead(MODE))
|
||||
APFlag = true;
|
||||
else
|
||||
APFlag = false;
|
||||
|
||||
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("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", "EQMODWiFi"); // Default EQMOD
|
||||
if (preferences.getString("AP_PASS", "none") == "none")
|
||||
preferences.putString("AP_PASS", "CShillit0");
|
||||
ssid = preferences.getString("AP_SSID", "none");
|
||||
pass = preferences.getString("AP_PASS", "none");
|
||||
preferences.end();
|
||||
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAPConfig(ip, ip, netmask); // softAP ip
|
||||
WiFi.softAP(ssid.c_str(), pass.c_str()); // softAP ssid, pass
|
||||
}
|
||||
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
|
||||
dbgSerial.println("Station Mode");
|
||||
// Check preferences for ssid, pass
|
||||
preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace
|
||||
if (preferences.getString("STA_SSID", "none") == "none")
|
||||
preferences.putString("STA_SSID", "HAPInet"); // Default Home Network
|
||||
if (preferences.getString("STA_PASS", "none") == "none")
|
||||
preferences.putString("STA_PASS", "HAPIconnection");
|
||||
ssid = preferences.getString("STA_SSID", "none");
|
||||
pass = preferences.getString("STA_PASS", "none");
|
||||
preferences.end();
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid.c_str(), pass.c_str());
|
||||
int i = 0;
|
||||
while ((WiFi.status() != WL_CONNECTED) && (i++ < 100)) {
|
||||
delay(100);
|
||||
dbgSerial.print(".");
|
||||
}
|
||||
if (i >= 100) {
|
||||
WiFi.begin("HAPInet", "HAPIconnect");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(100);
|
||||
dbgSerial.print("!");
|
||||
}
|
||||
}
|
||||
dbgSerial.println(" connected");
|
||||
/*
|
||||
server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
request->send(200, "text/plain", "Hello World");
|
||||
});
|
||||
|
||||
server.begin();
|
||||
*/
|
||||
}
|
||||
|
||||
dbgSerial.print("ssid: "); dbgSerial.println(ssid.c_str());
|
||||
dbgSerial.print("pass: "); dbgSerial.println(pass.c_str());
|
||||
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("Now listening at IP %s, UDP port %d\n", WiFi.softAPIP().toString().c_str(), localUdpPort);
|
||||
else
|
||||
dbgSerial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,523 @@
|
|||
/*
|
||||
* Copyright 2017, 2018 John Archbold
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
|
||||
/********************************************************
|
||||
Test HBX communications
|
||||
=======================
|
||||
*********************************************************/
|
||||
void HBXTestLoop(void) {
|
||||
TestCount = 0;
|
||||
//while (digitalRead(TESTHBX) == 0) {
|
||||
while (1) {
|
||||
dbgSerial.println("Test HBX commands to ETX");
|
||||
HBXTest();
|
||||
TestCount += 1;
|
||||
TestLoopTime = millis();
|
||||
// Read motor status until jumper removed
|
||||
while((millis() - TestLoopTime) < 1000) { // 5s between tests
|
||||
// HBXGet2Status();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HBXTest(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Initialize HBX communications as outputs
|
||||
// It will use I2C-like communications
|
||||
dbgSerial.println("**********************************************");
|
||||
dbgSerial.print("Test Number - ");
|
||||
dbgSerial.println(TestCount);
|
||||
dbgSerial.println("**********************************************");
|
||||
|
||||
HCL1Talk(); // Set for Talking on RAClk
|
||||
HCL2Talk(); // Set for Talking on DECClk
|
||||
HDAListen();
|
||||
TimerDelaymS(STARTTIME);
|
||||
axis[AzMotor].PrintStatus0 = 1; // Enable print of status = no change
|
||||
axis[AltMotor].PrintStatus0 = 1; // Enable print of status = no change
|
||||
|
||||
//if (TestCount == 0) {
|
||||
|
||||
dbgSerial.println("Test - HBX Initialization");
|
||||
axis[AzMotor].Position = ETX_AzCENTRE;
|
||||
axis[AzMotor].Target = axis[AzMotor].Position;
|
||||
axis[AzMotor].DirnSpeed = 0x000;
|
||||
axis[AzMotor].Speed = 0x000000;
|
||||
axis[AzMotor].ETXMotorStatus = MOVESLEW;
|
||||
|
||||
axis[AltMotor].Position = ETX_AltCENTRE;
|
||||
axis[AltMotor].Target = axis[AltMotor].Position;
|
||||
axis[AltMotor].DirnSpeed = 0x000;
|
||||
axis[AltMotor].Speed = 0x000000;
|
||||
axis[AltMotor].ETXMotorStatus = MOVESLEW;
|
||||
|
||||
// Reset the motors (RA and DEC)
|
||||
dbgSerial.println("Test - Wait for motors");
|
||||
|
||||
// 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)
|
||||
|
||||
do {
|
||||
P1 = 0;
|
||||
if (HBXSendCommand(GetLEDI, AzMotor))
|
||||
P2 = HBXGetByte(AzMotor);
|
||||
if ((P2 != 0) && (P2 != 0xFF)) P1 += 1;
|
||||
TimerDelaymS(CMNDTIME);
|
||||
if (HBXSendCommand(GetLEDI, AltMotor))
|
||||
P2 = HBXGetByte(AltMotor);
|
||||
if ((P2 != 0) && (P2 != 0xFF)) P1 += 1;
|
||||
TimerDelaymS(CMNDTIME);
|
||||
} while (P1 < 2);
|
||||
|
||||
|
||||
// Stop the motors (Az and Alt)
|
||||
dbgSerial.println("Test - Stop motors");
|
||||
HBXStop2Motors();
|
||||
|
||||
// Read status
|
||||
dbgSerial.println("");
|
||||
dbgSerial.println("1 Test - Read Status");
|
||||
HBXGet2Status(); // Check and read both motor states
|
||||
|
||||
dbgSerial.println("Test - Get Motor Type and set ETX Encoder LED currents");
|
||||
axis[AzMotor].MotorType = 0x00;
|
||||
while (!axis[AzMotor].MotorType) {
|
||||
if (HBXSendCommand(GetMotorType, AzMotor))
|
||||
axis[AzMotor].MotorType = HBXGetByte(AzMotor);
|
||||
HBXPrintStatus(AzMotor);
|
||||
}
|
||||
|
||||
preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace
|
||||
|
||||
// Handle position sensors LED current
|
||||
// -----------------------------------
|
||||
if (preferences.getUChar("AzLEDI", 0) == 0) { // If it does not exist, return 0
|
||||
// Calibrate motors
|
||||
if (HBXSendCommand(CalibrateLED, AzMotor));
|
||||
TimerDelaymS(2500);
|
||||
if (HBXSendCommand(CalibrateLED, AltMotor))
|
||||
TimerDelaymS(2500);
|
||||
// Read the calibration
|
||||
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.println(axis[AltMotor].HBXLEDI);
|
||||
// Save it to preferences
|
||||
preferences.putUChar("AzLEDI", axis[AzMotor].HBXLEDI);
|
||||
preferences.putUChar("AltLEDI", axis[AltMotor].HBXLEDI);
|
||||
}
|
||||
// Read stored LED currents
|
||||
axis[AzMotor].HBXLEDI = preferences.getUChar("AzLEDI", 0);
|
||||
axis[AltMotor].HBXLEDI = preferences.getUChar("AltLEDI", 0);
|
||||
preferences.end();
|
||||
|
||||
// Set the MC 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 to Zero
|
||||
axis[AzMotor].HBXP1 = 0x00;
|
||||
axis[AzMotor].HBXP2 = 0x00;
|
||||
axis[AzMotor].HBXP3 = 0x00;
|
||||
axis[AltMotor].HBXP1 = 0x00;
|
||||
axis[AltMotor].HBXP2 = 0x00;
|
||||
axis[AltMotor].HBXP3 = 0x00;
|
||||
|
||||
// Set the Offset Clear Command
|
||||
dbgSerial.println("Test - Reset any ETX offset bytes");
|
||||
if (HBXSendCommand(SetOffset, AzMotor))
|
||||
HBXSend2Bytes(AzMotor);
|
||||
HBXPrintStatus(AzMotor);
|
||||
TimerDelaymS(CMNDTIME);
|
||||
|
||||
if (HBXSendCommand(SetOffset, AltMotor))
|
||||
HBXSend2Bytes(AltMotor);
|
||||
HBXPrintStatus(AltMotor);
|
||||
TimerDelaymS(CMNDTIME);
|
||||
|
||||
//}
|
||||
/*
|
||||
dbgSerial.println("Test - Stop motors");
|
||||
HBXStop2Motors();
|
||||
// First Read, clear counters
|
||||
dbgSerial.println("Test - Read Both Motor States");
|
||||
HBXGet2Status();
|
||||
|
||||
dbgSerial.println("Test - Begin motor move tests");
|
||||
//}
|
||||
// Test different motor speeds
|
||||
dbgSerial.println("Test - Motor Speed Tests");
|
||||
dbgSerial.println("========================");
|
||||
|
||||
dbgSerial.println("Test - SIDEREAL");
|
||||
axis[AzMotor].ETXMotorStatus |= MOVEDIRN; // Forward
|
||||
axis[AltMotor].ETXMotorStatus |= MOVEDIRN;
|
||||
axis[AzMotor].Speed = AzSIDEREALRATE; // Sidereal
|
||||
axis[AltMotor].Speed = AltSIDEREALRATE;
|
||||
HBXPrintPosn(5, 1000); // Show location each second
|
||||
dbgSerial.println("Test - SIDEREAL - Stop motors");
|
||||
HBXStop2Motors();
|
||||
|
||||
dbgSerial.println("Test - OneDegree/sec forward");
|
||||
axis[AzMotor].ETXMotorStatus |= MOVEDIRN; // Forward
|
||||
axis[AltMotor].ETXMotorStatus |= MOVEDIRN;
|
||||
axis[AzMotor].Speed = AzDEGREERATE1; // One degree/sec
|
||||
axis[AltMotor].Speed = AltDEGREERATE1; // One degree/sec
|
||||
HBXPrintPosn(5, 500); // Show location each tenth of a second
|
||||
dbgSerial.println("Test - OneDegree/sec forward - Stop motors");
|
||||
HBXStop2Motors();
|
||||
|
||||
dbgSerial.println("Test - OneDegree/sec reverse");
|
||||
axis[AzMotor].ETXMotorStatus &= ~MOVEDIRN; // Reverse
|
||||
axis[AltMotor].ETXMotorStatus &= ~MOVEDIRN;
|
||||
axis[AzMotor].Speed = AzDEGREERATE1; // One degree/sec
|
||||
axis[AltMotor].Speed = AltDEGREERATE1; // One degree/sec
|
||||
HBXPrintPosn(5, 500); // Show location each each tenth of a second
|
||||
dbgSerial.println("Test - OneDegree/sec reverse - Stop motors");
|
||||
HBXStop2Motors();
|
||||
|
||||
dbgSerial.println("Test - TwoDegrees/sec forward");
|
||||
axis[AzMotor].ETXMotorStatus |= MOVEDIRN; // Forward
|
||||
axis[AltMotor].ETXMotorStatus |= MOVEDIRN;
|
||||
axis[AzMotor].Speed = AzDEGREERATE1*2; // Two degrees/sec
|
||||
axis[AltMotor].Speed = AltDEGREERATE1*2; // Two degrees/sec
|
||||
HBXPrintPosn(5, 1000); // Show location each tenth of a second
|
||||
dbgSerial.println("Test - TwoDegrees/sec forward - Stop motors");
|
||||
HBXStop2Motors();
|
||||
|
||||
dbgSerial.println("Test - TwoDegrees/sec reverse");
|
||||
axis[AzMotor].ETXMotorStatus &= ~MOVEDIRN; // Reverse
|
||||
axis[AltMotor].ETXMotorStatus &= ~MOVEDIRN;
|
||||
axis[AzMotor].Speed = AzDEGREERATE1*2; // Two degrees/sec
|
||||
axis[AltMotor].Speed = AltDEGREERATE1*2; // Two degrees/sec
|
||||
HBXPrintPosn(5, 1000); // Show location each each tenth of a second
|
||||
dbgSerial.println("Test - TwoDegrees/sec reverse - Stop motors");
|
||||
*/
|
||||
HBXStop2Motors();
|
||||
|
||||
dbgSerial.println("");
|
||||
dbgSerial.println("Test - 0x01 Command");
|
||||
axis[AzMotor].MotorControl &= ~MOVEDECR; // Forward
|
||||
axis[AltMotor].MotorControl &= ~MOVEDECR;
|
||||
axis[AzMotor].MotorControl |= SpeedHBX; // High speed
|
||||
axis[AltMotor].MotorControl |= SpeedHBX;
|
||||
axis[AzMotor].Speed = axis[AzMotor].SIDEREALRATE; // Start at Sidereal
|
||||
axis[AltMotor].Speed = axis[AltMotor].SIDEREALRATE;
|
||||
|
||||
do {
|
||||
// HBXPrintSpeed(1, 10000); // Print location
|
||||
axis[AzMotor].Speed += axis[AzMotor].SIDEREALRATE;
|
||||
axis[AzMotor].ETXMotorState = ETXStepMotor;
|
||||
ETXState(AzMotor);
|
||||
TimerDelaymS(CMNDTIME);
|
||||
// delay(2000);
|
||||
// } while (axis[AzMotor].Speed < 0x600000);
|
||||
|
||||
// do {
|
||||
// HBXPrintSpeed(1, 10000); // Print location
|
||||
axis[AltMotor].Speed += axis[AltMotor].SIDEREALRATE;
|
||||
axis[AltMotor].ETXMotorState = ETXStepMotor;
|
||||
ETXState(AltMotor);
|
||||
TimerDelaymS(CMNDTIME);
|
||||
HBXGet2Status();
|
||||
TimerDelaymS(CMNDTIME);
|
||||
TimerDelaymS(2000);
|
||||
} while (axis[AltMotor].Speed < (axis[AltMotor].SIDEREALRATE << 3));
|
||||
|
||||
dbgSerial.println("Test - 0x01 Command - Stop motors");
|
||||
HBXStop2Motors();
|
||||
|
||||
// Read status
|
||||
dbgSerial.println("");
|
||||
dbgSerial.println("2 Test - Read Status");
|
||||
HBXGet2Status();
|
||||
|
||||
// Stop the motors (Az and Alt)
|
||||
dbgSerial.println("Test - Stop motors");
|
||||
HBXStop2Motors();
|
||||
|
||||
dbgSerial.println("Test - End of Loop");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void HBXPrintSpeed(unsigned int count, unsigned int duration) {
|
||||
int j = 0;
|
||||
|
||||
axis[AzMotor].Position = ETX_AzCENTRE; // Reset position
|
||||
axis[AltMotor].Position = ETX_AltCENTRE;
|
||||
axis[AzMotor].Increment = 0;
|
||||
axis[AltMotor].Increment = 0;
|
||||
PreviousTime = millis();
|
||||
dbgSerial.print("Az, ");
|
||||
dbgSerial.println(axis[AzMotor].Speed);
|
||||
dbgSerial.print("Alt, ");
|
||||
dbgSerial.println(axis[AltMotor].Speed);
|
||||
HBXStart2Motors(); // Start the motors
|
||||
do {
|
||||
ETXState(AzMotor); // Check the Az motor state
|
||||
ETXState(AltMotor); // Check the Alt motor state
|
||||
dbgSerial.print(millis() - PreviousTime);
|
||||
dbgSerial.print(", ");
|
||||
SendSpeed(duration); // Duration is delay between reads
|
||||
j += 1;
|
||||
while ((millis() - PreviousTime) < duration);
|
||||
PreviousTime = millis();
|
||||
} while(j < count);
|
||||
}
|
||||
|
||||
void SendSpeed(unsigned long duration) {
|
||||
|
||||
HBXGetStatus(AzMotor);
|
||||
axis[AzMotor].Increment = axis[AzMotor].HBXP1 * 256 + axis[AzMotor].HBXP2;
|
||||
HBXGetStatus(AltMotor);
|
||||
axis[AltMotor].Increment = axis[AltMotor].HBXP1 * 256 + axis[AltMotor].HBXP2;
|
||||
|
||||
dbgSerial.println("");
|
||||
dbgSerial.print("Az-Speed: ");
|
||||
dbgSerial.print(axis[AzMotor].Speed);
|
||||
dbgSerial.print(",Posn: ");
|
||||
dbgSerial.print(axis[AzMotor].Position);
|
||||
dbgSerial.print(",Incr: ");
|
||||
dbgSerial.println(axis[AzMotor].Increment);
|
||||
dbgSerial.print("Alt-Speed: ");
|
||||
dbgSerial.print(axis[AltMotor].Speed);
|
||||
dbgSerial.print(",Posn: ");
|
||||
dbgSerial.print(axis[AltMotor].Position);
|
||||
dbgSerial.print(",Incr: ");
|
||||
dbgSerial.println(axis[AltMotor].Increment);
|
||||
}
|
||||
|
||||
void HBXPrintPosn(unsigned int count, unsigned int duration) {
|
||||
int j = 0;
|
||||
|
||||
axis[AzMotor].Position = ETX_AzCENTRE; // Reset position
|
||||
axis[AltMotor].Position = ETX_AltCENTRE;
|
||||
axis[AzMotor].Increment = 0;
|
||||
axis[AltMotor].Increment = 0;
|
||||
PreviousTime = millis();
|
||||
|
||||
HBXStart2Motors(); // Start the motors
|
||||
|
||||
do {
|
||||
ETXState(AzMotor); // Check the Az motor state
|
||||
ETXState(AltMotor); // Check the Alt motor state
|
||||
SendData(duration); // Duration is delay between reads
|
||||
j += 1;
|
||||
} while(j < count);
|
||||
}
|
||||
|
||||
void SendData(unsigned int duration) {
|
||||
|
||||
// dbgSerial.println(" SendPosn");
|
||||
|
||||
while ((millis() - PreviousTime) < duration) ; // 1/10 second
|
||||
dbgSerial.print(millis() - PreviousTime);
|
||||
dbgSerial.print(" - ");
|
||||
PreviousTime = millis();
|
||||
|
||||
HBXGetStatus(AzMotor);
|
||||
axis[AzMotor].Increment = axis[AzMotor].HBXP1 * 256 + axis[AzMotor].HBXP2;
|
||||
|
||||
HBXGetStatus(AltMotor);
|
||||
axis[AltMotor].Increment = axis[AltMotor].HBXP1 * 256 + axis[AltMotor].HBXP2;
|
||||
|
||||
dbgSerial.print("Az = ");
|
||||
dbgSerial.print(axis[AzMotor].Position);
|
||||
dbgSerial.print(" : ");
|
||||
dbgSerial.print(axis[AzMotor].Increment);
|
||||
dbgSerial.print(", Alt = ");
|
||||
dbgSerial.print(axis[AltMotor].Position);
|
||||
dbgSerial.print(" : ");
|
||||
dbgSerial.println(axis[AltMotor].Increment);
|
||||
}
|
||||
|
||||
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.print("Motor: ");
|
||||
dbgSerial.print(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 ResetH2X:
|
||||
dbgSerial.print("ResetH2X ");
|
||||
break;
|
||||
default:
|
||||
dbgSerial.print("UNKNOWN ");
|
||||
break;
|
||||
}
|
||||
|
||||
if (axis[Motor].HBXCount) {
|
||||
dbgSerial.print(", Data: ");
|
||||
dbgSerial.print(axis[Motor].HBXP1, HEX);
|
||||
if (axis[Motor].HBXCount > 1) dbgSerial.print(", ");
|
||||
axis[Motor].HBXCount -= 1;
|
||||
}
|
||||
if (axis[Motor].HBXCount) {
|
||||
dbgSerial.print(axis[Motor].HBXP2, HEX);
|
||||
if (axis[Motor].HBXCount > 1) dbgSerial.print(", ");
|
||||
axis[Motor].HBXCount -= 1;
|
||||
}
|
||||
if (axis[Motor].HBXCount) {
|
||||
dbgSerial.print(axis[Motor].HBXP3, HEX);
|
||||
if (axis[Motor].HBXCount > 1) dbgSerial.print(", ");
|
||||
axis[Motor].HBXCount -= 1;
|
||||
}
|
||||
if (axis[Motor].HBXCount) {
|
||||
dbgSerial.print(axis[Motor].HBXP4, HEX);
|
||||
axis[Motor].HBXCount -= 1;
|
||||
}
|
||||
dbgSerial.println("");
|
||||
}
|
||||
}
|
||||
|
||||
bool HBXStop2Motors(void) {
|
||||
axis[AzMotor].ETXMotorState = ETXStopMotor;
|
||||
ETXState(AzMotor);
|
||||
axis[AltMotor].ETXMotorState = ETXStopMotor;
|
||||
ETXState(AltMotor);
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool HBXStart2Motors(void) {
|
||||
axis[AzMotor].ETXMotorState = ETXCheckStartup;
|
||||
axis[AzMotor].EQGMotorStatus |= MOVEAXIS;
|
||||
dbgSerial.print("Az, ");
|
||||
dbgSerial.println(axis[AzMotor].Speed);
|
||||
ETXState(AzMotor);
|
||||
dbgSerial.print("Az, ");
|
||||
dbgSerial.println(axis[AzMotor].Speed);
|
||||
axis[AltMotor].ETXMotorState = ETXCheckStartup;
|
||||
axis[AltMotor].EQGMotorStatus |= MOVEAXIS;
|
||||
dbgSerial.print("Az, ");
|
||||
dbgSerial.println(axis[AzMotor].Speed);
|
||||
ETXState(AltMotor);
|
||||
dbgSerial.print("Az, ");
|
||||
dbgSerial.println(axis[AzMotor].Speed);
|
||||
return(true);
|
||||
}
|
||||
|
||||
void HBXPrintPosn(unsigned char Motor) {
|
||||
if (Motor == MotorAz) {
|
||||
dbgSerial.println("");
|
||||
dbgSerial.print("Time: ");
|
||||
dbgSerial.print(millis());
|
||||
// dbgSerial.print(StatusTimer - StatusTime);
|
||||
// StatusTime = StatusTimer;
|
||||
|
||||
|
||||
/* dbgSerial.print(" AzRaw: ");
|
||||
puthexb(axis[AzMotor].HBXP1);
|
||||
putbyte(',');
|
||||
puthexb(axis[AzMotor].HBXP2);
|
||||
putbyte(',');
|
||||
puthexb(axis[AzMotor].HBXP3);
|
||||
putbyte(',');
|
||||
puthexb(axis[AzMotor].HBXP4);
|
||||
*/
|
||||
dbgSerial.print(" AzPosn: ");
|
||||
puthexl(axis[AzMotor].Position);
|
||||
putbyte(',');
|
||||
puthexl(axis[AzMotor].Target);
|
||||
putbyte(',');
|
||||
puthexl(axis[AzMotor].SlowDown);
|
||||
dbgSerial.print(" AzSpeed: ");
|
||||
puthexl(axis[AzMotor].Speed);
|
||||
putbyte(',');
|
||||
puthexl(axis[AzMotor].TargetSpeed);
|
||||
putbyte('-');
|
||||
puthexw(axis[AzMotor].EQGMotorStatus);
|
||||
putbyte(',');
|
||||
puthexw(axis[AzMotor].MotorControl);
|
||||
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* dbgSerial.print(" AltRaw: ");
|
||||
puthexb(axis[AltMotor].HBXP1);
|
||||
putbyte(',');
|
||||
puthexb(axis[AltMotor].HBXP2);
|
||||
putbyte(',');
|
||||
puthexb(axis[AltMotor].HBXP3);
|
||||
putbyte(',');
|
||||
puthexb(axis[AltMotor].HBXP4);
|
||||
*/
|
||||
dbgSerial.print(" AltPosn: ");
|
||||
puthexl(axis[AltMotor].Position);
|
||||
putbyte(',');
|
||||
puthexl(axis[AltMotor].Target);
|
||||
putbyte(',');
|
||||
puthexl(axis[AltMotor].SlowDown);
|
||||
dbgSerial.print(" AltSpeed: ");
|
||||
puthexl(axis[AltMotor].Speed);
|
||||
putbyte(',');
|
||||
puthexl(axis[AltMotor].TargetSpeed);
|
||||
putbyte('-');
|
||||
puthexw(axis[AltMotor].EQGMotorStatus);
|
||||
putbyte(',');
|
||||
puthexw(axis[AltMotor].MotorControl);
|
||||
dbgSerial.println("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Ładowanie…
Reference in New Issue