Off-The-Shelf Hacker: PancakeBot Hot Plate Temperature Mapping

In a few past columns, I’ve been investigating the idea of measuring the temperatures of the PancakeBot, a device that prints pancakes in patterns the user designs. I’ve wondered if there is a way to relate real-time temperatures of the element and the hot plate surface, to the way the PancakeBot goes about printing a pancake. As with all prototyping and a lot of analysis, it takes time to figure out what you need to do, then actually put it into action and get some results.
This week, we’ll look at placing the temperature sensors, capturing some preliminary baseline data, how we might generate basic metrics for analysis and where we might go next with our PancakeBot hacking process. Getting through this initial testing setup, was quite a bit of work, so we’ll sync the temperature data with some real-world pancake prints, in a future installment.
Mounting the Thermocouple
The first step to capturing temperature data was to find a place to mount the thermocouple. I wanted to place it against the heating element, to ensure a fast response to changing temperatures. I settled on bending the tip of the thermocouple, slightly and wedging it under a 1.5-inch long piece of quarter inch wide brass flat stock. Brass conducts heat well and using a small bracket wasn’t going to slow down the response very much. The little bracket was attached under one of the hotplate foot mounting screws. I then temporarily looped the long thermocouple lead around a hotplate foot, to keep it out of the way. The wire was then routed out to the amplifier board. Here’s a closeup of the thermocouple and the bracket:

Thermocouple mounted to heating element on the bottom of the PancakeBot
During one of several trial temperature runs, I noticed that the thermocouple readings weren’t changing, even though the IR sensor registered an increasing surface temperature. Sure enough, upon inspection, the thermocouple tip had slipped out from under the brass strip. A quick tip re-orientation under the strip again gave me changing heating element numbers.
The wedged tip, brass strip mounting method is OK for proof of principle. It will certainly have to be refined for long-term temperature monitoring since the vibration of the PancakeBot arm and servos definitely will work the thermo tip loose again.
Reading the Hotplate Surface with the IR Thermometer
Reading the surface temperature with the infrared thermometer was straightforward. I placed the Arduino, breadboard and thermocouple amplifier board next to the PancakeBot, on a little plastic box. The infrared thermometer was then positioned about a quarter inch above the hot plate surface.
Note that the sensor reading drops off as the distance from the sensor to the surface increases. The reading may change by 10 or 15 degrees F. at one inch, as opposed to a quarter inch. It’s probably close enough this time, although the behavior may cause issues, in your projects, depending on your requirements.
The PancakeBot arm wasn’t in place for this phase of testing. Clearly, the infrared sensor will need to be re-positioned for actual printing, otherwise, it will cause interference when the arm moves up and back. For upcoming pancake printing runs, I’ll likely move the infrared sensor to a corner of the hot plate.
Would it make sense to mount the IR thermometer on the arm to measure the surface temperature, under the batter dispenser, as a pancake prints? What insights might we draw from that data? How hard would it be to put the sensor on the arm? What benefits would we get from this effort? All thought provoking questions, as we prototype our crazy hacking schemes.
Syncing Events to the Data Stream
Down the line, I’d like to try to sync the temperature data with the various phases of the actual pancake printing process. What effect does instantaneous temperature, both at the element and on the surface have to a line, curve or area fill, as you print the Eiffel Tower or the face of a celebrity?
My plan is to coordinate the temperature data and PancakeBot moves using a time index.
To that end, I added a time index to the data stream coming from the Arduino. It’s nothing more than a counter, in the code, that increments upward, once per line of data. One line per second, seemed like a reasonable starting point, for the data collection interval, so that’s what I used.
Readers probably are aware that time delays, in your Arduino code, don’t necessarily reflect the actual elapsed time through the main program loop. Sending text data out over the serial line, complicated decision making and trips through functions, all contribute to an actual “loop cycle” duration. You have to account for these things, to get reasonably accurate time counts.
I originally wanted to get a data sample every half second (500 milliseconds).
Using a stopwatch I found that 500-millisecond delay setting gave somewhere around 650 milliseconds, between each line of data coming out of the USB port.
After some experimentation and bumping the counter against actual stopwatch seconds (using an app on my Galaxy 5S Active super-phone), a 750-millisecond delay gave me a pretty accurate one second loop time.
Here’s the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
#include <SPI.h> #include <Adafruit_MAX31856.h> #include <Wire.h> #include <Adafruit_MLX90614.h> Adafruit_MLX90614 mlx = Adafruit_MLX90614(); // use hardware SPI, just pass in the CS pin Adafruit_MAX31856 max = Adafruit_MAX31856(10); int tcount = 0; void setup() { Serial.begin(115200); max.begin(); max.setThermocoupleType(MAX31856_TCTYPE_K); switch ( max.getThermocoupleType() ) { case MAX31856_TCTYPE_B: break; case MAX31856_TCTYPE_E: break; case MAX31856_TCTYPE_J: break; case MAX31856_TCTYPE_K: break; case MAX31856_TCTYPE_N: break; case MAX31856_TCTYPE_R: break; case MAX31856_TCTYPE_S: break; case MAX31856_TCTYPE_T: break; case MAX31856_VMODE_G8: break; case MAX31856_VMODE_G32: break; default: break; } mlx.begin(); } void loop() { // 4 number data output with "," seperator // 1st number = time counter - use with sample duration // 2nd number = thermocouple temp measured by MAX amp board // 3rd number = ambient temp measured by MLX IR sensor // 4th number = object temp measured by MLX IR sensor // 1st number - time counter Serial.print(tcount); Serial.print(","); tcount++; // 2nd number - thermocouple Serial.print(Celcius2Fahrenheit(max.readThermocoupleTemperature())); Serial.print(","); uint8_t fault = max.readFault(); if (fault) { if (fault & MAX31856_FAULT_CJRANGE) Serial.println("Cold Junction Range Fault"); if (fault & MAX31856_FAULT_TCRANGE) Serial.println("Thermocouple Range Fault"); if (fault & MAX31856_FAULT_CJHIGH) Serial.println("Cold Junction High Fault"); if (fault & MAX31856_FAULT_CJLOW) Serial.println("Cold Junction Low Fault"); if (fault & MAX31856_FAULT_TCHIGH) Serial.println("Thermocouple High Fault"); if (fault & MAX31856_FAULT_TCLOW) Serial.println("Thermocouple Low Fault"); if (fault & MAX31856_FAULT_OVUV) Serial.println("Over/Under Voltage Fault"); if (fault & MAX31856_FAULT_OPEN) Serial.println("Thermocouple Open Fault"); } // 3rd number - ambient Serial.print(mlx.readAmbientTempF()); Serial.print(","); // 4th number - object Serial.print(mlx.readObjectTempF()); Serial.println(); delay(750); //sample duration - adjusted - gives 1 second per sample with this code } double Celcius2Fahrenheit(double celsius) { return 1.8 * celsius + 32; } |
We have to also remember that the heating element and cooking surface temperature increase gradually, as you change the setting on the hot plate knob. I arbitrarily picked four minutes to allow the temperatures to stabilize, as I bumped the setting from off, to warm, to medium and finally high. That gave a test duration of 16 minutes, which corresponds to 960 seconds, in our data file. Running the stopwatch, as I captured 16 minutes of temperature changes ensured accuracy on the time. The stopwatch versus the captured time index only varied by one second, at the end.
Let’s look at capturing and plotting the data next.
Recording and Plotting the Real-Time Data
At some point, I may write a cute little processing program to read in the PancakeBot temperature data and spit out a pretty chart. My legendary quick turnaround methodology dictates that I just grab the data from Arduino, through the serial port on the Linux notebook and shove it into a LibreOffice spreadsheet. A couple of clicks later and there’s a pretty chart. The technique is easily adapted to large or small datasets and takes only a few minutes to set up. I keep harping back to Linux because I strongly believe it is the future of nano-computing and follows the Unix “many small programs linked together to do big jobs” philosophy.
Of course, as we gradually move toward using a Raspberry Pi or CHIP computer for PancakeBot data collection and control, there’s a chance that the data handling may move over to an MQTT broker/client messaging model. We’ll see.
When capturing data from the Arduino to the Linux notebook, it’s important to set communication parameters of the USB/serial port correctly. For example, I switched the speed from 9600 bits/second (bps) to 115200 bps, in the Arduino code. After that change, the cat command simply returned without showing any data. Turns out that you’ll see nothing if the speeds don’t match between the Arduino (sending machine) and the Linux USB port (receiving machine). I used the stty command to fix the problem:
1 |
rob% stty -icrnl -F /dev/ttyUSB0 115200 |
The -icrnl switch converts all carriage returns to newlines. Otherwise, you’ll get a blank line between every line of data and then have to use a filter step to get rid of the empty line, before importing the data into your plotting application. The -F option specifies the USB port and the 115200, is the desired port speed, which matches what comes from the Arduino.
It’s then easy to cat the data, using the Linux command line.
1 |
rob% cat /dev/ttyUSB0 > bottemp.txt |
I instinctively use .txt for text files. It’s a simple matter to just copy the file over to a .csv extension for importing into LibreOffice Calc. I also retain a copy, just in case.
1 |
rob% mv bottemp.txt bottemp.csv |
Pull the file into LibreOffice with File → Open and then travel to the directory containing your data file. Once there, open the file type drop-down menu (toward the bottom of the window) and select the ‘Text Csv’ file format. Highlight the bottemp.csv file from the list and then hit the Open button.
On the popup Import window, check the ‘comma’ delimiter box and hit Open. I like to select line graphs for this type of chart, but you can visualize the data in whatever form suits you.
Here’s a screenshot of the data and the chart. I didn’t change the labels. Blue is the time index, orange is the thermocouple data, green is the infra-red sensor reading and yellow is the thermocouple cold-joint temperature.

Captured PancakeBot data and graphic
Notice how the infrared (hot plate surface) temperature lags the thermocouple (heating element) temperature. I adjusted the hot plate temperature knob roughly every four minutes and 20 seconds for the initial 16-minute baseline. That corresponds with off, warm, medium and high settings on the knob.
What’s Next?
Now that we have a general methodology for capturing, syncing and displaying our real-time PancakeBot temperature readings, the next step is to set everything up and run through printing a few pancakes of various designs and see what kind of data comes out.
Is there a way to coordinate the temperature readings with a particular print’s G-Code? I don’t know. That’s an area we can explore. Wouldn’t it be interesting to try to optimize the temperature settings on the hotplate to give the best resolution on a printed pancake? We’ll take a look at that kind of thing as well.
What other revelations might we find by applying “big data” analysis techniques to a real-World physical computing situation?
Applied metrics are certainly a skill-set for Off-The-Shelf Hackers of the near future.
Previous “Hack the Pancake Stack” columns:
Off-The-Shelf Hacker: Picking the Right Data Bus for the Job
Hack the Pancake Stack: What’s Inside the PancakeBot?
Off-The-Shelf Hacker: Avoid Burning the Christmas Turkey with Thermocouples
Hack the Pancake Stack: Running PancakeBot under Xubuntu Linux