Telescope Control Library
Axis.h@19:fd854309cb4c, 2018-09-24 (annotated)
- 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?
User | Revision | Line number | New 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 |