Smart-Home am Beispiel der Präsenzerkennung im Raum Projektarbeit Lennart Heimbs, Johannes Krug, Sebastian Dohle und Kevin Holzschuh bei Prof. Oliver Hofmann SS2019
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AirQualitySensor.ino 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * The MySensors Arduino library handles the wireless radio link and protocol
  3. * between your home built sensors/actuators and HA controller of choice.
  4. * The sensors forms a self healing radio network with optional repeaters. Each
  5. * repeater and gateway builds a routing tables in EEPROM which keeps track of the
  6. * network topology allowing messages to be routed to nodes.
  7. *
  8. * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
  9. * Copyright (C) 2013-2018 Sensnology AB
  10. * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
  11. *
  12. * Documentation: http://www.mysensors.org
  13. * Support Forum: http://forum.mysensors.org
  14. *
  15. * This program is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU General Public License
  17. * version 2 as published by the Free Software Foundation.
  18. *
  19. *******************************
  20. *
  21. * DESCRIPTION
  22. *
  23. * Connect the MQ2 sensor as follows :
  24. *
  25. * A H A >>> 5V
  26. * B >>> A0
  27. * H >>> GND
  28. * B >>> 10K ohm >>> GND
  29. *
  30. * Contribution: epierre
  31. * Based on http://sandboxelectronics.com/?p=165
  32. * License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
  33. * Modified by HEK to work in 1.4
  34. *
  35. */
  36. // Enable debug prints to serial monitor
  37. #define MY_DEBUG
  38. // Enable and select radio type attached
  39. #define MY_RADIO_RF24
  40. //#define MY_RADIO_NRF5_ESB
  41. //#define MY_RADIO_RFM69
  42. //#define MY_RADIO_RFM95
  43. #include <MySensors.h>
  44. #define CHILD_ID_MQ 0
  45. /************************Hardware Related Macros************************************/
  46. #define MQ_SENSOR_ANALOG_PIN (0) //define which analog input channel you are going to use
  47. #define RL_VALUE (5) //define the load resistance on the board, in kilo ohms
  48. #define RO_CLEAN_AIR_FACTOR (9.83) //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
  49. //which is derived from the chart in datasheet
  50. /***********************Software Related Macros************************************/
  51. #define CALIBARAION_SAMPLE_TIMES (50) //define how many samples you are going to take in the calibration phase
  52. #define CALIBRATION_SAMPLE_INTERVAL (500) //define the time interval(in milliseconds) between each samples in the
  53. //calibration phase
  54. #define READ_SAMPLE_INTERVAL (50) //define how many samples you are going to take in normal operation
  55. #define READ_SAMPLE_TIMES (5) //define the time interval(in milliseconds) between each samples in
  56. //normal operation
  57. /**********************Application Related Macros**********************************/
  58. #define GAS_LPG (0)
  59. #define GAS_CO (1)
  60. #define GAS_SMOKE (2)
  61. /*****************************Globals***********************************************/
  62. uint32_t SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
  63. //VARIABLES
  64. float Ro = 10000.0; // this has to be tuned 10K Ohm
  65. int val = 0; // variable to store the value coming from the sensor
  66. float valMQ =0.0;
  67. float lastMQ =0.0;
  68. float LPGCurve[3] = {2.3,0.21,-0.47}; //two points are taken from the curve.
  69. //with these two points, a line is formed which is "approximately equivalent"
  70. //to the original curve.
  71. //data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59)
  72. float COCurve[3] = {2.3,0.72,-0.34}; //two points are taken from the curve.
  73. //with these two points, a line is formed which is "approximately equivalent"
  74. //to the original curve.
  75. //data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000, 0.15)
  76. float SmokeCurve[3] = {2.3,0.53,-0.44}; //two points are taken from the curve.
  77. //with these two points, a line is formed which is "approximately equivalent"
  78. //to the original curve.
  79. //data format:{ x, y, slope}; point1: (lg200, 0.53), point2:(lg10000,-0.22)
  80. MyMessage msg(CHILD_ID_MQ, V_LEVEL);
  81. void setup()
  82. {
  83. Ro = MQCalibration(
  84. MQ_SENSOR_ANALOG_PIN); //Calibrating the sensor. Please make sure the sensor is in clean air
  85. }
  86. void presentation()
  87. {
  88. // Send the sketch version information to the gateway and Controller
  89. sendSketchInfo("Air Quality Sensor", "1.0");
  90. // Register all sensors to gateway (they will be created as child devices)
  91. present(CHILD_ID_MQ, S_AIR_QUALITY);
  92. }
  93. void loop()
  94. {
  95. uint16_t valMQ = MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO);
  96. Serial.println(val);
  97. Serial.print("LPG:");
  98. Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_LPG) );
  99. Serial.print( "ppm" );
  100. Serial.print(" ");
  101. Serial.print("CO:");
  102. Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO) );
  103. Serial.print( "ppm" );
  104. Serial.print(" ");
  105. Serial.print("SMOKE:");
  106. Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_SMOKE) );
  107. Serial.print( "ppm" );
  108. Serial.print("\n");
  109. if (valMQ != lastMQ) {
  110. send(msg.set((int16_t)ceil(valMQ)));
  111. lastMQ = ceil(valMQ);
  112. }
  113. sleep(SLEEP_TIME); //sleep for: sleepTime
  114. }
  115. /****************** MQResistanceCalculation ****************************************
  116. Input: raw_adc - raw value read from adc, which represents the voltage
  117. Output: the calculated sensor resistance
  118. Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
  119. across the load resistor and its resistance, the resistance of the sensor
  120. could be derived.
  121. ************************************************************************************/
  122. float MQResistanceCalculation(int raw_adc)
  123. {
  124. return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
  125. }
  126. /***************************** MQCalibration ****************************************
  127. Input: mq_pin - analog channel
  128. Output: Ro of the sensor
  129. Remarks: This function assumes that the sensor is in clean air. It use
  130. MQResistanceCalculation to calculates the sensor resistance in clean air
  131. and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
  132. 10, which differs slightly between different sensors.
  133. ************************************************************************************/
  134. float MQCalibration(int mq_pin)
  135. {
  136. int i;
  137. float val=0;
  138. for (i=0; i<CALIBARAION_SAMPLE_TIMES; i++) { //take multiple samples
  139. val += MQResistanceCalculation(analogRead(mq_pin));
  140. delay(CALIBRATION_SAMPLE_INTERVAL);
  141. }
  142. val = val/CALIBARAION_SAMPLE_TIMES; //calculate the average value
  143. val = val/RO_CLEAN_AIR_FACTOR; //divided by RO_CLEAN_AIR_FACTOR yields the Ro
  144. //according to the chart in the datasheet
  145. return val;
  146. }
  147. /***************************** MQRead *********************************************
  148. Input: mq_pin - analog channel
  149. Output: Rs of the sensor
  150. Remarks: This function use MQResistanceCalculation to calculate the sensor resistance (Rs).
  151. The Rs changes as the sensor is in the different concentration of the target
  152. gas. The sample times and the time interval between samples could be configured
  153. by changing the definition of the macros.
  154. ************************************************************************************/
  155. float MQRead(int mq_pin)
  156. {
  157. int i;
  158. float rs=0;
  159. for (i=0; i<READ_SAMPLE_TIMES; i++) {
  160. rs += MQResistanceCalculation(analogRead(mq_pin));
  161. delay(READ_SAMPLE_INTERVAL);
  162. }
  163. rs = rs/READ_SAMPLE_TIMES;
  164. return rs;
  165. }
  166. /***************************** MQGetGasPercentage **********************************
  167. Input: rs_ro_ratio - Rs divided by Ro
  168. gas_id - target gas type
  169. Output: ppm of the target gas
  170. Remarks: This function passes different curves to the MQGetPercentage function which
  171. calculates the ppm (parts per million) of the target gas.
  172. ************************************************************************************/
  173. int MQGetGasPercentage(float rs_ro_ratio, int gas_id)
  174. {
  175. if ( gas_id == GAS_LPG ) {
  176. return MQGetPercentage(rs_ro_ratio,LPGCurve);
  177. } else if ( gas_id == GAS_CO ) {
  178. return MQGetPercentage(rs_ro_ratio,COCurve);
  179. } else if ( gas_id == GAS_SMOKE ) {
  180. return MQGetPercentage(rs_ro_ratio,SmokeCurve);
  181. }
  182. return 0;
  183. }
  184. /***************************** MQGetPercentage **********************************
  185. Input: rs_ro_ratio - Rs divided by Ro
  186. pcurve - pointer to the curve of the target gas
  187. Output: ppm of the target gas
  188. Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
  189. of the line could be derived if y(rs_ro_ratio) is provided. As it is a
  190. logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
  191. value.
  192. ************************************************************************************/
  193. int MQGetPercentage(float rs_ro_ratio, float *pcurve)
  194. {
  195. return (pow(10,( ((log(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
  196. }