Off-The-Shelf Hacker: Picking the Right Data Bus for the Job

Over the past weekend, I moved a bit closer to adding instrumentation to the PancakeBot, the customized pancake printer The New Stack occasionally takes out on the road for our pancake podcast series. As regular readers may recall, I covered how to hook up a thermocouple and it’s associated amplifier to an Arduino Duemilanove to read temperatures and push the resulting data over to a Linux notebook.
This week, we’ll look at integrating the MLX90614 infrared contactless temperature sensor into the mix.
There are actually two versions of the MLX90614, a 5-volt and a 3.3-volt model. When “packaged” sensors started showing up on the DIY/Maker community a few years back, they usually worked with 5-volts, both at logic levels and for the power. Arduinos and other microcontrollers universally used 5-volts, as well. Over time, much of the industry has transitioned to 3.3-volt and sometimes even 1.8-volt, as the part’s size and power requirements decreased. Also, chips like the ESP8266 use 3.3-volt for logic and power, so it’s standard just to buy 3.3-volt sensors nowadays.
With the infrared sensor on the bench, let’s see how we can put it to use, alongside the thermocouple and MAX 31856 universal amplifier combo.
My plan is that the thermocouple will attach to the hotplate heating element and directly monitor its temperature, while the PancakeBot goes through it’s culinary routine. At the same time, the infra-red sensor will monitor the surface temperature of the hotplate. We can then try to correlate the temperature data with the physical pancake printing as it progresses.
Logging and analyzing data is an important part of the physical computing stack. We’ll look at feeding “real time” data back into the pancake printing process. This is also a great opportunity to investigate practical use of the thermocouple-amplifier and I2C (infrared sensor) buses in the same project.`
Using SPI and the I2C Interfaces Together
The MAX31856 thermocouple amplifier module outputs data over a Serial Peripheral Interface (SPI) bus. In a previous column, we learned that the SPI interface is for short-distance, high-speed data exchange usually between a microcontroller and peripheral device. A shortcoming of the protocol is that you need an additional control line connected to a GPIO pin, for each device you add to the bus. You quickly run out of GPIO pins, if you hook up very many devices.
The good thing is SPIs are all high speed. Little color TFT LCDs displays use the SPI bus. The bus handles a lot of data very quickly. In our case we could hook up a TFT LCD to the Arduino, in addition to the thermocouple/amplifier combination, to display temperatures. A portable device like that could be useful and perhaps a candidate for a future story. For now, we’ll just stick to using the one thermo/amp setup on this project.
In contrast, the MLX 90614 infra-red temperature sensor sends data over the I2C bus. This bus handles moderate data bandwidth, only uses two wires (plus power and ground) and will accommodate over 100 devices, in parallel. Today we’ll just examine using one. Feel free to experiment with using several I2C modules, in your projects.
Connecting the SPI and I2C Buses to the Arduino
Combining SPI and I2C buses in the same project is common practice. Take a look at the Fritzing schematic for the project (I substituted the UNO Fritzing icon for the Duemilanove part, which has seemingly vanished from the web, never to be seen again. That’s O.K. the UNO has an identical pin-out, which works for illustration purposes.):

MAX31856, MLX90614 And Arduino Fritzing Wiring Diagram
The wiring is straightforward. The MAX 32856 thermo-amplifier board requires four GPIO pins plus power and ground. The MLX 90614 board only requires the two GPIO pins, along with power and ground.
The two resistors act as pull-ups for the data lines. You may recall that we always want to have a known logic level on a data pin, to ensure predictable output. Pulling the line up toward the source voltage gives a default “high” or “1” value. Devices like the MLX 90614 pull the device “low” or to a “0” value during operation and make it possible to detect changes on the data line, using program code. Without a pull-up, the pin just floats between high (logic 1) and low (logic 0), generating random goofy output.
I powered the Duemilanove Arduino through the USB cable.
SPI and I2C Code
The code to read the SPI thermo-amp and I2C infra-red sensor values is straightforward, as well.
First, libraries are pull in to handle the specific operational details of the SPI and I2C devices.
Next, the serial communication is started and the devices are initialized. The loop() section reads each device, every half-second and prints a comma-delimited data string, to the serial line. Each line of data goes out to the serial port, on my Linux notebook, over the USB cable.
I cobbled the code together from examples, gleaned from the Arduino IDE, once I downloaded the MAX 31856 and MLX 90614 libraries. I like to read temperatures in Fahrenheit, so the simple C° to F° conversion function is applied to the thermocouple reading, for that purpose. The MLX infra-red code outputs F° by default.
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 |
#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); void setup() { Serial.begin(9600); 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() { // 3 number data output with "," separator // 1st number = thermocouple temp measured by MAX amp board // 2nd number = ambient temp measured by MLX IR sensor // 3rd number = object temp measured by MLX IR sensor // 1st 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"); } // 2nd number - ambient Serial.print(mlx.readAmbientTempF()); Serial.print(","); // 3rd number - object Serial.print(mlx.readObjectTempF()); Serial.println(); delay(500); } double Celcius2Fahrenheit(double celsius) { return 1.8 * celsius + 32; } |
Data collection on the Linux notebook was accomplished with the usual “cat on the command line” technique. You might also take a look at minicom, a commonly used Linux serial monitor application. Here’s what the output looked like.

Comma-delimited temperature data output screenshot.
Next Steps
We’re getting closer to instrumenting and hacking the PancakeBot.
I’m thinking about wiring up the thermo-amp and infrared sensor to an Arduino Pro or Pro Mini, in place of the larger Duemilanove, for version 2.0 of this project.
Or, we could use an ESP8266-07 module, with integrated WiFi. Going this route would also make it easy to use MQTT as the data transfer protocol, since we’ve covered that topic in past stories, as well.
What do you think? Exciting, right?