Hubo Library
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
AnalogRawInput.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <assert.h>
4 
5 #include "../hubolib.h"
6 
7 using namespace HuboLib;
8 
9 /*
10 Compile and link:
11  g++ AnalogRawInput.cpp -L../ -lhubo -lpthread -lrt -o AnalogRawInput.out
12 Run:
13  sudo ./AnalogRawInput.out
14 Purpose:
15  Sometimes it is necessary to follow an analog signal once it reaches a certain threshold. Since the Linux scheduler
16  cannot work efficient at higher rates than 1ms further decreasing of the cycle time would not help. Too much
17  time would be wasted due to thread context changes...
18  However, from within any of the callbacks provided by the library it is save to call Get_AI_Channel_Raw() in order
19  to low level access the MCP3208/MCP3008 chips. You can for example poll the converters in a loop in order to
20  achieve a higher resolution or save values in an array for later evaluation (e.g. by the main thread).
21  Make sure to not use Get_AI_Channel_Raw() from any other thread but the libraries background thread!
22  Maximum frequencies that can be achieved this way are around 8kHz. However, note that nearly no other application
23  will run during the "blocking" of a callback function due to the high priority it runs at!
24 */
25 
26 void CycleTickCallback (unsigned long* pADChannelValues, unsigned char* pDigitalInputValues, unsigned char* pDigitalOutputValues);
27 double DigitToVolt (unsigned long digit);
28 
29 int main(void)
30 {
31  // Initialize the library once in your program.
32  if (!Initialize())
33  {
34  printf ("Error: Initialize\n");
35  return 1;
36  }
37 
38  // Note - in order to access raw AD valued you do not need to setup oversampling!
39  // This avoids overhead if for example just the voltage of a power supply should get monitored in the background!
40 
41  // Let's sample every 1s (1Hz).
42  Set_Cycle_Time (1000);
43 
44  // Register the callback.
46 
47  // Let the main thread run a while... in between use the cycle tick callback for latching analog values.
48  for (int i=0; i<10; i++)
49  {
50  printf ("Main thread waiting...\n");
51  usleep(1000000);
52  }
53 
54  // Once not needed anymore the callbacks can be unregistered.
56 
57  // Free library resources.
58  Uninitialize();
59 
60  return 0;
61 }
62 
63 void CycleTickCallback (unsigned long* pADChannelValues, unsigned char* pDigitalInputValues, unsigned char* pDigitalOutputValues)
64 {
65  // Usually we'd avoid lengthily operations in callback routines as this would lead the cycle tick to get broken.
66  // However, this time we wait for an analog signal to be within the range of 1.4V and 1.6V. If we detect such a signal
67  // We latch 1000 values as fast as we can and compute the average of them.
68 
69  printf ("CycleTickCallback called.\n");
70 
71  // Note that we do not need to have valid values in pADChannelValues nor do we need to access it (...while we could of cause...).
72  unsigned short value = 0;
73  if (!Get_AI_Channel_Raw (0, value))
74  {
75  printf ("Failed to retrieve analog value from MCP3x08.\n");
76  assert (false);
77  return;
78  }
79 
80  double currentVolt = DigitToVolt(value);
81 
82  printf ("Rough value = %lf\n", currentVolt);
83 
84  // Within the range of 1.4V to 1.6V we retrieve raw values as fast as we can.
85  // Maybe because we need to follow a signal faster than our usual cycle time...
86  if (currentVolt < 1.4 || currentVolt > 1.6)
87  return;
88 
89  // In order to get here connect a 1.5V battery to analog input 0.
90 
91  unsigned long currentValue = 0;
92  int channel = 0;
93 
94  unsigned long long startTime = GetTime_MicroSeconds();
95 
96  // Latch 1000 samples.
97  for (int i=0; i<1000; i++)
98  {
99  if (Get_AI_Channel_Raw (0, value))
100  currentValue += value;
101  else
102  {
103  printf ("Failed to retrieve analog value from MCP3x08.\n");
104  assert (false);
105  return;
106  }
107  }
108  unsigned long long stopTime = GetTime_MicroSeconds();
109 
110  printf ("Precise value = %lf duration = %lfms (at 1000 samples).\n", DigitToVolt(currentValue)/1000.0, (stopTime-startTime)/1000.0);
111 
112  // Output of a 1.5V battery that has been observed.
113  // Rough value = 1.502805
114  // Precise value = 1.502918 duration = 119.265000ms (at 1000 samples).
115 }
116 
117 // Helper: Convert the digits into a voltage.
118 double DigitToVolt(unsigned long digit)
119 {
120  // We have a resolution of 4096 digit for the MCP3208, 1024 digit for the MCP3008.
121  return (((double)digit)*Get_VRef()/4096.0);
122 }
123 
bool Initialize()
Initializes the library.
bool Get_AI_Channel_Raw(int channel, unsigned short &value)
Gets an unbuffered value from the MCP3x08.
double Get_VRef()
Retrieves the reference voltage value used for ADC count convertion.
bool Set_Cycle_Time(long cycleTime)
Sets the backgrounds threads polling interval in ms.
int main(void)
bool Unregister_CycleTickCallback(T_pfn_CycleTickCallback pFnCycleTickCallback)
Unregister a callback previouly registered by a call to Register_CycleTickCallback().
void CycleTickCallback(unsigned long *pADChannelValues, unsigned char *pDigitalInputValues, unsigned char *pDigitalOutputValues)
double DigitToVolt(unsigned long digit)
void Uninitialize()
Releases any resources bound to the library.
unsigned long long GetTime_MicroSeconds()
Returns the number of micro seconds.
bool Register_CycleTickCallback(T_pfn_CycleTickCallback pFnCycleTickCallback)
Registers a callback function called on every cycle tick.