NTC (Negative Temperature Coefficient) thermistors are resistors that exhibit large changes in resistance with varying temperature. Because they change a lot, they are easy to interface into an analog input. The only drawback is that they are very nonlinear. This EasyStep shows you how easy it is to handle a thermistor with the EC1.
It should take you way less than an hour to do this EasyStep, depending on how deeply you delve into the SPLat code. The screen shot below shows you the end result displayed on the PC screen, using the SimpleHMI function in SPLat/PC.
What you will need (in addition to an EC1!)
- An NTC thermistor, 10KΩ. (The resistance is always specified at 25°C).;
- A 10KΩ resistor;
- Some way of connecting the above to the EC1
Rather than separate thermistor and resistor I used a little module I happened to have, like this. It came in this collection (middle of bottom row in the photo). You don't need a module, though, it's just a bit easier to wire. A separate thermistor and resistor will do just fine, providing you have the capacity to hook them up.
Thermistors still give the best bang per buck in terms of accuracy. You can buy a 10KΩ, 5% thermistor for well under a dollar. As a rough rule of thumb, the temperature error in °C is about the half the percentage tolerance of the device. Don't fret too much over accuracy; if you need good accuracy, say for fermentation control, you should in any event calibrate your system.
Wiring it up
The illustrations below show the connections for my module on the left, and for breadboarding a thermistor and resistor on the right. The wire colours are the same in both
The resistor and thermistor form a simple voltage divider, with the thermistor in the lower leg. At 25°C the thermistor resistance is 10KΩ, so the analog input voltage will be exactly half the supply voltage. Under those conditions an fAnIn 0 instruction will return the number 0.5. If the thermistor is heated up, its resistance will drop, the analog input voltage will drop and the number returned by fAnIn 0 will get smaller. From there it is a "simple" matter to calculate the temperature.
The source voltage for the voltage divider is the EC1's 3.3V supply. That is the same voltage that is used as the reference voltage for the EC1's analog to digital converter. This means the measurement is ratiometric. The analog reading will not change with variations in the 3.3V (nominal) supply, because the analog reading is just the fraction of the reference voltage seen at the analog input pin.
What the program does
- Reads the thermistor input;
- Calculates the temperature using a polynomial approximation to the thermistor's resistance vs temperature curve (linearises the reading);
- Sends the result to the SimpleHMI client in SPLat/PC for display on the PC screen.
Those are the primary functions. They take 3 lines of code. However it does some other smart stuff as well:
- Filters the readings to reduce the amount of noise, i.e. random fluctuation caused by electrical noise. This inevitably slows down the response speed, so it also ...
- ... adapts rapidly to larger changes in reading ( > 1°C);
- Converts from °C to °F and displays both on the PC screen
To run the program
I am going to introduce this program in several easy stages, to make it as easy as possible for you to understand the explanations. If you are impatient and just want an end result, you can run the full program now and take it for a spin. Later I will break it down into small bite sized chunks, and show you that just 8 lines of code perform the basic measurement and display.
To install and run the full program:
- Close all running copies of SPLat/PC
- Click this link to download the program and launch it into SPLat/PC. Depending on what browser you are running, you will need to select the appropriate option to run the file in the matching application (SPLat/PC).
- Connect SPLat/PC to the EC1. Details.
The Module window in SPLat/PC should now look something like this:
- Hit CTRL+F12 to translate the program and send it to the EC1 and run it;
- Now click the SIO button on SPLat/PC's Module window;
You may get a pop-up titled "Reminder". Dismiss it. You should now have the SIO window. - Locate the SimpleHMI tab at the top and click it. You should get the SimpleHMI screen.
It should be displaying the temperature as illustrated earlier;
Note: If the reading goes the wrong way, i.e. reduces when you heat the thermistor, and you are using a module similar to mine, try swapping the red and black wires. If it is still behaving strangely, use an ohmmeter to find the pair of pins with >12KΩ between them at room temperature. Those two pins should be red and black. Try either way around for those two, and swap if the reading goes the wrong way when you heat the thermistor.
The program stage 1
The very basic program is listed below. To show/hide the program listing click here. There are pop-ups for each major functional block of code, and clickable links on individual instructions that take you to the formal descriptions of the instructions.
Place your mouse over the ;[...] to see the pop-up.
;--- Simple NTC thermistor temperature measurement ---- ; This is the very basic program, with no filtering. ; It takes 3 lines of code (flagged like this [3]) to read the thermistor, convert to °C and display the result ;[...] aiTherm EQU 0 ;define the analog input being used HMIPort EQU 251 ;Declare the serial port we are using to display readings = USB -> SPLat/PC SIO window oGreenLed oEQU 0 ;Name the output that controls the green LED on the EC1 iButton iEQU 0 ;Name the input on the EC1 that has a push button ;[...] # Open_Serial Port(HMIPort) User(38400,8,N) ;Open the serial port ;[...] LaunchTask ReadTherm LaunchTask KillSwitch LaunchTask HeartBeat RunTasksForever ;------------ Thermistor temperature measurement and display ReadTherm: fAnIn aiTherm ;Read raw thermistor voltage to W [1] ;[...] # Thermistor Params(10000, 3840) Theta(1) Feed(3.3, 3.3, 10000) RangeC(0, 80) Order(5) ;Display(12) ; °C in W [2] ;[...] # HMI Port(HMIPort) Cursor(0,0) fDispW(5, 1) Text("°C ") ;Display °C [3] Pause 10 ;Do it 10 times per second GoTo ReadTherm ; Do it all over again ;-------------------------------------------------------------------------- ;[...] KillSwitch: WaitOnK iButton Die: GoSub Die ;-------------------------------------------------------------------------- ;[...] HeartBeat: On oGreenLed Pause 5 Off oGreenLed Pause 95 GoTo HeartBeat
Stage 2 - Filtering the results
If you run the basic stage 1 program above (go ahead, copy/paste it into SPLat/PC), you will observe that the readings fluctuate quite a lot, sometimes by several tenths of a degree. This fluctuation is caused by circuit noise, electrical interference that can be very hard to eliminate. The next thing I am going to do is add a filter that will calculate a running average of many readings, in order to minimise the effect of the noise.
To show/hide the program listing click here. I have bolded the new bit.
;--- Simple NTC thermistor temperature measurement ---- ; This version adds filtering to the result, to reduce the noise. ;[...] aiTherm EQU 0 ;define the analog input being used HMIPort EQU 251 ;Declare the serial port we are using to display readings = USB -> SPLat/PC SIO window oGreenLed oEQU 0 ;Name the output that controls the green LED on the EC1 iButton iEQU 0 ;Name the input on the EC1 that has a push button ;[...] # Open_Serial Port(HMIPort) User(38400,8,N) ;Open the serial port ;[...] LaunchTask ReadTherm LaunchTask KillSwitch LaunchTask HeartBeat RunTasksForever ;------------ Thermistor temperature measurement and display ReadTherm: fAnIn aiTherm ;Raw thermistor voltage to W ;[...] # Thermistor Params(10000, 3840) Theta(1) Feed(3.3, 3.3, 10000) RangeC(0, 80) Order(5) ;Display(12) ; °C in W ;vvvvvvvv Noise filter vvvvvvvvvvvv ;[...] kFactor fEQU 100 ;Filter constant. Bigger number = heavier filtering fTempOld defFLOAT ;Stores the "old" (long term average) reading fTempNew defFLOAT ;Temporary storage for the current reading fStore fTempNew ;Save for use later fLoadQ kFactor ;The filter constant fRecallW fTempOld ;Old value fMul ;Old x Factor fRecallQ fTempNew ;New fAdd ;(Old * Factor) + New fSwap ;Move it to Q fLoadW kFactor ;Filter factor fInc ;Filter factor + 1 fDiv ;((Old * Factor) + New) / (Filter factor + 1) = New value BigJump: fStore fTempOld ;Save for next time ;^^^^^^^^ Noise filter ^^^^^^^^^^^^^^^ ;[...] # HMI Port(HMIPort) Cursor(0,0) fDispW(5, 1) Text("°C ") ;Display °C Pause 10 ;Do it 10 times per second GoTo ReadTherm ; Do it all over again ;-------------------------------------------------------------------------- ;[...] KillSwitch: WaitOnK iButton Die: GoSub Die ;-------------------------------------------------------------------------- ;[...] HeartBeat: On oGreenLed Pause 5 Off oGreenLed Pause 95 GoTo HeartBeat
Go ahead and copy/paste the filtered version into SPLat/PC and run it in your EC1 board. Notice it takes quite a while for the result to rise to its full value and settle. But once it is settled, it will not have all the random fluctuations of the earlier version.
State 3 - Speeding up the filter
The filter was great at reducing the noise, but cost us quite dearly in terms of response time. The next (and final) version of the program overcomes much of the slowdown introduced by the filter. It does this by comparing each new reading with the old filtered result. If the change is more than one degree it forces the end result to equal the new reading.
To show/hide the program listing click here. I have bolded the new bits, including some added code for displaying °F.
;--- Simple NTC thermistor temperature measurement ---- ; This version has filtering plus rapid step response. ;[...] aiTherm EQU 0 ;define the analog input being used HMIPort EQU 251 ;Declare the serial port we are using to display readings = USB -> SPLat/PC SIO window oGreenLed oEQU 0 ;Name the output that controls the green LED on the EC1 iButton iEQU 0 ;Name the input on the EC1 that has a push button ;[...] # Open_Serial Port(HMIPort) User(38400,8,N) ;Open the serial port ;[...] LaunchTask ReadTherm LaunchTask KillSwitch LaunchTask HeartBeat RunTasksForever ;------------ Thermistor temperature measurement and display ReadTherm: fAnIn aiTherm ;Raw thermistor voltage to W ;[...] # Thermistor Params(10000, 3840) Theta(1) Feed(3.3, 3.3, 10000) RangeC(0, 80) Order(5) ;Display(12) ; °C in W fStore fTempNew ;Save the new C reading ;vvvvv Rapid step response vvvvvvvv kChangeLim fEQU 1 ;This number of degrees change is treated as a genuine step change fRecallQ fTempOld ;The old value fSub ;Calculate the change since last time fAbs ;Absolute value of the change fLoadQ kChangeLim ;Value to compare with fTestWgtQ ;Test if change > limit fRecallW fTempNew ;Get back the new reading, in case we jump next GoIfT BigJump ;g/ the test showed change > limit ;^^^^^ Rapid step response ^^^^^^^^^ ;vvvvvvvv Noise filter vvvvvvvvvvvv ;[...] kFactor fEQU 100 ;Filter constant. Bigger number = heavier filtering fTempOld defFLOAT ;Stores the "old" (long term average) reading fTempNew defFLOAT ;Temporary storage for the current reading fLoadQ kFactor ;The filter constant fRecallW fTempOld ;Old value fMul ;Old x Factor fRecallQ fTempNew ;New fAdd ;(Old * Factor) + New fSwap ;Move it to Q fLoadW kFactor ;Filter factor fInc ;Filter factor + 1 fDiv ;((Old * Factor) + New) / (Filter factor + 1) = New value BigJump: fStore fTempOld ;Save for next time ;^^^^^^^^ Noise filter ^^^^^^^^^^^^^^^ ;[...] # HMI Port(HMIPort) Cursor(0,0) fDispW(5, 1) Text("°C ") ;Display °C fLoadQ 1.8 ;Converting to °F fMul fLoadQ 32 fAdd # HMI fDispW(5, 1) Text("°F") ;Display °F Pause 10 ;Do it 10 times per second GoTo ReadTherm ; Do it all over again ;-------------------------------------------------------------------------- ;[...] KillSwitch: WaitOnK iButton Die: GoSub Die ;-------------------------------------------------------------------------- ;[...] HeartBeat: On oGreenLed Pause 5 Off oGreenLed Pause 95 GoTo HeartBeat