Graph Sensor Data with Python and Matplotlib
Plot Sensor Data
In the Python Programming Tutorial: Getting Started with the Raspberry Pi, the final example shows how to sample temperature data from the TMP102 once per second over 10 seconds and then save that information to a comma separated value (csv) file. To start plotting sensor data, let's modify that example to collect data over 10 seconds and then plot it (instead of saving it to a file).
TMP102 Module
In order to simplify I2C reading and writing to the TMP102, we will create our own TMP102 Python module that we can load into each of our programs. Open a new file named tmp102.py:
nano tmp102.py
Copy in the following Python code:
import smbus # Module variables i2c_ch = 1 bus = None # TMP102 address on the I2C bus i2c_address = 0x48 # Register addresses reg_temp = 0x00 reg_config = 0x01 # Calculate the 2's complement of a number def twos_comp(val, bits): if (val & (1 << (bits - 1))) != 0: val = val - (1 << bits) return val # Read temperature registers and calculate Celsius def read_temp(): global bus # Read temperature registers val = bus.read_i2c_block_data(i2c_address, reg_temp, 2) temp_c = (val[0] << 4) | (val[1] >> 4) # Convert to 2s complement (temperatures can be negative) temp_c = twos_comp(temp_c, 12) # Convert registers value to temperature (C) temp_c = temp_c * 0.0625 return temp_c # Initialize communications with the TMP102 def init(): global bus # Initialize I2C (SMBus) bus = smbus.SMBus(i2c_ch) # Read the CONFIG register (2 bytes) val = bus.read_i2c_block_data(i2c_address, reg_config, 2) # Set to 4 Hz sampling (CR1, CR0 = 0b10) val[1] = val[1] & 0b00111111 val[1] = val[1] | (0b10 << 6) # Write 4 Hz sampling back to CONFIG bus.write_i2c_block_data(i2c_address, reg_config, val) # Read CONFIG to verify that we changed it val = bus.read_i2c_block_data(i2c_address, reg_config, 2)
Save the code with ctrl + x, press y, and press enter. This allows us to call the init()
and read_temp()
functions to easily get temperature (in Celsius) from the TMP102.
Temperature Logging and Graphing
In the same directory as the tmp102.py file, create a new file (using your favorite editor), and paste in the following code:
import time import datetime as dt import matplotlib.pyplot as plt import tmp102 # Create figure for plotting fig = plt.figure() ax = fig.add_subplot(1, 1, 1) xs = [] ys = [] # Initialize communication with TMP102 tmp102.init() # Sample temperature every second for 10 seconds for t in range(0, 10): # Read temperature (Celsius) from TMP102 temp_c = round(tmp102.read_temp(), 2) # Add x and y to lists xs.append(dt.datetime.now().strftime('%H:%M:%S.%f')) ys.append(temp_c) # Wait 1 second before sampling temperature again time.sleep(1) # Draw plot ax.plot(xs, ys) # Format plot plt.xticks(rotation=45, ha='right') plt.subplots_adjust(bottom=0.30) plt.title('TMP102 Temperature over Time') plt.ylabel('Temperature (deg C)') # Draw the graph plt.show()
Save (give it a name like tempgraph.py) and exit. Run the program with:
python tempgraph.py
Wait while the program collects data (about 10 seconds). Feel free to breathe on or fan near the temperature sensor to change the ambient temperature (gives you some interesting data to look at). Once the collection has finished, you should be presented with a plot showing how the temperature changed over time.
Code to Note
We create the graph in a very similar manner to the Formatting example in Introduction to Matplotlib. The only difference is that we build the xs
and ys
lists programmatically. Each second, the temperature is read from the TMP102 sensor and appended to the ys
list. The local time (of the Raspberry Pi) is captured with dt.datetime.now()
and appended to the xs
list.
The xs
and ys
lists are then used to create a plot with ax.plot(xs, ys)
. Note that we are explicitly creating a figure and a single set of axes (instead of calling the plt.plot()
shortcut). We will use the handle to the axes in the next sections when we look at animating the plot.