Now you can download a copy of these docs so you can use them offline! Download now
PWM.cpp
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) FIRST 2008. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5 /*----------------------------------------------------------------------------*/
6 
7 #include "PWM.h"
8 
9 #include "DigitalModule.h"
10 #include "NetworkCommunication/UsageReporting.h"
11 #include "Resource.h"
12 #include "Utility.h"
13 #include "WPIErrors.h"
14 
15 constexpr float PWM::kDefaultPwmPeriod;
16 constexpr float PWM::kDefaultPwmCenter;
17 const int32_t PWM::kDefaultPwmStepsDown;
18 const int32_t PWM::kPwmDisabled;
19 static Resource *allocated = NULL;
20 
28 void PWM::InitPWM(uint8_t moduleNumber, uint32_t channel)
29 {
30  m_table = NULL;
31  char buf[64];
32  Resource::CreateResourceObject(&allocated, tDIO::kNumSystems * kPwmChannels);
33  if (!CheckPWMModule(moduleNumber))
34  {
35  snprintf(buf, 64, "Digital Module %d", moduleNumber);
36  wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf);
37  return;
38  }
39  if (!CheckPWMChannel(channel))
40  {
41  snprintf(buf, 64, "PWM Channel %d", channel);
42  wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
43  return;
44  }
45 
46  snprintf(buf, 64, "PWM %d (Module: %d)", channel, moduleNumber);
47  if (allocated->Allocate((moduleNumber - 1) * kPwmChannels + channel - 1, buf) == ~0ul)
48  {
49  CloneError(allocated);
50  return;
51  }
52  m_channel = channel;
53  m_module = DigitalModule::GetInstance(moduleNumber);
54  m_module->SetPWM(m_channel, kPwmDisabled);
55  m_eliminateDeadband = false;
56 
57  nUsageReporting::report(nUsageReporting::kResourceType_PWM, channel, moduleNumber - 1);
58 }
59 
67 PWM::PWM(uint8_t moduleNumber, uint32_t channel)
68  : m_module(NULL)
69 {
70  InitPWM(moduleNumber, channel);
71 }
72 
81 PWM::PWM(uint32_t channel)
82  : m_module(NULL)
83 {
84  InitPWM(GetDefaultDigitalModule(), channel);
85 }
86 
93 {
94  if (m_module)
95  {
96  m_module->SetPWM(m_channel, kPwmDisabled);
97  allocated->Free((m_module->GetNumber() - 1) * kPwmChannels + m_channel - 1);
98  }
99 }
100 
107 void PWM::EnableDeadbandElimination(bool eliminateDeadband)
108 {
109  if (StatusIsFatal()) return;
110  m_eliminateDeadband = eliminateDeadband;
111 }
112 
123 void PWM::SetBounds(int32_t max, int32_t deadbandMax, int32_t center, int32_t deadbandMin, int32_t min)
124 {
125  if (StatusIsFatal()) return;
126  m_maxPwm = max;
127  m_deadbandMaxPwm = deadbandMax;
128  m_centerPwm = center;
129  m_deadbandMinPwm = deadbandMin;
130  m_minPwm = min;
131 }
132 
133 
144 void PWM::SetBounds(double max, double deadbandMax, double center, double deadbandMin, double min)
145 {
146  if (StatusIsFatal()) return;
147 
148  double loopTime = m_module->GetLoopTiming()/(kSystemClockTicksPerMicrosecond*1e3);
149 
150  m_maxPwm = (int32_t)((max-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
151  m_deadbandMaxPwm = (int32_t)((deadbandMax-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
152  m_centerPwm = (int32_t)((center-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
153  m_deadbandMinPwm = (int32_t)((deadbandMin-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
154  m_minPwm = (int32_t)((min-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
155 }
156 
157 uint32_t PWM::GetModuleNumber()
158 {
159  return m_module->GetNumber();
160 }
161 
172 void PWM::SetPosition(float pos)
173 {
174  if (StatusIsFatal()) return;
175  if (pos < 0.0)
176  {
177  pos = 0.0;
178  }
179  else if (pos > 1.0)
180  {
181  pos = 1.0;
182  }
183 
184  int32_t rawValue;
185  // note, need to perform the multiplication below as floating point before converting to int
186  rawValue = (int32_t)( (pos * (float) GetFullRangeScaleFactor()) + GetMinNegativePwm());
187 
188  wpi_assert((rawValue >= GetMinNegativePwm()) && (rawValue <= GetMaxPositivePwm()));
189  wpi_assert(rawValue != kPwmDisabled);
190 
191  // send the computed pwm value to the FPGA
192  SetRaw((uint8_t)rawValue);
193 }
194 
206 {
207  if (StatusIsFatal()) return 0.0;
208  int32_t value = GetRaw();
209  if (value < GetMinNegativePwm())
210  {
211  return 0.0;
212  }
213  else if (value > GetMaxPositivePwm())
214  {
215  return 1.0;
216  }
217  else
218  {
219  return (float)(value - GetMinNegativePwm()) / (float)GetFullRangeScaleFactor();
220  }
221 }
222 
236 void PWM::SetSpeed(float speed)
237 {
238  if (StatusIsFatal()) return;
239  // clamp speed to be in the range 1.0 >= speed >= -1.0
240  if (speed < -1.0)
241  {
242  speed = -1.0;
243  }
244  else if (speed > 1.0)
245  {
246  speed = 1.0;
247  }
248 
249  // calculate the desired output pwm value by scaling the speed appropriately
250  int32_t rawValue;
251  if (speed == 0.0)
252  {
253  rawValue = GetCenterPwm();
254  }
255  else if (speed > 0.0)
256  {
257  rawValue = (int32_t)(speed * ((float)GetPositiveScaleFactor()) +
258  ((float) GetMinPositivePwm()) + 0.5);
259  }
260  else
261  {
262  rawValue = (int32_t)(speed * ((float)GetNegativeScaleFactor()) +
263  ((float) GetMaxNegativePwm()) + 0.5);
264  }
265 
266  // the above should result in a pwm_value in the valid range
267  wpi_assert((rawValue >= GetMinNegativePwm()) && (rawValue <= GetMaxPositivePwm()));
268  wpi_assert(rawValue != kPwmDisabled);
269 
270  // send the computed pwm value to the FPGA
271  SetRaw((uint8_t)rawValue);
272 }
273 
287 {
288  if (StatusIsFatal()) return 0.0;
289  int32_t value = GetRaw();
290  if (value == PWM::kPwmDisabled)
291  {
292  return 0.0;
293  }
294  else if (value > GetMaxPositivePwm())
295  {
296  return 1.0;
297  }
298  else if (value < GetMinNegativePwm())
299  {
300  return -1.0;
301  }
302  else if (value > GetMinPositivePwm())
303  {
304  return (float)(value - GetMinPositivePwm()) / (float)GetPositiveScaleFactor();
305  }
306  else if (value < GetMaxNegativePwm())
307  {
308  return (float)(value - GetMaxNegativePwm()) / (float)GetNegativeScaleFactor();
309  }
310  else
311  {
312  return 0.0;
313  }
314 }
315 
323 void PWM::SetRaw(uint8_t value)
324 {
325  if (StatusIsFatal()) return;
326  m_module->SetPWM(m_channel, value);
327 }
328 
336 uint8_t PWM::GetRaw()
337 {
338  if (StatusIsFatal()) return 0;
339  return m_module->GetPWM(m_channel);
340 }
341 
347 void PWM::SetPeriodMultiplier(PeriodMultiplier mult)
348 {
349  if (StatusIsFatal()) return;
350  switch(mult)
351  {
352  case kPeriodMultiplier_4X:
353  m_module->SetPWMPeriodScale(m_channel, 3); // Squelch 3 out of 4 outputs
354  break;
355  case kPeriodMultiplier_2X:
356  m_module->SetPWMPeriodScale(m_channel, 1); // Squelch 1 out of 2 outputs
357  break;
358  case kPeriodMultiplier_1X:
359  m_module->SetPWMPeriodScale(m_channel, 0); // Don't squelch any outputs
360  break;
361  default:
362  wpi_assert(false);
363  }
364 }
365 
366 
367 void PWM::ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew) {
368  SetSpeed(value.f);
369 }
370 
372  if (m_table != NULL) {
373  m_table->PutNumber("Value", GetSpeed());
374  }
375 }
376 
378  SetSpeed(0);
379  if (m_table != NULL) {
380  m_table->AddTableListener("Value", this, true);
381  }
382 }
383 
385  SetSpeed(0);
386  if (m_table != NULL) {
387  m_table->RemoveTableListener(this);
388  }
389 }
390 
392  return "Speed Controller";
393 }
394 
395 void PWM::InitTable(ITable *subTable) {
396  m_table = subTable;
397  UpdateTable();
398 }
399 
401  return m_table;
402 }
403 
uint16_t GetLoopTiming()
virtual void SetPosition(float pos)
Definition: PWM.cpp:172
virtual void RemoveTableListener(ITableListener *listener)=0
void InitTable(ITable *subTable)
Definition: PWM.cpp:395
virtual float GetSpeed()
Definition: PWM.cpp:286
ITable * GetTable()
Definition: PWM.cpp:400
virtual void PutNumber(std::string key, double value)=0
void ValueChanged(ITable *source, const std::string &key, EntryValue value, bool isNew)
Definition: PWM.cpp:367
uint8_t GetPWM(uint32_t channel)
Definition: ITable.h:26
virtual void AddTableListener(ITableListener *listener)=0
virtual ~PWM()
Definition: PWM.cpp:92
static bool CheckPWMChannel(uint32_t channel)
Definition: SensorBase.cpp:160
virtual float GetPosition()
Definition: PWM.cpp:205
void UpdateTable()
Definition: PWM.cpp:371
static bool CheckPWMModule(uint8_t moduleNumber)
Definition: SensorBase.cpp:98
static const int32_t kDefaultPwmStepsDown
Definition: PWM.h:75
void Free(uint32_t index)
Definition: Resource.cpp:105
uint32_t Allocate(const char *resourceDesc)
Definition: Resource.cpp:62
void SetPeriodMultiplier(PeriodMultiplier mult)
Definition: PWM.cpp:347
static constexpr float kDefaultPwmCenter
Definition: PWM.h:71
PWM(uint32_t channel)
Definition: PWM.cpp:81
virtual bool StatusIsFatal() const
Check if the current error code represents a fatal error.
Definition: ErrorBase.cpp:178
virtual void SetRaw(uint8_t value)
Definition: PWM.cpp:323
void SetPWM(uint32_t channel, uint8_t value)
static DigitalModule * GetInstance(uint8_t moduleNumber)
static void CreateResourceObject(Resource **r, uint32_t elements)
Definition: Resource.cpp:39
static constexpr float kDefaultPwmPeriod
Definition: PWM.h:67
void StartLiveWindowMode()
Definition: PWM.cpp:377
void SetBounds(int32_t max, int32_t deadbandMax, int32_t center, int32_t deadbandMin, int32_t min)
Definition: PWM.cpp:123
std::string GetSmartDashboardType()
Definition: PWM.cpp:391
void EnableDeadbandElimination(bool eliminateDeadband)
Definition: PWM.cpp:107
virtual uint8_t GetRaw()
Definition: PWM.cpp:336
void StopLiveWindowMode()
Definition: PWM.cpp:384
void SetPWMPeriodScale(uint32_t channel, uint32_t squelchMask)
Definition: ITable.h:13
virtual void SetSpeed(float speed)
Definition: PWM.cpp:236

Generated on Sat Apr 26 2014 12:26:45 for WPILibC++ by doxygen 1.8.6