Now you can download a copy of these docs so you can use them offline! Download now
Ultrasonic.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 "Ultrasonic.h"
8 
9 #include "Counter.h"
10 #include "DigitalInput.h"
11 #include "DigitalOutput.h"
12 #include "NetworkCommunication/UsageReporting.h"
13 #include "Timer.h"
14 #include "Utility.h"
15 #include "WPIErrors.h"
16 #include "LiveWindow/LiveWindow.h"
17 
18 constexpr double Ultrasonic::kPingTime;
19 const uint32_t Ultrasonic::kPriority;
20 constexpr double Ultrasonic::kMaxUltrasonicTime;
21 constexpr double Ultrasonic::kSpeedOfSoundInchesPerSec;
22 Task Ultrasonic::m_task("UltrasonicChecker", (FUNCPTR)UltrasonicChecker); // task doing the round-robin automatic sensing
23 Ultrasonic *Ultrasonic::m_firstSensor = NULL; // head of the ultrasonic sensor list
24 bool Ultrasonic::m_automaticEnabled = false; // automatic round robin mode
25 SEM_ID Ultrasonic::m_semaphore = 0;
26 
36 void Ultrasonic::UltrasonicChecker()
37 {
38  Ultrasonic *u = NULL;
39  while (m_automaticEnabled)
40  {
41  if (u == NULL) u = m_firstSensor;
42  if (u == NULL) return;
43  if (u->IsEnabled())
44  u->m_pingChannel->Pulse(kPingTime); // do the ping
45  u = u->m_nextSensor;
46  Wait(0.1); // wait for ping to return
47  }
48 }
49 
57 void Ultrasonic::Initialize()
58 {
59  m_table = NULL;
60  bool originalMode = m_automaticEnabled;
61  if (m_semaphore == 0) m_semaphore = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
62  SetAutomaticMode(false); // kill task when adding a new sensor
63  semTake(m_semaphore, WAIT_FOREVER); // link this instance on the list
64  {
65  m_nextSensor = m_firstSensor;
66  m_firstSensor = this;
67  }
68  semGive(m_semaphore);
69 
70  m_counter = new Counter(m_echoChannel); // set up counter for this sensor
71  m_counter->SetMaxPeriod(1.0);
72  m_counter->SetSemiPeriodMode(true);
73  m_counter->Reset();
74  m_counter->Start();
75  m_enabled = true; // make it available for round robin scheduling
76  SetAutomaticMode(originalMode);
77 
78  static int instances = 0;
79  instances++;
80  nUsageReporting::report(nUsageReporting::kResourceType_Ultrasonic, instances);
81  LiveWindow::GetInstance()->AddSensor("Ultrasonic", m_echoChannel->GetModuleForRouting(), m_echoChannel->GetChannel(), this);
82 }
83 
94 Ultrasonic::Ultrasonic(uint32_t pingChannel, uint32_t echoChannel, DistanceUnit units)
95 {
96  m_pingChannel = new DigitalOutput(pingChannel);
97  m_echoChannel = new DigitalInput(echoChannel);
98  m_allocatedChannels = true;
99  m_units = units;
100  Initialize();
101 }
102 
110 Ultrasonic::Ultrasonic(DigitalOutput *pingChannel, DigitalInput *echoChannel, DistanceUnit units)
111 {
112  if (pingChannel == NULL || echoChannel == NULL)
113  {
114  wpi_setWPIError(NullParameter);
115  return;
116  }
117  m_allocatedChannels = false;
118  m_pingChannel = pingChannel;
119  m_echoChannel = echoChannel;
120  m_units = units;
121  Initialize();
122 }
123 
131 Ultrasonic::Ultrasonic(DigitalOutput &pingChannel, DigitalInput &echoChannel, DistanceUnit units)
132 {
133  m_allocatedChannels = false;
134  m_pingChannel = &pingChannel;
135  m_echoChannel = &echoChannel;
136  m_units = units;
137  Initialize();
138 }
139 
152 Ultrasonic::Ultrasonic(uint8_t pingModuleNumber, uint32_t pingChannel,
153  uint8_t echoModuleNumber, uint32_t echoChannel, DistanceUnit units)
154 {
155  m_pingChannel = new DigitalOutput(pingModuleNumber, pingChannel);
156  m_echoChannel = new DigitalInput(echoModuleNumber, echoChannel);
157  m_allocatedChannels = true;
158  m_units = units;
159  Initialize();
160 }
161 
169 {
170  bool wasAutomaticMode = m_automaticEnabled;
171  SetAutomaticMode(false);
172  if (m_allocatedChannels)
173  {
174  delete m_pingChannel;
175  delete m_echoChannel;
176  }
177  wpi_assert(m_firstSensor != NULL);
178 
179  semTake(m_semaphore, WAIT_FOREVER);
180  {
181  if (this == m_firstSensor)
182  {
183  m_firstSensor = m_nextSensor;
184  if (m_firstSensor == NULL)
185  {
186  SetAutomaticMode(false);
187  }
188  }
189  else
190  {
191  wpi_assert(m_firstSensor->m_nextSensor != NULL);
192  for (Ultrasonic *s = m_firstSensor; s != NULL; s = s->m_nextSensor)
193  {
194  if (this == s->m_nextSensor)
195  {
196  s->m_nextSensor = s->m_nextSensor->m_nextSensor;
197  break;
198  }
199  }
200  }
201  }
202  semGive(m_semaphore);
203  if (m_firstSensor != NULL && wasAutomaticMode)
204  SetAutomaticMode(true);
205 }
206 
216 void Ultrasonic::SetAutomaticMode(bool enabling)
217 {
218  if (enabling == m_automaticEnabled)
219  return; // ignore the case of no change
220 
221  m_automaticEnabled = enabling;
222  if (enabling)
223  {
224  // enabling automatic mode.
225  // Clear all the counters so no data is valid
226  for (Ultrasonic *u = m_firstSensor; u != NULL; u = u->m_nextSensor)
227  {
228  u->m_counter->Reset();
229  }
230  // Start round robin task
231  wpi_assert(m_task.Verify() == false); // should be false since was previously disabled
232  m_task.Start();
233  }
234  else
235  {
236  // disabling automatic mode. Wait for background task to stop running.
237  while (m_task.Verify())
238  Wait(0.15); // just a little longer than the ping time for round-robin to stop
239 
240  // clear all the counters (data now invalid) since automatic mode is stopped
241  for (Ultrasonic *u = m_firstSensor; u != NULL; u = u->m_nextSensor)
242  {
243  u->m_counter->Reset();
244  }
245  m_task.Stop();
246  }
247 }
248 
256 {
257  // TODO: Either assert or disable, not both.
258  wpi_assert(!m_automaticEnabled);
259  SetAutomaticMode(false); // turn off automatic round robin if pinging single sensor
260  m_counter->Reset(); // reset the counter to zero (invalid data now)
261  m_pingChannel->Pulse(kPingTime); // do the ping to start getting a single range
262 }
263 
270 {
271  return m_counter->Get() > 1;
272 }
273 
280 {
281  if (IsRangeValid())
282  return m_counter->GetPeriod() * kSpeedOfSoundInchesPerSec / 2.0;
283  else
284  return 0;
285 }
286 
293 {
294  return GetRangeInches() * 25.4;
295 }
296 
303 {
304  switch(m_units)
305  {
306  case Ultrasonic::kInches:
307  return GetRangeInches();
308  case Ultrasonic::kMilliMeters:
309  return GetRangeMM();
310  default:
311  return 0.0;
312  }
313 }
314 
320 void Ultrasonic::SetDistanceUnits(DistanceUnit units)
321 {
322  m_units = units;
323 }
324 
330 Ultrasonic::DistanceUnit Ultrasonic::GetDistanceUnits()
331 {
332  return m_units;
333 }
334 
336  if (m_table != NULL) {
337  m_table->PutNumber("Value", GetRangeInches());
338  }
339 }
340 
342 
343 }
344 
346 
347 }
348 
350  return "Ultrasonic";
351 }
352 
353 void Ultrasonic::InitTable(ITable *subTable) {
354  m_table = subTable;
355  UpdateTable();
356 }
357 
359  return m_table;
360 }
361 
virtual ~Ultrasonic()
Definition: Ultrasonic.cpp:168
bool Start(uint32_t arg0=0, uint32_t arg1=0, uint32_t arg2=0, uint32_t arg3=0, uint32_t arg4=0, uint32_t arg5=0, uint32_t arg6=0, uint32_t arg7=0, uint32_t arg8=0, uint32_t arg9=0)
Definition: Task.cpp:52
void Start()
Definition: Counter.cpp:542
void Ping()
Definition: Ultrasonic.cpp:255
virtual void PutNumber(std::string key, double value)=0
void Reset()
Definition: Counter.cpp:569
Definition: ITable.h:26
virtual uint32_t GetModuleForRouting()
void UpdateTable()
Definition: Ultrasonic.cpp:335
bool Verify()
Definition: Task.cpp:132
static void SetAutomaticMode(bool enabling)
Definition: Ultrasonic.cpp:216
void AddSensor(const char *subsystem, const char *name, LiveWindowSendable *component)
Definition: LiveWindow.cpp:82
double GetRangeInches()
Definition: Ultrasonic.cpp:279
double PIDGet()
Definition: Ultrasonic.cpp:302
void StartLiveWindowMode()
Definition: Ultrasonic.cpp:341
static LiveWindow * GetInstance()
Definition: LiveWindow.cpp:13
void SetMaxPeriod(double maxPeriod)
Definition: Counter.cpp:623
void Pulse(float length)
std::string GetSmartDashboardType()
Definition: Ultrasonic.cpp:349
double GetRangeMM()
Definition: Ultrasonic.cpp:292
bool Stop()
Definition: Task.cpp:81
void SetSemiPeriodMode(bool highSemiPeriod)
Definition: Counter.cpp:483
ITable * GetTable()
Definition: Ultrasonic.cpp:358
int32_t Get()
Definition: Counter.cpp:555
void InitTable(ITable *subTable)
Definition: Ultrasonic.cpp:353
Definition: Task.h:17
DistanceUnit GetDistanceUnits()
Definition: Ultrasonic.cpp:330
void StopLiveWindowMode()
Definition: Ultrasonic.cpp:345
bool IsRangeValid()
Definition: Ultrasonic.cpp:269
void SetDistanceUnits(DistanceUnit units)
Definition: Ultrasonic.cpp:320
Ultrasonic(DigitalOutput *pingChannel, DigitalInput *echoChannel, DistanceUnit units=kInches)
Definition: Ultrasonic.cpp:110
uint32_t GetChannel()

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