Telescope Control Library

Dependents:   PushToGo-F429

Committer:
caoyu@caoyuan9642-desktop.MIT.EDU
Date:
Mon Sep 24 19:36:48 2018 -0400
Revision:
19:fd854309cb4c
Parent:
10:e356188d208e
Fix bug in nudging with small speeds mentioned in the last commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
caoyuan9642 0:6cb2eaf8b133 1 /*
caoyuan9642 0:6cb2eaf8b133 2 * Axis.h
caoyuan9642 0:6cb2eaf8b133 3 *
caoyuan9642 2:2ee28add0821 4 * Created on: 2018��2��24��
caoyuan9642 0:6cb2eaf8b133 5 * Author: caoyuan9642
caoyuan9642 0:6cb2eaf8b133 6 */
caoyuan9642 0:6cb2eaf8b133 7
caoyuan9642 0:6cb2eaf8b133 8 #ifndef PUSHTOGO_AXIS_H_
caoyuan9642 0:6cb2eaf8b133 9 #define PUSHTOGO_AXIS_H_
caoyuan9642 0:6cb2eaf8b133 10 #include "StepperMotor.h"
caoyuan9642 0:6cb2eaf8b133 11 #include <math.h>
caoyuan9642 0:6cb2eaf8b133 12 #include "mbed.h"
caoyuan9642 0:6cb2eaf8b133 13 #include "CelestialMath.h"
caoyuan9642 0:6cb2eaf8b133 14 #include "TelescopeConfiguration.h"
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 15 #include "PEC.h"
caoyuan9642 0:6cb2eaf8b133 16
caoyuan9642 0:6cb2eaf8b133 17 //#define AXIS_SLEW_SIGNAL 0x00010000
caoyuan9642 0:6cb2eaf8b133 18 #define AXIS_GUIDE_SIGNAL 0x00020000
caoyuan9642 0:6cb2eaf8b133 19 #define AXIS_STOP_SIGNAL 0x00040000
caoyuan9642 0:6cb2eaf8b133 20 #define AXIS_EMERGE_STOP_SIGNAL 0x00080000
caoyuan9642 0:6cb2eaf8b133 21 #define AXIS_STOP_KEEPSPEED_SIGNAL 0x00100000
caoyuan9642 0:6cb2eaf8b133 22 #define AXIS_SPEEDCHANGE_SIGNAL 0x00200000
caoyuan9642 0:6cb2eaf8b133 23
caoyuan9642 0:6cb2eaf8b133 24 /**
caoyuan9642 0:6cb2eaf8b133 25 * status of the Axis object
caoyuan9642 0:6cb2eaf8b133 26 */
caoyuan9642 0:6cb2eaf8b133 27 typedef enum
caoyuan9642 0:6cb2eaf8b133 28 {
caoyuan9642 0:6cb2eaf8b133 29 AXIS_STOPPED = 0, AXIS_SLEWING, AXIS_TRACKING, AXIS_INERTIAL
caoyuan9642 0:6cb2eaf8b133 30 } axisstatus_t;
caoyuan9642 0:6cb2eaf8b133 31
caoyuan9642 0:6cb2eaf8b133 32 typedef enum
caoyuan9642 0:6cb2eaf8b133 33 {
caoyuan9642 0:6cb2eaf8b133 34 AXIS_NOT_SLEWING,
caoyuan9642 0:6cb2eaf8b133 35 AXIS_SLEW_ACCELERATING,
caoyuan9642 0:6cb2eaf8b133 36 AXIS_SLEW_CONSTANT_SPEED,
caoyuan9642 0:6cb2eaf8b133 37 AXIS_SLEW_DECELERATING
caoyuan9642 0:6cb2eaf8b133 38 } axisslewstate_t;
caoyuan9642 0:6cb2eaf8b133 39
caoyuan9642 0:6cb2eaf8b133 40 /** Define the rotation direction
caoyuan9642 0:6cb2eaf8b133 41 * AXIS_ROTATE_POSITIVE: +angle
caoyuan9642 0:6cb2eaf8b133 42 * AXIS_ROTATE_NEGATIVE: -angle
caoyuan9642 0:6cb2eaf8b133 43 */
caoyuan9642 0:6cb2eaf8b133 44 typedef enum
caoyuan9642 0:6cb2eaf8b133 45 {
caoyuan9642 0:6cb2eaf8b133 46 AXIS_ROTATE_STOP = 0, AXIS_ROTATE_POSITIVE = 1, AXIS_ROTATE_NEGATIVE = 2
caoyuan9642 0:6cb2eaf8b133 47 } axisrotdir_t;
caoyuan9642 0:6cb2eaf8b133 48
caoyuan9642 0:6cb2eaf8b133 49 typedef enum
caoyuan9642 0:6cb2eaf8b133 50 {
caoyuan9642 0:6cb2eaf8b133 51 FINISH_COMPLETE = 0,
caoyuan9642 0:6cb2eaf8b133 52 FINISH_STOPPED = 1,
caoyuan9642 0:6cb2eaf8b133 53 FINISH_EMERG_STOPPED = 2,
caoyuan9642 0:6cb2eaf8b133 54 FINISH_ERROR = 4
caoyuan9642 0:6cb2eaf8b133 55 } finishstate_t;
caoyuan9642 0:6cb2eaf8b133 56
caoyu@caoyuan9642-desktop.MIT.EDU 10:e356188d208e 57 class PEC;
caoyu@caoyuan9642-desktop.MIT.EDU 10:e356188d208e 58
caoyuan9642 0:6cb2eaf8b133 59 /** General Rotating Axis class
caoyuan9642 0:6cb2eaf8b133 60 * Handles low-level stepper timing, calculates the speed and distance to rotate
caoyuan9642 0:6cb2eaf8b133 61 * API provides comprehensive slewing, tracking and guiding.
caoyuan9642 0:6cb2eaf8b133 62 */
caoyuan9642 0:6cb2eaf8b133 63 class Axis
caoyuan9642 0:6cb2eaf8b133 64 {
caoyuan9642 0:6cb2eaf8b133 65 public:
caoyuan9642 0:6cb2eaf8b133 66
caoyuan9642 0:6cb2eaf8b133 67 /**
caoyuan9642 0:6cb2eaf8b133 68 * Create a RotationAxis object
caoyuan9642 0:6cb2eaf8b133 69 * @param stepsPerDeg Steps per degree of the stepper motor
caoyuan9642 0:6cb2eaf8b133 70 * @param stepper Pointer to stepper driver to use
caoyuan9642 3:d3ea3816dad7 71 * @param name Name of the axis, for example "RA" or "DEC"
caoyuan9642 0:6cb2eaf8b133 72 */
caoyuan9642 0:6cb2eaf8b133 73 Axis(double stepsPerDeg, StepperMotor *stepper, const char *name = "Axis");
caoyuan9642 0:6cb2eaf8b133 74
caoyuan9642 0:6cb2eaf8b133 75 virtual ~Axis();
caoyuan9642 0:6cb2eaf8b133 76
caoyu@caoyuan9642-desktop.MIT.EDU 8:21a33760bf10 77 friend class PEC;
caoyu@caoyuan9642-desktop.MIT.EDU 8:21a33760bf10 78
caoyuan9642 0:6cb2eaf8b133 79 /**
caoyuan9642 3:d3ea3816dad7 80 * Asynchronously perform a goto to a specified angle (in degrees) in the specified direction with slewing rate
caoyuan9642 0:6cb2eaf8b133 81 * @param dir Rotation direction
caoyuan9642 0:6cb2eaf8b133 82 * @param angleDeg Angle to rotate
caoyuan9642 3:d3ea3816dad7 83 * @param withCorrection Use correction or not. If false, the mount will roughly slew to the target. A further correction step is needed (slewed again) if precision positioning is needed. Useful
caoyuan9642 3:d3ea3816dad7 84 * for long slews where the target would have changed during the slew.
caoyuan9642 0:6cb2eaf8b133 85 * @return osStatus
caoyuan9642 0:6cb2eaf8b133 86 */
caoyuan9642 0:6cb2eaf8b133 87 osStatus startSlewTo(axisrotdir_t dir, double angle, bool withCorrection =
caoyuan9642 0:6cb2eaf8b133 88 true)
caoyuan9642 0:6cb2eaf8b133 89 {
caoyuan9642 0:6cb2eaf8b133 90 msg_t *message = task_pool.alloc();
caoyuan9642 0:6cb2eaf8b133 91 if (!message)
caoyuan9642 0:6cb2eaf8b133 92 {
caoyuan9642 0:6cb2eaf8b133 93 return osErrorNoMemory;
caoyuan9642 0:6cb2eaf8b133 94 }
caoyuan9642 0:6cb2eaf8b133 95 message->signal = msg_t::SIGNAL_SLEW_TO;
caoyuan9642 0:6cb2eaf8b133 96 message->value = angle;
caoyuan9642 0:6cb2eaf8b133 97 message->dir = dir;
caoyuan9642 0:6cb2eaf8b133 98 message->withCorrection = withCorrection;
caoyuan9642 0:6cb2eaf8b133 99 osStatus s;
caoyuan9642 0:6cb2eaf8b133 100
caoyuan9642 0:6cb2eaf8b133 101 debug_if(0, "%s: CLR SLEW 0x%08x\n", axisName, Thread::gettid());
caoyuan9642 0:6cb2eaf8b133 102 slew_finish_sem.wait(0); // Make sure the semaphore is cleared. THIS MUST BE DONE BEFORE THE MESSAGE IS ENQUEUED
caoyuan9642 0:6cb2eaf8b133 103
caoyuan9642 0:6cb2eaf8b133 104 if ((s = task_queue.put(message)) != osOK)
caoyuan9642 0:6cb2eaf8b133 105 {
caoyuan9642 0:6cb2eaf8b133 106 task_pool.free(message);
caoyuan9642 0:6cb2eaf8b133 107 return s;
caoyuan9642 0:6cb2eaf8b133 108 }
caoyuan9642 0:6cb2eaf8b133 109
caoyuan9642 0:6cb2eaf8b133 110 return osOK;
caoyuan9642 0:6cb2eaf8b133 111 }
caoyuan9642 0:6cb2eaf8b133 112
caoyuan9642 0:6cb2eaf8b133 113 /**
caoyuan9642 0:6cb2eaf8b133 114 * Wait for a slew to finish. Must be called after and only once after a call to startSlewTo, from the same thread
caoyuan9642 3:d3ea3816dad7 115 * @return Finish state of the slew, signaling whether there are errors or being stopped/emergency stopped
caoyuan9642 0:6cb2eaf8b133 116 */
caoyuan9642 0:6cb2eaf8b133 117 finishstate_t waitForSlew()
caoyuan9642 0:6cb2eaf8b133 118 {
caoyuan9642 0:6cb2eaf8b133 119 debug_if(0, "%s: WAIT SLEW 0x%08x\n", axisName, Thread::gettid());
caoyuan9642 0:6cb2eaf8b133 120 if (slew_finish_sem.wait() <= 0)
caoyuan9642 0:6cb2eaf8b133 121 {
caoyuan9642 0:6cb2eaf8b133 122 return FINISH_ERROR;
caoyuan9642 0:6cb2eaf8b133 123 }
caoyuan9642 0:6cb2eaf8b133 124
caoyuan9642 0:6cb2eaf8b133 125 // Check mount status
caoyuan9642 0:6cb2eaf8b133 126 return slew_finish_state;
caoyuan9642 0:6cb2eaf8b133 127 }
caoyuan9642 0:6cb2eaf8b133 128
caoyuan9642 3:d3ea3816dad7 129 /**
caoyuan9642 3:d3ea3816dad7 130 * Synchronously perform a goto to a specified angle (in degrees) in the specified direction with slewing rate
caoyuan9642 0:6cb2eaf8b133 131 * It will perform an acceleration, a GoTo, and a deceleration before returning
caoyuan9642 0:6cb2eaf8b133 132 * @param dir Rotation direction
caoyuan9642 0:6cb2eaf8b133 133 * @param angleDeg Angle to rotate
caoyuan9642 0:6cb2eaf8b133 134 * @return osStatus
caoyuan9642 3:d3ea3816dad7 135 * @sa{startSlewTo}
caoyuan9642 0:6cb2eaf8b133 136 */
caoyuan9642 0:6cb2eaf8b133 137 osStatus slewTo(axisrotdir_t dir, double angle)
caoyuan9642 0:6cb2eaf8b133 138 {
caoyuan9642 0:6cb2eaf8b133 139 osStatus s;
caoyuan9642 0:6cb2eaf8b133 140 if ((s = startSlewTo(dir, angle)) != osOK)
caoyuan9642 0:6cb2eaf8b133 141 return s;
caoyuan9642 0:6cb2eaf8b133 142 return waitForSlew();
caoyuan9642 0:6cb2eaf8b133 143 }
caoyuan9642 0:6cb2eaf8b133 144
caoyuan9642 3:d3ea3816dad7 145 /** Perform a indefinite slewing, until stop() is called
caoyuan9642 0:6cb2eaf8b133 146 * @param dir Direction to start continuous slewing
caoyuan9642 0:6cb2eaf8b133 147 * @return osStatus
caoyuan9642 3:d3ea3816dad7 148 * @sa{stop}
caoyuan9642 0:6cb2eaf8b133 149 */
caoyuan9642 0:6cb2eaf8b133 150 osStatus startSlewingIndefinite(axisrotdir_t dir)
caoyuan9642 0:6cb2eaf8b133 151 {
caoyuan9642 0:6cb2eaf8b133 152 msg_t *message = task_pool.alloc();
caoyuan9642 0:6cb2eaf8b133 153 if (!message)
caoyuan9642 0:6cb2eaf8b133 154 {
caoyuan9642 0:6cb2eaf8b133 155 return osErrorNoMemory;
caoyuan9642 0:6cb2eaf8b133 156 }
caoyuan9642 0:6cb2eaf8b133 157 message->signal = msg_t::SIGNAL_SLEW_INDEFINITE;
caoyuan9642 0:6cb2eaf8b133 158 message->dir = dir;
caoyuan9642 0:6cb2eaf8b133 159 message->withCorrection = false;
caoyuan9642 0:6cb2eaf8b133 160 osStatus s;
caoyuan9642 0:6cb2eaf8b133 161 if ((s = task_queue.put(message)) != osOK)
caoyuan9642 0:6cb2eaf8b133 162 {
caoyuan9642 0:6cb2eaf8b133 163 task_pool.free(message);
caoyuan9642 0:6cb2eaf8b133 164 return s;
caoyuan9642 0:6cb2eaf8b133 165 }
caoyuan9642 0:6cb2eaf8b133 166
caoyuan9642 0:6cb2eaf8b133 167 return osOK;
caoyuan9642 0:6cb2eaf8b133 168 }
caoyuan9642 0:6cb2eaf8b133 169
caoyuan9642 0:6cb2eaf8b133 170 /** Start tracking, until stop() is called
caoyuan9642 0:6cb2eaf8b133 171 * @param dir Direction to start continuous slewing
caoyuan9642 0:6cb2eaf8b133 172 * @return osStatus
caoyuan9642 0:6cb2eaf8b133 173 * @sa{RotationAxis::stop}
caoyuan9642 0:6cb2eaf8b133 174 */
caoyuan9642 0:6cb2eaf8b133 175 osStatus startTracking(axisrotdir_t dir)
caoyuan9642 0:6cb2eaf8b133 176 {
caoyuan9642 0:6cb2eaf8b133 177 msg_t *message = task_pool.alloc();
caoyuan9642 0:6cb2eaf8b133 178 if (!message)
caoyuan9642 0:6cb2eaf8b133 179 {
caoyuan9642 0:6cb2eaf8b133 180 return osErrorNoMemory;
caoyuan9642 0:6cb2eaf8b133 181 }
caoyuan9642 0:6cb2eaf8b133 182 message->signal = msg_t::SIGNAL_TRACK;
caoyuan9642 0:6cb2eaf8b133 183 message->dir = dir;
caoyuan9642 0:6cb2eaf8b133 184 osStatus s;
caoyuan9642 0:6cb2eaf8b133 185 if ((s = task_queue.put(message)) != osOK)
caoyuan9642 0:6cb2eaf8b133 186 {
caoyuan9642 0:6cb2eaf8b133 187 task_pool.free(message);
caoyuan9642 0:6cb2eaf8b133 188 return s;
caoyuan9642 0:6cb2eaf8b133 189 }
caoyuan9642 0:6cb2eaf8b133 190
caoyuan9642 0:6cb2eaf8b133 191 return osOK;
caoyuan9642 0:6cb2eaf8b133 192 }
caoyuan9642 0:6cb2eaf8b133 193
caoyuan9642 0:6cb2eaf8b133 194 /**
caoyuan9642 3:d3ea3816dad7 195 * Guide on specified direction for specified time
caoyuan9642 3:d3ea3816dad7 196 * @param dir Direction of guiding
caoyuan9642 3:d3ea3816dad7 197 * @param time_ms Time to guide in milliseconds
caoyuan9642 3:d3ea3816dad7 198 * @return osStatus
caoyuan9642 3:d3ea3816dad7 199 */
caoyuan9642 0:6cb2eaf8b133 200 osStatus guide(axisrotdir_t dir, int time_ms)
caoyuan9642 0:6cb2eaf8b133 201 {
caoyuan9642 0:6cb2eaf8b133 202 if (dir == AXIS_ROTATE_NEGATIVE)
caoyuan9642 0:6cb2eaf8b133 203 time_ms = -time_ms;
caoyuan9642 0:6cb2eaf8b133 204 // Put the guide pulse into the queue
caoyuan9642 0:6cb2eaf8b133 205 osStatus s;
caoyuan9642 0:6cb2eaf8b133 206 if ((s = guide_queue.put((void*) (time_ms))) != osOK)
caoyuan9642 0:6cb2eaf8b133 207 {
caoyuan9642 0:6cb2eaf8b133 208 return s;
caoyuan9642 0:6cb2eaf8b133 209 }
caoyuan9642 0:6cb2eaf8b133 210 task_thread->signal_set(AXIS_GUIDE_SIGNAL); // Signal the task thread to read the queue
caoyuan9642 0:6cb2eaf8b133 211 return osOK;
caoyuan9642 0:6cb2eaf8b133 212 }
caoyuan9642 0:6cb2eaf8b133 213
caoyuan9642 0:6cb2eaf8b133 214 /**
caoyuan9642 0:6cb2eaf8b133 215 * Remove all queued commands if there are any. This function should be called if you want to ensure the mount if completely stopped
caoyuan9642 0:6cb2eaf8b133 216 */
caoyuan9642 0:6cb2eaf8b133 217 void flushCommandQueue()
caoyuan9642 0:6cb2eaf8b133 218 {
caoyuan9642 0:6cb2eaf8b133 219 while (!task_queue.empty())
caoyuan9642 0:6cb2eaf8b133 220 {
caoyuan9642 0:6cb2eaf8b133 221 osEvent evt = task_queue.get(0);
caoyuan9642 0:6cb2eaf8b133 222 if (evt.status == osEventMessage)
caoyuan9642 0:6cb2eaf8b133 223 {
caoyuan9642 0:6cb2eaf8b133 224 task_pool.free((msg_t*) evt.value.p);
caoyuan9642 0:6cb2eaf8b133 225 }
caoyuan9642 0:6cb2eaf8b133 226 }
caoyuan9642 0:6cb2eaf8b133 227 }
caoyuan9642 0:6cb2eaf8b133 228
caoyuan9642 0:6cb2eaf8b133 229 /**
caoyuan9642 3:d3ea3816dad7 230 * Stop slewing or tracking. Calling this function will stop the axis from slewing, or tracking
caoyuan9642 3:d3ea3816dad7 231 * @note In the case of slewing, the axis will perform a deceleration and then stop
caoyuan9642 0:6cb2eaf8b133 232 * @note If there are queued commands, they will be run immediately afterwards
caoyuan9642 0:6cb2eaf8b133 233 */
caoyuan9642 0:6cb2eaf8b133 234 void stop()
caoyuan9642 0:6cb2eaf8b133 235 {
caoyuan9642 0:6cb2eaf8b133 236 flushCommandQueue();
caoyuan9642 0:6cb2eaf8b133 237 task_thread->signal_set(AXIS_STOP_SIGNAL);
caoyuan9642 0:6cb2eaf8b133 238 }
caoyuan9642 0:6cb2eaf8b133 239
caoyuan9642 0:6cb2eaf8b133 240 /**
caoyuan9642 0:6cb2eaf8b133 241 * Perform an emergency stop. This should stop in ALL situations IMMEDIATELY without performing deceleration.
caoyuan9642 0:6cb2eaf8b133 242 * @note this call will kill all queued commands, so the mount will be fully stopped
caoyuan9642 0:6cb2eaf8b133 243 */
caoyuan9642 0:6cb2eaf8b133 244 void emergency_stop()
caoyuan9642 0:6cb2eaf8b133 245 {
caoyuan9642 0:6cb2eaf8b133 246 flushCommandQueue();
caoyuan9642 0:6cb2eaf8b133 247 task_thread->signal_set(AXIS_EMERGE_STOP_SIGNAL);
caoyuan9642 0:6cb2eaf8b133 248 }
caoyuan9642 0:6cb2eaf8b133 249
caoyuan9642 0:6cb2eaf8b133 250 /**
caoyuan9642 3:d3ea3816dad7 251 * Only takes effect when decelerating from a slew. Signals the axis to keep its current speed, and enters AXIS_INERTIAL state.
caoyuan9642 0:6cb2eaf8b133 252 * This state can be exited by performing another slew/slew_indefinite and stopped in the normal way
caoyuan9642 0:6cb2eaf8b133 253 */
caoyuan9642 0:6cb2eaf8b133 254 void stopKeepSpeed()
caoyuan9642 0:6cb2eaf8b133 255 {
caoyuan9642 0:6cb2eaf8b133 256 task_thread->signal_set(AXIS_STOP_KEEPSPEED_SIGNAL);
caoyuan9642 0:6cb2eaf8b133 257 }
caoyuan9642 0:6cb2eaf8b133 258
caoyuan9642 3:d3ea3816dad7 259 /** Set current angle of the axis in degrees.
caoyuan9642 3:d3ea3816dad7 260 * @param new angle
caoyuan9642 3:d3ea3816dad7 261 * @note Must be called only when the axis is stopped, otherwise behavior is unexpected
caoyuan9642 0:6cb2eaf8b133 262 */
caoyuan9642 0:6cb2eaf8b133 263 void setAngleDeg(double angle)
caoyuan9642 0:6cb2eaf8b133 264 {
caoyuan9642 0:6cb2eaf8b133 265 stepper->setStepCount(angle * stepsPerDeg);
caoyuan9642 0:6cb2eaf8b133 266 }
caoyuan9642 0:6cb2eaf8b133 267
caoyuan9642 3:d3ea3816dad7 268 /** Returns the current angle of the axis in degrees
caoyuan9642 3:d3ea3816dad7 269 * @note Can be called in any context
caoyuan9642 0:6cb2eaf8b133 270 */
caoyuan9642 0:6cb2eaf8b133 271 double getAngleDeg()
caoyuan9642 0:6cb2eaf8b133 272 {
caoyuan9642 0:6cb2eaf8b133 273 return remainder(stepper->getStepCount() / stepsPerDeg, 360);
caoyuan9642 0:6cb2eaf8b133 274 }
caoyuan9642 0:6cb2eaf8b133 275
caoyuan9642 3:d3ea3816dad7 276 /** Returns the axis status
caoyuan9642 3:d3ea3816dad7 277 */
caoyuan9642 0:6cb2eaf8b133 278 axisstatus_t getStatus()
caoyuan9642 0:6cb2eaf8b133 279 {
caoyuan9642 0:6cb2eaf8b133 280 return status;
caoyuan9642 0:6cb2eaf8b133 281 }
caoyuan9642 0:6cb2eaf8b133 282
caoyu@caoyuan9642-desktop.MIT.EDU 10:e356188d208e 283 /** Returns the current slew speed (only for indefinite slew)
caoyuan9642 0:6cb2eaf8b133 284 */
caoyuan9642 0:6cb2eaf8b133 285 double getSlewSpeed() const
caoyuan9642 0:6cb2eaf8b133 286 {
caoyuan9642 0:6cb2eaf8b133 287 return slewSpeed;
caoyuan9642 0:6cb2eaf8b133 288 }
caoyuan9642 0:6cb2eaf8b133 289
caoyu@caoyuan9642-desktop.MIT.EDU 10:e356188d208e 290 /** Set slew speed of the axis (only for indefinite slew)
caoyuan9642 3:d3ea3816dad7 291 * @param new slew speed in deg/s
caoyuan9642 3:d3ea3816dad7 292 * @note Can now be called when a indefinite slew is in progress.
caoyuan9642 3:d3ea3816dad7 293 * @note If called during a target slew, the speed will be updated on the next slew
caoyuan9642 0:6cb2eaf8b133 294 */
caoyuan9642 0:6cb2eaf8b133 295 void setSlewSpeed(double slewSpeed)
caoyuan9642 0:6cb2eaf8b133 296 {
caoyuan9642 0:6cb2eaf8b133 297 if (slewSpeed > 0)
caoyuan9642 0:6cb2eaf8b133 298 this->slewSpeed = slewSpeed;
caoyuan9642 0:6cb2eaf8b133 299
caoyuan9642 3:d3ea3816dad7 300 task_thread->signal_set(AXIS_SPEEDCHANGE_SIGNAL); // Signal the thread to use the new speed during a indefinite slew
caoyuan9642 0:6cb2eaf8b133 301 }
caoyuan9642 0:6cb2eaf8b133 302
caoyuan9642 3:d3ea3816dad7 303 /**
caoyuan9642 3:d3ea3816dad7 304 * Returns track speed of the axis in units of sidereal speed
caoyuan9642 3:d3ea3816dad7 305 */
caoyuan9642 0:6cb2eaf8b133 306 double getTrackSpeedSidereal() const
caoyuan9642 0:6cb2eaf8b133 307 {
caoyuan9642 0:6cb2eaf8b133 308 return trackSpeed / sidereal_speed;
caoyuan9642 0:6cb2eaf8b133 309 }
caoyuan9642 0:6cb2eaf8b133 310
caoyuan9642 3:d3ea3816dad7 311 /** Set track speed in sidereal speed
caoyuan9642 3:d3ea3816dad7 312 * @param new track speed in sidereal rate
caoyuan9642 0:6cb2eaf8b133 313 * @note Must be called only when the axis is stopped
caoyuan9642 0:6cb2eaf8b133 314 */
caoyuan9642 0:6cb2eaf8b133 315 void setTrackSpeedSidereal(double trackSpeed)
caoyuan9642 0:6cb2eaf8b133 316 {
caoyuan9642 0:6cb2eaf8b133 317 if (trackSpeed >= 0)
caoyuan9642 0:6cb2eaf8b133 318 {
caoyuan9642 0:6cb2eaf8b133 319 this->trackSpeed = trackSpeed * sidereal_speed;
caoyuan9642 0:6cb2eaf8b133 320 }
caoyuan9642 0:6cb2eaf8b133 321 }
caoyuan9642 0:6cb2eaf8b133 322
caoyuan9642 3:d3ea3816dad7 323 /**
caoyuan9642 3:d3ea3816dad7 324 * Returns guide speed of the axis in units of sidereal speed
caoyuan9642 3:d3ea3816dad7 325 */
caoyuan9642 0:6cb2eaf8b133 326 double getGuideSpeedSidereal() const
caoyuan9642 0:6cb2eaf8b133 327 {
caoyuan9642 0:6cb2eaf8b133 328 return guideSpeed / sidereal_speed;
caoyuan9642 0:6cb2eaf8b133 329 }
caoyuan9642 0:6cb2eaf8b133 330
caoyuan9642 3:d3ea3816dad7 331 /** @param new guide speed in sidereal rate.
caoyuan9642 3:d3ea3816dad7 332 * @note If called when a pulse guide is being performed, the value will be updated on the next pulse
caoyuan9642 0:6cb2eaf8b133 333 */
caoyuan9642 0:6cb2eaf8b133 334 void setGuideSpeedSidereal(double guideSpeed)
caoyuan9642 0:6cb2eaf8b133 335 {
caoyuan9642 0:6cb2eaf8b133 336 if (guideSpeed > 0)
caoyuan9642 0:6cb2eaf8b133 337 this->guideSpeed = guideSpeed * sidereal_speed;
caoyuan9642 0:6cb2eaf8b133 338 }
caoyuan9642 0:6cb2eaf8b133 339
caoyuan9642 3:d3ea3816dad7 340 /**
caoyuan9642 3:d3ea3816dad7 341 * Returns current speed (deg/s) of the axis
caoyuan9642 3:d3ea3816dad7 342 */
caoyuan9642 0:6cb2eaf8b133 343 double getCurrentSpeed() const
caoyuan9642 0:6cb2eaf8b133 344 {
caoyuan9642 0:6cb2eaf8b133 345 return currentSpeed;
caoyuan9642 0:6cb2eaf8b133 346 }
caoyuan9642 0:6cb2eaf8b133 347
caoyuan9642 3:d3ea3816dad7 348 /**
caoyuan9642 3:d3ea3816dad7 349 * Returns which phase of slewing the axis is currently in
caoyuan9642 3:d3ea3816dad7 350 */
caoyuan9642 0:6cb2eaf8b133 351 axisslewstate_t getSlewState() const
caoyuan9642 0:6cb2eaf8b133 352 {
caoyuan9642 0:6cb2eaf8b133 353 return slewState;
caoyuan9642 0:6cb2eaf8b133 354 }
caoyuan9642 0:6cb2eaf8b133 355
caoyuan9642 3:d3ea3816dad7 356 /**
caoyuan9642 3:d3ea3816dad7 357 * Returns current axis rotation direction
caoyuan9642 3:d3ea3816dad7 358 */
caoyuan9642 0:6cb2eaf8b133 359 axisrotdir_t getCurrentDirection() const
caoyuan9642 0:6cb2eaf8b133 360 {
caoyuan9642 0:6cb2eaf8b133 361 return currentDirection;
caoyuan9642 0:6cb2eaf8b133 362 }
caoyuan9642 2:2ee28add0821 363
caoyuan9642 3:d3ea3816dad7 364 /**
caoyuan9642 3:d3ea3816dad7 365 * Return true if a guiding pulse is being performed
caoyuan9642 3:d3ea3816dad7 366 */
caoyuan9642 2:2ee28add0821 367 bool isGuiding() const
caoyuan9642 2:2ee28add0821 368 {
caoyuan9642 2:2ee28add0821 369 return guiding;
caoyuan9642 2:2ee28add0821 370 }
caoyuan9642 0:6cb2eaf8b133 371
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 372 PEC* getPEC(){
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 373 return pec;
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 374 }
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 375
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 376 void setPEC(PEC* pec) {
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 377 this->pec = pec;
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 378 }
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 379
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 380 bool isPECEnabled() const {
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 381 return pecEnabled;
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 382 }
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 383
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 384 void setPECEnabled(bool pecEnabled) {
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 385 this->pecEnabled = pecEnabled;
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 386 }
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 387
caoyuan9642 0:6cb2eaf8b133 388 protected:
caoyuan9642 0:6cb2eaf8b133 389
caoyuan9642 0:6cb2eaf8b133 390 typedef struct
caoyuan9642 0:6cb2eaf8b133 391 {
caoyuan9642 0:6cb2eaf8b133 392 enum sig_t
caoyuan9642 0:6cb2eaf8b133 393 {
caoyuan9642 0:6cb2eaf8b133 394 SIGNAL_SLEW_TO = 0, SIGNAL_SLEW_INDEFINITE, SIGNAL_TRACK
caoyuan9642 0:6cb2eaf8b133 395 } signal;
caoyuan9642 0:6cb2eaf8b133 396 double value;
caoyuan9642 0:6cb2eaf8b133 397 axisrotdir_t dir;bool withCorrection;
caoyuan9642 3:d3ea3816dad7 398 } msg_t; /// Message for inter-thread communication
caoyuan9642 0:6cb2eaf8b133 399
caoyuan9642 0:6cb2eaf8b133 400 /*Configurations*/
caoyuan9642 0:6cb2eaf8b133 401 double stepsPerDeg; ///steps per degree
caoyuan9642 0:6cb2eaf8b133 402 StepperMotor *stepper; ///Pointer to stepper motor
caoyuan9642 3:d3ea3816dad7 403 const char *axisName; /// Name of the axis
caoyuan9642 3:d3ea3816dad7 404 char *taskName; /// Name of the thread
caoyuan9642 0:6cb2eaf8b133 405
caoyuan9642 0:6cb2eaf8b133 406 /*Runtime values*/
caoyuan9642 0:6cb2eaf8b133 407 volatile double currentSpeed; /// Current speed in deg/s
caoyuan9642 0:6cb2eaf8b133 408 volatile axisrotdir_t currentDirection; // Current direction
caoyu@caoyuan9642-desktop.MIT.EDU 10:e356188d208e 409 double slewSpeed; /// Slewing speed in deg/s (only for indefinite slew)
caoyuan9642 0:6cb2eaf8b133 410 double trackSpeed; /// Tracking speed in deg/s (no accel/deceleration)
caoyuan9642 3:d3ea3816dad7 411 double guideSpeed; /// Guide speed in deg/s. this amount will be subtracted/added to the trackSpeed
caoyuan9642 3:d3ea3816dad7 412 volatile axisstatus_t status; /// State of the axis
caoyuan9642 3:d3ea3816dad7 413 volatile axisslewstate_t slewState; /// Phase of slewing
caoyuan9642 0:6cb2eaf8b133 414 Thread *task_thread; ///Thread for executing all lower-level tasks
caoyuan9642 0:6cb2eaf8b133 415 Queue<msg_t, 16> task_queue; ///Queue of messages
caoyuan9642 0:6cb2eaf8b133 416 Queue<void, 16> guide_queue; ///Guide pulse queue
caoyuan9642 0:6cb2eaf8b133 417 MemoryPool<msg_t, 16> task_pool; ///MemoryPool for allocating messages
caoyuan9642 3:d3ea3816dad7 418 Semaphore slew_finish_sem; /// Semaphore for signaling finished slew
caoyuan9642 3:d3ea3816dad7 419 volatile finishstate_t slew_finish_state; /// Finish state of slew
caoyuan9642 3:d3ea3816dad7 420 Timer tim; /// Timer
caoyuan9642 3:d3ea3816dad7 421 bool guiding; /// isGuiding
caoyuan9642 0:6cb2eaf8b133 422
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 423 PEC *pec; /// PEC
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 424 bool pecEnabled; /// Is pec enabled
caoyu@caoyuan9642-desktop.MIT.EDU 9:d0413a9b1386 425
caoyuan9642 3:d3ea3816dad7 426 void task(); /// Task thread entrance
caoyuan9642 0:6cb2eaf8b133 427
caoyuan9642 0:6cb2eaf8b133 428 /*Low-level functions for internal use*/
caoyuan9642 3:d3ea3816dad7 429 void slew(axisrotdir_t dir, double dest, bool indefinite, bool useCorrection);
caoyuan9642 0:6cb2eaf8b133 430 void track(axisrotdir_t dir);
caoyuan9642 0:6cb2eaf8b133 431
caoyuan9642 0:6cb2eaf8b133 432 /*These functions can be overriden to provide mode selection before each type of operation is performed, such as microstepping and current setting*/
caoyuan9642 3:d3ea3816dad7 433
caoyuan9642 3:d3ea3816dad7 434 /// Change low-level mode before slewing
caoyuan9642 0:6cb2eaf8b133 435 virtual void slew_mode()
caoyuan9642 0:6cb2eaf8b133 436 {
caoyuan9642 0:6cb2eaf8b133 437 }
caoyuan9642 3:d3ea3816dad7 438
caoyuan9642 3:d3ea3816dad7 439 /// Change low-level mode before tracking
caoyuan9642 0:6cb2eaf8b133 440 virtual void track_mode()
caoyuan9642 0:6cb2eaf8b133 441 {
caoyuan9642 0:6cb2eaf8b133 442 }
caoyuan9642 3:d3ea3816dad7 443
caoyuan9642 3:d3ea3816dad7 444 /// Change low-level mode before correcting
caoyuan9642 0:6cb2eaf8b133 445 virtual void correction_mode()
caoyuan9642 0:6cb2eaf8b133 446 {
caoyuan9642 0:6cb2eaf8b133 447 }
caoyuan9642 3:d3ea3816dad7 448
caoyuan9642 3:d3ea3816dad7 449 /// Change low-level mode before going idle
caoyuan9642 0:6cb2eaf8b133 450 virtual void idle_mode()
caoyuan9642 0:6cb2eaf8b133 451 {
caoyuan9642 0:6cb2eaf8b133 452 }
caoyuan9642 0:6cb2eaf8b133 453 }
caoyuan9642 0:6cb2eaf8b133 454 ;
caoyuan9642 0:6cb2eaf8b133 455
caoyuan9642 0:6cb2eaf8b133 456 #endif /* PUSHTOGO_AXIS_H_ */
caoyuan9642 0:6cb2eaf8b133 457