2020-12-26 14:12:05 -08:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
2019-11-14 22:51:33 -08:00
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
|
#include <hal/SimDevice.h>
|
|
|
|
|
#include <hal/Types.h>
|
2020-06-29 22:25:09 -07:00
|
|
|
#include <units/angle.h>
|
2021-06-13 16:38:05 -07:00
|
|
|
#include <wpi/sendable/Sendable.h>
|
|
|
|
|
#include <wpi/sendable/SendableHelper.h>
|
2019-11-14 22:51:33 -08:00
|
|
|
|
|
|
|
|
#include "frc/AnalogTrigger.h"
|
|
|
|
|
#include "frc/Counter.h"
|
|
|
|
|
|
|
|
|
|
namespace frc {
|
|
|
|
|
class DutyCycle;
|
|
|
|
|
class DigitalSource;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Class for supporting duty cycle/PWM encoders, such as the US Digital MA3 with
|
|
|
|
|
* PWM Output, the CTRE Mag Encoder, the Rev Hex Encoder, and the AM Mag
|
|
|
|
|
* Encoder.
|
|
|
|
|
*/
|
2021-06-13 16:38:05 -07:00
|
|
|
class DutyCycleEncoder : public wpi::Sendable,
|
|
|
|
|
public wpi::SendableHelper<DutyCycleEncoder> {
|
2019-11-14 22:51:33 -08:00
|
|
|
public:
|
2019-12-06 20:58:04 -08:00
|
|
|
/**
|
|
|
|
|
* Construct a new DutyCycleEncoder on a specific channel.
|
|
|
|
|
*
|
|
|
|
|
* @param channel the channel to attach to
|
|
|
|
|
*/
|
|
|
|
|
explicit DutyCycleEncoder(int channel);
|
|
|
|
|
|
2019-11-14 22:51:33 -08:00
|
|
|
/**
|
|
|
|
|
* Construct a new DutyCycleEncoder attached to an existing DutyCycle object.
|
|
|
|
|
*
|
|
|
|
|
* @param dutyCycle the duty cycle to attach to
|
|
|
|
|
*/
|
|
|
|
|
explicit DutyCycleEncoder(DutyCycle& dutyCycle);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a new DutyCycleEncoder attached to an existing DutyCycle object.
|
|
|
|
|
*
|
|
|
|
|
* @param dutyCycle the duty cycle to attach to
|
|
|
|
|
*/
|
|
|
|
|
explicit DutyCycleEncoder(DutyCycle* dutyCycle);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a new DutyCycleEncoder attached to an existing DutyCycle object.
|
|
|
|
|
*
|
|
|
|
|
* @param dutyCycle the duty cycle to attach to
|
|
|
|
|
*/
|
|
|
|
|
explicit DutyCycleEncoder(std::shared_ptr<DutyCycle> dutyCycle);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a new DutyCycleEncoder attached to a DigitalSource object.
|
|
|
|
|
*
|
2021-10-14 18:09:38 -07:00
|
|
|
* @param digitalSource the digital source to attach to
|
2019-11-14 22:51:33 -08:00
|
|
|
*/
|
|
|
|
|
explicit DutyCycleEncoder(DigitalSource& digitalSource);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a new DutyCycleEncoder attached to a DigitalSource object.
|
|
|
|
|
*
|
2021-10-14 18:09:38 -07:00
|
|
|
* @param digitalSource the digital source to attach to
|
2019-11-14 22:51:33 -08:00
|
|
|
*/
|
|
|
|
|
explicit DutyCycleEncoder(DigitalSource* digitalSource);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a new DutyCycleEncoder attached to a DigitalSource object.
|
|
|
|
|
*
|
2021-10-14 18:09:38 -07:00
|
|
|
* @param digitalSource the digital source to attach to
|
2019-11-14 22:51:33 -08:00
|
|
|
*/
|
|
|
|
|
explicit DutyCycleEncoder(std::shared_ptr<DigitalSource> digitalSource);
|
|
|
|
|
|
|
|
|
|
~DutyCycleEncoder() override = default;
|
|
|
|
|
|
|
|
|
|
DutyCycleEncoder(DutyCycleEncoder&&) = default;
|
|
|
|
|
DutyCycleEncoder& operator=(DutyCycleEncoder&&) = default;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the frequency in Hz of the duty cycle signal from the encoder.
|
|
|
|
|
*
|
|
|
|
|
* @return duty cycle frequency in Hz
|
|
|
|
|
*/
|
|
|
|
|
int GetFrequency() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get if the sensor is connected
|
|
|
|
|
*
|
|
|
|
|
* This uses the duty cycle frequency to determine if the sensor is connected.
|
|
|
|
|
* By default, a value of 100 Hz is used as the threshold, and this value can
|
|
|
|
|
* be changed with SetConnectedFrequencyThreshold.
|
|
|
|
|
*
|
|
|
|
|
* @return true if the sensor is connected
|
|
|
|
|
*/
|
|
|
|
|
bool IsConnected() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Change the frequency threshold for detecting connection used by
|
|
|
|
|
* IsConnected.
|
|
|
|
|
*
|
|
|
|
|
* @param frequency the minimum frequency in Hz.
|
|
|
|
|
*/
|
|
|
|
|
void SetConnectedFrequencyThreshold(int frequency);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reset the Encoder distance to zero.
|
|
|
|
|
*/
|
|
|
|
|
void Reset();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the encoder value since the last reset.
|
|
|
|
|
*
|
|
|
|
|
* This is reported in rotations since the last reset.
|
|
|
|
|
*
|
|
|
|
|
* @return the encoder value in rotations
|
|
|
|
|
*/
|
|
|
|
|
units::turn_t Get() const;
|
|
|
|
|
|
2021-12-05 14:28:08 -08:00
|
|
|
/**
|
|
|
|
|
* Set the encoder duty cycle range. As the encoder needs to maintain a duty
|
|
|
|
|
* cycle, the duty cycle cannot go all the way to 0% or all the way to 100%.
|
|
|
|
|
* For example, an encoder with a 4096 us period might have a minimum duty
|
|
|
|
|
* cycle of 1 us / 4096 us and a maximum duty cycle of 4095 / 4096 us. Setting
|
|
|
|
|
* the range will result in an encoder duty cycle less than or equal to the
|
|
|
|
|
* minimum being output as 0 rotation, the duty cycle greater than or equal to
|
|
|
|
|
* the maximum being output as 1 rotation, and values in between linearly
|
|
|
|
|
* scaled from 0 to 1.
|
|
|
|
|
*
|
|
|
|
|
* @param min minimum duty cycle (0-1 range)
|
|
|
|
|
* @param max maximum duty cycle (0-1 range)
|
|
|
|
|
*/
|
|
|
|
|
void SetDutyCycleRange(double min, double max);
|
|
|
|
|
|
2019-11-14 22:51:33 -08:00
|
|
|
/**
|
|
|
|
|
* Set the distance per rotation of the encoder. This sets the multiplier used
|
|
|
|
|
* to determine the distance driven based on the rotation value from the
|
|
|
|
|
* encoder. Set this value based on the how far the mechanism travels in 1
|
|
|
|
|
* rotation of the encoder, and factor in gearing reductions following the
|
|
|
|
|
* encoder shaft. This distance can be in any units you like, linear or
|
|
|
|
|
* angular.
|
|
|
|
|
*
|
|
|
|
|
* @param distancePerRotation the distance per rotation of the encoder
|
|
|
|
|
*/
|
|
|
|
|
void SetDistancePerRotation(double distancePerRotation);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the distance per rotation for this encoder.
|
|
|
|
|
*
|
|
|
|
|
* @return The scale factor that will be used to convert rotation to useful
|
|
|
|
|
* units.
|
|
|
|
|
*/
|
|
|
|
|
double GetDistancePerRotation() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the distance the sensor has driven since the last reset as scaled by
|
|
|
|
|
* the value from SetDistancePerRotation.
|
|
|
|
|
*
|
|
|
|
|
* @return The distance driven since the last reset
|
|
|
|
|
*/
|
|
|
|
|
double GetDistance() const;
|
|
|
|
|
|
2020-10-24 20:18:58 -07:00
|
|
|
/**
|
|
|
|
|
* Get the FPGA index for the DutyCycleEncoder.
|
|
|
|
|
*
|
|
|
|
|
* @return the FPGA index
|
|
|
|
|
*/
|
|
|
|
|
int GetFPGAIndex() const;
|
|
|
|
|
|
2020-10-23 20:18:49 -07:00
|
|
|
/**
|
|
|
|
|
* Get the channel of the source.
|
|
|
|
|
*
|
|
|
|
|
* @return the source channel
|
|
|
|
|
*/
|
|
|
|
|
int GetSourceChannel() const;
|
|
|
|
|
|
2021-06-13 16:38:05 -07:00
|
|
|
void InitSendable(wpi::SendableBuilder& builder) override;
|
2019-11-14 22:51:33 -08:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void Init();
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<DutyCycle> m_dutyCycle;
|
2020-03-20 16:32:52 -05:00
|
|
|
std::unique_ptr<AnalogTrigger> m_analogTrigger;
|
|
|
|
|
std::unique_ptr<Counter> m_counter;
|
2019-11-14 22:51:33 -08:00
|
|
|
int m_frequencyThreshold = 100;
|
|
|
|
|
double m_positionOffset = 0;
|
|
|
|
|
double m_distancePerRotation = 1.0;
|
|
|
|
|
mutable units::turn_t m_lastPosition{0.0};
|
2021-12-05 14:28:08 -08:00
|
|
|
double m_sensorMin = 0;
|
|
|
|
|
double m_sensorMax = 1;
|
2019-11-14 22:51:33 -08:00
|
|
|
|
|
|
|
|
hal::SimDevice m_simDevice;
|
|
|
|
|
hal::SimDouble m_simPosition;
|
2020-12-24 12:23:38 -08:00
|
|
|
hal::SimDouble m_simDistancePerRotation;
|
2019-11-14 22:51:33 -08:00
|
|
|
hal::SimBoolean m_simIsConnected;
|
|
|
|
|
};
|
|
|
|
|
} // namespace frc
|