This is an update to WIFI Meat Temperature Probe
The original temp probe worked ok but was not perfect, you had to connect to the web page hosted on the Meat Probe WEMOS ESP32 itself. So it was very limited to what you can do with it.
Due to having some time available while under Covid19 lock down, I changed the software.
The Meat Probe WEMOS ESP32 now works very differently due to the software changes.
1. ESP32 reads the K type thermocouple via MAX31855 as before.
2. Temperature reading is now stored in a mySQL database ever minute
3. A webpage pulls this temperature data from mySQL server and uses Google Charts to display the historical information in graph form. With the addition of the current value in numerical form.
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
#include <WiFi.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_MAX31855.h>
#define MAXCS 16
#define MAXCLK 25
Adafruit_MAX31855 thermocouple(MAXCLK, MAXCS, MAXDO);
int tempC=0; // Intialize a variable for temperature in celcius
int tempF=0; // Intialize a variable for temperature in farenhiet
// Create the temperature object, defining the pins used for communication
//MAX31855 temp(MISO, CS, SCK);
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
/*
CREATE TABLE test_arduino.meat (
num integer primary key auto_increment,
temp integer,
recorded timestamp
);
*/
// MySQL server listening address changed to any and worked as expected after changing user to insert user
const char* ssid = "ssid";
const char* password = "password";
char user[] = "username"; // MySQL user login username
char passwordSQL[] = "password"; // MySQL user login password
char query[128];
IPAddress server_addr(192,168,0,127); // IP of the MySQL server here
WiFiServer server(80);
void setup() {
Serial.begin(115200);
// Start I2C Communication SDA = 5 and SCL = 4 on Wemos Lolin32 ESP32 with built-in SSD1306 OLED
Wire.begin(5, 4);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C, false, false)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(2000); // Pause for 2 seconds
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Clear the buffer.
display.clearDisplay();
connectToNetwork();
}
void loop() {
delay(9000); // need to change to non blocking delay
delay(9000);
Serial.print("Junction=");
Serial.println(thermocouple.readInternal()); // get junction temp from MAX318555 i.e. ambient
Serial.print("Thermocouple=");
Serial.println(thermocouple.readCelsius()); // get temp from k-type thermocouple probe attached to MAX318555
// tempF =(thermocouple.readFarenheit());
tempC =(thermocouple.readCelsius());
// changed so we save result after reading temp
mySqlLoop();
display_temp();
}
void connectToNetwork() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
wifi_connecting();
Serial.println("Establishing connection to WiFi..");
}
wifi_connected();
Serial.println("Connected to network");
}
void mySqlLoop(){
char INSERT_SQL[] = "INSERT INTO test_arduino.meat (temp) VALUES (%d)";
WiFiClient client;
MySQL_Connection conn((Client *)&client);
if (conn.connect(server_addr, 3306, user, passwordSQL)) {
Serial.println("Database connected.");
data_connected();
}
else{
Serial.println("Connection failed.");
Serial.println("Recording data.");
data_failed();
}
// Initiate the query class instance
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
sprintf(query, INSERT_SQL, tempC);
// Execute the query
cur_mem->execute(query);
// Note: since there are no results, we do not need to read any data
// Deleting the cursor also frees up memory used
delete cur_mem;
Serial.println("closing connection\n");
data_updated();
//client.stop();
}
void display_temp(void) {
//display_setup();
display.clearDisplay();
display.setTextSize(3); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 8); // Start at top-left corner
display.cp437(true); // Use full 256 char 'Code Page 437' font
display.print(tempC);
display.print(" oC");
display.display();
delay(2000);
display.clearDisplay();
}
void data_connected(void) {
display_setup();
display.println(F(" DATA"));
display.println(F(" CONNECTED"));
display.display();
delay(2000);
display.clearDisplay();
}
void data_failed(void) {
display_setup();
display.println(F(" DATA"));
display.println(F(" FAILED "));
display.display();
delay(2000);
display.clearDisplay();
}
void data_updated(void) {
display_setup();
// display.write(' ');
display.println(F(" DATA"));
display.println(F(" UPDATED "));
display.display();
delay(2000);
display.clearDisplay();
delay(2000);
}
void wifi_connected(void) {
display_setup();
// display.write(' ');
display.println(F(" WIFI"));
display.println(F(" CONNECTED"));
display.display();
delay(2000);
display.clearDisplay();
}
void wifi_connecting(void) {
display_setup();
// display.write(' ');
display.println(F(" WIFI"));
display.println(F("CONNECTING"));
display.display();
delay(2000);
display.clearDisplay();
}
void display_setup(void) {
display.clearDisplay();
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.cp437(true); // Use full 256 char 'Code Page 437' font
}
******* CURRENT MEAT.PHP CODE BELOW ********
$con = mysqli_connect('ip','user_name','password','mySQL_Table');
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Meat Probe</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['temp','recorded'],
<?php
$query = "SELECT * FROM `meat` WHERE DATE(recorded) = DATE(NOW())";
$exec = mysqli_query($con,$query);
while($row = mysqli_fetch_array($exec)){
echo "['".$row['recorded']."',".$row['temp']."],";
}
?>
]);
var options = {
title: 'Meat Temp',
curveType: 'function', // add curve to chart to smooth out transitions
pieHole: 0.5,
pieSliceTextStyle: {
color: 'black',
},
legend: 'none'
};
var chart = new google.visualization.LineChart(document.getElementById("columnchart12"));
chart.draw(data,options); //try material line charts as newer and better apparently
}
</script>
</head>
<body>
<div class="alert alert-primary" role="alert">
<?php
$sql ="SELECT * FROM meat
WHERE num IN (SELECT num FROM meat WHERE recorded = (SELECT MAX(recorded) FROM meat))
ORDER BY num DESC
LIMIT 1";
$result = $con->query($sql);
if ($result->num_rows > 0) {
// output data of each row - doh only one row
while($row = $result->fetch_assoc()) {
echo " Probe Temp: " . $row["temp"]. "oC<br>";
}
} else {
echo "0 results";
}
?>
</div>
<div class="container-fluid">
<div id="columnchart12" style="width: 100%; height: 300px;"></div>
</div>
<div class="alert alert-primary" role="alert">
<h2><b>Cooking Temperatures</b></h2>
<p></p><p></p>
<table>
<tr>
<th></th>
<td><b> 74oC </b></td>
<td> Chicken, Turkey & Duck </td><td><b> 140oC </b></td><td> Gas Mark 1 </td>
</tr>
<tr>
<td>Rare</td>
<td><b> 52oC </b></td>
<td> Beef, Lamb & Veal </td><td><b> 150oC </b></td><td> Gas Mark 2 </td>
</tr>
<tr>
<td>Medium</td>
<td><b> 60oC </b></td>
<td> Beef, Lamb & Veal </td><td><b> 170oC </b></td><td> Gas Mark 3</td>
</tr>
<tr>
<td>Well Done </td>
<td><b> 71oC </b></td>
<td> Beef, Lamb & Veal </td><td><b> 180oC </b></td><td> Gas Mark 4</td>
</tr>
<tr>
<td>Medium</td>
<td><b> 63oC </b></td>
<td> Pork Roasts, Steaks & Chops </td><td><b> 190oC </b></td><td> Gas Mark 5</td>
</tr>
<tr>
<td>Well Done </td>
<td><b> 71oC </b></td>
<td> Pork Roasts, Steaks & Chops </td> <td><b> 200oC </b></td><td> Gas Mark 6 </td>
</tr>
<tr>
<td></td>
<td><b> 60oC </b></td>
<td> Fish </td> <td><b> 220oC </b></td><td> Gas Mark 7</td>
</tr>
<tr>
<td></td>
<td> </td>
<td> </td><td><b> 230oC </b></td>
<td> Gas Mark 8</td>
</tr>
<tr>
<td></td>
<td> </td>
<td> </td><td><b> 240oC </b></td>
<td> Gas Mark 9</td>
</tr>
</table>
</div>
</body>
</html>
The grafana graph below is from a cook of a brisket in the wood fired oven.
Comments
Post a Comment