Skip to content

Commit a1c50cb

Browse files
V1.7.02 - Updates
- Switched Mega and Uno to interrupt-driven stepper motor driving. - Added Unpark command to GO menu.
1 parent 2ce8720 commit a1c50cb

File tree

10 files changed

+233
-38
lines changed

10 files changed

+233
-38
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#include "InterruptCallback.h"
2+
#include "Utility.h"
3+
4+
//////////////////////////////////////
5+
// This is an hardware-independent abstraction layer over
6+
// whatever timer is used for the hardware being run
7+
//////////////////////////////////////
8+
9+
// NOTE: ESP8266 support is not complete and does not work. This code is never called.
10+
#ifdef ESP8266
11+
#include "Timers/ESP8266TimerInterrupt.h"
12+
#elif defined __AVR_ATmega328P__ || defined __AVR_ATmega2560__ // Arduino Uno or Mega
13+
#define USE_TIMER_1 true
14+
#define USE_TIMER_2 true
15+
#define USE_TIMER_3 false
16+
#define USE_TIMER_4 false
17+
#define USE_TIMER_5 false
18+
#include "Timers/TimerInterrupt.h"
19+
#else
20+
// Need to add support for ESP32 boards here
21+
22+
#error Only Arduino Uno, Mega and ESP8266 boards currently supported.
23+
#endif
24+
25+
#ifdef ESP8266
26+
ESP8266Timer interruptHandler;
27+
28+
void* actualPayload = NULL;
29+
volatile interrupt_callback_p actualCallback = NULL;
30+
31+
// This timer only supports a callback with no payload
32+
void ICACHE_RAM_ATTR esp8266callback(void)
33+
{
34+
if (actualCallback != NULL) {
35+
(*actualCallback)(actualPayload);
36+
}
37+
}
38+
39+
bool InterruptCallback::setInterval(float intervalMs, interrupt_callback_p callback, void* payload)
40+
{
41+
// Since this timer only supports a callback with no payload, we store the requested callback and payload
42+
// in static variables and install an intermediate callback for the interrupt to call. The intermerdiate
43+
// The calls the actual requested callback with the payload.
44+
actualPayload = payload;
45+
actualCallback = callback;
46+
47+
// This timer library requires microsecond interval definitions
48+
interruptHandler.setInterval(1000.0f * intervalMs, esp8266callback);
49+
}
50+
51+
void InterruptCallback::start()
52+
{
53+
}
54+
55+
void InterruptCallback::stop()
56+
{
57+
}
58+
59+
#else
60+
61+
62+
bool InterruptCallback::setInterval(float intervalMs, interrupt_callback_p callback, void* payload)
63+
{
64+
// We have requested to use Timer2 (see above)
65+
ITimer2.init();
66+
67+
// This timer supports the callback with payload
68+
return ITimer2.attachInterruptInterval<void*>(intervalMs, callback, payload, 0UL);
69+
}
70+
71+
void InterruptCallback::stop()
72+
{
73+
ITimer2.stopTimer();
74+
}
75+
76+
void InterruptCallback::start()
77+
{
78+
ITimer2.restartTimer();
79+
}
80+
81+
#endif
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
#include "Globals.h"
3+
4+
//////////////////////////////////////
5+
// This is an hardware-independent abstraction layer over
6+
// whatever timer is used for the hardware being run.
7+
//////////////////////////////////////
8+
9+
// The callback function signature
10+
typedef void (*interrupt_callback_p)(void*);
11+
12+
// The static class managing the callbacks.
13+
class InterruptCallback
14+
{
15+
public:
16+
// Requests the hardware to call the given callback with the given payload at the given interval in milliseconds.
17+
// The interrupts should be started before returning.
18+
bool static setInterval(float intervalMs, interrupt_callback_p callback, void* payload);
19+
20+
// Starts the timer interrupts (currently not called/used)
21+
void static start();
22+
23+
// Stops the timer interrupts (currently not called/used)
24+
void static stop();
25+
};
26+

Software/Arduino code/OpenAstroTracker/Mount.cpp

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include <EEPROM.h>
22

3+
#include "InterruptCallback.h"
4+
35
#include "LcdMenu.hpp"
46
#include "Mount.hpp"
57
#include "Utility.h"
@@ -52,6 +54,15 @@ char* formatStringsRA[] = {
5254
"%02d%02d%02d", // Compact
5355
};
5456

57+
/////////////////////////////////
58+
// This is the callback function for the timer interrupt. It does very minimal work,
59+
// only stepping the stepper motors as needed.
60+
/////////////////////////////////
61+
void mountLoop(void* payload) {
62+
Mount* mount = reinterpret_cast<Mount*>(payload);
63+
mount->interruptLoop();
64+
}
65+
5566
const float siderealDegreesInHour = 14.95902778;
5667
/////////////////////////////////
5768
//
@@ -77,6 +88,25 @@ Mount::Mount(int stepsPerRADegree, int stepsPerDECDegree, LcdMenu* lcdMenu) {
7788
readPersistentData();
7889
}
7990

91+
/////////////////////////////////
92+
//
93+
// startTimerInterrupts
94+
//
95+
/////////////////////////////////
96+
void Mount::startTimerInterrupts()
97+
{
98+
#ifndef ESP8266
99+
// 2 kHz updates
100+
if (!InterruptCallback::setInterval(0.5f, mountLoop, this))
101+
{
102+
#ifdef DEBUG_MODE
103+
logv("CANNOT set Timer!");
104+
#endif
105+
}
106+
#endif // !ESP8266
107+
}
108+
109+
80110
/////////////////////////////////
81111
//
82112
// readPersistentData
@@ -1079,33 +1109,17 @@ void Mount::delay(int ms) {
10791109

10801110
/////////////////////////////////
10811111
//
1082-
// loop
1112+
// interruptLoop()
10831113
//
1084-
// Process any stepper movement. Must be called frequently
10851114
/////////////////////////////////
1086-
void Mount::loop() {
1087-
bool raStillRunning = false;
1088-
bool decStillRunning = false;
1089-
1090-
unsigned long now = millis();
1091-
#if defined DEBUG_MODE && defined SEND_PERIODIC_UPDATES
1092-
if (now - _lastMountPrint > 2000) {
1093-
Serial.println(getStatusString());
1094-
_lastMountPrint = now;
1095-
}
1096-
#endif
1097-
if (isGuiding()) {
1098-
if (millis() > _guideEndTime) {
1099-
stopGuiding();
1115+
void Mount::interruptLoop()
1116+
{
1117+
if (_mountStatus & STATUS_GUIDE_PULSE) {
1118+
if (_mountStatus & STATUS_GUIDE_PULSE_RA) {
1119+
_stepperTRK->runSpeed();
11001120
}
1101-
else
1102-
{
1103-
if (_mountStatus & STATUS_GUIDE_PULSE_RA) {
1104-
_stepperTRK->runSpeed();
1105-
}
1106-
if (_mountStatus & STATUS_GUIDE_PULSE_DEC) {
1107-
_stepperDEC->runSpeed();
1108-
}
1121+
if (_mountStatus & STATUS_GUIDE_PULSE_DEC) {
1122+
_stepperDEC->runSpeed();
11091123
}
11101124
return;
11111125
}
@@ -1124,6 +1138,37 @@ void Mount::loop() {
11241138
_stepperRA->run();
11251139
}
11261140
}
1141+
}
1142+
1143+
/////////////////////////////////
1144+
//
1145+
// loop
1146+
//
1147+
// Process any stepper change in movement.
1148+
/////////////////////////////////
1149+
void Mount::loop() {
1150+
bool raStillRunning = false;
1151+
bool decStillRunning = false;
1152+
1153+
// Since the ESP8266 cannot process timer interrupts at the required
1154+
// speed, we'll just stick to deterministic calls here.
1155+
#ifdef ESP8266
1156+
interruptLoop();
1157+
#endif
1158+
1159+
unsigned long now = millis();
1160+
#if defined DEBUG_MODE && defined SEND_PERIODIC_UPDATES
1161+
if (now - _lastMountPrint > 2000) {
1162+
Serial.println(getStatusString());
1163+
_lastMountPrint = now;
1164+
}
1165+
#endif
1166+
if (isGuiding()) {
1167+
if (millis() > _guideEndTime) {
1168+
stopGuiding();
1169+
}
1170+
return;
1171+
}
11271172

11281173
if (_stepperDEC->isRunning()) {
11291174
decStillRunning = true;

Software/Arduino code/OpenAstroTracker/Mount.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,12 @@ class Mount {
128128
// Gets the position in one of eight directions or tracking
129129
long getCurrentStepperPosition(int direction);
130130

131-
// Process any stepper movement. Must be called frequently
131+
// Process any stepper movement.
132132
void loop();
133133

134+
// Low-leve process any stepper movement on interrupt callback.
135+
void interruptLoop();
136+
134137
// Set RA and DEC to the home position
135138
void setTargetToHome();
136139

@@ -178,6 +181,9 @@ class Mount {
178181

179182
// Get the number of steps to use for backlash correction
180183
int getBacklashCorrection();
184+
185+
// Called when startup is complete and the mount needs to start updating steppers.
186+
void startTimerInterrupts();
181187

182188
private:
183189

@@ -238,7 +244,7 @@ class Mount {
238244
float _trackingSpeed;
239245
float _trackingSpeedCalibration;
240246
unsigned long _lastDisplayUpdate;
241-
int _mountStatus;
247+
volatile int _mountStatus;
242248
char scratchBuffer[24];
243249
bool _stepperWasRunning;
244250
bool _correctForBacklash;

Software/Arduino code/OpenAstroTracker/OpenAstroTracker.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717
#include "Globals.h"
1818

19-
String version = "V1.7.01";
19+
String version = "V1.7.02";
2020

2121
///////////////////////////////////////////////////////////////////////////
2222
// Please see the Globals.h file for configuration of the firmware.

Software/Arduino code/OpenAstroTracker/OpenAstroTracker.vcxproj

Lines changed: 10 additions & 3 deletions
Large diffs are not rendered by default.

Software/Arduino code/OpenAstroTracker/OpenAstroTracker.vcxproj.filters

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@
5757
<ClInclude Include="Globals.h">
5858
<Filter>Header Files</Filter>
5959
</ClInclude>
60+
<ClInclude Include="InterruptCallback.h">
61+
<Filter>Header Files</Filter>
62+
</ClInclude>
63+
<ClInclude Include="Timers\ESP8266TimerInterrupt.h">
64+
<Filter>Header Files</Filter>
65+
</ClInclude>
66+
<ClInclude Include="Timers\ESP8266_ISR_Timer-Impl.h">
67+
<Filter>Header Files</Filter>
68+
</ClInclude>
69+
<ClInclude Include="Timers\ESP8266_ISR_Timer.h">
70+
<Filter>Header Files</Filter>
71+
</ClInclude>
72+
<ClInclude Include="Timers\TimerInterrupt.h">
73+
<Filter>Header Files</Filter>
74+
</ClInclude>
6075
</ItemGroup>
6176
<ItemGroup>
6277
<ClCompile Include="DayTime.cpp">
@@ -80,5 +95,11 @@
8095
<ClCompile Include="MeadeCommandProcessor.cpp">
8196
<Filter>Source Files</Filter>
8297
</ClCompile>
98+
<ClCompile Include="InterruptCallback.cpp">
99+
<Filter>Source Files</Filter>
100+
</ClCompile>
101+
<ClCompile Include="Timers\TimerInterrupt.cpp">
102+
<Filter>Source Files</Filter>
103+
</ClCompile>
83104
</ItemGroup>
84105
</Project>

Software/Arduino code/OpenAstroTracker/b_setup.ino

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,11 @@ void setup() {
2929
#endif
3030

3131
//debug_init();
32-
//Serial.begin(38400);
3332
Serial.begin(57600);
3433
//BT.begin(9600);
3534

3635
#ifdef DEBUG_MODE
37-
Serial.println("Hello");
36+
Serial.println("Hello, universe!");
3837
#endif
3938

4039
// Show a splash screen
@@ -83,6 +82,9 @@ void setup() {
8382
// For LCD screen, it's better to initialize the target to where we are (RA)
8483
mount.targetRA() = mount.currentRA();
8584

85+
// Hook into the timers for periodic interrupts to run the steppers.
86+
mount.startTimerInterrupts();
87+
8688
// Start the tracker.
8789
mount.startSlewing(TRACKING);
8890

@@ -123,7 +125,7 @@ void setup() {
123125
#endif // HEADLESS_CLIENT
124126

125127
#ifdef DEBUG_MODE
126-
Serial.println("SetupDone");
128+
Serial.println("Setup done!");
127129
#endif
128130

129131
}

Software/Arduino code/OpenAstroTracker/c722_menuPOI.ino

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ PointOfInterest pointOfInterest[] = {
2323
{ ">M101 Pinwheel", 14, 3, 56, 54, 15, 0 },
2424
// Add new items above here, not below.
2525
{ ">Home" , 0, 0, 0, 90, 0, 0 },
26+
{ ">Unpark" , 0, 0, 0, 90, 0, 0 },
2627
{ ">Park" , 0, 0, 0, 90, 0, 0 },
2728
// And definitely don't add here.
2829
};
2930

3031
int currentPOI = 0;
3132
int parkPOI = sizeof(pointOfInterest) / sizeof(pointOfInterest[0]) - 1;
32-
byte homePOI = sizeof(pointOfInterest) / sizeof(pointOfInterest[0]) - 2;
33+
int unparkPOI = sizeof(pointOfInterest) / sizeof(pointOfInterest[0]) - 2;
34+
byte homePOI = sizeof(pointOfInterest) / sizeof(pointOfInterest[0]) - 3;
3335

3436
bool processPOIKeys() {
3537
byte key;
@@ -45,6 +47,9 @@ bool processPOIKeys() {
4547
else if (currentPOI == parkPOI) {
4648
mount.park();
4749
}
50+
else if (currentPOI == unparkPOI) {
51+
mount.startSlewing(TRACKING);
52+
}
4853
else {
4954
PointOfInterest* poi = &pointOfInterest[currentPOI];
5055
mount.targetRA().set(poi->hourRA, poi->minRA, poi->secRA);

0 commit comments

Comments
 (0)