diff --git a/wpilibc/wpilibC++Sim/include/Jaguar.h b/wpilibc/wpilibC++Sim/include/Jaguar.h index d30c13dc52..51ac4fe8c8 100644 --- a/wpilibc/wpilibC++Sim/include/Jaguar.h +++ b/wpilibc/wpilibC++Sim/include/Jaguar.h @@ -5,14 +5,14 @@ /*----------------------------------------------------------------------------*/ #pragma once -#include "simulation/SimContinuousOutput.h" +#include "SafePWM.h" #include "SpeedController.h" #include "PIDOutput.h" /** * Luminary Micro Jaguar Speed Control */ -class Jaguar : public SpeedController +class Jaguar : public SafePWM, public SpeedController { public: explicit Jaguar(uint32_t channel); @@ -24,6 +24,5 @@ public: virtual void PIDWrite(float output); private: - void InitJaguar(int channel); - SimContinuousOutput* impl; + void InitJaguar(); }; diff --git a/wpilibc/wpilibC++Sim/include/MotorSafety.h b/wpilibc/wpilibC++Sim/include/MotorSafety.h new file mode 100644 index 0000000000..ea7dfc4fb3 --- /dev/null +++ b/wpilibc/wpilibC++Sim/include/MotorSafety.h @@ -0,0 +1,20 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ +#pragma once + +#define DEFAULT_SAFETY_EXPIRATION 0.1 + +class MotorSafety +{ +public: + virtual void SetExpiration(float timeout) = 0; + virtual float GetExpiration() = 0; + virtual bool IsAlive() = 0; + virtual void StopMotor() = 0; + virtual void SetSafetyEnabled(bool enabled) = 0; + virtual bool IsSafetyEnabled() = 0; + virtual void GetDescription(char *desc) = 0; +}; diff --git a/wpilibc/wpilibC++Sim/include/MotorSafetyHelper.h b/wpilibc/wpilibC++Sim/include/MotorSafetyHelper.h new file mode 100644 index 0000000000..944a197273 --- /dev/null +++ b/wpilibc/wpilibC++Sim/include/MotorSafetyHelper.h @@ -0,0 +1,35 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ +#pragma once + +#include "ErrorBase.h" +#include "HAL/cpp/Synchronized.hpp" + +class MotorSafety; + +class MotorSafetyHelper : public ErrorBase +{ +public: + MotorSafetyHelper(MotorSafety *safeObject); + ~MotorSafetyHelper(); + void Feed(); + void SetExpiration(float expirationTime); + float GetExpiration(); + bool IsAlive(); + void Check(); + void SetSafetyEnabled(bool enabled); + bool IsSafetyEnabled(); + static void CheckMotors(); +private: + double m_expiration; // the expiration time for this object + bool m_enabled; // true if motor safety is enabled for this motor + double m_stopTime; // the FPGA clock value when this motor has expired + ReentrantSemaphore m_syncMutex; // protect accesses to the state for this object + MotorSafety *m_safeObject; // the object that is using the helper + MotorSafetyHelper *m_nextHelper; // next object in the list of MotorSafetyHelpers + static MotorSafetyHelper *m_headHelper; // the head of the list of MotorSafetyHelper objects + static ReentrantSemaphore m_listMutex; // protect accesses to the list of helpers +}; diff --git a/wpilibc/wpilibC++Sim/include/PWM.h b/wpilibc/wpilibC++Sim/include/PWM.h new file mode 100644 index 0000000000..998a78fe0f --- /dev/null +++ b/wpilibc/wpilibC++Sim/include/PWM.h @@ -0,0 +1,102 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ +#pragma once + +#include "SensorBase.h" +#include "simulation/SimContinuousOutput.h" +#include "LiveWindow/LiveWindowSendable.h" +#include "tables/ITableListener.h" + +/** + * Class implements the PWM generation in the FPGA. + * + * The values supplied as arguments for PWM outputs range from -1.0 to 1.0. They are mapped + * to the hardware dependent values, in this case 0-255 for the FPGA. + * Changes are immediately sent to the FPGA, and the update occurs at the next + * FPGA cycle. There is no delay. + * + * As of revision 0.1.10 of the FPGA, the FPGA interprets the 0-255 values as follows: + * - 255 = full "forward" + * - 254 to 129 = linear scaling from "full forward" to "center" + * - 128 = center value + * - 127 to 2 = linear scaling from "center" to "full reverse" + * - 1 = full "reverse" + * - 0 = disabled (i.e. PWM output is held low) + */ +class PWM : public SensorBase, public ITableListener, public LiveWindowSendable +{ +public: + enum PeriodMultiplier + { + kPeriodMultiplier_1X = 1, + kPeriodMultiplier_2X = 2, + kPeriodMultiplier_4X = 4 + }; + + explicit PWM(uint32_t channel); + virtual ~PWM(); + virtual void SetRaw(unsigned short value); + void SetPeriodMultiplier(PeriodMultiplier mult); + void EnableDeadbandElimination(bool eliminateDeadband); + void SetBounds(int32_t max, int32_t deadbandMax, int32_t center, int32_t deadbandMin, + int32_t min); + void SetBounds(double max, double deadbandMax, double center, double deadbandMin, double min); + uint32_t GetChannel() + { + return m_channel; + } + +protected: + /** + * kDefaultPwmPeriod is in ms + * + * - 20ms periods (50 Hz) are the "safest" setting in that this works for all devices + * - 20ms periods seem to be desirable for Vex Motors + * - 20ms periods are the specified period for HS-322HD servos, but work reliably down + * to 10.0 ms; starting at about 8.5ms, the servo sometimes hums and get hot; + * by 5.0ms the hum is nearly continuous + * - 10ms periods work well for Victor 884 + * - 5ms periods allows higher update rates for Luminary Micro Jaguar speed controllers. + * Due to the shipping firmware on the Jaguar, we can't run the update period less + * than 5.05 ms. + * + * kDefaultPwmPeriod is the 1x period (5.05 ms). In hardware, the period scaling is implemented as an + * output squelch to get longer periods for old devices. + */ + static constexpr float kDefaultPwmPeriod = 5.05; + /** + * kDefaultPwmCenter is the PWM range center in ms + */ + static constexpr float kDefaultPwmCenter = 1.5; + /** + * kDefaultPWMStepsDown is the number of PWM steps below the centerpoint + */ + static const int32_t kDefaultPwmStepsDown = 1000; + static const int32_t kPwmDisabled = 0; + + virtual void SetPosition(float pos); + virtual float GetPosition(); + virtual void SetSpeed(float speed); + virtual float GetSpeed(); + + bool m_eliminateDeadband; + int32_t m_centerPwm; + + void ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew); + void UpdateTable(); + void StartLiveWindowMode(); + void StopLiveWindowMode(); + std::string GetSmartDashboardType(); + void InitTable(ITable *subTable); + ITable * GetTable(); + + ITable *m_table; + +private: + void InitPWM(uint32_t channel); + uint32_t m_channel; + SimContinuousOutput* impl; +}; diff --git a/wpilibc/wpilibC++Sim/include/SafePWM.h b/wpilibc/wpilibC++Sim/include/SafePWM.h new file mode 100644 index 0000000000..bed5c214f5 --- /dev/null +++ b/wpilibc/wpilibC++Sim/include/SafePWM.h @@ -0,0 +1,38 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ +#pragma once + +#include "MotorSafety.h" +#include "PWM.h" + +class MotorSafetyHelper; + +/** + * A safe version of the PWM class. + * It is safe because it implements the MotorSafety interface that provides timeouts + * in the event that the motor value is not updated before the expiration time. + * This delegates the actual work to a MotorSafetyHelper object that is used for all + * objects that implement MotorSafety. + */ +class SafePWM : public PWM, public MotorSafety +{ +public: + explicit SafePWM(uint32_t channel); + ~SafePWM(); + + void SetExpiration(float timeout); + float GetExpiration(); + bool IsAlive(); + void StopMotor(); + bool IsSafetyEnabled(); + void SetSafetyEnabled(bool enabled); + void GetDescription(char *desc); + + virtual void SetSpeed(float speed); +private: + void InitSafePWM(); + MotorSafetyHelper *m_safetyHelper; +}; diff --git a/wpilibc/wpilibC++Sim/include/Talon.h b/wpilibc/wpilibC++Sim/include/Talon.h index c51cc82253..d9fb0ef12d 100644 --- a/wpilibc/wpilibC++Sim/include/Talon.h +++ b/wpilibc/wpilibC++Sim/include/Talon.h @@ -5,14 +5,14 @@ /*----------------------------------------------------------------------------*/ #pragma once -#include "simulation/SimContinuousOutput.h" +#include "SafePWM.h" #include "SpeedController.h" #include "PIDOutput.h" /** * CTRE Talon Speed Controller */ -class Talon : public SpeedController +class Talon : public SafePWM, public SpeedController { public: explicit Talon(uint32_t channel); @@ -24,6 +24,5 @@ public: virtual void PIDWrite(float output); private: - void InitTalon(int channel); - SimContinuousOutput* impl; + void InitTalon(); }; diff --git a/wpilibc/wpilibC++Sim/include/Victor.h b/wpilibc/wpilibC++Sim/include/Victor.h index 5873176afa..fce4139f05 100644 --- a/wpilibc/wpilibC++Sim/include/Victor.h +++ b/wpilibc/wpilibC++Sim/include/Victor.h @@ -5,14 +5,14 @@ /*----------------------------------------------------------------------------*/ #pragma once -#include "simulation/SimContinuousOutput.h" +#include "SafePWM.h" #include "SpeedController.h" #include "PIDOutput.h" /** * IFI Victor Speed Controller */ -class Victor : public SpeedController +class Victor : public SafePWM, public SpeedController { public: explicit Victor(uint32_t channel); @@ -24,6 +24,5 @@ public: virtual void PIDWrite(float output); private: - void InitVictor(int channel); - SimContinuousOutput* impl; + void InitVictor(); }; diff --git a/wpilibc/wpilibC++Sim/src/Jaguar.cpp b/wpilibc/wpilibC++Sim/src/Jaguar.cpp index da6945756c..3b04efdfcb 100644 --- a/wpilibc/wpilibC++Sim/src/Jaguar.cpp +++ b/wpilibc/wpilibC++Sim/src/Jaguar.cpp @@ -6,35 +6,36 @@ #include "Jaguar.h" +//#include "NetworkCommunication/UsageReporting.h" #include "LiveWindow/LiveWindow.h" /** * Common initialization code called by all constructors. */ -void Jaguar::InitJaguar(int channel) +void Jaguar::InitJaguar() { /* * Input profile defined by Luminary Micro. - * + * * Full reverse ranges from 0.671325ms to 0.6972211ms * Proportional reverse ranges from 0.6972211ms to 1.4482078ms * Neutral ranges from 1.4482078ms to 1.5517922ms * Proportional forward ranges from 1.5517922ms to 2.3027789ms * Full forward ranges from 2.3027789ms to 2.328675ms */ - char buffer[50]; - int n = sprintf(buffer, "pwm/1/%d", channel); - impl = new SimContinuousOutput(buffer); + SetBounds(2.31, 1.55, 1.507, 1.454, .697); + SetPeriodMultiplier(kPeriodMultiplier_1X); + SetRaw(m_centerPwm); - // TODO: LiveWindow::GetInstance()->AddActuator("Jaguar", GetChannel(), this); + LiveWindow::GetInstance()->AddActuator("Jaguar", GetChannel(), this); } /** * @param channel The PWM channel that the Jaguar is attached to. */ -Jaguar::Jaguar(uint32_t channel) +Jaguar::Jaguar(uint32_t channel) : SafePWM(channel) { - InitJaguar(channel); + InitJaguar(); } Jaguar::~Jaguar() @@ -52,7 +53,7 @@ Jaguar::~Jaguar() */ void Jaguar::Set(float speed, uint8_t syncGroup) { - impl->Set(speed); + SetSpeed(speed); } /** @@ -62,7 +63,7 @@ void Jaguar::Set(float speed, uint8_t syncGroup) */ float Jaguar::Get() { - return impl->Get(); + return GetSpeed(); } /** @@ -70,7 +71,7 @@ float Jaguar::Get() */ void Jaguar::Disable() { - impl->Set(0); + SetRaw(kPwmDisabled); } /** @@ -82,4 +83,3 @@ void Jaguar::PIDWrite(float output) { Set(output); } - diff --git a/wpilibc/wpilibC++Sim/src/MotorSafetyHelper.cpp b/wpilibc/wpilibC++Sim/src/MotorSafetyHelper.cpp new file mode 100644 index 0000000000..23e49d5669 --- /dev/null +++ b/wpilibc/wpilibC++Sim/src/MotorSafetyHelper.cpp @@ -0,0 +1,156 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "MotorSafetyHelper.h" + +#include "DriverStation.h" +#include "MotorSafety.h" +#include "Timer.h" +#include "WPIErrors.h" + +#include + +MotorSafetyHelper *MotorSafetyHelper::m_headHelper = NULL; +ReentrantSemaphore MotorSafetyHelper::m_listMutex; + +/** + * The constructor for a MotorSafetyHelper object. + * The helper object is constructed for every object that wants to implement the Motor + * Safety protocol. The helper object has the code to actually do the timing and call the + * motors Stop() method when the timeout expires. The motor object is expected to call the + * Feed() method whenever the motors value is updated. + * @param safeObject a pointer to the motor object implementing MotorSafety. This is used + * to call the Stop() method on the motor. + */ +MotorSafetyHelper::MotorSafetyHelper(MotorSafety *safeObject) +{ + m_safeObject = safeObject; + m_enabled = false; + m_expiration = DEFAULT_SAFETY_EXPIRATION; + m_stopTime = Timer::GetFPGATimestamp(); + + Synchronized sync(m_listMutex); + m_nextHelper = m_headHelper; + m_headHelper = this; +} + + +MotorSafetyHelper::~MotorSafetyHelper() +{ + Synchronized sync(m_listMutex); + if (m_headHelper == this) + { + m_headHelper = m_nextHelper; + } + else + { + MotorSafetyHelper *prev = NULL; + MotorSafetyHelper *cur = m_headHelper; + while (cur != this && cur != NULL) + prev = cur, cur = cur->m_nextHelper; + if (cur == this) + prev->m_nextHelper = cur->m_nextHelper; + } +} + +/* + * Feed the motor safety object. + * Resets the timer on this object that is used to do the timeouts. + */ +void MotorSafetyHelper::Feed() +{ + Synchronized sync(m_syncMutex); + m_stopTime = Timer::GetFPGATimestamp() + m_expiration; +} + +/* + * Set the expiration time for the corresponding motor safety object. + * @param expirationTime The timeout value in seconds. + */ +void MotorSafetyHelper::SetExpiration(float expirationTime) +{ + Synchronized sync(m_syncMutex); + m_expiration = expirationTime; +} + +/** + * Retrieve the timeout value for the corresponding motor safety object. + * @returns the timeout value in seconds. + */ +float MotorSafetyHelper::GetExpiration() +{ + Synchronized sync(m_syncMutex); + return m_expiration; +} + +/** + * Determine if the motor is still operating or has timed out. + * @returns a true value if the motor is still operating normally and hasn't timed out. + */ +bool MotorSafetyHelper::IsAlive() +{ + Synchronized sync(m_syncMutex); + return !m_enabled || m_stopTime > Timer::GetFPGATimestamp(); +} + +/** + * Check if this motor has exceeded its timeout. + * This method is called periodically to determine if this motor has exceeded its timeout + * value. If it has, the stop method is called, and the motor is shut down until its value is + * updated again. + */ +void MotorSafetyHelper::Check() +{ + DriverStation *ds = DriverStation::GetInstance(); + if (!m_enabled || ds->IsDisabled() || ds->IsTest()) return; + + Synchronized sync(m_syncMutex); + if (m_stopTime < Timer::GetFPGATimestamp()) + { + char buf[128]; + char desc[64]; + m_safeObject->GetDescription(desc); + snprintf(buf, 128, "%s... Output not updated often enough.", desc); + wpi_setWPIErrorWithContext(Timeout, buf); + m_safeObject->StopMotor(); + } +} + +/** + * Enable/disable motor safety for this device + * Turn on and off the motor safety option for this PWM object. + * @param enabled True if motor safety is enforced for this object + */ +void MotorSafetyHelper::SetSafetyEnabled(bool enabled) +{ + Synchronized sync(m_syncMutex); + m_enabled = enabled; +} + +/** + * Return the state of the motor safety enabled flag + * Return if the motor safety is currently enabled for this devicce. + * @returns True if motor safety is enforced for this device + */ +bool MotorSafetyHelper::IsSafetyEnabled() +{ + Synchronized sync(m_syncMutex); + return m_enabled; +} + +/** + * Check the motors to see if any have timed out. + * This static method is called periodically to poll all the motors and stop any that have + * timed out. + */ +void MotorSafetyHelper::CheckMotors() +{ + Synchronized sync(m_listMutex); + for (MotorSafetyHelper *msh = m_headHelper; msh != NULL; msh = msh->m_nextHelper) + { + msh->Check(); + } +} diff --git a/wpilibc/wpilibC++Sim/src/PWM.cpp b/wpilibc/wpilibC++Sim/src/PWM.cpp new file mode 100644 index 0000000000..f077d42ab2 --- /dev/null +++ b/wpilibc/wpilibC++Sim/src/PWM.cpp @@ -0,0 +1,273 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "PWM.h" + +//#include "NetworkCommunication/UsageReporting.h" +#include "Utility.h" +#include "WPIErrors.h" + +constexpr float PWM::kDefaultPwmPeriod; +constexpr float PWM::kDefaultPwmCenter; +const int32_t PWM::kDefaultPwmStepsDown; +const int32_t PWM::kPwmDisabled; + +/** + * Initialize PWMs given a channel. + * + * This method is private and is the common path for all the constructors for creating PWM + * instances. Checks channel value range and allocates the appropriate channel. + * The allocation is only done to help users ensure that they don't double assign channels. + */ +void PWM::InitPWM(uint32_t channel) +{ + m_table = NULL; + char buf[64]; + + if (!CheckPWMChannel(channel)) + { + snprintf(buf, 64, "PWM Channel %d", channel); + wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf); + return; + } + + sprintf(buf, "pwm/1/%d", channel); + impl = new SimContinuousOutput(buf); + m_channel = channel; + m_eliminateDeadband = false; + + m_centerPwm = kPwmDisabled; // In simulation, the same thing. +} + +/** + * Allocate a PWM given a channel number. + * + * @param channel The PWM channel. + */ +PWM::PWM(uint32_t channel) +{ + InitPWM(channel); +} + +/** + * Free the PWM channel. + * + * Free the resource associated with the PWM channel and set the value to 0. + */ +PWM::~PWM() +{ +} + +/** + * Optionally eliminate the deadband from a speed controller. + * @param eliminateDeadband If true, set the motor curve on the Jaguar to eliminate + * the deadband in the middle of the range. Otherwise, keep the full range without + * modifying any values. + */ +void PWM::EnableDeadbandElimination(bool eliminateDeadband) +{ + m_eliminateDeadband = eliminateDeadband; +} + +/** + * Set the bounds on the PWM values. + * This sets the bounds on the PWM values for a particular each type of controller. The values + * determine the upper and lower speeds as well as the deadband bracket. + * @param max The Minimum pwm value + * @param deadbandMax The high end of the deadband range + * @param center The center speed (off) + * @param deadbandMin The low end of the deadband range + * @param min The minimum pwm value + */ +void PWM::SetBounds(int32_t max, int32_t deadbandMax, int32_t center, int32_t deadbandMin, int32_t min) +{ + // Nothing to do in simulation. +} + + +/** + * Set the bounds on the PWM pulse widths. + * This sets the bounds on the PWM values for a particular type of controller. The values + * determine the upper and lower speeds as well as the deadband bracket. + * @param max The max PWM pulse width in ms + * @param deadbandMax The high end of the deadband range pulse width in ms + * @param center The center (off) pulse width in ms + * @param deadbandMin The low end of the deadband pulse width in ms + * @param min The minimum pulse width in ms + */ +void PWM::SetBounds(double max, double deadbandMax, double center, double deadbandMin, double min) +{ + // Nothing to do in simulation. +} + +/** + * Set the PWM value based on a position. + * + * This is intended to be used by servos. + * + * @pre SetMaxPositivePwm() called. + * @pre SetMinNegativePwm() called. + * + * @param pos The position to set the servo between 0.0 and 1.0. + */ +void PWM::SetPosition(float pos) +{ + if (pos < 0.0) + { + pos = 0.0; + } + else if (pos > 1.0) + { + pos = 1.0; + } + + impl->Set(pos); +} + +/** + * Get the PWM value in terms of a position. + * + * This is intended to be used by servos. + * + * @pre SetMaxPositivePwm() called. + * @pre SetMinNegativePwm() called. + * + * @return The position the servo is set to between 0.0 and 1.0. + */ +float PWM::GetPosition() +{ + float value = impl->Get(); + if (value < 0.0) + { + return 0.0; + } + else if (value > 1.0) + { + return 1.0; + } + else + { + return value; + } +} + +/** + * Set the PWM value based on a speed. + * + * This is intended to be used by speed controllers. + * + * @pre SetMaxPositivePwm() called. + * @pre SetMinPositivePwm() called. + * @pre SetCenterPwm() called. + * @pre SetMaxNegativePwm() called. + * @pre SetMinNegativePwm() called. + * + * @param speed The speed to set the speed controller between -1.0 and 1.0. + */ +void PWM::SetSpeed(float speed) +{ + // clamp speed to be in the range 1.0 >= speed >= -1.0 + if (speed < -1.0) + { + speed = -1.0; + } + else if (speed > 1.0) + { + speed = 1.0; + } + + impl->Set(speed); +} + +/** + * Get the PWM value in terms of speed. + * + * This is intended to be used by speed controllers. + * + * @pre SetMaxPositivePwm() called. + * @pre SetMinPositivePwm() called. + * @pre SetMaxNegativePwm() called. + * @pre SetMinNegativePwm() called. + * + * @return The most recently set speed between -1.0 and 1.0. + */ +float PWM::GetSpeed() +{ + float value = impl->Get(); + if (value > 1.0) + { + return 1.0; + } + else if (value < -1.0) + { + return -1.0; + } + else + { + return value; + } +} + +/** + * Set the PWM value directly to the hardware. + * + * Write a raw value to a PWM channel. + * + * @param value Raw PWM value. + */ +void PWM::SetRaw(unsigned short value) +{ + wpi_assert(value == kPwmDisabled); + impl->Set(0); +} + +/** + * Slow down the PWM signal for old devices. + * + * @param mult The period multiplier to apply to this channel + */ +void PWM::SetPeriodMultiplier(PeriodMultiplier mult) +{ + // Do nothing in simulation. +} + + +void PWM::ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew) { + SetSpeed(value.f); +} + +void PWM::UpdateTable() { + if (m_table != NULL) { + m_table->PutNumber("Value", GetSpeed()); + } +} + +void PWM::StartLiveWindowMode() { + SetSpeed(0); + if (m_table != NULL) { + m_table->AddTableListener("Value", this, true); + } +} + +void PWM::StopLiveWindowMode() { + SetSpeed(0); + if (m_table != NULL) { + m_table->RemoveTableListener(this); + } +} + +std::string PWM::GetSmartDashboardType() { + return "Speed Controller"; +} + +void PWM::InitTable(ITable *subTable) { + m_table = subTable; + UpdateTable(); +} + +ITable * PWM::GetTable() { + return m_table; +} diff --git a/wpilibc/wpilibC++Sim/src/SafePWM.cpp b/wpilibc/wpilibC++Sim/src/SafePWM.cpp new file mode 100644 index 0000000000..fb51f32fc4 --- /dev/null +++ b/wpilibc/wpilibC++Sim/src/SafePWM.cpp @@ -0,0 +1,106 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "SafePWM.h" + +#include "MotorSafetyHelper.h" + +/** + * Initialize a SafePWM object by setting defaults + */ +void SafePWM::InitSafePWM() +{ + m_safetyHelper = new MotorSafetyHelper(this); + m_safetyHelper->SetSafetyEnabled(false); +} + +/** + * Constructor for a SafePWM object taking a channel number. + * @param channel The PWM channel number (0..19). + */ +SafePWM::SafePWM(uint32_t channel): PWM(channel) +{ + InitSafePWM(); +} + +SafePWM::~SafePWM() +{ + delete m_safetyHelper; +} + +/* + * Set the expiration time for the PWM object + * @param timeout The timeout (in seconds) for this motor object + */ +void SafePWM::SetExpiration(float timeout) +{ + m_safetyHelper->SetExpiration(timeout); +} + +/** + * Return the expiration time for the PWM object. + * @returns The expiration time value. + */ +float SafePWM::GetExpiration() +{ + return m_safetyHelper->GetExpiration(); +} + +/** + * Check if the PWM object is currently alive or stopped due to a timeout. + * @returns a bool value that is true if the motor has NOT timed out and should still + * be running. + */ +bool SafePWM::IsAlive() +{ + return m_safetyHelper->IsAlive(); +} + +/** + * Stop the motor associated with this PWM object. + * This is called by the MotorSafetyHelper object when it has a timeout for this PWM and needs to + * stop it from running. + */ +void SafePWM::StopMotor() +{ + SetRaw(kPwmDisabled); +} + +/** + * Enable/disable motor safety for this device + * Turn on and off the motor safety option for this PWM object. + * @param enabled True if motor safety is enforced for this object + */ +void SafePWM::SetSafetyEnabled(bool enabled) +{ + m_safetyHelper->SetSafetyEnabled(enabled); +} + +/** + * Check if motor safety is enabled for this object + * @returns True if motor safety is enforced for this object + */ +bool SafePWM::IsSafetyEnabled() +{ + return m_safetyHelper->IsSafetyEnabled(); +} + +void SafePWM::GetDescription(char *desc) +{ + sprintf(desc, "PWM %d", GetChannel()); +} + +/** + * Feed the MotorSafety timer when setting the speed. + * This method is called by the subclass motor whenever it updates its speed, thereby reseting + * the timeout value. + * @param speed Value to pass to the PWM class + */ +void SafePWM::SetSpeed(float speed) +{ + PWM::SetSpeed(speed); + m_safetyHelper->Feed(); +} diff --git a/wpilibc/wpilibC++Sim/src/Talon.cpp b/wpilibc/wpilibC++Sim/src/Talon.cpp index a0e9420be8..7732b8f1ee 100644 --- a/wpilibc/wpilibC++Sim/src/Talon.cpp +++ b/wpilibc/wpilibC++Sim/src/Talon.cpp @@ -6,6 +6,7 @@ #include "Talon.h" +//#include "NetworkCommunication/UsageReporting.h" #include "LiveWindow/LiveWindow.h" /** @@ -22,20 +23,20 @@ * - 125 = the "low end" of the deadband range * - 49 = full "reverse" */ -void Talon::InitTalon(int channel) { - char buffer[50]; - int n = sprintf(buffer, "pwm/1/%d", channel); - impl = new SimContinuousOutput(buffer); +void Talon::InitTalon() { + SetBounds(2.037, 1.539, 1.513, 1.487, .989); + SetPeriodMultiplier(kPeriodMultiplier_2X); + SetRaw(m_centerPwm); - // TODO: LiveWindow::GetInstance()->AddActuator("Talon", slot, channel, this); + LiveWindow::GetInstance()->AddActuator("Talon", GetChannel(), this); } /** * @param channel The PWM channel that the Talon is attached to. */ -Talon::Talon(uint32_t channel) +Talon::Talon(uint32_t channel) : SafePWM(channel) { - InitTalon(channel); + InitTalon(); } Talon::~Talon() @@ -53,7 +54,7 @@ Talon::~Talon() */ void Talon::Set(float speed, uint8_t syncGroup) { - impl->Set(speed); + SetSpeed(speed); } /** @@ -63,7 +64,7 @@ void Talon::Set(float speed, uint8_t syncGroup) */ float Talon::Get() { - return impl->Get(); + return GetSpeed(); } /** @@ -71,7 +72,7 @@ float Talon::Get() */ void Talon::Disable() { - impl->Set(0); + SetRaw(kPwmDisabled); } /** diff --git a/wpilibc/wpilibC++Sim/src/Victor.cpp b/wpilibc/wpilibC++Sim/src/Victor.cpp index 721053d241..333e2d25f8 100644 --- a/wpilibc/wpilibC++Sim/src/Victor.cpp +++ b/wpilibc/wpilibC++Sim/src/Victor.cpp @@ -6,6 +6,7 @@ #include "Victor.h" +//#include "NetworkCommunication/UsageReporting.h" #include "LiveWindow/LiveWindow.h" /** @@ -23,20 +24,21 @@ * - 125 = the "low end" of the deadband range * - 56 = full "reverse" */ -void Victor::InitVictor(int channel) { - char buffer[50]; - int n = sprintf(buffer, "pwm/1/%d", channel); - impl = new SimContinuousOutput(buffer); +void Victor::InitVictor() { + SetBounds(2.027, 1.525, 1.507, 1.49, 1.026); - // TODO: LiveWindow::GetInstance()->AddActuator("Victor", slot, channel, this); + SetPeriodMultiplier(kPeriodMultiplier_2X); + SetRaw(m_centerPwm); + + LiveWindow::GetInstance()->AddActuator("Victor", GetChannel(), this); } /** * @param channel The PWM channel that the Victor is attached to. */ -Victor::Victor(uint32_t channel) +Victor::Victor(uint32_t channel) : SafePWM(channel) { - InitVictor(channel); + InitVictor(); } Victor::~Victor() @@ -48,13 +50,13 @@ Victor::~Victor() * * The PWM value is set using a range of -1.0 to 1.0, appropriately * scaling the value for the FPGA. - * + * * @param speed The speed value between -1.0 and 1.0 to set. * @param syncGroup Unused interface. */ void Victor::Set(float speed, uint8_t syncGroup) { - impl->Set(speed); + SetSpeed(speed); } /** @@ -64,7 +66,7 @@ void Victor::Set(float speed, uint8_t syncGroup) */ float Victor::Get() { - return impl->Get(); + return GetSpeed(); } /** @@ -72,7 +74,7 @@ float Victor::Get() */ void Victor::Disable() { - impl->Set(0); + SetRaw(kPwmDisabled); } /**