## Tuesday, September 13, 2016

### C/C++ on Intel Edison/Galileo – part5:Temperature sensor

In this blog post, we will explore the ways of interfacing a temperature sensor using both mraa and upm.

The Grove temperature sensor that we are going to use is a class of transducer know as the thermistor. It is called so because it's resistance (the 'istor') part is controlled by the thermal energy ('therm' part) applied on the sensor. We are going to use the Grove temperature sensor.

We have already learned from the previous blog post that with ADC, we can measure the change in the resistance of a device connected to the analog input of Edison/Galileo.

## Hardware connection:

Connect the temperature sensor to analog port 0. Note that in the circuit fritzing diagram, the Grove temperature sensor depicted is older one but the one used in this tutorial is same as in the link above however, this has no impact on the circuit connection. ## Using mraa to read the temperature

The resistance offered by the thermistor varies linearly with applied/ambient thermal energy. From the wiki page of the Grove temperature module, by following the example, we can learn how the measured resistance value relates to the ambient temperature. Using the equations listed in the above link. Usually, these equations will be listed in the manufacturer's datasheet.

Using these equations, we will now implement a mraa based implementation that will read the resistance using ADC and applies the required transformation on the read value to print the temperature in degree Celsius on the console.

```#include <stdio.h>
#include <mraa.h>
#include <math.h>           // for the log function

const int B  = 4275;         // B value for thermistor
const int R0 = 100;          // R0 is 100k ohms

#define TEMP_ADC_PIN    0    // ADC pin is 0

int main(void)
{
mraa_aio_context   adcPin;           // used as AIO context
float              R, temperature;   // Used in calculations

/* Step1: Initialize the mraa */
mraa_init();

/* Step2: Initlaize the ADC pin */

/* Step3: Read the ADC value */

/* Step4: Apply the transformation */
R = 1023.0/((float)adcValue)-1.0;    // Promote to float
R = 100000.0*R;

temperature = 1.0/(log(R/100000.0)/B+1/298.15)-273.15;

/* Step5: Print the temperature */
printf ("The temperature is %0.2f degree Celcius\n", temperature);

return 0;
}
```

As usual, we start by creating context for analog IO, called “adc_pin” and the context is initialized:

```
/* Step1: Initialize the mraa */
mraa_init();

/* Step2: Initlaize the ADC pin */

```

Then the value is read using this context and then, transformation is done on this raw value in accordance to the equation and then the value is printed.
`adcValue = mraa_aio_read(adcPin); `
```R = 1023.0/((float)adcValue)-1.0;
R = 100000.0*R; temperature = 1.0/(log(R/100000.0)/B+1/298.15)-273.15;

printf ("The temperature is %0.2f degree Celcius\n", temperature);
```

### Trying it out:

Run the following command from within your Edison console to download and compile the source code:

```curl https://raw.githubusercontent.com/navin-bhaskar/C-CPP-on-Intel-Edison-Galileo/master/part5-temperature/temp_mraa.c > temp_mraa.c
gcc -o temp temp_mraa.c -lmraa -lm```
Note that we are adding the math lib (via -lm) for using the log() function
Run the code by typing
`./temp`
You should see the temperature printed on your console

## Using the upm library

Now we will use the upm library to interface the Grove temperature sensor module with the Edison/Galileo. upm is a C++ library that kind of abstracts all the lower level details and presents a clean and consistent APIs across a class of sensors. For example, in case of temperature sensor, you can find consistent APIs for different temperature sensor (sometimes with some difference in the way they behave) and the methods provided by upm library for a particular sensor will take care of details such as the physical interface used and the way the sensor is to be operated on.

Even though we will be using C++ from now on, I will limit to the language’s usage only to instantiate and use of the sensor object under consideration and rest of the things in the code will largely be in ‘C’ style.

```
#include <stdio.h>  // for printf()

/* Step1: Bring in the upm */
#include <upm/grove.h>

#define TEMP_ADC_PIN    0    // ADC pin is 0

int main(void)
{
int temperature;

/* Step2: Instantiate an instance of Grove temperature sensor */
upm::GroveTemp *temp = new upm::GroveTemp(TEMP_ADC_PIN);

/* Step3: Record the temperature and print */
temperature = temp->value();
printf ("The temperature is %d degree Celcius\n", temperature);

return 0;
}
```

To begin with, we include the grove library defined within the upm.  Then, we instantiate the Grove temperature sensor module by supplying the ADC input pin as input.

``` #include <upm/grove.h>

#define TEMP_ADC_PIN    0    // ADC pin is 0

upm::GroveTemp *temp = new upm::GroveTemp(TEMP_ADC_PIN);
```
This creates and returns pointer to a “new” GroveTemp object which you can use to access the methods exposed by the GroveTemp Then we read the temperature value using the value() method. Since we used the “new” keyword to create the object, we use the arrow notation (used for accessing the properties in of pointers to objects)

```temperature = temp->value();
printf ("The temperature is %d degree Celcius\n", temperature);
```

Thus retrieved value is printed out

### Trying it out:

Fetch the source from github:
`curl https://raw.githubusercontent.com/navin-bhaskar/C-CPP-on-Intel-Edison-Galileo/master/part5-temperature/temp_upm.cpp > temp_upm.cpp`
we would be using the ‘g++’ compiler which is GNU’s C++ compiler to generate the executable out of the downloaded source file

```g++ temp_upm.cpp -o temp_upm -lupm-grove
```
Note that we are adding the "upm-grove" lib in the command line. "upm-grove" is where the upm objects for Grove kit is defined.
Run the executable using following command to see the temperature value printed on your console:

```./temp_upm
```
You should see the temperature being printed out