Hubo Library

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
JamDemo.cpp
Go to the documentation of this file.
1 /*
2 Compile and link:
3 g++ JamDemo.cpp CSC5262.cpp -L../ -lhubo -lpthread -lrt -o JamDemo
4 Run:
5 sudo ./JamDemo
6 Purpose:
7 The demo uses a Raspberry Pi Zero and 2 cascaded Hubos to illustrate:
8 - a PIR sensor on the master Hubo (DI 7) counting pulses that increment the digital outputs on the first Hubo slave,
9 - a reed contact closure on the master Hubo (DI 6) that switches the open collector output (DO 1) and
10 - a 2-way controller that reads a DS18x20 temperature and switches RCSocket (31/1)
11 when the temperature is out of limits TEMP_ON and TEMP_OFF.
12 */
13
14 #include <stdio.h>
15 #include <assert.h>
16 #include <pthread.h>
17
18 #include "../hubolib.h"
19 #include "../hubocfg.h"
20 #include "CSC5262.h"
21
22 using namespace std;
23 using namespace HuboLib;
24 using namespace BCM2835;
25
26
27 // Global initialization.
28 bool InitializeApplication ();
29
30 // Helper for temporary priority changes.
31 bool SaveThreadPriority ();
32 void BoostThreadPriority ();
33 void RestoreThreadPriority ();
34 sched_param g_param;
35 int g_policy = 0;
36 pthread_t g_threadHandle = 0;
37
38 // RCSocket to control remote switches.
39 #define FAMILY_CODE (31)
40 #define TEMP_CONTROLLER_SOCKET (1)
41 #define REED_CONTACT_SOCKET (2)
42 CSC5262 rcSwitch (350, 17, true);
43
44 // Initialize 1wire devices and search for at least one 1wire temperature sensor.
45 bool Initialize1WireDevices ();
46 vector <string> g_1WireDeviceList;
47 int g_FirstDS18x20Sensor = -1;
48
49 // Initialize Hubo hardware and at least one slave module that is cascaded to it.
50 bool InitializeHuboHardware ();
51 vector<int> g_SlaveAddressList;
52
53 // Update temperature controller
54 // Sensor: first 1wire temperature sensor
55 // Actuator: RCSocket 31/1
56 void TemperatureControl ();
57 bool GetTemperature (double& temperature);
58 #define TEMP_ON (25.0)
59 #define TEMP_OFF (27.0)
60
61 // PIR counter
62 void PIRCounter();
63 unsigned short g_Count = 0;
64 #define PIR_DI_CHANNEL (7) // channel 7 is connected to the PIR.
65 #define SLAVE_INDEX (0) // We use the first slave (index 0) found.
66
67 // Reed contact switching motor
68 void HandleReedContact ();
69 #define REED_DI_CHANNEL (6) // channel 6 is connected to the reed contact closure.
70 #define MOTOR_DO_CHANNEL (1) // the motor is connected on (open collector) output channel 1
71
72
73 int main(int argc, char *argv[])
74 {
75 // Initialization.
76 if (!InitializeApplication())
77 {
78 printf ("Failed to initialize. Are you running the program as sudoer?\n");
79 return -1;
80 }
81
82 while (1)
83 {
84 // Turn motor on output channel 1 on and of depending on reed contact on input channel 6.
85 HandleReedContact();
86
87 // Check PIR-Counter for new event.
88 PIRCounter();
89
90 // Update temperature controller.
91 TemperatureControl();
92
93 // Sleep some time.
94 Delay_MicroSeconds(1000L*10L);
95 }
96
97 // Even if we should never get here...
98 Uninitialize();
99
100 return 0;
101 }
102
103 void HandleReedContact ()
104 {
105 bool bReedContactOpen = true;
106 static bool bLastReedContactOpen = true;
107
108 if (!Get_DI_Channel(REED_DI_CHANNEL, bReedContactOpen))
109 {
110 printf ("Failed to retrieve DI channel.\n");
111 return;
112 }
113 Set_DO_Channel (MOTOR_DO_CHANNEL, bReedContactOpen ? 0 : 1);
114 if (bLastReedContactOpen != bReedContactOpen)
115 printf ("Set DO channel %d to %s.\n", MOTOR_DO_CHANNEL, bReedContactOpen ? "0" : "1");
116
117 bLastReedContactOpen = bReedContactOpen;
118 }
119
120 void PIRCounter()
121 {
122 static bool lastPirState = false;
123 bool newPirState = false;
124
125 if (!Get_DI_Channel(PIR_DI_CHANNEL, newPirState))
126 {
127 printf ("Failed to retrieve digital input.\n");
128 return;
129 }
130 if (lastPirState== false && newPirState==true)
131 {
132 g_Count++;
133 printf ("PIR signal %d caught.\n", g_Count);
134 Set_Slave_DO_Channels (SLAVE_INDEX, (unsigned char) g_Count);
135 }
136 lastPirState = newPirState;
137 }
138
139 void TemperatureControl ()
140 {
141 double temperature = 0.0;
142 if (!GetTemperature (temperature))
143 return;
144
145 printf ("Temperature = %lf deg. C ", temperature);
146
147 BoostThreadPriority ();
148
149 if (temperature < TEMP_ON)
150 {
151 // Turn heating switch on.
152 printf ("-> heating on.\n");
153 rcSwitch.SwitchSocket(FAMILY_CODE, TEMP_CONTROLLER_SOCKET, true, 4, 10);
154 }
155 else
156 if (temperature > TEMP_OFF)
157 {
158 // Turn heating switch off.
159 printf ("-> heating off.\n");
160 rcSwitch.SwitchSocket(FAMILY_CODE, TEMP_CONTROLLER_SOCKET, false, 4, 10);
161 }
162 else
163 printf ("-> no change.\n");
164
165 RestoreThreadPriority ();
166 }
167
168 bool GetTemperature (double& temperature)
169 {
170 // Did we find a sensor?
171 if (g_FirstDS18x20Sensor == -1)
172 return false;
173
174 // Double check whether the list has changed in the meantime.
175 if (!Is_DS18x20_Devices(g_1WireDeviceList[g_FirstDS18x20Sensor].c_str()))
176 return false;
177
178 // Could we retrieve a temperature value?
179 bool bCRC = false;
180 long t_duration_ms = 0;
181 if (!Get_DS18x20_Temperature (g_1WireDeviceList[g_FirstDS18x20Sensor].c_str(), temperature, bCRC, t_duration_ms))
182 return false;
183
184 // Correct CRC?
185 if (!bCRC)
186 return false;
187
188 // 85°C represent the reset value - thus we ignore it.
189 if (temperature == 85.0)
190 return false;
191
192 // The duration for an update should be less than one second typically.
193 if (t_duration_ms > 2000)
194 return false;
195
196 return true;
197 }
198
199 bool InitializeApplication()
200 {
201 // Try reading thread scheduling information.
202 if (!SaveThreadPriority())
203 {
204 printf ("Failed to save scheduling parameter. Are you running the program as sudoer?\n");
205 return false;
206 }
207
208 // If this call doesn't return true then we must not use the GPIO part of Hubo library!
209 printf ("Initializing GPIO.\n");
210 if (!IsGPIOInitialized ())
211 {
212 printf ("GPIO not properly initialized. Are you running the program as sudoer?\n");
213 return false;
214 }
215
216 // Initialize 1-wire device list.
217 if (!Initialize1WireDevices ())
218 {
219 printf ("A 1wire sensor could not be found.\n");
220 return false;
221 }
222
223 // Initialize Hubo hardware and expect at least one slave board installed.
224 if (!InitializeHuboHardware ())
225 {
226 printf ("Hubo hardware containing at least one cascaded slave could not be found.\n");
227 return false;
228 }
229
230 return true;
231 }
232
233 bool InitializeHuboHardware()
234 {
235 // If required - set the I2C device to work with. The Raspberry Pi uses "/dev/i2c-1" which is default, the Banana Pi uses "/dev/i2c-0"
236 #ifdef BPI
237 g_I2CConfig.m_sI2CDevice = "/dev/i2c-0";
238 #endif
239
240 printf ("Initializing Hubo hardware and detecting slaves.\n");
241
242 // Initialize the library once in your program.
243 Initialize();
244 Set_Cycle_Time(20);
245
246 // We need to find one slave as we'd use the first slave for outputting the PIR signals.
247 if (GetSlaveDeviceList (g_SlaveAddressList))
248 {
249 for (unsigned int i=0; i<g_SlaveAddressList.size(); i++)
250 printf ("Found slave address 0x%02X.\n", g_SlaveAddressList[i]);
251 }
252 else
253 return false;
254
255 // Wait until all background buffers are filled.
256
257 // Define all channels to be read (set to 1) from the ADC.
258 unsigned short overSampling[MAX_MCP3x08_CHANNELS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
259 Set_MCP3x08_Oversampling (overSampling);
260
261 // Wait as long until we have valid values in the buffer.
262 printf ("Waiting for MCP3x08 buffered values... ");
263 Wait_For_MCP3x08_Buffered_Values();
264 printf ("received.\n");
265
266 printf ("Waiting for MCP23017 buffered values... ");
267 Wait_For_MCP23017_Buffered_Values ();
268 printf ("received.\n");
269
270 printf ("Waiting for MCP23017 (slaves) buffered values... ");
271 Wait_For_MCP23017_Slaves_Buffered_Values ();
272 printf ("received.\n");
273
274 return true;
275 }
276
277 bool Initialize1WireDevices ()
278 {
279 printf ("Initializing 1wire devices.\n");
280
281 Get_1w_Devices(g_1WireDeviceList);
282
283 // We should find the bus master and at least 1 temperature sensor.
284 if (g_1WireDeviceList.size() < 2)
285 return false;
286
287 double temperature;
288 bool bCRC;
289 long t_duration_ms;
290
291 // For each device in the list...
292 for (int i=0; i<g_1WireDeviceList.size(); i++)
293 {
294 // ... print the device ID...
295 printf ("%02d. %s: ", i+1, g_1WireDeviceList[i].c_str());
296
297 // ... and if it's a DS18x20 temperature sensor...
298 if (Is_DS18x20_Devices(g_1WireDeviceList[i].c_str()))
299 {
300 // ... retrieve the data.
301 bool bResult = Get_DS18x20_Temperature (g_1WireDeviceList[i].c_str(), temperature, bCRC, t_duration_ms);
302 printf ("Result=%s ", bResult?"true":"false");
303 printf ("bCRC=%s ", bCRC?"true":"false");
304 printf ("temp=%lf duration=%ld index=%d\n", temperature, t_duration_ms, i);
305 g_FirstDS18x20Sensor = i;
306 return true;
307 }
308 else
309 printf ("\n");
310 }
311
312 return false;
313 }
314
315 bool SaveThreadPriority()
316 {
317 printf ("Saving thread parameters.\n");
318
319 // Thread handle.
320 g_threadHandle = pthread_self();
321
322 // Save current scheduling parameters of thread.
323 int ret = pthread_getschedparam (g_threadHandle, &g_policy, &g_param);
324
325 assert (ret == 0);
326 return ret == 0;
327 }
328
329 void BoostThreadPriority()
330 {
331 // Scheduling params.
332 sched_param param = g_param;
333
334 // Set scheduling parameters of thread to real time values (FIFO scheduling type and max prio).
335 param.sched_priority = sched_get_priority_max(SCHED_FIFO); // New max priority for new scheduling concept.
336 int ret = pthread_setschedparam(g_threadHandle, SCHED_FIFO, &param);
337 assert (ret == 0);
338 }
339
340 void RestoreThreadPriority()
341 {
342 // Restore scheduling parameters of thread.
343 int ret = pthread_setschedparam(g_threadHandle, g_policy, &g_param);
344 assert (ret == 0);
345 }
346
347 bool strToUChar(char* str, unsigned char& value)
348 {
349 unsigned long v;
350 if (sscanf(str, "%lu", &v) != 1)
351 return false;
352 value = (unsigned char)v;
353 if (value != (unsigned long)v)
354 return false;
355 return true;
356 }
357
HuboLib::I2C_Config::m_sI2CDevice
const char * m_sI2CDevice
Definition: hubocfg.h:48
HuboLib::Wait_For_MCP3x08_Buffered_Values
bool Wait_For_MCP3x08_Buffered_Values()
Waits until the input buffer of the MCP3x08 are initialized from the hardware.
TEMP_ON
#define TEMP_ON
Definition: JamDemo.cpp:58
strToUChar
bool strToUChar(char *str, unsigned char &value)
Definition: JamDemo.cpp:347
HuboLib::Delay_MicroSeconds
void Delay_MicroSeconds(unsigned long delay_micros)
delays the execution of the calling thread for the given number of micro seconds. ...
MAX_MCP3x08_CHANNELS
#define MAX_MCP3x08_CHANNELS
Definition: hubolib.h:39
BCM2835::IsGPIOInitialized
bool IsGPIOInitialized()
Returns the status of the initialisation of the GPIO part of the library.
main
int main(int argc, char *argv[])
Definition: JamDemo.cpp:73
HuboLib::Set_DO_Channel
bool Set_DO_Channel(int channel, bool bValue)
Requests the background thread to set one of the digital outputs to the value specified.
CSC5262
Definition: CSC5262.h:5
HuboLib::Initialize
bool Initialize()
Initializes the library.
g_policy
int g_policy
Definition: JamDemo.cpp:35
g_param
sched_param g_param
Definition: JamDemo.cpp:34
g_Count
unsigned short g_Count
Definition: JamDemo.cpp:63
std
g_FirstDS18x20Sensor
int g_FirstDS18x20Sensor
Definition: JamDemo.cpp:47
InitializeHuboHardware
bool InitializeHuboHardware()
Definition: JamDemo.cpp:233
SaveThreadPriority
bool SaveThreadPriority()
Definition: JamDemo.cpp:315
TEMP_CONTROLLER_SOCKET
#define TEMP_CONTROLLER_SOCKET
Definition: JamDemo.cpp:40
HuboLib::Is_DS18x20_Devices
bool Is_DS18x20_Devices(const char *pSensorID)
Check whether a 1wire device name refers to a DS18S20 or DS18B20 temperature sensor.
HuboLib::Set_Cycle_Time
bool Set_Cycle_Time(long cycleTime)
Sets the backgrounds threads polling interval in ms.
InitializeApplication
bool InitializeApplication()
Definition: JamDemo.cpp:199
MOTOR_DO_CHANNEL
#define MOTOR_DO_CHANNEL
Definition: JamDemo.cpp:70
g_1WireDeviceList
vector< string > g_1WireDeviceList
Definition: JamDemo.cpp:46
HuboLib::Wait_For_MCP23017_Slaves_Buffered_Values
bool Wait_For_MCP23017_Slaves_Buffered_Values()
Waits until input and output buffers of the MCP23017 slaves are initialized from the hardware...
GetTemperature
bool GetTemperature(double &temperature)
Definition: JamDemo.cpp:168
HuboLib::g_I2CConfig
I2C_Config g_I2CConfig
HuboLib::Set_MCP3x08_Oversampling
bool Set_MCP3x08_Oversampling(unsigned short overSampling[MAX_MCP3x08_CHANNELS])
Specifies the ADC channels to be sampled as well as the number they get oversampled.
HuboLib::Uninitialize
void Uninitialize()
Releases any resources bound to the library.
g_threadHandle
pthread_t g_threadHandle
Definition: JamDemo.cpp:36
HuboLib::Get_DS18x20_Temperature
bool Get_DS18x20_Temperature(const char *pSensorID, double &temperature, bool &bCRC, long &t_duration_ms)
Retrieve temperature, CRC value and the time that was required to read the temperature.
SLAVE_INDEX
#define SLAVE_INDEX
Definition: JamDemo.cpp:65
g_SlaveAddressList
vector< int > g_SlaveAddressList
Definition: JamDemo.cpp:51
Initialize1WireDevices
bool Initialize1WireDevices()
Definition: JamDemo.cpp:277
FAMILY_CODE
#define FAMILY_CODE
Definition: JamDemo.cpp:39
HuboLib::Get_1w_Devices
bool Get_1w_Devices(std::vector< std::string > &deviceList)
Returns a list of 1wire devices found on the bus.
RestoreThreadPriority
void RestoreThreadPriority()
Definition: JamDemo.cpp:340
REED_DI_CHANNEL
#define REED_DI_CHANNEL
Definition: JamDemo.cpp:69
HuboLib::Set_Slave_DO_Channels
bool Set_Slave_DO_Channels(int slaveNo, unsigned char value)
Requests the background thread to update all 8 bits of the digital output to the value specified for ...
HuboLib::Wait_For_MCP23017_Buffered_Values
bool Wait_For_MCP23017_Buffered_Values()
Waits until input and output buffers of the MCP23017 master are initialized from the hardware...
BoostThreadPriority
void BoostThreadPriority()
Definition: JamDemo.cpp:329
BCM2835
Definition: hubocfg.h:71
rcSwitch
CSC5262 rcSwitch(350, 17, true)
PIRCounter
void PIRCounter()
Definition: JamDemo.cpp:120
HuboLib::GetSlaveDeviceList
bool GetSlaveDeviceList(std::vector< int > &slaveAddressList)
Returns the list of I2C addresses of the MCP23017 slaves.
HuboLib::Get_DI_Channel
bool Get_DI_Channel(int channel, bool &bValue)
Retrieves the value of one digital input.
CSC5262::SwitchSocket
bool SwitchSocket(unsigned char SystemCode, unsigned char Receiver, bool bTurnOn, int repeatedSuccess, int totalTransmittion)
Definition: CSC5262.cpp:128
HandleReedContact
void HandleReedContact()
Definition: JamDemo.cpp:103
CSC5262.h
PIR_DI_CHANNEL
#define PIR_DI_CHANNEL
Definition: JamDemo.cpp:64
TemperatureControl
void TemperatureControl()
Definition: JamDemo.cpp:139
HuboLib
Definition: hubocfg.h:10
TEMP_OFF
#define TEMP_OFF
Definition: JamDemo.cpp:59