Strict Standards: Declaration of action_plugin_googleanalytics::register() should be compatible with DokuWiki_Action_Plugin::register($controller) in /home/ulcape/www/wiki.ulcape.org/lib/plugins/googleanalytics/action.php on line 6

Strict Standards: Declaration of action_plugin_stripslashes::register() should be compatible with DokuWiki_Action_Plugin::register($controller) in /home/ulcape/www/wiki.ulcape.org/lib/plugins/stripslashes/action.php on line 0
CAPE Wiki » tutorials:pic:pic18_adc_mpx4115a
 
Strict Standards: Declaration of syntax_plugin_code::render() should be compatible with DokuWiki_Syntax_Plugin::render($format, &$renderer, $data) in /home/ulcape/www/wiki.ulcape.org/lib/plugins/code/syntax.php on line 41

ADC Using the MPX4115A Pressure Sensor

Understanding the MPX4115A

The Motorola MPX4115A is a atmospheric pressure sensor powered by 5V and delivers and output from ~0.25V to ~4.75V based on the pressure detected at room temperature (25C). As the pressure rises, so will the output of the sensor. ~0.25V represents <15 kPa pressure relative to a vacuum and ~4.75V represents >115 kPa. For example, 1 atmosphere of pressure at sea level is equal to 101,325 Pa or 101 kPa. Notice the approximate voltages given. See the graph below.

Before continuing, be sure to read through the ADC tutorial.

MPX4115Agraph.jpg

There is a transfer function below for this graph:

  • Vout = Vs* (.009*P-.095) ± Error
    • Vs = 5.1 volts
    • P = pressure in kiloPascals
    • Error = ±1.5 (kPa)

Connect the sensor

The sensor contains 6 pins, however only 3 will be used:

  • power (pin 3)
  • ground (pin 2)
  • output (pin 1)

Mpx4115apinout.jpg

Using an ADC channel on the PIC, connect the output (pin 1) of the sensor to the input of an ADC channel. For our example, we will use channel 0. Connect the ground (pin 2) to the common ground and connect the power (pin 3) to 5V power.

Convert ADC Value to a Pressure Value

Using the ADC tutorial, the variable xvalue stores the binary number of the analog voltage of channel 0. After an ADC conversion occurs and the value is stored, some simple calculations can be made in order to produce the value of the pressure in kiloPascals.

 1:  #include <p18cxxx.h>
 2:  #include <usart.h>
 3:  #include <adc.h>
 4:
 5:  void main()
 6:  {
 7:
 8:       int xvalue = 0;
 9:
10:       TRISC = 0x00;
11:       TRISA = 0xFF;
12:
13:       OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 129);
14:       OpenADC(ADC_FOSC_2 & ADC_RIGHT_JUST & ADC_8ANA_0REF, ADC_CH0 & ADC_INT_OFF);
15:
16:       ConvertADC();
17:       while(BusyADC());
18:
19:       xvalue = ReadADC();            // store binary value
20:
21:  }

Assuming room temperature, the minimum voltage produced by the sensor is ~0.25V and the maximum is ~4.75V. Therefore, the minimum digital binary number from an ADC conversion should be 51 and the maximum number should be 972. Knowing this information, the following calculations are done in the PIC to linearly convert any number between 51 and 972 to the appropriate pressure between 15 and 115, respectively.

Luckily, the sensor’s output is extremely linear. Using the equation of a line, ideally, the value of y> should be 15 when 51 is stored in xvalue.

Issues with Floats and Memory

In the case of using division, floating numbers can be an issue if there is no software support for floating point numbers. If there is no support, then a simple division such as x = 9/10; would produce 0 instead of a fractional number. However, there is a simple way to work around this.

23:  y = (100/921 * xvalue) + 10;

Normally, the above calculation would be fine, however, if the division of 921 occurs before the multiplication 100, then the answer will be 10. By separating the equation into smaller portions, we can perform a proper division leading to a more accurate answer. Begin by initializing z as a long int, giving a memory range of 32 bits.

 9:  long int z = 0;

By performing the multiplication first, we can have a certain amount of precision using division exclusively in the integer domain. The largest number possible is 97200 making a long int datatype more than enough.

23:  z = (100 * xvalue);

Then, z can be divided by 921 and stored in y.

23:  z = (100 * xvalue);
24:  y = z/921;

Lastly, add 10 to compensate for the adjustment of the line.

23:  z = (100 * xvalue);
24:  y = z/921 + 10;

Final Code

Finally, the equation is complete. When xvalue is 51, y equals 15. When xvalue is 972, y equals 115. y now represents the pressure value in kiloPascals. The value can be printed to screen using the putsUSART() function, itoa function and the xvalueASCII variable.

 1:  #include <p18cxxx.h>
 2:  #include <usart.h>
 3:  #include <adc.h>
 4:
 5:  void main()
 6:  {
 7:
 8:       int xvalue = 0;
 9:       long int z = 0;
10:       int y = 0;
11:       char xvalueASCII[5] = 0;
12:
13:       TRISC = 0x00;
14:       TRISA = 0xFF;
15:
16:       OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 129);
17:       OpenADC(ADC_FOSC_2 & ADC_RIGHT_JUST & ADC_8ANA_0REF, ADC_CH0 & ADC_INT_OFF);
18:
19:       ConvertADC();
20:       while(BusyADC());
21:
22:       xvalue = ReadADC();            // store binary value
23:       z = (100 * xvalue);                // calculations convert ADC value to pressure value in kiloPascals - multiplication
24:       y = z/921 + 10;                    // calculations convert ADC value to pressure value in kiloPascals - division and addition
25:       itoa(y, xvalueASCII);          // convert binary value to a series of printable characters
26:       putsUSART( xvalueASCII );      // print the string of printable characters
27:
28:  }

The output of the string should be a number between 15 and 115.

duty free alcohol airport duty free cigs uk buy duty free cuban cigars where to buy cosmetics duty free fragrances buy tobacco duty free