/TheGardenDroid_Arduino/TempSensor.cpp

https://github.com/marekjs/TheGardenDroid · C++ · 206 lines · 147 code · 22 blank · 37 comment · 21 complexity · 7a31e37d6b2764314865d53063d6f172 MD5 · raw file

  1. /**
  2. * TempSensor.cpp -Temprature sensor interface specificly for the DS1621 attached to the Arduino.
  3. * Created by Lee Clarke, Oct 21, 2010.
  4. * Released into the public domain.
  5. */
  6. #include "TempSensor.h"
  7. #include "PString.h"
  8. #include "Sensor.h"
  9. #include <Wire.h>
  10. #define DEV_TYPE 0x90 >> 1 // shift required by wire.h
  11. #define DEV_ADDR 0x00 // DS1621 address is 0
  12. #define SLAVE_ID DEV_TYPE | DEV_ADDR
  13. // DS1621 Registers & Commands
  14. #define RD_TEMP 0xAA // read temperature register
  15. #define ACCESS_TH 0xA1 // access high temperature register
  16. #define ACCESS_TL 0xA2 // access low temperature register
  17. #define ACCESS_CFG 0xAC // access configuration register
  18. #define RD_CNTR 0xA8 // read counter register
  19. #define RD_SLOPE 0xA9 // read slope register
  20. #define START_CNV 0xEE // start temperature conversion
  21. #define STOP_CNV 0X22 // stop temperature conversion
  22. // DS1621 configuration bits
  23. #define DONE B10000000 // conversion is done
  24. #define THF B01000000 // high temp flag
  25. #define TLF B00100000 // low temp flag
  26. #define NVB B00010000 // non-volatile memory is busy
  27. #define POL B00000010 // output polarity (1 = high, 0 = low)
  28. #define ONE_SHOT B00000001 // 1 = one conversion; 0 = continuous conversion
  29. TempSensor::TempSensor(int sensorId, String name, unsigned long pollInterval)
  30. :Sensor(sensorId, name, pollInterval){
  31. negTempC = false;
  32. }
  33. /**
  34. * Retrieves the Temp values and sets results to fields.
  35. *
  36. * Return 1 for success, 0 if data was not due for update, -1 for fail.
  37. */
  38. int TempSensor::getSensorValue() {
  39. int resp = -1;
  40. int tC, tFrac;
  41. tC = getHrTemp(); // read high-resolution temperature
  42. if (tC < 0) {
  43. tC = -tC; // fix for integer division if negitive
  44. //resp += "-"; // indicate negative
  45. negTempC = true;
  46. }
  47. tFrac = tC % 100; // extract fractional part
  48. tC /= 100; // extract whole part
  49. tempC = tC + (tFrac*.01);
  50. tempF = (tempC*9/5)+32;
  51. resp = 1;
  52. return resp;
  53. }
  54. int TempSensor::getSensorState(){
  55. int resp = 0;
  56. if (this->sendStatus > 0)
  57. {
  58. resp = (int)this->sendStatus;
  59. }
  60. else {
  61. //TODO: decide if want to add additional codes or return 0
  62. }
  63. return resp;
  64. }
  65. /* --------Temp support-----------*/
  66. // Start/Stop DS1621 temperature conversion
  67. void TempSensor::startConversion(boolean start)
  68. {
  69. Wire.beginTransmission(SLAVE_ID);
  70. if (start == true)
  71. Wire.send(START_CNV);
  72. else
  73. Wire.send(STOP_CNV);
  74. this->sendStatus = Wire.endTransmission();
  75. }
  76. // Set configuration register
  77. void TempSensor::setConfig(byte cfg)
  78. {
  79. Wire.beginTransmission(SLAVE_ID);
  80. Wire.send(ACCESS_CFG);
  81. Wire.send(cfg);
  82. Wire.endTransmission();
  83. delay(15); // allow EE write time to finish
  84. }
  85. // Read a DS1621 register
  86. byte getReg(byte reg)
  87. {
  88. Wire.beginTransmission(SLAVE_ID);
  89. Wire.send(reg); // set register to read
  90. Wire.endTransmission();
  91. Wire.requestFrom(SLAVE_ID, 1);
  92. byte regVal = Wire.receive();
  93. return regVal;
  94. }
  95. void TempSensor::setHighThresh(int tC) {
  96. setThresh(ACCESS_TH,tC);
  97. }
  98. void TempSensor::setLowThresh(int tC) {
  99. setThresh(ACCESS_TL,tC);
  100. }
  101. // Sets temperature threshold
  102. // -- whole degrees C only
  103. // -- works only with ACCESS_TL and ACCESS_TH
  104. void TempSensor::setThresh(byte reg, int tC)
  105. {
  106. if (reg == ACCESS_TL || reg == ACCESS_TH) {
  107. Wire.beginTransmission(SLAVE_ID);
  108. Wire.send(reg); // select temperature reg
  109. Wire.send(byte(tC)); // set threshold
  110. Wire.send(0); // clear fractional bit
  111. Wire.endTransmission();
  112. delay(15);
  113. }
  114. }
  115. // Reads temperature or threshold
  116. // -- whole degrees C only
  117. // -- works only with RD_TEMP, ACCESS_TL, and ACCESS_TH
  118. int TempSensor::getTemp(byte reg)
  119. {
  120. int tC;
  121. if (reg == RD_TEMP || reg == ACCESS_TL || reg == ACCESS_TH) {
  122. byte tVal = getReg(reg);
  123. if (tVal >= B10000000) { // negative?
  124. tC = 0xFF00 | tVal; // extend sign bits
  125. }
  126. else {
  127. tC = tVal;
  128. }
  129. return tC; // return threshold
  130. }
  131. return 0; // bad reg, return 0
  132. }
  133. // Read high resolution temperature
  134. // -- returns temperature in 1/100ths degrees
  135. // -- DS1620 must be in 1-shot mode
  136. int TempSensor::getHrTemp()
  137. {
  138. startConversion(true); // initiate conversion
  139. byte cfg = 0;
  140. while (cfg < DONE) { // let it finish
  141. cfg = getReg(ACCESS_CFG);
  142. }
  143. int tHR = getTemp(RD_TEMP); // get whole degrees reading
  144. byte cRem = getReg(RD_CNTR); // get counts remaining
  145. byte slope = getReg(RD_SLOPE); // get counts per degree
  146. if (tHR >= 0)
  147. tHR = (tHR * 100 - 25) + ((slope - cRem) * 100 / slope);
  148. else {
  149. tHR = -tHR;
  150. tHR = (25 - tHR * 100) + ((slope - cRem) * 100 / slope);
  151. }
  152. return tHR;
  153. }
  154. void TempSensor::tempThresholdTripped()
  155. {
  156. Serial.print("### Temp Thresholds Exceeded! ####");
  157. Serial.print("** PIN2 == true **");
  158. /* I plan to use this as a freeze warning indicator to trigger heat, I wonder if it would work
  159. * in reverse.. say setting high to 22 and Low to say 24, would that cause it to send tOut high
  160. * when it hits 22 and set Low ehn it goes back up to 24?*/
  161. /* NOTE: if the temp is between threshH and threshL when system starts then tOut ==0
  162. * This means that the los threshold will NOT trigger an alarm.
  163. * I think the solution would be to set the ThreshH to currentTemp-1 or some lower
  164. * alarm value such as 0C this would enable a trigger when the temp drops low like a
  165. * freeze alarm.
  166. */
  167. Serial.println("");
  168. }
  169. String TempSensor::toString()
  170. {
  171. this->getSensorValue();
  172. char buf[20];
  173. PString str(buf, sizeof(buf));
  174. String resp;
  175. if(negTempC){
  176. str.print("-");
  177. }
  178. str.print(tempC);
  179. str.print("|");
  180. str.print(tempF);
  181. // str.print("F");
  182. resp = String(buf);
  183. return resp;
  184. }