The methods are declared above now appear in the code and this is where I will define what each method actually does. My end goal is that this code has enough comments to make it clear as to what its intended behavior is.
/*
* getTemperature - determines the temperature in celsius based on the * incoming voltage value assuming 2.73v equals 0°C
*
temperature *
* Returns - float - the actual temperature in celsius based on the incoming voltage
*/
float getTemperature(float temperatureVoltage) {
float currentTemperature = 0.0f;
// From the datasheet, every 10 mv is equal to 1 °K - 0°C is 273°K equal to 2.73v
// Temperature is scaled by 100 to bring it into the celsius scale from kelvin
currentTemperature = (temperatureVoltage - baseVoltage) * 100;
return currentTemperature; }
In the above code, I have a method, getTemperature which takes a temperature reading in volts and converts it to a temperature value in degrees celsius. I could just convert the value read in
directly to Fahrenheit but not everyone is familiar with the Fahrenheit scale and Celsius is closer to the original value making debugging easier if the values look odd from the expected values. The raw temperature value is the value I will be reading from the analog input pin of the Arduino®. While I could keep it as a voltage reading, it will be easier to for me to relate to the value if it is in unit of measure that I am familiar with. In this case having it in a temperature unit is much easier then a raw voltage value.
/*
* convertTemperatureToF - converts the temperature from Celsius to Fahrenheit
*
* Params - temperatureInCelsius - the incoming temperature in Celsius *
* Returns - float - the temperature expressed in Fahrenheit */
float convertTemperatureToF(float temperatureInCelsius) {
float convertedTemperature = 0.0f;
convertedTemperature = (temperatureInCelsius * CtoFConversion) + CtoFDelta;
return convertedTemperature; }
/*
* convertTemperatureToC - converts the temperature from Fahrenheit to Celsius
*
* Params - temperatureInCelsius - the incoming temperature in Fahrenheit *
* Returns - float - the temperature expressed in Celsius */
float convertTemperatureToC(float temperatureInFahrenheit) {
float convertedTemperature = 0.0f;
convertedTemperature = (temperatureInFahrenheit - CtoFDelta) * FtoCConversion;
return convertedTemperature; }
This method converts a temperature in Fahrenheit to Celsius. SETUP
Again, the setup method is where I will configure my Arduino® to operate as I need. In this case I will want to set the analog reference voltage to the default which in the case of the Arduino® UNO or the Arduino® MEGA, will be 5.0v. This informs the micro-controller I want to measure voltages in the range of 0v to 5.0v. For our purposes, this resolution will be fine.
void setup() { analogReference(DEFAULT); Serial.begin(9600); }
So what do I mean regarding resolution? Well the analog to digital converter in the Atmel® micro-controller has 10 bits of data for precision. For a 5.0v voltage range, this means that there will be 5.0v / 1024 or 0.0048828125 volts per step of the analog to digital converter. For each increment of the analog to digital converter, the voltage that it represents increases by 0.0048828125 volts. I have also configured my serial port here so I can write sample data out to my development system to verify that the data looks appropriate.
The loop method once again is where all of the real work is done. Here I am also using
comments in the code to explain what everything is doing so the next person looking at this code can understand it without any assistance from me.
void loop() { int temperatureValue = 0; float currentTempVoltage = 0.0f; float currentTemperature = 0.0f;
// Read in the temperature value which will be in a range from 0 to 1023 temperatureValue = analogRead(temperaturePin);
// Convert our incoming voltage representation to a value we can utilize currentTempVoltage = ((float)temperatureValue * voltageReference) / maxSampleCount;
// We now have the current temperature expressed in celsius currentTemperature = getTemperature(currentTempVoltage);
// Print out the current temperature in both C and F Serial.print("The current temperature is: ");
Serial.print(currentTemperature); Serial.print("°C which is ");
Serial.print(convertTemperatureToF(currentTemperature)); Serial.println("°F");
// Rest for a second and check again delay(1000);
}
The first thing that is done is to read in the current temperature value in volts as a digital
representation. Once a value has been read, it can then be converted for display to the end user. In the above code, I first convert the temperature from a digital representation to an actual temperature. Given the LM335 is designed to be sensitive to 1°Kelvin which represents 10 milli-volts (mV) for each one degree Kelvin of change, I will convert from the digital representation to a Celsius
temperature value. So how did I go from Kelvin to Celsius? Kelvin has the same scale as Celsius however it starts at absolute zero and continues up on the same scale. With absolute zero being
-273.0°C, I simply use this value to convert from Kelvin to Celsius. Once I have done that, I can then use one of my methods I declared above to convert from the Celsius value to Fahrenheit. Once I have my values in the units of measure that I want, I can then print them to the serial port for verification on my development system.
A sample of the output generated by this sketch is as follows:
The current temperature is: 26.61C which is 79.90F The current temperature is: 26.12C which is 79.02F The current temperature is: 26.12C which is 79.02F The current temperature is: 26.12C which is 79.02F
The current temperature is: 28.08C which is 82.54F The current temperature is: 29.05C which is 84.30F The current temperature is: 29.54C which is 85.17F The current temperature is: 28.56C which is 83.42F The current temperature is: 28.08C which is 82.54F The current temperature is: 27.59C which is 81.66F
As you can see in the above data, my temperature readings are in the expected range i.e. room temperature or close to it depending on the room etc. Also you should note that I placed my finger on the device during the output display which is why the temperature started to rise and then began to fall once I removed my finger from the device. I did this to ensure that the circuit and code were working as expected. The only thing I have not done is to calibrate my temperature device to ensure it is
reading the correct value. This is done by connecting the ADJ pin of the temperature sensor to a potentiometer and than fine tuning the input to the current room temperature.
Image created using:
In the above circuit diagram you can see where I have placed a potentiometer attached to the
ADJ input of the temperature sensor to allow me to calibrate it to the current room temperature. While
not overly critical for what we are doing, having the ability to do this will be crucial when we want to use the same basic circuit to monitor temperatures with a suitable level of accuracy.
For analog inputs, that covers it for the most part. There are more fine details that could be discussed such as over voltage prevention, static electricity, etc. however as an introduction, I think we have the basics covered. One thing you may have noticed is that under tools, I mentioned a voltage meter however did not mention when it should be used. The voltage meter is one of those tools that I have handy whenever something doesn't look right. For sanity sake, I can use the voltage meter to ensure that I have wired my LM335 correctly and it is measuring a voltage in the general range I expect. Typical voltage meters are actually multimeters which can measure in addition to voltage, current and resistance. One such feature on my multimeter is the continuity check where I can ensure that I have wired things properly by checking two points and audibly verifying that I have continuity between them. So while I may mention that a voltage meter or multimeter is one of the tools
recommended, I may not indicate when I use it. Basically it is one of those tools that you should have for whatever circumstances come up.
Digital Input
For digital inputs, the Arduino® has a number of pins available to accomplish this. When we say digital input, we are referring to the micro-controller being able to recognize an incoming signal as either HIGH or LOW. For the devices we are looking at, this would be equivalent to zero (0) volts representing a LOW value and five (5) volts representing a HIGH* value. The main thing to
remember with digital inputs is that the value to trigger either a HIGH or LOW is not exact. There is a range of values that will cause the input to be HIGH or LOW. The datasheet indicates that a LOW signal is anything from -0.5v through 1.5v when the micro-controller is powered by 5v. The datasheet also indicates that a HIGH signal is anything from 3.0v through 5.5v when the micro-controller is powered by 5v. The main thing to note is that any voltage between 1.5v and 3.0v will be undefined and should be avoided to prevent unexpected application execution. Using our last example, I am now going to create a circuit and sketch that will only trigger when the temperature reaches a certain value such as 80°F which would be 26.67°C.
* the Arduino® UNO runs on 5 volts hence the value when set to HIGH will be 5 volts. Other boards, such as the , run at a lower voltage such as 3.3v so the output voltage when set to HIGH will be equivalent to that lower voltage.