WiFi Temperature Sensor

Published by cybermah in the blog cybermah's blog. Views: 728


Introduction
My project is a Wifi temperature sensor. I was looking for a way to monitor my Smoker. The current wireless one I have, you had to be within 10 feet or it would be out of range. It kinda defeats the purpose of Wireless. I wanted something that I could go anywhere in and around the house and still see what the temperature is.

BOM
  • NodeMCU
  • MAX31856
  • K-Type Thermocouple
Software
  • Arduino IDE
  • ESP8266 board library
  • Temperature Sensor (code below)
  • Adafruit_MAX31856 library (code below)
  • Android App
Schematics

Sensor wiring diagram.
[​IMG]

MAX31856 Schematic
[​IMG]


Instructions
The way the sensor works is the NodeMCU will communicate using SPI to the MAX31856 tempertature sensor which reads the voltage on a thermocouple and converts it to a temperature value in degrees C. Then the NodeMCU will take the value received and put it on an MQTT topic using Wifi. An app, MQTT Dash, will read the topic and display the temperature on your android phone. I have a MQTT server here, but if you use a public MQTT server, you could monitor the temperature anywhere in the world. Not practical for a Smoker, but for monitoring temperature of your home it would work great.

Assemble the hardware as per the fritzing diagram above.
For the code part, I used the Arduino IDE. So download and install it. You will need some libraries added to the IDE in order to program the NodeMCU.

1. Open the IDE
2. Goto File / Preferences
3. In the Additional boards Manager URLs, add the following
4. Click ok
5. Goto Tools
6. Board
7. Board Manager
8. Search for esp8266
9. Click on the esp8266 by ESP8266 Community and install it.
10. Open the Board Manager again and select the NodeMCU 1.0(ESP-12E Module)
11. Your IDE should be ready to program NodeMCUs now.
12. Test by opening the Examples, esp8266, Blink
13. Connect your NodeMCU to your pc
14. Compile and Upload Blink to the board.
15. A blue light should blink on and off. If it does your ready to continue

Now for the code
1. Open the Arduino IDE
2. Select File / New
3. Copy the Temperature sensor code attached
4. Copy the Adafruit-MAX31856 code attached and place it in the same directory as the code above.
5. You can also download the library, but don’t install it in the IDE, we need to make a small change in it.
6. Click on Sketch / Add File and select max31856.cpp
7. Click on Sketch / Add File and select max31856.h
8. The change required in the max31856.cpp
a. Find the SPISetting entry line 27
b. it should be static SPISettings max31856_spisettings = SPISettings(100000, MSBFIRST, SPI_MODE3);
9. Now for the Sensor code
a. Add your SSID and password for your WiFi connection
b. Change the connection information for MQTT. I have my own, but you can find free ones on the web to use
c. Compile and Upload the code to your NodeMCU​
d. If you have a MQTT viewer, open it and point to the topic /hello
10. Android App
a. Open google play and install MQTT Dash
b. Open the app Hit the plus sign in the upper right corner
c. Enter a name
d. add the address and port of your MQTT server
e. add your username and password to your MQTT server
f. save it.
g. Select your entry you just made
h. Hit the plus symbol
i. Chose Range/progress
j. Give it a name
k. put in the topic /temperature
l. Select the range you plan to monitor
m. Save it.
n. you should start to see the temperature show up now
Conclusion:
You will notice in the code there are some improvements that should be made to make the sensor more efficient.
  1. Remove the debug serial print statements.
  2. remove the delay() and switch it to ESP.deepsleep. Depending on your sleep time, you could run this sensor over a year without having to change or charge your battery. I have my delay set to 60 seconds at the moment, but that was for testing. Because of the different uses for this sensor, I would adjust this time for the application I'm using it for.
After playing around with this temperature sensor for a bit, I already have 3 or 4 real life projects I would like to use it for. The initial one to monitor my smoker, for this one I would use a delay of 10 - 30 seconds, but I would also like to use the sensor to monitor my pipes in my house, every winter they freeze, I could use this sensor to notify me that they are close to freezing, this application I would use the deep sleep of 15 - 30 mins.

The nice part about this sensor is it uses WiFi and mqtt to send the data, this means it is very easy to connect it to a number of home automation systems or even public mqtt brokers for simple monitoring.


Thanks
Dana.

Source Code
Code (Text):
  1.  
  2. [FONT=Courier New][SIZE=4]#include <MQTTClient.h>
  3. #include <ESP8266WiFi.h>
  4. #include <SPI.h>
  5. #include "Adafruit_MAX31856.h"
  6.  
  7. const char ssid[] = "[B]your_ssid[/B]";
  8. const char pass[] = "[B]your_password[/B]";
  9.  
  10. WiFiClient net;
  11. MQTTClient client;
  12.  
  13. unsigned long lastMillis = 0;
  14.  
  15. // Use software SPI: CS, DI, DO, CLK
  16. Adafruit_MAX31856 maxim = Adafruit_MAX31856(15, 13, 12,14);
  17. // use hardware SPI, just pass in the CS pin
  18. //Adafruit_MAX31856 maxim = Adafruit_MAX31856(15);
  19.  
  20. void setup() {
  21.   Serial.begin(115200);
  22.  
  23.    WiFi.begin(ssid, pass);
  24.  
  25.   // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
  26.   // You need to set the IP address directly.
  27.   client.begin("[B]192.168.2.28[/B]", 1883, net);
  28.   client.onMessage(messageReceived);
  29.  
  30.   connect();
  31.  
  32.   Serial.println("MAX31856 thermocouple test");
  33.   maxim.begin();
  34.  
  35.   maxim.setThermocoupleType(MAX31856_TCTYPE_K);
  36. }
  37.  
  38. void loop() {
  39.   Serial.print("Cold Junction Temp: "); Serial.println(maxim.readCJTemperature());
  40.   Serial.print("Thermocouple Temp: "); Serial.println(maxim.readThermocoupleTemperature());
  41.   // Check and print any faults
  42.   uint8_t fault = maxim.readFault();
  43.   if (fault) {
  44.     if (fault & MAX31856_FAULT_CJRANGE) Serial.println("Cold Junction Range Fault");
  45.     if (fault & MAX31856_FAULT_TCRANGE) Serial.println("Thermocouple Range Fault");
  46.     if (fault & MAX31856_FAULT_CJHIGH)  Serial.println("Cold Junction High Fault");
  47.     if (fault & MAX31856_FAULT_CJLOW)   Serial.println("Cold Junction Low Fault");
  48.     if (fault & MAX31856_FAULT_TCHIGH)  Serial.println("Thermocouple High Fault");
  49.     if (fault & MAX31856_FAULT_TCLOW)   Serial.println("Thermocouple Low Fault");
  50.     if (fault & MAX31856_FAULT_OVUV)    Serial.println("Over/Under Voltage Fault");
  51.     if (fault & MAX31856_FAULT_OPEN)    Serial.println("Thermocouple Open Fault");
  52.   }
  53.   delay(60000);
  54.  
  55.   client.loop();
  56.   delay(10);  // <- fixes some issues with WiFi stability
  57.  
  58.   if (!client.connected()) {
  59.     connect();
  60.   }
  61.  
  62.   // publish a message roughly every second.
  63.   if (millis() - lastMillis > 1000) {
  64.     lastMillis = millis();
  65.     client.publish("/temperature", String(maxim.readThermocoupleTemperature()));
  66.   }
  67. }
  68.  
  69. void messageReceived(String &topic, String &payload) {
  70.   Serial.println("incoming: " + topic + " - " + payload);
  71. }
  72.  
  73. void connect() {
  74.   Serial.print("checking wifi...");
  75.   while (WiFi.status() != WL_CONNECTED) {
  76.     Serial.print(".");
  77.     delay(1000);
  78.   }
  79.  
  80.   Serial.print("\nconnecting...");
  81.   while (!client.connect("admin", "admin", "admin")) {
  82.     Serial.print(".");
  83.     delay(1000);
  84.   }
  85.  
  86.   Serial.println("\nconnected!");
  87.  
  88.   client.subscribe("/temperature");
  89.   // client.unsubscribe("/temperature");
  90. }[/SIZE][/FONT]
  91.  
Code (Text):
  1.  
  2. [FONT=Courier New][SIZE=4]/***************************************************
  3.   This is a library for the Adafruit Thermocouple Sensor w/MAX31855K
  4.  
  5.   Designed specifically to work with the Adafruit Thermocouple Sensor
  6.   ----> https://www.adafruit.com/products/269
  7.  
  8.   These displays use SPI to communicate, 3 pins are required to
  9.   interface
  10.   Adafruit invests time and resources providing this open source code,
  11.   please support Adafruit and open-source hardware by purchasing
  12.   products from Adafruit!
  13.  
  14.   Written by Limor Fried/Ladyada for Adafruit Industries.
  15.   BSD license, all text above must be included in any redistribution
  16. ****************************************************/
  17.  
  18. #ifndef ADAFRUIT_MAX31856_H
  19. #define ADAFRUIT_MAX31856_H
  20.  
  21. #define MAX31856_CR0_REG           0x00
  22. #define MAX31856_CR0_AUTOCONVERT   0x80
  23. #define MAX31856_CR0_1SHOT         0x40
  24. #define MAX31856_CR0_OCFAULT1      0x20
  25. #define MAX31856_CR0_OCFAULT0      0x10
  26. #define MAX31856_CR0_CJ            0x08
  27. #define MAX31856_CR0_FAULT         0x04
  28. #define MAX31856_CR0_FAULTCLR      0x02
  29.  
  30. #define MAX31856_CR1_REG           0x01
  31. #define MAX31856_MASK_REG          0x02
  32. #define MAX31856_CJHF_REG          0x03
  33. #define MAX31856_CJLF_REG          0x04
  34. #define MAX31856_LTHFTH_REG        0x05
  35. #define MAX31856_LTHFTL_REG        0x06
  36. #define MAX31856_LTLFTH_REG        0x07
  37. #define MAX31856_LTLFTL_REG        0x08
  38. #define MAX31856_CJTO_REG          0x09
  39. #define MAX31856_CJTH_REG          0x0A
  40. #define MAX31856_CJTL_REG          0x0B
  41. #define MAX31856_LTCBH_REG         0x0C
  42. #define MAX31856_LTCBM_REG         0x0D
  43. #define MAX31856_LTCBL_REG         0x0E
  44. #define MAX31856_SR_REG            0x0F
  45.  
  46. #define MAX31856_FAULT_CJRANGE     0x80
  47. #define MAX31856_FAULT_TCRANGE     0x40
  48. #define MAX31856_FAULT_CJHIGH      0x20
  49. #define MAX31856_FAULT_CJLOW       0x10
  50. #define MAX31856_FAULT_TCHIGH      0x08
  51. #define MAX31856_FAULT_TCLOW       0x04
  52. #define MAX31856_FAULT_OVUV        0x02
  53. #define MAX31856_FAULT_OPEN        0x01
  54.  
  55. typedef enum
  56. {
  57.   MAX31856_TCTYPE_B  = 0b0000,
  58.   MAX31856_TCTYPE_E  = 0b0001,
  59.   MAX31856_TCTYPE_J  = 0b0010,
  60.   MAX31856_TCTYPE_K  = 0b0011,
  61.   MAX31856_TCTYPE_N  = 0b0100,
  62.   MAX31856_TCTYPE_R  = 0b0101,
  63.   MAX31856_TCTYPE_S  = 0b0110,
  64.   MAX31856_TCTYPE_T  = 0b0111,
  65.   MAX31856_VMODE_G8  = 0b1000,
  66.   MAX31856_VMODE_G32 = 0b1100,
  67. } max31856_thermocoupletype_t;
  68.  
  69. #if (ARDUINO >= 100)
  70. #include "Arduino.h"
  71. #else
  72. #include "WProgram.h"
  73. #endif
  74.  
  75. class Adafruit_MAX31856 {
  76. public:
  77.   Adafruit_MAX31856(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso, int8_t spi_clk);
  78.   Adafruit_MAX31856(int8_t spi_cs);
  79.  
  80.   boolean begin(void);
  81.  
  82.   void setThermocoupleType(max31856_thermocoupletype_t type);
  83.   max31856_thermocoupletype_t getThermocoupleType(void);
  84.  
  85.   uint8_t readFault(void);
  86.   void oneShotTemperature(void);
  87.  
  88.   float readCJTemperature(void);
  89.   float readThermocoupleTemperature(void);
  90.  
  91.   void setTempFaultThreshholds(float flow, float fhigh);
  92.   void setColdJunctionFaultThreshholds(int8_t low, int8_t high);
  93.  
  94. private:
  95.   int8_t _sclk, _miso, _mosi, _cs;
  96.  
  97.   void readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n);
  98.  
  99.   uint8_t  readRegister8(uint8_t addr);
  100.   uint16_t readRegister16(uint8_t addr);
  101.   uint32_t readRegister24(uint8_t addr);
  102.  
  103.   void     writeRegister8(uint8_t addr, uint8_t reg);
  104.   uint8_t spixfer(uint8_t addr);
  105. };
  106.  
  107. #endif[/SIZE][/FONT]
  108.  
Code (Text):
  1.  
  2. [FONT=Courier New][SIZE=4]/***************************************************
  3.   This is a library for the Adafruit Thermocouple Sensor w/MAX31856
  4.  
  5.   Designed specifically to work with the Adafruit Thermocouple Sensor
  6.   ----> https://www.adafruit.com/products/xxxx
  7.  
  8.   These sensors use SPI to communicate, 4 pins are required to
  9.   interface
  10.   Adafruit invests time and resources providing this open source code,
  11.   please support Adafruit and open-source hardware by purchasing
  12.   products from Adafruit!
  13.  
  14.   Written by Limor Fried/Ladyada for Adafruit Industries.
  15.   BSD license, all text above must be included in any redistribution
  16. ****************************************************/
  17.  
  18. #include "Adafruit_MAX31856.h"
  19. #ifdef __AVR
  20.   #include <avr/pgmspace.h>
  21. #elif defined(ESP8266)
  22.   #include <pgmspace.h>
  23. #endif
  24.  
  25. #include <stdlib.h>
  26. #include <SPI.h>
  27.  
  28. static SPISettings max31856_spisettings = SPISettings([B]100000, MSBFIRST, SPI_MODE3[/B]);
  29.  
  30. // Software (bitbang) SPI
  31. Adafruit_MAX31856::Adafruit_MAX31856(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso, int8_t spi_clk) {
  32.   _sclk = spi_clk;
  33.   _cs = spi_cs;
  34.   _miso = spi_miso;
  35.   _mosi = spi_mosi;
  36.   pinMode(_cs, OUTPUT);
  37. }
  38.  
  39. // Hardware SPI init
  40. Adafruit_MAX31856::Adafruit_MAX31856(int8_t spi_cs) {
  41.   _cs = spi_cs;
  42.   pinMode(_cs, OUTPUT);
  43.   _sclk = _miso = _mosi = -1;
  44. }
  45.  
  46. boolean Adafruit_MAX31856::begin(void) {
  47.   digitalWrite(_cs, HIGH);
  48.   if (_sclk != -1) {
  49.     //define pin modes
  50.     pinMode(_sclk, OUTPUT);
  51.     pinMode(_mosi, OUTPUT);
  52.     pinMode(_miso, INPUT);
  53.   } else {
  54.     //start and configure hardware SPI
  55.     SPI.begin();
  56.   }
  57.   // assert on any fault
  58.   writeRegister8(MAX31856_MASK_REG, 0x0);
  59.   writeRegister8(MAX31856_CR0_REG, MAX31856_CR0_OCFAULT0);
  60.   setThermocoupleType(MAX31856_TCTYPE_K);
  61.  
  62.   return true;
  63. }
  64.  
  65.  
  66. void Adafruit_MAX31856::setThermocoupleType(max31856_thermocoupletype_t type) {
  67.   uint8_t t = readRegister8(MAX31856_CR1_REG);
  68.   t &= 0xF0; // mask off bottom 4 bits
  69.   t |= (uint8_t)type & 0x0F;
  70.   Serial.println(t);
  71.   writeRegister8(MAX31856_CR1_REG, t);
  72. }
  73.  
  74. max31856_thermocoupletype_t Adafruit_MAX31856::getThermocoupleType(void) {
  75.   uint8_t t = readRegister8(MAX31856_CR1_REG);
  76.   Serial.println("what t is:" + t);
  77.   t &= 0x0F;
  78.   Serial.println(t);
  79.   return (max31856_thermocoupletype_t)(t);
  80. }
  81.  
  82. uint8_t Adafruit_MAX31856::readFault(void) {
  83.   return readRegister8(MAX31856_SR_REG);
  84. }
  85.  
  86. void Adafruit_MAX31856::setColdJunctionFaultThreshholds(int8_t low, int8_t high) {
  87.   writeRegister8(MAX31856_CJLF_REG, low);
  88.   writeRegister8(MAX31856_CJHF_REG, high);
  89. }
  90.  
  91. void Adafruit_MAX31856::setTempFaultThreshholds(float flow, float fhigh) {
  92.   int16_t low, high;
  93.  
  94.   flow *= 16;
  95.   low = flow;
  96.  
  97.   fhigh *= 16;
  98.   high = fhigh;
  99.  
  100.   writeRegister8(MAX31856_LTHFTH_REG, high >> 8);
  101.   writeRegister8(MAX31856_LTHFTL_REG, high);
  102.  
  103.   writeRegister8(MAX31856_LTLFTH_REG, low >> 8);
  104.   writeRegister8(MAX31856_LTLFTL_REG, low);
  105. }
  106.  
  107. void Adafruit_MAX31856::oneShotTemperature(void) {
  108.  
  109.   writeRegister8(MAX31856_CJTO_REG, 0x0);
  110.  
  111.   uint8_t t = readRegister8(MAX31856_CR0_REG);
  112.  
  113.   t &= ~MAX31856_CR0_AUTOCONVERT; // turn off autoconvert!
  114.   t |= MAX31856_CR0_1SHOT;
  115.  
  116.   writeRegister8(MAX31856_CR0_REG, t);
  117.  
  118.   delay(250); // MEME FIX autocalculate based on oversampling
  119. }
  120.  
  121. float Adafruit_MAX31856::readCJTemperature(void) {
  122.   oneShotTemperature();
  123.  
  124.   int16_t temp16 = readRegister16(MAX31856_CJTH_REG);
  125.   float tempfloat = temp16;
  126.   tempfloat /= 256.0;
  127.  
  128.   return tempfloat;
  129. }
  130.  
  131. float Adafruit_MAX31856::readThermocoupleTemperature(void) {
  132.   oneShotTemperature();
  133.  
  134.   int32_t temp24 = readRegister24(MAX31856_LTCBH_REG);
  135.   if (temp24 & 0x800000) {
  136.     temp24 |= 0xFF000000;  // fix sign
  137.   }
  138.  
  139.   temp24 >>= 5;  // bottom 5 bits are unused
  140.  
  141.   float tempfloat = temp24;
  142.   tempfloat *= 0.0078125;
  143.  
  144.   return tempfloat;
  145. }
  146.  
  147. /**********************************************/
  148.  
  149. uint8_t Adafruit_MAX31856::readRegister8(uint8_t addr) {
  150.   uint8_t ret = 0;
  151.   readRegisterN(addr, &ret, 1);
  152.  
  153.   return ret;
  154. }
  155.  
  156. uint16_t Adafruit_MAX31856::readRegister16(uint8_t addr) {
  157.   uint8_t buffer[2] = {0, 0};
  158.   readRegisterN(addr, buffer, 2);
  159.  
  160.   uint16_t ret = buffer[0];
  161.   ret <<= 8;
  162.   ret |=  buffer[1];
  163.  
  164.   return ret;
  165. }
  166.  
  167. uint32_t Adafruit_MAX31856::readRegister24(uint8_t addr) {
  168.   uint8_t buffer[3] = {0, 0, 0};
  169.   readRegisterN(addr, buffer, 3);
  170.  
  171.   uint32_t ret = buffer[0];
  172.   ret <<= 8;
  173.   ret |=  buffer[1];
  174.   ret <<= 8;
  175.   ret |=  buffer[2];
  176.  
  177.   return ret;
  178. }
  179.  
  180.  
  181. void Adafruit_MAX31856::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
  182.   addr &= 0x7F; // make sure top bit is not set
  183.  
  184.   if (_sclk == -1)
  185.     SPI.beginTransaction(max31856_spisettings);
  186.   else
  187.     digitalWrite(_sclk, HIGH);
  188.  
  189.   digitalWrite(_cs, LOW);
  190.  
  191.   spixfer(addr);
  192.  
  193.   //Serial.print("$"); Serial.print(addr, HEX); Serial.print(": ");
  194.   while (n--) {
  195.     buffer[0] = spixfer(0xFF);
  196.     //Serial.print(" 0x"); Serial.print(buffer[0], HEX);
  197.     buffer++;
  198.   }
  199.   //Serial.println();
  200.  
  201.   if (_sclk == -1)
  202.     SPI.endTransaction();
  203.  
  204.   digitalWrite(_cs, HIGH);
  205. }
  206.  
  207.  
  208. void Adafruit_MAX31856::writeRegister8(uint8_t addr, uint8_t data) {
  209.   addr |= 0x80; // make sure top bit is set
  210.  
  211.   if (_sclk == -1)
  212.     SPI.beginTransaction(max31856_spisettings);
  213.   else
  214.     digitalWrite(_sclk, HIGH);
  215.  
  216.   digitalWrite(_cs, LOW);
  217.  
  218.   spixfer(addr);
  219.   spixfer(data);
  220.  
  221.   //Serial.print("$"); Serial.print(addr, HEX); Serial.print(" = 0x"); Serial.println(data, HEX);
  222.  
  223.   if (_sclk == -1)
  224.     SPI.endTransaction();
  225.  
  226.   digitalWrite(_cs, HIGH);
  227. }
  228.  
  229.  
  230.  
  231. uint8_t Adafruit_MAX31856::spixfer(uint8_t x) {
  232.   if (_sclk == -1)
  233.     return SPI.transfer(x);
  234.  
  235.   // software spi
  236.   //Serial.println("Software SPI");
  237.   uint8_t reply = 0;
  238.   for (int i=7; i>=0; i--) {
  239.     reply <<= 1;
  240.     digitalWrite(_sclk, LOW);
  241.     digitalWrite(_mosi, x & (1<<i));
  242.     digitalWrite(_sclk, HIGH);
  243.     if (digitalRead(_miso))
  244.       reply |= 1;
  245.   }
  246.   return reply;
  247. }[/SIZE][/FONT]
  248.  
You need to be logged in to comment