Smart Coaster

Published by Alpha007 in the blog Alpha007's blog. Views: 381


Introduction
How many times have you made a cup of coffee or tea and it’s been too hot to drink, and then by the time you get to it, it’s become too cold? :(
I love drinking tea and most of the times I have burned my mouth. :mad:
My Solution:
A Smart coaster to place your cup on, a coaster monitoring the temperature and notifying you before it gets too cold.
If you place a cup of hot tea/coffee on it, it will start a timer program which shows you, when it is ready to drink. A RGB led will be present to show if the temperature is right or not.
I am using Thermo 6 MAX31875 click board as it would be the perfect solution for this project due to the low power consumption.
If you go through the code i have explained everything in detail and you will know that this prototype device can not only be used to monitor your hot beverages temperature but also can be used to monitor the temperature of cold beverages so that you will always enjoy your drinks at optimum temperature and be happy!! ;)

BOM
  • Atmega328p mirocontroller. [Quantity - 1] (Arduino Uno Microcontroller)
  • Thermo 6 click board based on the Maxim Integrated MAX31875 temperature sensor. [Quantity - 1]
  • LED - RGB Diffused Common Anode. [Quantity - 1]
  • 28 Pin - DIP IC Socket/Base. [Quantity - 1]
  • 40 pin Female and Male Berg strip. [Quantity - 1 each]
  • HT7533A-1 3.3V 100mA Low Power LDO. [Quantity - 1]
  • 9v Battery. [Quantity - 1]
  • 9v Battery Snap Connector. [Quantity - 1]

Software
  • Arduino IDE

Instructions
  • MAX31875 Features:-
Tiny, 0.84mm x 0.84mm x 0.35mm WLP
Excellent Temperature Accuracy -
±1.5°C from +10°C to +45°C (±0.5°C Typical)

±2°C from -10°C to +100°C (±0.6°C Typical)

±3°C from -20°C to +125°C (±1°C Typical)​
<10μA Average Power Supply Current
I2C and SMBus Support
Selectable PEC for Reliable Communications
Up to 1MHz Bus Speed
+1.6V to +3.6V Power Supply Voltage

MAX31875 Registers Details.png
  • MAX31875 Typical Application Circuit:-
MAX31875.png

  • MAX31875 Power Consumption:-
The MAX31875 is a low-power temperature sensor whose average power supply current is affected by the conversion resolution and the conversion rate. Understanding the relationships between these values can help to optimize performance tradeoffs.
In Standby mode, and between conversions, the power supply current is typically 500nA. During a conversion, the typical supply current increases to 80μA. The duration of a conversion depends on the conversion resolution selected in the Configuration register. A 10-bit conversion requires 35ms (typical). Each 1-bit increase in resolution doubles the conversion time, and each 1-bit decrease halves the conversion time. Therefore, if 12-bit resolution is selected, the conversion time will typically be 140ms.
The conversion rate is also selectable, and, along with resolution, helps to set the conversion duty cycle and
average power supply current. As an example, 10-bit
conversions occurring at a rate of one conversion per second will result in an average power supply current of
IAVE = 80μA x 0.035 + 0.5μA x 0.965 = 2.8μA.

  • RGB LED (Common Anode) Typical Circuit:-
For this project I have used 330 ohm resistors for each R, G and B pins of the RGB Led.
RGB LED.jpg

  • Atmega328p Microcontroller Pinout:-
Atmega328 Pinout digram.png

  • HT7533A-1 3.3V LDO:-
HT7533A-1 3.3V Three-Terminal Regulator TO-92 Typical Circuit Diagram.png


As you can see all the components from regulator to the microcontroller and sensor consume low power. Atmega328p was used due to the ease of programming via the Arduino IDE and also you can program it to consume extremely low power. :cool:
I have also added battery monitoring feature if the battery level falls below 20% our rgb led will go through yellow, cyan and purple colour when you start your device to notify you that the battery is low. :cool:

Maxim has a nice video tutorial on this thermo 6 click board:-
https://www.maximintegrated.com/en/products/analog/sensors-and-sensor-interface/MAX31875.html

Now they have made a tutorial using their microcontroller programmed via mbed so i searched the repository and got the following code which was edited to work with Arduino boards:-
https://os.mbed.com/teams/MaximIntegrated/code/MAX31875_demo/file/bc0f96339b73/main.cpp/


Video
Let's see your project in action! Paste the YouTube link here and it will automatically be embedded.
Working Demo Video of the prototype:-


Schematics
Schematic.png


Source Code
Arduino MAX31875 Interfacing
Code (Text):
  1. [/FONT]
  2. /*
  3. * This Arduino code reads the temperature values from
  4. * Thermo 6 MAX31875 click board and prints it serially at 9600 baud rate
  5. */
  6. #include <Wire.h>
  7. #define SERIAL_BAUD 9600
  8. #define TEMP_ADDRESS  0x48
  9. #define TEMP_REG  0x00
  10. #define CONFIG_REG  0x01
  11. void configTemp(void)
  12. {
  13.   //creates an array to store the values to be written to the configuration register
  14.   //values chosen will program the MAX31875 for 8 conversions/second and 12-bit resolution
  15.   char data[3] = {CONFIG_REG, 0x00, 0x66};
  16.   Wire.beginTransmission(TEMP_ADDRESS);
  17.   Wire.write(data[0]);
  18.   Wire.write(data[1]);
  19.   Wire.write(data[2]);
  20.   Wire.endTransmission();
  21. }
  22. int readTemp(void)
  23. {
  24.   int temp_raw = 0;
  25.   char data[2] = {TEMP_REG, 0};
  26.   //the first I2C command sets the MAX31875 to point to the temperature register
  27.   Wire.beginTransmission(TEMP_ADDRESS);
  28.   Wire.write(data[0]);
  29.   Wire.write(data[1]);
  30.   Wire.endTransmission();
  31.   //wait for temperature readings to happen
  32.   delay(100);
  33.   //request temperature reading from sensor
  34.   Wire.requestFrom(TEMP_ADDRESS, 2);
  35.   //receive temperature reading from sensor
  36.   if (2 <= Wire.available()) { // if two bytes were received
  37.   temp_raw = Wire.read();  // receive high byte (overwrites previous reading)
  38.   temp_raw = temp_raw << 8;  // shift high byte to be high 8 bits
  39.   temp_raw |= Wire.read(); // receive low byte as lower 8 bits
  40.   //Serial.println(temp_raw);  // print the reading
  41.   }
  42.   //returns the 16-bit raw temperature reading
  43.   return temp_raw;
  44. }
  45. void setup() {
  46.   Wire.begin();
  47.   Serial.begin(SERIAL_BAUD);
  48.   Serial.println("MAX31875 Interfacing Code");
  49.  
  50.   //write the configuration register
  51.   configTemp();
  52. }
  53. void loop() {
  54. /*
  55.   //This if uncommented will let you know about all the I2C devices connected on the Arduino
  56.   //Also the address of the devices
  57.   Serial.println("I2C Scanner");
  58.   byte error, address;
  59.   int nDevices;
  60.   Serial.println("Scanning...");
  61.   nDevices = 0;
  62.   for (address = 1; address < 127; address++)
  63.   {
  64.   // The i2c scanner uses the return value of the Write.endTransmisstion to see if a device did acknowledge to the address.
  65.   Wire.beginTransmission(address);
  66.   error = Wire.endTransmission();
  67.   if (error == 0)
  68.   {
  69.   Serial.print("I2C device found at address 0x");
  70.   if (address < 16) {
  71.   Serial.print("0");
  72.   }
  73.   Serial.print(address, HEX);
  74.   Serial.println(" !");
  75.   nDevices++;
  76.   }
  77.   else if (error == 4)
  78.   {
  79.   Serial.print("Unknown error at address 0x");
  80.   if (address < 16) {
  81.   Serial.print("0");
  82.   }
  83.   Serial.println(address, HEX);
  84.   }
  85.   }
  86.   if (nDevices == 0) {
  87.   Serial.println("No I2C devices found\n");
  88.   }
  89.   else {
  90.   Serial.println("Done.\n");
  91.   }
  92. */
  93.   int temperature_raw;
  94.   float temperature_C;
  95.   temperature_raw = readTemp();
  96.   Serial.print("Temperature in raw:- ");
  97.   Serial.println(temperature_raw);
  98.   if(temperature_raw != 0)
  99.   {
  100.   temperature_C = temperature_raw/256.0;
  101.   Serial.print("Temperature in Celsius:- ");
  102.   Serial.println(temperature_C);
  103.   }
  104.   else {
  105.   Serial.println("Temp Read Error ");
  106.   }
  107.  
  108.   delay(2500);  //2500 milliseconds delay
  109. }
  110.  
  111. [FONT=Georgia]

Main Code with all the electronic components
Code (Text):
  1. [/FONT]
  2.  
  3. #include <Wire.h>
  4.  
  5. /*
  6. * Serial baud rate for debugging program using Serial Monitor
  7. */
  8. #define SERIAL_BAUD 9600
  9.  
  10. #define Red_Pin  11
  11. #define Green_Pin  10
  12. #define Blue_Pin  9
  13.  
  14. //comment this line if using a Common Cathode LED
  15. #define COMMON_ANODE
  16.  
  17. //Optimum Temperature For Hot Beverages (Changes from person to person)
  18. const int hot_max = 80; //in celsius above this can cause significant scald burns.
  19. const int hot_min = 60; //in celsius below this it will be luke warm not good to drink
  20.  
  21. //Optimum Temperature For Cold Beverages  (Changes from person to person)
  22. const int cold_max = 12; //in celsius above this drink will not seem cold enough to enjoy
  23. const int cold_min = 3; //in celsius below this it will be too cold
  24.  
  25.  
  26. #define voltSensePin A0
  27.  
  28. uint16_t minVolt = 3399 + 100;
  29. uint16_t maxVolt = 9000;
  30. float dividerRatio = 3.404858;
  31. byte batLevel = 0;
  32.  
  33.  
  34. /*
  35. * MAX31875 Temperature Sensor I2C address
  36. */
  37. #define TEMP_ADDRESS  0x48
  38.  
  39.  
  40. /*
  41. * Address of Temperature Register
  42. * The temperature data format is 16 bits,
  43. * two’s complement,
  44. * and
  45. * the register is read out in 2 bytes: an upper byte and a lower byte.
  46. *
  47. */
  48. #define TEMP_REG  0x00
  49.  
  50.  
  51. /*
  52. * Address of Configuration Register
  53. * Configuration register contains 16 bits of data
  54. * and
  55. * initiates single conversions (1-shot),
  56. * enables bus timeout, controls shutdown, sets the data format,
  57. * and
  58. * selects the automatic conversion rate.
  59. */
  60. #define CONFIG_REG  0x01
  61.  
  62. float temperature_C;
  63. float room_temp;
  64.  
  65. void configTemp(void)
  66. {
  67.   /*
  68.   * Default Power-On Reset (POR) Configuration of Configuration Register
  69.   * 0x0040 means -
  70.   * Normal data format
  71.   * 0.25 conversions per second
  72.   * Timeout enabled
  73.   * 10-bit (0.25°C) resolution
  74.   */
  75.  
  76.   /*
  77.   * For our work here we are setting following Configuration of Configuration Register
  78.   * 0x0066 means -
  79.   * Normal data format
  80.   * 8 conversions per second
  81.   * Timeout enabled
  82.   * 12-bit (0.0625°C) resolution
  83.   */
  84.   char data[3] = {CONFIG_REG, 0x00, 0x66};
  85.  
  86.   Wire.beginTransmission(TEMP_ADDRESS);
  87.   Wire.write(data[0]);  //Configuration Register Address
  88.   Wire.write(data[1]);  //Data High
  89.   Wire.write(data[2]);  //Data Low
  90.   Wire.endTransmission();
  91. }
  92.  
  93.  
  94. uint16_t readTemp(void)
  95. {
  96.   uint16_t temp_raw = 0;
  97.   char data[2] = {TEMP_REG, 0};
  98.  
  99.   //the first I2C command sets the MAX31875 to point to the temperature register
  100.   Wire.beginTransmission(TEMP_ADDRESS);
  101.   Wire.write(data[0]);
  102.   Wire.write(data[1]);
  103.   Wire.endTransmission();
  104.  
  105.   //wait for temperature readings to happen
  106.   delay(100);
  107.  
  108.   //request temperature reading from sensor
  109.   Wire.requestFrom(TEMP_ADDRESS, 2);
  110.  
  111.   //receive temperature reading from sensor
  112.   if (2 <= Wire.available())
  113.   {
  114.   // Check if two bytes were received
  115.   temp_raw = Wire.read();  // receive high byte (overwrites previous reading)
  116.   temp_raw = temp_raw << 8;  // shift high byte to be high 8 bits
  117.   temp_raw |= Wire.read(); // receive low byte as lower 8 bits
  118.   //Serial.println(temp_raw);  // print the reading
  119.   }
  120.  
  121.   //returns the 16-bit raw temperature reading
  122.   return temp_raw;
  123. }
  124.  
  125. void setRGBColor(int redValue, int greenValue, int blueValue)
  126. {
  127.   #ifdef COMMON_ANODE
  128.   redValue = 255 - redValue;
  129.   greenValue = 255 - greenValue;
  130.   blueValue = 255 - blueValue;
  131.   #endif
  132.  
  133.   analogWrite(Red_Pin, redValue);
  134.   analogWrite(Green_Pin, greenValue);
  135.   analogWrite(Blue_Pin, blueValue);
  136. }
  137.  
  138. void batteryLevelMeasure(){
  139.   long sensorValue = analogRead(voltSensePin);
  140.   delay(50);
  141.   sensorValue = 0;
  142.  
  143.   for (int i=0; i<10; i++)
  144.   {
  145.   sensorValue = sensorValue + analogRead(voltSensePin);
  146.   delay(50);
  147.   }
  148.   sensorValue = sensorValue/10;  
  149.   //Serial.print("Raw Analog Value at A0:- ");
  150.   //Serial.println(sensorValue);
  151.  
  152.   float batVolt = sensorValue * (3.3 /1024);
  153.   batVolt = batVolt * 1000;  //in milli volts
  154.   //Serial.print("Battery Voltage at A0:- ");
  155.   //Serial.println(batVolt);
  156.   batVolt = batVolt * dividerRatio;
  157.  
  158.   uint16_t batRead = batVolt;
  159.   Serial.print("Battery Voltage:- ");
  160.   Serial.println(batVolt);
  161.  
  162.   if (batRead <= minVolt)
  163.   {
  164.   batLevel = 0;
  165.   }
  166.   else if (batRead >= maxVolt) {
  167.   batLevel = 100;
  168.   }
  169.   else {  
  170.   long data = batRead - minVolt;
  171.    
  172.   data = data * 100;
  173.    
  174.   data = data / (maxVolt-minVolt) ;
  175.    
  176.   batLevel = data;
  177.   }
  178.  
  179.   Serial.print("BL,");
  180.   Serial.println(batLevel);
  181. }
  182.  
  183.  
  184. void setup() {
  185.   pinMode(Red_Pin, OUTPUT);
  186.   pinMode(Green_Pin, OUTPUT);
  187.   pinMode(Blue_Pin, OUTPUT);
  188.  
  189.   Wire.begin();  //For ESP8266 Default I2C pins:- GPIO pins 4(SDA) and 5(SCL).
  190.  
  191.   Serial.begin(SERIAL_BAUD);
  192.  
  193.   Serial.println("");
  194.   Serial.println("Smart Coaster");  
  195.  
  196.   //write the configuration register
  197.   configTemp();
  198.  
  199.   delay(100);
  200.  
  201.   uint16_t temperature_raw = readTemp();
  202.   if(temperature_raw != 0)
  203.   {
  204.   room_temp = temperature_raw/256.0;
  205.   Serial.print("Room Temperature in Celsius:- ");
  206.   Serial.println(room_temp);
  207.   }
  208.   Serial.print("Between ");
  209.   Serial.print(hot_min);
  210.   Serial.print(" degree celsius & ");
  211.   Serial.print(hot_max);
  212.   Serial.print(" degree celsius ");
  213.   Serial.print("temperature is the ");
  214.   Serial.println("Optimum Hot Temperature to Drink");
  215.  
  216.   Serial.print("Greater than ");
  217.   Serial.print(hot_max);
  218.   Serial.print(" degree celsius ");
  219.   Serial.print("temperature is ");
  220.   Serial.println("Too Hot Temperature to Drink");
  221.  
  222.   Serial.print("Less than ");
  223.   Serial.print(hot_min);
  224.   Serial.print(" degree celsius ");
  225.   Serial.print("temperature is ");
  226.   Serial.println("Luke warm to Drink will not taste that great");
  227.  
  228.   setRGBColor(255, 0, 0); // Red Color
  229.   delay(100);
  230.   setRGBColor(0, 255, 0); // Green Color
  231.   delay(100);
  232.   setRGBColor(0, 0, 255); // Blue Color
  233.   delay(100);
  234.  
  235.   setRGBColor(255, 255, 255); // White Color
  236.   delay(500);
  237.  
  238.   batteryLevelMeasure();
  239.  
  240.   if (batLevel < 20)
  241.   {
  242.   setRGBColor(255, 255, 0);  // yellow (turn red and green on)
  243.   delay(100);  
  244.   setRGBColor(0, 255, 255);  // Cyan (turn green and blue on)
  245.   delay(100);
  246.   setRGBColor(255, 0, 255);  // Purple (turn red and blue on)
  247.   delay(100);  
  248.   }
  249.  
  250.   setRGBColor(0, 0, 0);  // turn off the rgb led
  251.   delay(500);
  252. }
  253.  
  254. void setRGBHot(float temp)
  255. {
  256.   if (temp <= hot_max && temp >= hot_min)
  257.   {
  258.   setRGBColor(0, 255, 0); //Green Colour - Optimum Hot Temperature to Drink
  259.   Serial.println("Optimum Hot Temperature to Drink");
  260.   }
  261.   else if (temp > hot_max)
  262.   {
  263.   setRGBColor(255, 0, 0); // Red Color - Too Hot Temperature to Drink
  264.   Serial.println("Too Hot Temperature to Drink");
  265.   }
  266.   else if (temp < hot_min)
  267.   {
  268.   setRGBColor(0, 0, 255); //Blue Colour - Luke warm to Drink will not taste great
  269.   Serial.println("Luke warm to Drink will not taste great");
  270.   }
  271. }
  272.  
  273. void setRGBCold(float temp)
  274. {
  275.   if (temp <= cold_max && temp >= cold_min)
  276.   {
  277.   setRGBColor(0, 255, 0); //Green Colour - Optimum Cold Temperature to Drink
  278.   Serial.println("Optimum Cold Temperature to Drink");
  279.   }
  280.   else if (temp > cold_max)
  281.   {
  282.   setRGBColor(255, 0, 0); // Red Color - Too Hot Temperature to Drink
  283.   Serial.println("Cold Drink will not taste great");
  284.   }
  285.   else if (temp < cold_min)
  286.   {
  287.   setRGBColor(0, 0, 255); //Blue Colour - Luke warm to Drink will not taste great
  288.   Serial.println("Too Cold Temperature to Drink");
  289.   }
  290. }
  291.  
  292. long previousMillis = 0;  // will store last time temperature was checked and RGB LED was updated
  293. long intervalTime = 5000;  // interval at which temperature was checked (milliseconds)
  294.  
  295. void loop()
  296. {
  297.   unsigned long currentMillis = millis();
  298.   if(currentMillis - previousMillis >= intervalTime)
  299.   {
  300.   Serial.println("");
  301.   //Serial.print("Temperature in raw:- ");
  302.   uint16_t temperature_raw = readTemp();
  303.   //Serial.println(temperature_raw);
  304.    
  305.   if(temperature_raw != 0)
  306.   {
  307.   temperature_C = temperature_raw/256.0;
  308.   Serial.print("Temperature in Celsius:- ");
  309.   Serial.println(temperature_C);
  310.  
  311.   Serial.print("Hot Beverage:- ");
  312.   setRGBHot(temperature_C);
  313.   }
  314.   else {
  315.   Serial.println("Temp Read Error ");
  316.   }
  317.    
  318.   // save the last time you checked the temperture and updated the RGB LED
  319.   previousMillis = currentMillis;  
  320.    
  321.   }
  322. }[/FONT]
  323.  
  324. [FONT=Georgia]
  325. [FONT=Georgia]
CAD Files
I haven't made the 3d case yet but as soon as it gets designed and printed i will upload it.

You need to be logged in to comment