Laelaps  2.3.5
RoadNarrows Robotics Small Outdoor Mobile Robot Project
diagWatchDog.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Laelaps
4 //
5 // Program: laelaps_diag
6 //
7 // File: diagImu.cxx
8 //
9 /*! \file
10  *
11  * \brief Perform Laelaps IMU diagnostics.
12  *
13  * \author Robin Knight (robin.knight@roadnarrows.com)
14  *
15  * \par Copyright
16  * \h_copy 2015-2017. RoadNarrows LLC.\n
17  * http://www.roadnarrows.com\n
18  * All Rights Reserved
19  */
20 /*
21  * @EulaBegin@
22  *
23  * Unless otherwise stated explicitly, all materials contained are copyrighted
24  * and may not be used without RoadNarrows LLC's written consent,
25  * except as provided in these terms and conditions or in the copyright
26  * notice (documents and software) or other proprietary notice provided with
27  * the relevant materials.
28  *
29  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY
30  * MEMBERS/EMPLOYEES/CONTRACTORS OF ROADNARROWS OR DISTRIBUTORS OF THIS SOFTWARE
31  * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
32  * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
33  * DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN
34  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  * THE AUTHORS AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
37  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
38  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
39  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
40  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
41  *
42  * @EulaEnd@
43  */
44 ////////////////////////////////////////////////////////////////////////////////
45 
46 #include <unistd.h>
47 #include <termios.h>
48 #include <string.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <stdarg.h>
52 
53 #include <iostream>
54 #include <fstream>
55 #include <string>
56 #include <vector>
57 
58 #include "rnr/rnrconfig.h"
59 #include "rnr/log.h"
60 #include "rnr/opts.h"
61 #include "rnr/pkg.h"
62 
63 // common
64 #include "Laelaps/laelaps.h"
65 #include "Laelaps/laeUtils.h"
66 
67 // hardware
68 #include "Laelaps/laeSysDev.h"
69 #include "Laelaps/laeI2C.h"
70 #include "Laelaps/laeWatchDog.h"
71 #include "Laelaps/laeWd.h"
72 
73 #include "laelaps_diag.h"
74 
75 using namespace std;
76 using namespace laelaps;
77 
78 static const char *SubSysName = "WatchDog";
79 
80 static DiagStats initWatchDog()
81 {
82  DiagStats stats;
83 
84  printSubHdr("Initialize WatchDog");
85 
86  //
87  // Requirements
88  //
89  stats.testCnt += 1;
90  if( I2CBus.isOpen() )
91  {
92  printTestResult(PassTag, "Communication interface %s is open.",
93  I2CBus.getDevName().c_str());
94  stats.passCnt += 1;
95  }
96  else
97  {
98  printTestResult(FatalTag,
99  "Communication interface not open - cannot continue.");
100  stats.fatal = true;
101  return stats;
102  }
103 
104  return stats;
105 }
106 
107 static DiagStats readInfo()
108 {
109  uint_t uVerNum;
110  DiagStats stats;
111 
112  printSubHdr("Read WatchDog Info");
113 
114  ++stats.testCnt;
115  if( WatchDog.cmdGetFwVersion(uVerNum) < 0 )
116  {
117  printTestResult(FailTag, "%s: Failed to read firmware version number.",
118  SubSysName);
119  uVerNum = 0;
120  }
121  else
122  {
123  printTestResult(PassTag, "%s: Read firmware version number.", SubSysName);
124  ++stats.passCnt;
125  }
126 
127  printf("Info:\n");
128  printf(" Name: %s\n", SubSysName);
129  printf(" Desc: Arduino compatible Atmega328 sub-processor\n");
130  printf(" FW Version: %u\n", uVerNum);
131 
132  return stats;
133 }
134 
135 static DiagStats testAlarms()
136 {
137  static uint_t alarms[] =
138  {
139  LaeWdArgAlarmNone,
140  LaeWdArgAlarmGen,
141  LaeWdArgAlarmBatt,
142  LaeWdArgAlarmTemp,
143  LaeWdArgAlarmEStop,
144  LaeWdArgAlarmBatt | LaeWdArgAlarmBattCrit,
145  LaeWdArgAlarmTemp | LaeWdArgAlarmCrit,
146  LaeWdArgAlarmNone
147  };
148 
149  static const char *names[] =
150  {
151  "no", "general", "battery", "temperature", "estop",
152  "battery critical", "temperature critical",
153  "no"
154  };
155 
156  DiagStats stats;
157 
158  printSubHdr("Test WatchDog Alarm Control");
159 
160  for(size_t i = 0; i < arraysize(names); ++i)
161  {
162  ++stats.testCnt;
163  printf("%s Set %s alarms = (0x%04x)\r", WaitTag, names[i], alarms[i]);
164  fflush(stdout);
165  if( WatchDog.cmdSetAlarms(alarms[i]) < 0 )
166  {
167  printf("%s\n", FailTag);
168  }
169  else
170  {
171  usleep(4000000);
172  printf("%s\n", PassTag);
173  ++stats.passCnt;
174  }
175  }
176 
177  return stats;
178 }
179 
180 static DiagStats testBatteryCharge()
181 {
182  static uint_t charge[] =
183  {
184  100, 90, 75, 60, 50, 40, 25, 10, 0, 100
185  };
186 
187  DiagStats stats;
188 
189  printSubHdr("Test Battery Charge LED Control");
190 
191  for(size_t i = 0; i < arraysize(charge); ++i)
192  {
193  ++stats.testCnt;
194  printf("%s Set battery charge to %u%%\r", WaitTag, charge[i]);
195  fflush(stdout);
196  if( WatchDog.cmdSetBatterySoC(charge[i]) < 0 )
197  {
198  printf("%s\n", FailTag);
199  }
200  else
201  {
202  usleep(2000000);
203  printf("%s\n", PassTag);
204  ++stats.passCnt;
205  }
206  }
207 
208  return stats;
209 }
210 
211 static DiagStats testLeds()
212 {
213  static byte_t rgb[][3] =
214  {
215  {255, 0, 0}, {255, 255, 0}, {0, 255, 0},
216  {0, 255, 255}, {0, 0, 255}, {255, 0, 255}
217  };
218 
219  static const char *colors[] =
220  {
221  "red", "yellow", "green", "cyan", "blue", "magenta"
222  };
223 
224  DiagStats stats;
225 
226  printSubHdr("Test USER LED Control");
227 
228  for(size_t i = 0; i < arraysize(colors); ++i)
229  {
230  ++stats.testCnt;
231  printf("%s Set RGB LED to %s = (%u, %u, %u)\r",
232  WaitTag, colors[i], rgb[i][0], rgb[i][1], rgb[i][2]);
233  fflush(stdout);
234  if( WatchDog.cmdSetRgbLed(rgb[i][0], rgb[i][1], rgb[i][2]) < 0 )
235  {
236  printf("%s\n", FailTag);
237  }
238  else
239  {
240  usleep(1000000);
241  printf("%s\n", PassTag);
242  ++stats.passCnt;
243  }
244  }
245 
246  ++stats.testCnt;
247  if( WatchDog.cmdResetRgbLed() < 0 )
248  {
249  printTestResult(FailTag, "Failed to reset RGB LED to state defaults.");
250  }
251  else
252  {
253  printTestResult(PassTag, "Reset RGB LED to state defaults.");
254  ++stats.passCnt;
255  }
256 
257  return stats;
258 }
259 
260 static DiagStats testDigitalIO()
261 {
262  uint_t pin;
263  uint_t value;
264  const char *sTag;
265  DiagStats stats;
266 
267  printSubHdr("Test Digital I/O Control");
268 
269  for(pin = LaeWdArgDPinNumMin; pin <= LaeWdArgDPinNumMax; ++pin)
270  {
271  printf("%s * Pin %u\n", WaitTag, pin);
272 
273  //
274  // Configure pin as output.
275  //
276  ++stats.testCnt;
277  if( WatchDog.cmdConfigDPin(pin, LaeWdArgDPinDirOut) == LAE_OK )
278  {
279  ++stats.passCnt;
280  sTag = PassTag;
281  }
282  else
283  {
284  sTag = FailTag;
285  }
286  printTestResult(sTag, "Configure digital pin %u to output.", pin);
287 
288  //
289  // Write high value to pin.
290  //
291  ++stats.testCnt;
292  value = LaeWdArgDPinValHigh;
293  if( WatchDog.cmdWriteDPin(pin, value) == LAE_OK )
294  {
295  ++stats.passCnt;
296  sTag = PassTag;
297  }
298  else
299  {
300  sTag = FailTag;
301  }
302  printTestResult(sTag, "Write digital pin %u value to high=%u.", pin, value);
303 
304  //
305  // Read pin's value.
306  //
307  ++stats.testCnt;
308  if( WatchDog.cmdReadDPin(pin, value) == LAE_OK )
309  {
310  ++stats.passCnt;
311  sTag = PassTag;
312  printTestResult(sTag, "Read digital pin %u value=%u.", pin, value);
313  }
314  else
315  {
316  sTag = FailTag;
317  printTestResult(sTag, "Read digital pin %u.", pin);
318  }
319 
320  //
321  // Write low value to pin.
322  //
323  ++stats.testCnt;
324  value = LaeWdArgDPinValLow;
325  if( WatchDog.cmdWriteDPin(pin, value) == LAE_OK )
326  {
327  ++stats.passCnt;
328  sTag = PassTag;
329  }
330  else
331  {
332  sTag = FailTag;
333  }
334  printTestResult(sTag, "Write digital pin %u value to low=%u.", pin, value);
335  }
336 
337  return stats;
338 }
339 
340 static DiagStats testAnalogOutput()
341 {
342  uint_t pin;
343  uint_t value;
344  const char *sTag;
345  DiagStats stats;
346 
347  printSubHdr("Test Analog Output");
348 
349  for(pin = LaeWdArgAOutPinNumMin; pin <= LaeWdArgAOutPinNumMax; ++pin)
350  {
351  printf("%s * Pin %u\n", WaitTag, pin);
352 
353  //
354  // Write analog high value to pin.
355  //
356  ++stats.testCnt;
357  value = LaeWdArgAOutPinValMax;
358  if( WatchDog.cmdWriteAPin(pin, value) == LAE_OK )
359  {
360  ++stats.passCnt;
361  sTag = PassTag;
362  }
363  else
364  {
365  sTag = FailTag;
366  }
367  printTestResult(sTag, "Write pin %u analog value=%u.", pin, value);
368 
369  //
370  // Write digital high value to pin.
371  //
372  ++stats.testCnt;
373  value = LaeWdArgDPinValLow;
374  if( WatchDog.cmdWriteDPin(pin, value) == LAE_OK )
375  {
376  ++stats.passCnt;
377  sTag = PassTag;
378  }
379  else
380  {
381  sTag = FailTag;
382  }
383  printTestResult(sTag, "Write pin %u digital value to low=%u.", pin, value);
384  }
385 
386  return stats;
387 }
388 
389 
390 static DiagStats testAnalogInput()
391 {
392  uint_t pin;
393  uint_t value;
394  const char *sTag;
395  DiagStats stats;
396 
397  printSubHdr("Test Analog Input");
398 
399  for(pin = LaeWdArgAInPinNumMin; pin <= LaeWdArgAInPinNumMax; ++pin)
400  {
401  printf("%s * Pin %u\n", WaitTag, pin);
402 
403  //
404  // Read pin's value.
405  //
406  ++stats.testCnt;
407  if( WatchDog.cmdReadAPin(pin, value) == LAE_OK )
408  {
409  ++stats.passCnt;
410  sTag = PassTag;
411  printTestResult(sTag, "Read analog pin %u value=%u.", pin, value);
412  }
413  else
414  {
415  sTag = FailTag;
416  printTestResult(sTag, "Read analog pin %u.", pin);
417  }
418  }
419 
420  return stats;
421 }
422 
423 DiagStats runWatchDogDiagnostics()
424 {
425  DiagStats statsTest;
426  DiagStats statsTotal;
427 
428  printHdr("WatchDog Diagnostics");
429 
430  //
431  // Init Tests
432  //
433  statsTest = initWatchDog();
434  printSubTotals(statsTest);
435  statsTotal += statsTest;
436 
437  //
438  // Read and Print Information Tests
439  //
440  if( !statsTotal.fatal )
441  {
442  statsTest = readInfo();
443  printSubTotals(statsTest);
444  statsTotal += statsTest;
445  }
446 
447  //
448  // Alarm Tests
449  //
450  if( !statsTotal.fatal )
451  {
452  statsTest = testAlarms();
453  printSubTotals(statsTest);
454  statsTotal += statsTest;
455  }
456 
457  //
458  // Battery Charge Tests
459  //
460  if( !statsTotal.fatal )
461  {
462  statsTest = testBatteryCharge();
463  printSubTotals(statsTest);
464  statsTotal += statsTest;
465  }
466 
467  //
468  // RGB LED Tests
469  //
470  if( !statsTotal.fatal )
471  {
472  statsTest = testLeds();
473  printSubTotals(statsTest);
474  statsTotal += statsTest;
475  }
476 
477  //
478  // Digital I/O Tests
479  //
480  if( !statsTotal.fatal )
481  {
482  statsTest = testDigitalIO();
483  printSubTotals(statsTest);
484  statsTotal += statsTest;
485  }
486 
487  //
488  // Analog Output Tests
489  //
490  if( !statsTotal.fatal )
491  {
492  statsTest = testAnalogOutput();
493  printSubTotals(statsTest);
494  statsTotal += statsTest;
495  }
496 
497  //
498  // Analog Input Tests
499  //
500  if( !statsTotal.fatal )
501  {
502  statsTest = testAnalogInput();
503  printSubTotals(statsTest);
504  statsTotal += statsTest;
505  }
506 
507  //
508  // Summary
509  //
510  printTotals(statsTotal);
511 
512  return statsTotal;
513 }
Diagnotics header file.
virtual int cmdReadDPin(uint_t pin, uint_t &val)
Read the value of a digital pin command.
Definition: laeWd.cxx:445
std::string getDevName()
Get associated I2C device name.
Definition: laeI2C.h:193
virtual int cmdWriteDPin(uint_t pin, uint_t val)
Write a value to a digital pin command.
Definition: laeWd.cxx:506
Laelaps WatchDog software class interface.
Laelaps I2C class interface.
virtual int cmdResetRgbLed()
Reset the LED RGB color to state defaults.
Definition: laeWd.cxx:376
virtual int cmdSetBatterySoC(uint_t uBatterySoC)
Set battery&#39;s state of charge state command.
Definition: laeWd.cxx:289
virtual int cmdSetRgbLed(uint_t red, uint_t green, uint_t blue)
Set the LED RGB color command.
Definition: laeWd.cxx:353
The <b><i>Laelaps</i></b> namespace encapsulates all <b><i>Laelaps</i></b> related constructs...
Definition: laeAlarms.h:64
Simple diagnostics statistics class.
Definition: laelaps_diag.h:106
Laelaps common utilities.
bool isOpen()
Check if device is open.
Definition: laeI2C.h:203
virtual int cmdReadAPin(uint_t pin, uint_t &val)
Read the value of an analog pin command.
Definition: laeWd.cxx:555
Laelaps system devices.
Laelaps built-in Arduino sub-processor.
virtual int cmdGetFwVersion(uint_t &uVerNum)
Get the firmware version command.
Definition: laeWd.cxx:263
virtual int cmdConfigDPin(uint_t pin, uint_t dir)
Configure a digital pin command.
Definition: laeWd.cxx:396
virtual int cmdWriteAPin(uint_t pin, uint_t val)
Write the value to an analog pin command.
Definition: laeWd.cxx:616
Top-level package include file.
virtual int cmdSetAlarms(uint_t uAlarms)
Set (clear) alarms command.
Definition: laeWd.cxx:323