INITIAL RELEASE

pull/1/head
ozarchie 2018-09-19 12:28:41 +10:00 zatwierdzone przez GitHub
rodzic c9ff98157f
commit 0bc6cba53c
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
16 zmienionych plików z 3975 dodań i 0 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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