May 2007

Nothing too groundbreaking here, but I'm happy with the results. The idea was to build a data logging device to measure temperature with two probes as well as have the ability to read a few other additional analog sources. My objectives were:
What I came up with was this. The circuit itself should not cost more than 20$, but the addition of fancy cosmetics (enclosure, permanent power supply, etc) for the final version brought the cost up to 40$ flat.

The temperature sensors I used were LM335's whose voltage output is the temperature on the kelvin scale (°C + 273) multiplied by 0.01. In other words, 0°C is represented by 2.73V. This means the sensors have extrapolated upper and lower limits of 227°C (on a 5V supply) and absolute zero (-273°C), respectively. Since 8-bit data is 255 steps, each step read from a range of 0-5V is accurate to only ~0.02V, which, in the case of the LM335, is 2°C. For me, this was not acceptable.
So, I used a quad op-amp (LM2902) to subtract the voltage of each temperature sensor by 2.53V, and then multiply the result by 4. This narrows the temperature range from -273 - 227°C to -20 - 105°C in a span of 0-5V, yielding an overall accuracy of about 0.5°C. Below is the equation:
Vout = 4 (Vin - 2.53)

You can see that the output is very linear. Error is easily fixed through software calibration.
The A/D converter I used was the ADC0808 chip (the ADC0809 is identical, just slightly less accurate), which is an 8-bit parallel analog to digital converter (ADC) with a built-in multiplexer accommodating 8 individual inputs. In this circuit the ADC's clock is a 555 IC generating a clock at roughly 10kHz (it's the slowest rate the ADC0808 datasheet allows. I did this since I don't need a high speed, but if you need more speed you can adjust this as much as the datasheet and/or parallel port allows). The digital output is sent directly to the data lines of the parallel port. Traditionally the data pins on parallel ports were output-only, however modern PC's generally have bi-directional ports where data can be read from these pins if Control Bit 5 is set High (this is a better explanation).

Spectrum analyzer showing the signal from the circuit's ~10khz clock.

The board without the DB-25 connector or analog input lines yet soldered on.
First, the temperature sensor pins in the schematic are NOT in order of the pins on the LM335. Pin 1 is negative, 2 is Adj, and 3 is positive. Second, although I didn't, I would highly recommend replacing R11 with a 500Ω pot, since a precise 2.53V supply from IC4 is vital for accurate temperature sensing. R10 can, and probably should, be 240Ω, but this, of course, will affect the value of R11 slightly (should be around 245Ω). R13 and R19 should be between 2kΩ and 4kΩ, though preferably closer to 2kΩ than 4kΩ. Third, c3 is simply filtering out any AC left in the supply, so the value should really be just whatever you have on hand. The capacitors on the 555 timer can be adjusted for different frequencies according to the datasheet.

The 555 clock viewed on a 'scope.
IC1 is in a continuous loop, meaning as soon as it finishes converting it outputs the binary and starts over. This eliminates a need for interruption from the CPU. All that is required is an address value specifying which analog line to read, and this is sent over three of the parallel port's control pins.

The program I wrote is a small Visual Basic 6 app that displays each channel's value (green), voltage (yellow), and then the temperature (cyan). The app can log at a given rate to a .csv (comma-separated values) file, which can be read directly by Microsoft Excel. The first two channels (the temperature sensors) are saved in degrees Celcius while all other channels are saved in volts. The desired channel is selected by setting the appropriate control pins High or Low as shown below:
| Channel | Decimal Output to Control Line |
| 0 | 42 |
| 1 | 40 |
| 2 | 46 |
| 3 | 44 |
| 4 | 34 |
| 5 | 32 |
| 6 | 38 |
| 7 | 36 |
A point of confusion may be my use of "channel" in the software. The "channels" listed in the program are actually those channels on the ADC0808 which are after the first two, that is, they are the ones not connected to the temperature sensors. The sensors are connected to the first two, so actually each "channel" is the real analog input minus 2. Below is a table:
ADC0808 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
Program |
Temp1 |
Temp2 |
Ch1 |
Ch2 |
Ch3 |
Ch4 |
Ch5 |
Ch6 |

Sample of data recorded overnight. You can see where the air conditioning kicks in :)
It works! However, the resolution is not great. The ADC seems to jump back and forth between integers all the time (possibly due to noise or something) resulting in a more inaccurate graph, as above. The simplest way to attain higher precision is by using a higher-resolution ADC chip. A parallel 10-bit or 12-bit ADC could easily be accomodated for by utilizing the parallel port's unused Status lines. If I were to redesign this for a higher resolution, I would likely choose a better ADC chip.
Nonetheless, this is still much more accurate than the aforementioned 2°C accuracy without the op-amp IC. Overall, I am quite pleased with the results.
UPDATE 18 July 2007
I have added an option in the software to take a moving average of the data to produce a smoother and more accurate graph. When a voltage is fed to the ADC, its poor resolution will cause it to flip back and forth between the two closest integers. The cumulative data tend to dwell more on the number that is closer to the actual voltage. This means that when samples are averaged together a higher degree of accuracy is possible.
For example, if a voltage is between two values 113 and 114, the ADC will read 113 part of the time and 114 part of the time, and (assuming the voltage is stable) if the samples are averaged over a period of time the value returned will be more accurate. Below is a sample graph that was captured using this algorithm:

Questions/Comments may be sent to adwiens AT gmail DOT com.