Introduction
Fan heaters work by forcing ambient air through heating elements. Manufacturers usually warn about not putting anything too close to the front of heaters as it could burn or catch fire, but what is the temperature of air at different distances from the heater? This question is what I tried to answer by measuring the temperature at different distances from a fan heater using Python's NI-DAQmx library.
Setup
To make the measurements I used 2 thermocouples, one to measure the ambient temperature and another to measure the air temperature at the exhaust of the heater at different distances from it.
Distances where all measured at the floor level, but the probe was set at the height where the air was the hottest. Since the hot air flows in a roughly parabolic way, it was difficult to find hottest spot by hand. But my plan was not to be accurate, but to to get a rough approximation of how the temperature dropped as distance from the heater increased, and also at the same time show how easy it is to use the cDAQ from within Python.
Code
NI-DAQmx is not only available in LabVIEW, but also in C, and in Python. For this project I used Python to record the temperature at distances of 10, 20, 30, 40, and 50 cm away from the heater. At every distance I gave myself 90 s to record the temperature and manually move the thermocouple up and down until I could find the hottest spot.
Let’s look at the code:
import time
import numpy
import nidaqmx
import nidaqmx.constants as constants
# Settings
filename = '../Data/Heater.npy'
dx = 10
frequency = 4
repetitions = 5
iterations = 90 * frequency
# Code
T = numpy.zeros((2, iterations, repetitions))
with nidaqmx.Task() as task:
task.ai_channels.add_ai_thrmcpl_chan('cDAQ1Mod1/ai0', thermocouple_type = constants.ThermocoupleType.K, cjc_source = constants.CJCSource.BUILT_IN)
task.ai_channels.add_ai_thrmcpl_chan('cDAQ1Mod1/ai1', thermocouple_type = constants.ThermocoupleType.K, cjc_source = constants.CJCSource.BUILT_IN)
task.timing.cfg_samp_clk_timing(4, active_edge = constants.Edge.RISING, sample_mode = constants.AcquisitionType.CONTINUOUS)
for i in range(repetitions - 1, -1, -1):
print('Press ENTER to measure at {:.0f} cm'.format(dx * (i + 1)))
input()
task.start()
t0 = time.time()
for j in range(iterations):
data = task.read()
T[0, j, i] = data[0]
T[1, j, i] = data[1]
print("[{:.1f} s] T0 = {:.1f} °C, T1 = {:.1f} °C".format(time.time() - t0, round(data[0], 1), round(data[1], 1)))
print()
task.stop()
numpy.save(filename, T)
The first things one notices are the similarities between Python's NI-DAQmx code and LabVIEW's NI-DAQmx nodes. Let's review the NI-DAQmx code.
First a task is created. A task is a collection of channels with timing, triggering, and other properties.
with nidaqmx.Task() as task:
Next, two thermocouple channels are added to the task. Here I specified the name of the channel, the thermocouple type and the cold junction compensation setting.
task.ai_channels.add_ai_thrmcpl_chan('cDAQ1Mod1/ai0', thermocouple_type = constants.ThermocoupleType.K, cjc_source = constants.CJCSource.BUILT_IN)
task.ai_channels.add_ai_thrmcpl_chan('cDAQ1Mod1/ai1', thermocouple_type = constants.ThermocoupleType.K, cjc_source = constants.CJCSource.BUILT_IN)
Then the sampling setting are configured to sample at 4 Hz, at the rising edge of the clock signal and to sample continuously.
task.timing.cfg_samp_clk_timing(4, active_edge = constants.Edge.RISING, sample_mode = constants.AcquisitionType.CONTINUOUS)
At this point everything is set to begin sampling. This is done starting the task.
task.start()
At this moment data can be read, and the function returns a list with 2 values, the samples captured from each of the previously added channels.
data = task.read()
When no more samples need be captured the task must be stopped.
task.stop()
As it can be seen, the library is easy to use and requires few lines of code to configure the hardware and begin capturing data.
Results
As I had to manually find the height where I would get the highest temperature reading, and also considering that the temperature reading does not change instantly, and that the hot air flow is likely turbulent, finding the hottest spot was very hard. For the same reason the results might not be very reliable, but still good enough as a rough approximation.
The first thing that I did was to plot the complete 5 time series to see how much temperature varied as I probed different heights.
It definitely does not look great (and it was not even my first attempt). I took the maximum value at each distance and made a new plot.
It's hard to know how close I was to the true values, but the results may still be minimally useful to roughly estimate how to position the heater so that it does not damage or burn anything in the room.
Conclusions
I initially though that finding the hottest spot in front of the heater would be a relatively simple, but it ended up being very difficult. The huge temperature oscillations while looking for the hottest spot, as seen in the plot, show how much trouble I had find the spot.
More interesting than the experiment itself is how the NI-DAQmx library can be used to make measurements. The shown Python library is a wrapper of the NI-DAQmx C library. There are other Python NI-DAQmx wrapper, but the one shown here is the one supported by NI. The library is as simple to use as LabVIEW's library. This is not very surprising considering that both rely on the NI-DAQmx driver, and for the same reason they are more or less equivalent. For the same reason, the capabilities, features or difficulty of using the data acquisition library is the one factor that will not be relevant when deciding what programming environment to use when building a data acquisition system.