API Documentation v0.0.1
Loading...
Searching...
No Matches
Hornet_Stepper.h
1/**************************************************************************************
2 * ____ _ _ _
3 * / __ \ | | | | | |
4 * | | | |_ __ ___ _ __ | |__| | ___ _ __ _ __ ___| |_
5 * | | | | '_ \ / _ \ '_ \| __ |/ _ \| '__| '_ \ / _ \ __|
6 * | |__| | |_) | __/ | | | | | | (_) | | | | | | __/ |_
7 * \____/| .__/ \___|_| |_|_| |_|\___/|_| |_| |_|\___|\__|
8 * | |
9 * |_|
10 * ----------------------------------------------------------------------------------
11 * Copyright 2016-2024 OpenHornet
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 * ----------------------------------------------------------------------------------
25 * Note: All other portions of OpenHornet not within the 'OpenHornet-Software'
26 * GitHub repository is released under the Creative Commons Attribution -
27 * Non-Commercial - Share Alike License. (CC BY-NC-SA 4.0)
28 * ----------------------------------------------------------------------------------
29 * This Project uses Doxygen as a documentation generator.
30 * Please use Doxygen capable comments.
31 **************************************************************************************/
32
78#ifndef HORNET_STEPPER_H
79#define HORNET_STEPPER_H
80
81#include <AccelStepper.h>
82#include <Arduino.h>
83#include <stdlib.h>
84#include "DcsBios.h"
85#include <MultiMap.h> // by Rob Tillart
86
91struct MapPoint {
92 unsigned int value; // DCS-BIOS input value (0-65535)
93 unsigned int position; // Stepper step position (e.g. 0-720)
94 };
95
101private:
102 const int mechZero = 0; // Mechanical stop position (is always 0)
103 int zeroPos; // Dial zero position (e.g., 20 steps from mech 0)
104 int maxPos; // Maximum position (e.g., 720 steps from mech 0)
105 int dirForward; // Direction for forward movement (1 or -1)
106 unsigned int capValue; // DCS-BIOS value to cap at max mech stop
107 int normalSpeed; // Normal operating speed
108 int normalAccel; // Normal operating acceleration
109
110 MapPoint* mapPoints; // Array of value-position mapping pairs (optional)
111 uint8_t numMapPoints; // The size of mapPoints array
112 unsigned int* inputVals; // Extracted input values array for multiMapBS
113 unsigned int* outputPos; // Extracted output positions array for multiMapBS
114 bool useMultiMap; // Flag to use multiMap vs linear mapping
115
116 AccelStepper stepper; // Stepper motor object
117 bool homingInProgress; // Track if homing is in progress
118 bool testInProgress; // Track if test is in progress
119
120public:
121 // Track button states to manually trigger homing
122 // DCS-Bios expects these to be static
123 static bool ufcEntPressed; // UFC ENTER button state (static; shared across instances)
124 static bool ufcClrPressed; // UFC CLEAR button state (static; shared across instances)
125
126
144 HornetStepper(int coil1, int coil2, int coil3, int coil4,
145 int zeroPos, int maxPos, int dirForward,
146 unsigned int capValue = 65535,
147 int normalSpeed = 300,
148 int normalAccel = 600,
149 MapPoint* mapPoints = nullptr,
150 uint8_t numMapPoints = 0)
151 : stepper(AccelStepper::FULL4WIRE,
152 (dirForward == -1) ? coil3 : coil1,
153 (dirForward == -1) ? coil4 : coil2,
154 (dirForward == -1) ? coil1 : coil3,
155 (dirForward == -1) ? coil2 : coil4)
156 {
157 this->zeroPos = zeroPos;
158 this->maxPos = maxPos;
159 this->dirForward = dirForward;
160 this->capValue = capValue;
161 this->normalSpeed = normalSpeed;
162 this->normalAccel = normalAccel;
163 this->homingInProgress = false;
164 this->testInProgress = false;
165
166 stepper.setMaxSpeed(normalSpeed);
167 stepper.setAcceleration(normalAccel);
168
169 // Handle mapping array - if nullptr passed, use linear mapping
170 if (mapPoints != nullptr && numMapPoints > 0) {
171 // Use provided mapping array for non-linear mapping
172 this->mapPoints = mapPoints;
173 this->numMapPoints = numMapPoints;
174 this->useMultiMap = true;
175
176 // Extract input values and output positions arrays for multiMapBS
177 this->inputVals = new unsigned int[numMapPoints];
178 this->outputPos = new unsigned int[numMapPoints];
179 for (uint8_t i = 0; i < numMapPoints; i++) {
180 this->inputVals[i] = mapPoints[i].value;
181 this->outputPos[i] = mapPoints[i].position;
182 }
183 } else {
184 // Use standard linear mapping (no array needed)
185 this->mapPoints = nullptr;
186 this->inputVals = nullptr;
187 this->outputPos = nullptr;
188 this->numMapPoints = 0;
189 this->useMultiMap = false;
190 }
191 }
192
197 if (useMultiMap && inputVals != nullptr) {
198 delete[] inputVals;
199 delete[] outputPos;
200 }
201 }
202
203
212 void findZero() {
213 int zeroingSpeed = 20; // Slow speed for zeroing operation
214 int zeroingAccel = 10;
215 stepper.setMaxSpeed(zeroingSpeed);
216 stepper.setAcceleration(zeroingAccel);
217
218 stepper.setCurrentPosition(maxPos); // Assume needle at max position
219 stepper.runToNewPosition(mechZero); // Move backwards to mech stop
220 stepper.setCurrentPosition(mechZero); // At mech stop, set coordinate sys to 0
221 stepper.runToNewPosition(zeroPos); // Move forward to position that is 0 on dial
222
223 stepper.setMaxSpeed(normalSpeed); // Resume normal speed and acceleration
224 stepper.setAcceleration(normalAccel);
225 }
226
227
233 void testFullRange(int testSpeed = 20, int testAccel = 10) {
234 testInProgress = true;
235 stepper.setMaxSpeed(testSpeed);
236 stepper.setAcceleration(testAccel);
237
238 stepper.runToNewPosition(maxPos);
239 delay(2000);
240 stepper.runToNewPosition(zeroPos);
241
242 stepper.setMaxSpeed(normalSpeed);
243 stepper.setAcceleration(normalAccel);
244 testInProgress = false;
245 }
246
247
257 void setTarget(unsigned int targetVal) {
258 // 1) Cap targetVal at capValue as needed
259 unsigned int trimmedVal = min(targetVal, capValue);
260
261 // 2) map capped value to stepper position
262 long targetPos;
263 if (useMultiMap) {
264 // Use multiMap with pre-extracted arrays
265 targetPos = multiMapCache<unsigned int>(trimmedVal, inputVals, outputPos, numMapPoints);
266 } else {
267 targetPos = map(trimmedVal, 0, capValue, zeroPos, maxPos);
268 }
269
270 // 3) call the moveTo() function of AccelStepper to pass the new target position.
271 stepper.moveTo(targetPos);
272 }
273
274
280 void run() {
281 bool shouldHome = ufcEntPressed && ufcClrPressed;
282
283 if (shouldHome && !homingInProgress && !testInProgress) {
284 homingInProgress = true;
285 findZero();
287 homingInProgress = false;
288 }
289
290 stepper.run();
291 }
292
293};
294
295// Static member definitions
296bool HornetStepper::ufcEntPressed = false;
297bool HornetStepper::ufcClrPressed = false;
298
299// DCS-BIOS callbacks for homing trigger buttons
300void onUfcEntChange(unsigned int newVal) {
301 // newVal is 0 when not pressed, non-zero when pressed
302 HornetStepper::ufcEntPressed = (newVal != 0);
303}
304DcsBios::IntegerBuffer ufcEntBuffer(FA_18C_hornet_UFC_ENT, onUfcEntChange);
305
306void onUfcClrChange(unsigned int newVal) {
307 // newVal is 0 when not pressed, non-zero when pressed
308 HornetStepper::ufcClrPressed = (newVal != 0);
309}
310DcsBios::IntegerBuffer ufcClrBuffer(FA_18C_hornet_UFC_CLR, onUfcClrChange);
311
312#endif
Common class to control stepper-run gauges in OpenHornet.
~HornetStepper()
Destructor to clean up allocated arrays.
void findZero()
findZero() is a function to zero the gauge
void setTarget(unsigned int targetVal)
setTarget() is a function to set the target position of the gauge
HornetStepper(int coil1, int coil2, int coil3, int coil4, int zeroPos, int maxPos, int dirForward, unsigned int capValue=65535, int normalSpeed=300, int normalAccel=600, MapPoint *mapPoints=nullptr, uint8_t numMapPoints=0)
Constructor for HornetStepper.
void run()
run() is a function to run the stepper motor (non-blocking)
void testFullRange(int testSpeed=20, int testAccel=10)
testFullRange() is a function to test the range of the gauge
Only in case of non-linear gauges, this struct is used. It represents a value-position mapping pair.