Smart Coaster

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​
1574630250032.png

  • MAX31875 Typical Application Circuit:-
1574630264264.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.
1574630278670.png


  • Atmega328p Microcontroller Pinout:-
1574630285986.png


  • HT7533A-1 3.3V LDO:-
1574630295523.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
1574630309227.png




Source Code
Arduino MAX31875 Interfacing
Code:
[/FONT]
/*
* This Arduino code reads the temperature values from
* Thermo 6 MAX31875 click board and prints it serially at 9600 baud rate
*/
#include <Wire.h>
#define SERIAL_BAUD 9600
#define TEMP_ADDRESS  0x48
#define TEMP_REG  0x00
#define CONFIG_REG  0x01
void configTemp(void)
{
  //creates an array to store the values to be written to the configuration register
  //values chosen will program the MAX31875 for 8 conversions/second and 12-bit resolution
  char data[3] = {CONFIG_REG, 0x00, 0x66};
  Wire.beginTransmission(TEMP_ADDRESS);
  Wire.write(data[0]);
  Wire.write(data[1]);
  Wire.write(data[2]);
  Wire.endTransmission();
}
int readTemp(void)
{
  int temp_raw = 0;
  char data[2] = {TEMP_REG, 0};
  //the first I2C command sets the MAX31875 to point to the temperature register
  Wire.beginTransmission(TEMP_ADDRESS);
  Wire.write(data[0]);
  Wire.write(data[1]);
  Wire.endTransmission();
  //wait for temperature readings to happen
  delay(100);
  //request temperature reading from sensor
  Wire.requestFrom(TEMP_ADDRESS, 2);
  //receive temperature reading from sensor
  if (2 <= Wire.available()) { // if two bytes were received
  temp_raw = Wire.read();  // receive high byte (overwrites previous reading)
  temp_raw = temp_raw << 8;  // shift high byte to be high 8 bits
  temp_raw |= Wire.read(); // receive low byte as lower 8 bits
  //Serial.println(temp_raw);  // print the reading
  }
  //returns the 16-bit raw temperature reading
  return temp_raw;
}
void setup() {
  Wire.begin();
  Serial.begin(SERIAL_BAUD);
  Serial.println("MAX31875 Interfacing Code");

  //write the configuration register
  configTemp();
}
void loop() {
/*
  //This if uncommented will let you know about all the I2C devices connected on the Arduino
  //Also the address of the devices
  Serial.println("I2C Scanner");
  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for (address = 1; address < 127; address++)
  {
  // The i2c scanner uses the return value of the Write.endTransmisstion to see if a device did acknowledge to the address.
  Wire.beginTransmission(address);
  error = Wire.endTransmission();
  if (error == 0)
  {
  Serial.print("I2C device found at address 0x");
  if (address < 16) {
  Serial.print("0");
  }
  Serial.print(address, HEX);
  Serial.println(" !");
  nDevices++;
  }
  else if (error == 4)
  {
  Serial.print("Unknown error at address 0x");
  if (address < 16) {
  Serial.print("0");
  }
  Serial.println(address, HEX);
  }
  }
  if (nDevices == 0) {
  Serial.println("No I2C devices found\n");
  }
  else {
  Serial.println("Done.\n");
  }
*/
  int temperature_raw;
  float temperature_C;
  temperature_raw = readTemp();
  Serial.print("Temperature in raw:- ");
  Serial.println(temperature_raw);
  if(temperature_raw != 0)
  {
  temperature_C = temperature_raw/256.0;
  Serial.print("Temperature in Celsius:- ");
  Serial.println(temperature_C);
  }
  else {
  Serial.println("Temp Read Error ");
  }

  delay(2500);  //2500 milliseconds delay
}

[FONT=Georgia]

Main Code with all the electronic components
Code:
[/FONT]

#include <Wire.h>

/*
* Serial baud rate for debugging program using Serial Monitor
*/
#define SERIAL_BAUD 9600

#define Red_Pin  11
#define Green_Pin  10
#define Blue_Pin  9

//comment this line if using a Common Cathode LED
#define COMMON_ANODE

//Optimum Temperature For Hot Beverages (Changes from person to person)
const int hot_max = 80; //in celsius above this can cause significant scald burns.
const int hot_min = 60; //in celsius below this it will be luke warm not good to drink

//Optimum Temperature For Cold Beverages  (Changes from person to person)
const int cold_max = 12; //in celsius above this drink will not seem cold enough to enjoy
const int cold_min = 3; //in celsius below this it will be too cold


#define voltSensePin A0

uint16_t minVolt = 3399 + 100;
uint16_t maxVolt = 9000;
float dividerRatio = 3.404858;
byte batLevel = 0;


/*
* MAX31875 Temperature Sensor I2C address
*/
#define TEMP_ADDRESS  0x48


/*
* Address of Temperature Register
* The temperature data format is 16 bits,
* two’s complement,
* and
* the register is read out in 2 bytes: an upper byte and a lower byte.
*
*/
#define TEMP_REG  0x00


/*
* Address of Configuration Register
* Configuration register contains 16 bits of data
* and
* initiates single conversions (1-shot),
* enables bus timeout, controls shutdown, sets the data format,
* and
* selects the automatic conversion rate.
*/
#define CONFIG_REG  0x01

float temperature_C;
float room_temp;

void configTemp(void)
{
  /*
  * Default Power-On Reset (POR) Configuration of Configuration Register
  * 0x0040 means -
  * Normal data format
  * 0.25 conversions per second
  * Timeout enabled
  * 10-bit (0.25°C) resolution
  */

  /*
  * For our work here we are setting following Configuration of Configuration Register
  * 0x0066 means -
  * Normal data format
  * 8 conversions per second
  * Timeout enabled
  * 12-bit (0.0625°C) resolution
  */
  char data[3] = {CONFIG_REG, 0x00, 0x66};

  Wire.beginTransmission(TEMP_ADDRESS);
  Wire.write(data[0]);  //Configuration Register Address
  Wire.write(data[1]);  //Data High
  Wire.write(data[2]);  //Data Low
  Wire.endTransmission();
}


uint16_t readTemp(void)
{
  uint16_t temp_raw = 0;
  char data[2] = {TEMP_REG, 0};

  //the first I2C command sets the MAX31875 to point to the temperature register
  Wire.beginTransmission(TEMP_ADDRESS);
  Wire.write(data[0]);
  Wire.write(data[1]);
  Wire.endTransmission();

  //wait for temperature readings to happen
  delay(100);

  //request temperature reading from sensor
  Wire.requestFrom(TEMP_ADDRESS, 2);

  //receive temperature reading from sensor
  if (2 <= Wire.available())
  {
  // Check if two bytes were received
  temp_raw = Wire.read();  // receive high byte (overwrites previous reading)
  temp_raw = temp_raw << 8;  // shift high byte to be high 8 bits
  temp_raw |= Wire.read(); // receive low byte as lower 8 bits
  //Serial.println(temp_raw);  // print the reading
  }

  //returns the 16-bit raw temperature reading
  return temp_raw;
}

void setRGBColor(int redValue, int greenValue, int blueValue)
{
  #ifdef COMMON_ANODE
  redValue = 255 - redValue;
  greenValue = 255 - greenValue;
  blueValue = 255 - blueValue;
  #endif

  analogWrite(Red_Pin, redValue);
  analogWrite(Green_Pin, greenValue);
  analogWrite(Blue_Pin, blueValue);
}

void batteryLevelMeasure(){
  long sensorValue = analogRead(voltSensePin);
  delay(50);
  sensorValue = 0;

  for (int i=0; i<10; i++)
  {
  sensorValue = sensorValue + analogRead(voltSensePin);
  delay(50);
  }
  sensorValue = sensorValue/10;
  //Serial.print("Raw Analog Value at A0:- ");
  //Serial.println(sensorValue);

  float batVolt = sensorValue * (3.3 /1024);
  batVolt = batVolt * 1000;  //in milli volts
  //Serial.print("Battery Voltage at A0:- ");
  //Serial.println(batVolt);
  batVolt = batVolt * dividerRatio;

  uint16_t batRead = batVolt;
  Serial.print("Battery Voltage:- ");
  Serial.println(batVolt);

  if (batRead <= minVolt)
  {
  batLevel = 0;
  }
  else if (batRead >= maxVolt) {
  batLevel = 100;
  }
  else { 
  long data = batRead - minVolt;
 
  data = data * 100;
 
  data = data / (maxVolt-minVolt) ;
 
  batLevel = data;
  }

  Serial.print("BL,");
  Serial.println(batLevel);
}


void setup() {
  pinMode(Red_Pin, OUTPUT);
  pinMode(Green_Pin, OUTPUT);
  pinMode(Blue_Pin, OUTPUT);

  Wire.begin();  //For ESP8266 Default I2C pins:- GPIO pins 4(SDA) and 5(SCL).

  Serial.begin(SERIAL_BAUD);

  Serial.println("");
  Serial.println("Smart Coaster");

  //write the configuration register
  configTemp();

  delay(100);

  uint16_t temperature_raw = readTemp();
  if(temperature_raw != 0)
  {
  room_temp = temperature_raw/256.0;
  Serial.print("Room Temperature in Celsius:- ");
  Serial.println(room_temp);
  }
  Serial.print("Between ");
  Serial.print(hot_min);
  Serial.print(" degree celsius & ");
  Serial.print(hot_max);
  Serial.print(" degree celsius ");
  Serial.print("temperature is the ");
  Serial.println("Optimum Hot Temperature to Drink");

  Serial.print("Greater than ");
  Serial.print(hot_max);
  Serial.print(" degree celsius ");
  Serial.print("temperature is ");
  Serial.println("Too Hot Temperature to Drink");

  Serial.print("Less than ");
  Serial.print(hot_min);
  Serial.print(" degree celsius ");
  Serial.print("temperature is ");
  Serial.println("Luke warm to Drink will not taste that great");

  setRGBColor(255, 0, 0); // Red Color
  delay(100);
  setRGBColor(0, 255, 0); // Green Color
  delay(100);
  setRGBColor(0, 0, 255); // Blue Color
  delay(100);

  setRGBColor(255, 255, 255); // White Color
  delay(500);

  batteryLevelMeasure();

  if (batLevel < 20)
  {
  setRGBColor(255, 255, 0);  // yellow (turn red and green on)
  delay(100);
  setRGBColor(0, 255, 255);  // Cyan (turn green and blue on)
  delay(100);
  setRGBColor(255, 0, 255);  // Purple (turn red and blue on)
  delay(100); 
  }

  setRGBColor(0, 0, 0);  // turn off the rgb led
  delay(500);
}

void setRGBHot(float temp)
{
  if (temp <= hot_max && temp >= hot_min)
  {
  setRGBColor(0, 255, 0); //Green Colour - Optimum Hot Temperature to Drink
  Serial.println("Optimum Hot Temperature to Drink");
  }
  else if (temp > hot_max)
  {
  setRGBColor(255, 0, 0); // Red Color - Too Hot Temperature to Drink
  Serial.println("Too Hot Temperature to Drink");
  }
  else if (temp < hot_min)
  {
  setRGBColor(0, 0, 255); //Blue Colour - Luke warm to Drink will not taste great
  Serial.println("Luke warm to Drink will not taste great");
  }
}

void setRGBCold(float temp)
{
  if (temp <= cold_max && temp >= cold_min)
  {
  setRGBColor(0, 255, 0); //Green Colour - Optimum Cold Temperature to Drink
  Serial.println("Optimum Cold Temperature to Drink");
  }
  else if (temp > cold_max)
  {
  setRGBColor(255, 0, 0); // Red Color - Too Hot Temperature to Drink
  Serial.println("Cold Drink will not taste great");
  }
  else if (temp < cold_min)
  {
  setRGBColor(0, 0, 255); //Blue Colour - Luke warm to Drink will not taste great
  Serial.println("Too Cold Temperature to Drink");
  }
}

long previousMillis = 0;  // will store last time temperature was checked and RGB LED was updated
long intervalTime = 5000;  // interval at which temperature was checked (milliseconds)

void loop()
{
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis >= intervalTime)
  {
  Serial.println("");
  //Serial.print("Temperature in raw:- ");
  uint16_t temperature_raw = readTemp();
  //Serial.println(temperature_raw);
 
  if(temperature_raw != 0)
  {
  temperature_C = temperature_raw/256.0;
  Serial.print("Temperature in Celsius:- ");
  Serial.println(temperature_C);

  Serial.print("Hot Beverage:- ");
  setRGBHot(temperature_C);
  }
  else {
  Serial.println("Temp Read Error ");
  }
 
  // save the last time you checked the temperture and updated the RGB LED
  previousMillis = currentMillis; 
 
  }
}


[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.

Blog entry information

Author
Alpha007
Views
1,553
Last update

More entries in General

Share this entry

Top