mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
Fixed FRCSim artf2599.
Made the wpilibC++Sim codebase's motor control as similar to the wpilibC++ motor control as possible. Change-Id: I5510d952cb40c4a3def210f46a566d7102d604ee
This commit is contained in:
@@ -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();
|
||||
};
|
||||
|
||||
20
wpilibc/wpilibC++Sim/include/MotorSafety.h
Normal file
20
wpilibc/wpilibC++Sim/include/MotorSafety.h
Normal file
@@ -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;
|
||||
};
|
||||
35
wpilibc/wpilibC++Sim/include/MotorSafetyHelper.h
Normal file
35
wpilibc/wpilibC++Sim/include/MotorSafetyHelper.h
Normal file
@@ -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
|
||||
};
|
||||
102
wpilibc/wpilibC++Sim/include/PWM.h
Normal file
102
wpilibc/wpilibC++Sim/include/PWM.h
Normal file
@@ -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;
|
||||
};
|
||||
38
wpilibc/wpilibC++Sim/include/SafePWM.h
Normal file
38
wpilibc/wpilibC++Sim/include/SafePWM.h
Normal file
@@ -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;
|
||||
};
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
156
wpilibc/wpilibC++Sim/src/MotorSafetyHelper.cpp
Normal file
156
wpilibc/wpilibC++Sim/src/MotorSafetyHelper.cpp
Normal file
@@ -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 <stdio.h>
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
273
wpilibc/wpilibC++Sim/src/PWM.cpp
Normal file
273
wpilibc/wpilibC++Sim/src/PWM.cpp
Normal file
@@ -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;
|
||||
}
|
||||
106
wpilibc/wpilibC++Sim/src/SafePWM.cpp
Normal file
106
wpilibc/wpilibC++Sim/src/SafePWM.cpp
Normal file
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user