ReduxLib C++ 2023.1.0
Loading...
Searching...
No Matches
CANandcoder.h
1// Copyright (c) Redux Robotics and other contributors.
2// This is open source and can be modified and shared under the 3-clause BSD license.
3
4#pragma once
5#include <stdint.h>
6#include <unordered_map>
7#include <mutex>
8#include <condition_variable>
9#include <optional>
10#include <units/angle.h>
11#include <units/angular_velocity.h>
12#include <units/time.h>
13#include <units/temperature.h>
14#include "redux/canand/CANandDevice.h"
15#include "redux/canand/CANandEventLoop.h"
16#include "redux/frames/Frame.h"
17
18/**
19 * Namespace for all classes relating to the CANandcoder
20*/
22
23/**
24 * A class to hold device faults for the CANandcoder, as returned by CANandcoder::GetActiveFaults and CANandcoder::GetStickyFaults
25 *
26 */
28 public:
29 /**
30 * Constructs from a fault field
31 * @param field the fault bitfield
32 * @param valid whether data is valid or not
33 */
34 inline CANandcoderFaults(uint8_t field, bool valid) {
35 powerCycle = field & 0b1;
36 canIDConflict = field & 0b10;
37 canGeneralError = field & 0b100;
38 outOfTemperatureRange = field & 0b1000;
39 hardwareFault = field & 0b10000;
40 magnetOutOfRange = field & 0b100000;
41 underVolt = field & 0b1000000;
42 faultsValid = valid;
43 }
44
45 /**
46 * The power cycle fault flag, which is set to true when the encoder first boots.
47 * Clearing sticky faults and then checking this flag can be used to determine if the encoder rebooted.
48 */
50
51 /**
52 * The CAN ID conflict flag, which is set to true if there is a CAN id conflict.
53 * In practice, you should physically inspect the encoder to ensure it's not flashing blue.
54 */
56
57 /**
58 * The CAN general error flag, which will raise if the encoder cannot RX packets reliably.
59 * This is usually due to wiring issues, such as a shorted CAN bus
60 */
62
63 /**
64 * The temperature range flag, which will raise if the encoder is not between 0-70 degrees Celsius.
65 * This may be of concern if the encoder is near very active motors.
66 */
68
69 /**
70 * The hardware fault flag, which will raise if a hardware issue is detected.
71 * Generally will raise if the device's controller cannot read the physical sensor itself.
72 */
74
75 /**
76 * The magnet out of range flag, which will raise if the measured shaft's magnet is not detected.
77 * This will match the encoder's LED shining red in normal operation.
78 */
80
81 /**
82 * The undervolt flag, which will raise if the encoder is experiencing brownout conditions.
83 */
85
86 /**
87 * Flag if any faults data has been received at all from the encoder. This will be false until the first status frame arrives
88 * after either the start of robot code or after ClearStickyFaults is called.
89 */
91};
92
93
94/**
95 * The settings class for the CANandcoder.
96 *
97 * <p>
98 * This class holds settings values that can be used to reconfigure CANandcoder via CANandcoder::SetSettings
99 * Additionally, objects of this class can be filled using CANandcoder.GetSettings which can be used to
100 * read the encoder's settings.
101 * </p>
102 *
103 * <pre>
104 * CANandcoder enc = CANandcoder{0};
105 *
106 * // Only settings that are explicitly set here will be edited, so other settings
107 * // such as the status frame period will remain untouched.
108 * CANandcoderSettings stg;
109 * stg.SetPositionFramePeriod(0_ms); // disables position readings
110 * stg.SetVelocityFramePeriod(20_ms); // sets the rate of velocity measurements to every 20 ms
111 * stg.SetInvertDirection(true); // inverts the encoder direction
112 *
113 * enc.SetSettings(stg);
114 *
115 * </pre>
116 *
117 * Note that all GetWhateverSetting(); functions return a <a href="https://en.cppreference.com/w/cpp/utility/optional">std::optional</a>, as CANandcoderSettings objects
118 * may not always have a value set for a setting. This is particularly true of instances returned by CANandcoder::GetSettingsAsync(),
119 * and you will need to use CANandcoderSettings::AllSettingsReceived() to check if all are present.
120 *
121 * However, objects returned by the blocking CANandcoder::GetSettings() method will always have all setting values populated.
122 *
123 * Example blocking fetch:
124 * <pre>
125 * CANandcoder canandcoder{0};
126 * std::optional<CANandcoderSettings> stg = canandcoder.GetSettings(stg);
127 * if (stg.has_value()) {
128 * fmt.print("status frame period: {}\n", *(*stg).GetStatusFramePeriod()); // print the status frame period (usually 1000 ms)
129 * }
130 * </pre>
131 *
132 */
134 friend class CANandcoder;
135 public:
136
137 /**
138 * Sets the velocity filter width in milliseconds to sample over.
139 * Velocity is computed by averaging all the points in the past widthMs milliseconds.
140 * By factory default, the velocity filter averages over the past 25 milliseconds.
141 *
142 * @param widthMs the new number of samples to average over. Minimum accepted is 0.25 milliseconds, maximum is 63.75 ms.
143 */
144 void SetVelocityFilterWidth(units::millisecond_t widthMs);
145
146 /**
147 * Sets the position frame period in seconds.
148 * By factory default, position frames are sent every 20 milliseconds (period=0.020_s)
149 * If 0 is passed in, position frames will be disabled and the methods CANandcoder::GetPosition()
150 * and CANandcoder::GetAbsPosition() will not return new values.
151 *
152 * @param period the new period for position frames in seconds in range [0_s, 65.535_s].
153 */
154 void SetPositionFramePeriod(units::second_t period);
155
156 /**
157 * Sets the velocity frame period in seconds.
158 * By factory default, velocity frames are sent every 20 milliseconds (period=0.020_s)
159 * If 0 is passed in, velocity frames will be disabled and CANandcoder::GetVelocity() will not return
160 * new values.
161 *
162 * @param period the new period for velocity frames in seconds in range [0_s, 65.535_s].
163 */
164 void SetVelocityFramePeriod(units::second_t period);
165
166 /**
167 * Sets the status frame period in seconds.
168 * By factory default, the encoder will broadcast 1 status message per second (period=0.020_s).
169 *
170 * @param period the new period for status frames in seconds in range [1_s, 16.383_s].
171 */
172 void SetStatusFramePeriod(units::second_t period);
173
174 /**
175 * Inverts the direction read from the sensor. By factory default, the sensor will read counterclockwise from its reading face
176 * as positive (invert=false).
177 * @param invert whether to invert (negate) readings from the encoder
178 */
179 void SetInvertDirection(bool invert);
180
181 /**
182 * Sets whether or not the sensor should disallow zeroing and factory resets from the onboard button.
183 * By factory default, the sensor will allow the zero button to function when pressed (disable=false)
184 * @param disable whether to disable the onboard zeroing button's functionality
185 */
186 void SetDisableZeroButton(bool disable);
187
188 /**
189 * Returns whether or not all settings fields have been written into the object -- if this returned false, we
190 * have not gotten all the settings from the encoder if this is a CANandcoderSettings object returned from
191 * CANandcoder::getSettings()
192 * @return whether the settings object has been filled
193 */
195
196
197 /**
198 * Gets the velocity filter width in milliseconds [0.25..63.75], or std::nullopt if the value has not been set on this object.
199 * @return the velocity filter width in milliseconds [0.25..63.75], or std::nullopt if the value has not been set on this object.
200 */
201 std::optional<units::millisecond_t> GetVelocityFilterWidth();
202
203 /**
204 * Gets the position frame period in seconds [0..65.535], or std::nullopt if the value has not been set on this object.
205 * A value of 0 means position messages are disabled.
206 * @return the position frame period in seconds [0..65.535], or std::nullopt if the value has not been set on this object.
207 */
208 std::optional<units::second_t> GetPositionFramePeriod();
209
210 /**
211 * Gets the velocity frame period in seconds [0..65.535], or std::nullopt if the value has not been set on this object.
212 * A value of 0 means velocity messages are disabled.
213 * @return the velocity frame period in seconds [0..65.535], or std::nullopt if the value has not been set on this object.
214 */
215 std::optional<units::second_t> GetVelocityFramePeriod();
216
217 /**
218 * Gets the status frame period in seconds [1..16.383], or std::nullopt if the value has not been set on this object.
219 * A value of 0 means status messages are disabled.
220 * @return the status frame period in seconds [1..16.383], or std::nullopt if the value has not been set on this object.
221 */
222 std::optional<units::second_t> GetStatusFramePeriod();
223
224 /**
225 * Gets whether or not the encoder has an inverted direction (0 for no, 1 for yes, std::nullopt for unset).
226 * @return whether or not the encoder has an inverted direction (0 for no, 1 for yes, std::nullopt for unset).
227 */
228 std::optional<bool> GetInvertDirection();
229
230 /**
231 * Gets whether or not the sensor should disallow zeroing and factory resets from the onboard button (0 for allow, 1 for disallow, std::nullopt for unset).
232 * @return whether or not the encoder has its onboard zero button's functionality disabled (0 for allow, 1 for disallow, std::nullopt for unset).
233 */
234 std::optional<bool> GetDisableZeroButton();
235
236 private:
237 std::unordered_map<uint8_t, uint64_t> values;
238};
239
240/**
241 * Struct class representing a CANandcoder's status.
242*/
244 /**
245 * Constructor for CANandcoderStatus
246 * @param activeFaultsRaw raw uint8_t field
247 * @param stickyFaultsRaw raw uint8_t field
248 * @param faultsValid whether the faults fields have valid adata
249 * @param temp MCU temp
250 * @param magnetInRange whether the encoder magnet is in range
251 */
252 CANandcoderStatus(uint8_t activeFaultsRaw, uint8_t stickyFaultsRaw, bool faultsValid, units::celsius_t temp, bool magnetInRange): \
253 activeFaults{activeFaultsRaw, faultsValid}, stickyFaults{stickyFaultsRaw, faultsValid}, temperature{temp}, magnetInRange{magnetInRange} {};
254 public:
255 /** Active faults. */
257 /** Sticky faults. */
259 /** Encoder MCU temperature (celsius). */
260 units::celsius_t temperature;
261 /** Whether the magnet is in range. */
263};
264
265
266/**
267 * Namespace for CANandcoder-specific constants and details not generally needed by end users
268 */
269namespace details {
270// constants_compiler: begin vendordep_CANandcoder_cpp
271
272/** CANandcoder-specific CAN message IDs*/
273class MSG : public redux::canand::MSG {
274 public:
275 /** CAN message id for Position frame */
276 static constexpr uint8_t POSITION_OUTPUT = 0x1F;
277 /** CAN message id for Velocity frame */
278 static constexpr uint8_t VELOCITY_OUTPUT = 0x1E;
279 /** CAN message id for Raw position frame */
280 static constexpr uint8_t RAW_POSITION_OUTPUT = 0x1D;
281};
282
283/** Setting IDs valid for CANandcoder */
284class SETTINGS {
285 public:
286 /** Setting msg id for Encoder zero offset */
287 static constexpr uint8_t ZERO_OFFSET = 0xFF;
288 /** Setting msg id for Velocity window width (value*250us) */
289 static constexpr uint8_t VELOCITY_WINDOW = 0xFE;
290 /** Setting msg id for Position frame period (ms) */
291 static constexpr uint8_t POSITION_FRAME_PERIOD = 0xFD;
292 /** Setting msg id for Velocity frame period (ms) */
293 static constexpr uint8_t VELOCITY_FRAME_PERIOD = 0xFC;
294 /** Setting msg id for Raw position frame period (ms) */
295 static constexpr uint8_t RAW_POSITION_FRAME_PERIOD = 0xFB;
296 /** Setting msg id for Invert direction (use cw instead of ccw) */
297 static constexpr uint8_t INVERT_DIRECTION = 0xFA;
298 /** Setting msg id for Relative position value */
299 static constexpr uint8_t RELATIVE_POSITION = 0xF9;
300 /** Setting msg id for Disable the zero button */
301 static constexpr uint8_t DISABLE_ZERO_BUTTON = 0xF8;
302 /** Setting msg id for status frame period (ms) */
303 static constexpr uint8_t STATUS_FRAME_PERIOD = 0x4;
304};
305
306/** CANandcoder-specific setting command IDs*/
308 public:
309 /** Setting command id for Factory defaults, but keep the encoder zero offset */
310 static constexpr uint8_t RESET_FACTORY_DEFAULT_KEEP_ZERO = 0xFF;
311};
312
313//constants_compiler: end
314
315/** Array of relevant settings IDS for the vendordep*/
316const uint8_t VDEP_SETTINGS[] = {
324};
325}
326
327/**
328 * Class for the CAN interface of the <a href="https://docs.reduxrobotics.com/canandcoder/index.html">CANandcoder.</a>
329 *
330 * <p>
331 * If you are using a CANandcoder with Spark Max or Talon with the PWM output, see
332 * <a href="https://docs.reduxrobotics.com/canandcoder/spark-max.html">our Spark Max docs</a>
333 * or
334 * <a href="https://docs.reduxrobotics.com/canandcoder/talon-srx.html">our Talon SRX docs</a>
335 * for information on how to use the encoder with the Rev and CTRE APIs.
336 * </p>
337 *
338 * <p>
339 * The C++ vendordep uses the <a href="https://docs.wpilib.org/en/stable/docs/software/basic-programming/cpp-units.html">units library</a>
340 * for all dimensioned values, including settings.
341 * </p>
342 *
343 * <p>
344 * Operations that receive data from the device (position, velocity, faults, temperature) generally do not block.
345 * The object receives data asynchronously from the CAN packet receive thread and reads thus return the last data received.
346 * </p>
347 * <p>
348 * Operations that set settings or change offsets will generally wait for up to 50ms by default as they will usually
349 * wait for a confirmation packet to be received in response -- unless the blocking timeout is set to zero, in which case
350 * the operation swill not block.
351 * </p>
352 *
353 * Example code:
354 * <pre>
355 * CANandcoder canandcoder{0}; // instantiates with encoder id 0
356 *
357 * // Reading the CANandcoder
358 * canandcoder.GetPosition(); // returns a multi-turn relative position, in rotations (turns)
359 * canandcoder.GetAbsPosition(); // returns an absolute position bounded from [0..1) over one rotation
360 * canandcoder.GetVelocity(); // returns measured velocity in rotations per second
361 *
362 * // Updating position
363 * canandcoder.SetPosition(-3.5_tr); // sets the relative position to -3.5 turns (does not persist on reboot)
364 * canandcoder.SetAbsPosition(330_deg, 0); // sets the absolute position to 330 degrees without blocking for confirmation (persists on reboot)
365 * canandcoder.ZeroAll(); // sets both the relative and absolute position to zero
366 *
367 * // Changing configuration
368 * CANandcoderSettings settings;
369 * settings.SetVelocityFilterPeriod(25_ms); // sets the velocity filter averaging period to 25 ms
370 * settings.SetInvertDirection(true); // make positive be clockwise instead of ccw opposite the sensor face
371 * canandcoder.SetSettings(settings, 50_ms); // apply the new settings to the device, with maximum 50 ms timeout per settings operation
372 *
373 * // Faults
374 * canandcoder.ClearStickyFaults(); // clears all sticky faults (including the power cycle flag). This call does not block.
375 *
376 * // this flag will always be true on boot until the sticky faults have been cleared,
377 * // so if this prints true the encoder has rebooted sometime between ClearStickyFaults and now.
378 * CANandcoderFaults faults = canandcoder.GetStickyFaults(); // fetches faults
379 * fmt::print("Encoder rebooted: {}\n", faults.powerCycle);
380 *
381 * // Timestamped data
382 * FrameData&lt;double&gt; posFrame = canandcoder.GetPositionFrame(); // gets current position + timestamp together
383 * posFrame.GetValue(); // fetched position in rotations
384 * posFrame.GetTimestamp(); // timestamp of the previous position
385 * </pre>
386 *
387 */
389 public:
390 /**
391 * Constructor with the device's id. This object will be constant with respect to whatever CAN id assigned to it,
392 * so if a device changes id it may change which device this object reads from.
393 * @param id the device id to use
394 */
395 CANandcoder(int id) : addr{7, 0, (uint8_t) (id & 0x3f)} {
397 };
399 // functions related to core functionality
400
401 /**
402 * Gets the current integrated position in rotations.
403 *
404 * <p> This value does not wrap around, so turning a sensed axle multiple rotations will return multiple sensed rotations of position.
405 * By default, positive is in the counter-clockwise direction from the sensor face.
406 * </p>
407 * <p> On encoder power-on, unlike the absolute value, this value will always initialize to zero. </p>
408 * @return signed relative position in rotations (range [-131072.0..131071.999938396484])
409 */
410 units::turn_t GetPosition();
411
412 /**
413 * Gets the current absolute position of the encoder, in a scaled value from 0 inclusive to 1 exclusive.
414 * By default, higher values are in the counter-clockwise direction from the sensor face.
415 * <p> This value will persist across encoder power cycles making it appropriate for swerves/arms/etc. </p>
416 * @return absolute position in fraction of a rotation [0..1)
417 */
418 units::turn_t GetAbsPosition();
419
420 /**
421 * Sets the new relative (multi-turn) position of the encoder to the given value.
422 *
423 * <p>
424 * Note that this does not update the absolute position, and this value is lost on a power cycle. To update the absolute position,
425 * use CANandcoder::SetAbsPosition
426 * </p>
427 * @param newPosition new position in rotations
428 * @param timeout maximum time to wait for the operation to be confirmed (default 0.050 seconds). Set to 0 to not check (and not block).
429 * @return true on success, false on timeout
430 */
431 bool SetPosition(units::turn_t newPosition, units::second_t timeout = 50_ms);
432
433 /**
434 * Sets the new absolute position value for the encoder which will persist across reboots
435 * @param newPosition new absolute position in fraction of a rotation (acceptable range [0..1))
436 * @param timeout maximum time to wait for the operation to be confirmed (default 0.050 seconds). Set to 0 to not check (and not block).
437 * @return true on success, false on timeout
438 */
439 bool SetAbsPosition(units::turn_t newPosition, units::second_t timeout = 50_ms);
440
441 /**
442 * Sets both the current absolute and relative encoder position to 0 -- generally equivalent to pressing the physical zeroing button on the encoder.
443 * @param timeout maximum time in seconds to wait for each operation to be confirmed (there are 2 ops for zeroing both absolute and relative positions,
444 * so the wait is up to 2x timouet). Set to 0 to not check (and not block).
445 * @return true on success, false on timeout
446 */
447 bool ZeroAll(units::second_t timeout = 50_ms);
448
449 /**
450 * Returns the measured velocity in rotations per second.
451 * @return velocity, in rotations (turns) per second
452 */
453 units::turns_per_second_t GetVelocity();
454
455 /**
456 * Returns whether the encoder magnet is in range of the sensor or not.
457 * This can be seen visually on the sensor -- a green LED is in range, whereas
458 * a red LED is out of range.
459 *
460 * @return whether the output shaft magnet is in range.
461 */
463
464 // functions related to diagonstic data
465
466 /**
467 * Fetches sticky faults.
468 * Sticky faults are the active faults, except once set they do not become unset until ClearStickyFaults() is called.
469 *
470 * @return CANandcoderFaults of the sticky faults
471 */
473
474 /**
475 * Fetches active faults.
476 * Active faults are only active for as long as the error state exists.
477 *
478 * @return CANandcoderFaults of the active faults
479 */
481
482 /**
483 * Get onboard encoder temperature readings in degrees Celsius.
484 * @return temperature in degrees Celsius
485 */
486 units::celsius_t GetTemperature();
487
488 /**
489 * Clears sticky faults.
490 *
491 * <p>It is recommended to clear this during initialization, so one can check if the encoder loses power during operation later. </p>
492 * <p>This call does not block, so it may take up to the next status frame (default every 1000 ms) for the sticky faults to be updated.</p>
493 */
495
496 /**
497 * Controls "party mode" -- an encoder identification tool that blinks the onboard LED
498 * various colors at a user-specified strobe period.
499 * The strobe period of the LED will be (50 milliseconds * level). Setting this to 0 disables party mode.
500 *
501 * This function does not block.
502 *
503 * @param level the party level value to set.
504 */
505 void SetPartyMode(uint8_t level);
506
507 // functions relating to settings
508
509 /**
510 * Fetches the CANandcoder's current configuration in a blocking manner.
511 * This function will need to block for at least 0.2-0.3 seconds waiting for the encoder to reply, so it is best
512 * to put this in a teleop or autonomous init function, rather than the main loop.
513 *
514 * @param timeout maximum number of seconds to wait for settings before giving up (default 0.350s)
515 * @return std::optional with CANandcoderSettings if received or std::nullopt on timeout
516 */
517 std::optional<CANandcoderSettings> GetSettings(units::second_t timeout = 350_ms);
518
519 /**
520 * Tells the CANandcoder to begin transmitting its settings; once they are all transmitted (after ~200-300ms),
521 * the values can be retrieved through the CANandcoder::GetSettingsAsync() function call
522 */
524
525 /**
526 * Non-blockingly returns a {@link CANandcoderSettings} object of the most recent known settings values received from the encoder.
527 *
528 * <p> <b>Most users will probably want to use CANandcoder::GetSettings() instead. </b> </p>
529 *
530 * One can call this after a CANandcoder::StartFetchSettings() call, and use CANandcoderSettings::AllSettingsReceived()
531 * to check if/when all values have been seen. As an example:
532 *
533 * <pre>
534 *
535 * // somewhere in an init function
536 * CANandcoder enc = CANandcoder(0);
537 * enc.StartFetchSettings();
538 *
539 * // ...
540 * // somewhere in a loop function
541 *
542 * CANandcoderSettings stg = enc.GetSettingsAsync(stg);
543 * if (stg.AllSettingsReceived()) {
544 * // do something with the returned settings
545 * fmt::print("Encoder velocity frame period: {}\n", *stg.GetVelocityFramePeriod());
546 * }
547 * </pre>
548 *
549 *
550 * If this is called after CANandcoder::SetSettings(), this method will return a settings object where only
551 * the fields where the encoder has echoed the new values back will be populated. To illustrate this, consider the following:
552 * <pre>
553 * // somewhere in a loop
554 * CANandcoderSettings stg_set;
555 * stg_set.SetVelocityFramePeriod(100_ms);
556 * enc.SetSettings(stg_set);
557 * CANandcoderSettings stg_get = enc.GetSettingsAsync();
558 *
559 * // will likely return std::nullopt, as the encoder hasn't confirmed the previous transaction
560 * *stg_get.GetVelocityFramePeriod();
561 *
562 * // after up to 100 ms...
563 * stg_get = enc.GetSettingsAsync();
564 * *stg_get.getVelocityFramePeriod(); // will likely return 100
565 * </pre>
566 *
567 * @return CANandcoderSettings of currently known settings
568 */
570
571 /**
572 * Applies the settings from a CANandcoderSettings object to the CANandcoder.
573 * For more information, see the CANandcoderSettings class documentation.
574 * @param settings the CANandcoderSettings to update the encoder with
575 * @param timeout maximum time in seconds to wait for each setting to be confirmed. (default 0.050s, set to 0 to not check and not block).
576 * @return true if successful, false if a setting operation timed out
577 */
578 bool SetSettings(const CANandcoderSettings& settings, units::second_t timeout = 50_ms);
579
580 /**
581 * Resets the encoder to factory defaults.
582 * @param clearZero whether to clear the zero offset from the encoder's memory as well
583 * @param timeout how long to wait for the new settings to be confirmed by the encoder (default 0.35s, set to 0 to not block)
584 * @return true if successful, false if a setting operation timed out or if timeout is 0
585 */
586 bool ResetFactoryDefaults(bool clearZero = false, units::second_t timeout = 350_ms);
587
588 /**
589 * Checks whether or not the CANandcoder has sent a message within the last timeout seconds.
590 * @param timeout window to check for message updates (default 2.0 seconds)
591 * @return true if there has been a message within the last timeout seconds, false if not
592 */
593 bool IsPresent(units::second_t timeout = 2000_ms);
594
595 /**
596 * Returns the current relative position frame, which includes CAN timestamp data.
597 * redux::canand::FrameData objects are immutable.
598 * @return the current position frame, which will hold the current position in the same units as CANandcoder::GetPosition()
599 */
601
602 /**
603 * Returns the current absolute position frame, which includes CAN timestamp data.
604 * @return the current position frame, which will hold the current position in the same units as CANandcoder::getAbsPosition()
605 */
607
608 /**
609 * Returns the current velocity frame, which includes CAN timestamp data.
610 * @return the current velocity frame, which will hold the current velocity in the same units as CANandcoder::getVelocity()
611 */
613
614 /**
615 * Returns a handle to the current status frame, which includes CAN timestamp data.
616 * @return the current status frame, as a CANandcoderStatus record.
617 */
619
620
621 // functions that directly modify settings
624 protected:
625
626 /** number of encoder ticks per rotation */
627 static constexpr double COUNTS_PER_ROTATION = 16384;
628
629 /** number of velocity ticks per rotation per second */
630 static constexpr double VEL_TICK_PER_RPS = 1024;
631
632 protected:
633
634 /** internal Frame variable holding current relative position state */
636
637 /** internal Frame variable holding current absolute position state */
639
640 /** internal Frame variable holding current velocity state */
642
643 /** internal Frame variable holding current status value state */
645
646 private:
647
648 bool dataRecvOnce{false};
649 std::chrono::time_point<std::chrono::steady_clock> lastMessageTime{std::chrono::steady_clock::now()};
650
651 CANandcoderSettings knownSettings{};
652 std::mutex knownSettingsLock;
653 std::condition_variable knownSettingsCV;
654
656
657};
658
659
660}
Definition: CANandAddress.h:60
Definition: CANandDevice.h:32
Definition: CANandMessage.h:26
Definition: CANandDevice.h:131
Definition: CANandDevice.h:148
Definition: Frame.h:82
bool underVolt
Definition: CANandcoder.h:84
bool faultsValid
Definition: CANandcoder.h:90
bool outOfTemperatureRange
Definition: CANandcoder.h:67
bool magnetOutOfRange
Definition: CANandcoder.h:79
bool canIDConflict
Definition: CANandcoder.h:55
bool hardwareFault
Definition: CANandcoder.h:73
bool canGeneralError
Definition: CANandcoder.h:61
CANandcoderFaults(uint8_t field, bool valid)
Definition: CANandcoder.h:34
bool powerCycle
Definition: CANandcoder.h:49
std::optional< units::second_t > GetStatusFramePeriod()
void SetVelocityFilterWidth(units::millisecond_t widthMs)
std::optional< units::second_t > GetVelocityFramePeriod()
std::optional< units::millisecond_t > GetVelocityFilterWidth()
std::optional< units::second_t > GetPositionFramePeriod()
void SetVelocityFramePeriod(units::second_t period)
void SetStatusFramePeriod(units::second_t period)
void SetPositionFramePeriod(units::second_t period)
Definition: CANandcoder.h:388
CANandcoder(int id)
Definition: CANandcoder.h:395
bool ResetFactoryDefaults(bool clearZero=false, units::second_t timeout=350_ms)
bool ZeroAll(units::second_t timeout=50_ms)
bool SetSettings(const CANandcoderSettings &settings, units::second_t timeout=50_ms)
redux::frames::Frame< CANandcoderStatus > status
Definition: CANandcoder.h:644
redux::frames::Frame< units::turn_t > position
Definition: CANandcoder.h:635
units::turns_per_second_t GetVelocity()
redux::frames::Frame< units::turn_t > & GetAbsPositionFrame()
Definition: CANandcoder.h:606
bool SetAbsPosition(units::turn_t newPosition, units::second_t timeout=50_ms)
redux::canand::CANandAddress & GetAddress() override
std::optional< CANandcoderSettings > GetSettings(units::second_t timeout=350_ms)
redux::frames::Frame< units::turns_per_second_t > velocity
Definition: CANandcoder.h:641
static constexpr double VEL_TICK_PER_RPS
Definition: CANandcoder.h:630
redux::frames::Frame< units::turn_t > & GetPositionFrame()
Definition: CANandcoder.h:600
bool SetPosition(units::turn_t newPosition, units::second_t timeout=50_ms)
redux::frames::Frame< CANandcoderStatus > & GetStatusFrame()
Definition: CANandcoder.h:618
redux::frames::Frame< units::turn_t > absPosition
Definition: CANandcoder.h:638
bool IsPresent(units::second_t timeout=2000_ms)
void HandleMessage(redux::canand::CANandMessage &msg) override
static constexpr double COUNTS_PER_ROTATION
Definition: CANandcoder.h:627
redux::frames::Frame< units::turns_per_second_t > & GetVelocityFrame()
Definition: CANandcoder.h:612
Definition: CANandcoder.h:273
static constexpr uint8_t RAW_POSITION_OUTPUT
Definition: CANandcoder.h:280
static constexpr uint8_t VELOCITY_OUTPUT
Definition: CANandcoder.h:278
static constexpr uint8_t POSITION_OUTPUT
Definition: CANandcoder.h:276
static constexpr uint8_t DISABLE_ZERO_BUTTON
Definition: CANandcoder.h:301
static constexpr uint8_t STATUS_FRAME_PERIOD
Definition: CANandcoder.h:303
static constexpr uint8_t ZERO_OFFSET
Definition: CANandcoder.h:287
static constexpr uint8_t RAW_POSITION_FRAME_PERIOD
Definition: CANandcoder.h:295
static constexpr uint8_t POSITION_FRAME_PERIOD
Definition: CANandcoder.h:291
static constexpr uint8_t VELOCITY_WINDOW
Definition: CANandcoder.h:289
static constexpr uint8_t VELOCITY_FRAME_PERIOD
Definition: CANandcoder.h:293
static constexpr uint8_t INVERT_DIRECTION
Definition: CANandcoder.h:297
static constexpr uint8_t RELATIVE_POSITION
Definition: CANandcoder.h:299
static constexpr uint8_t RESET_FACTORY_DEFAULT_KEEP_ZERO
Definition: CANandcoder.h:310
void RemoveCANListener(CANandDevice *device)
void AddCANListener(CANandDevice *device)
const uint8_t VDEP_SETTINGS[]
Definition: CANandcoder.h:316
Definition: CANandcoder.h:21
CANandcoderStatus(uint8_t activeFaultsRaw, uint8_t stickyFaultsRaw, bool faultsValid, units::celsius_t temp, bool magnetInRange)
Definition: CANandcoder.h:252
CANandcoderFaults activeFaults
Definition: CANandcoder.h:256
bool magnetInRange
Definition: CANandcoder.h:262
CANandcoderFaults stickyFaults
Definition: CANandcoder.h:258
units::celsius_t temperature
Definition: CANandcoder.h:260