In industrial applications, having accurate pressures becomes a critical thing. The issue becomes all to real when your chemical reactor goes a few pounds over the desired, pressure gets too low in your robotic actuator, or pneumatic braking is lost due to lack of force. What is needed in these situations is not only an industrial grade sensor, but a unit that compensates for environmental changes. Air is a fickle thing that changes density with temperature and altitude. Without a compensation mechanism, the system integrity comes into question whenever surrounding conditions differ from the initial test case. As industrial applications go, you only trust those who have proved to be a quality name. In this case we have turned to Honeywell.
Typical applications are far too many to number, but let's look at a few:
- Robotics
- Automotive
- Aircraft
- HVAC
- Centrifuges
- Mining
- Transportation
- Medical
- Electrical
- Controls
- Drones
- Displays
- Underwater Research
- Space
- Food Production
- Engine Controls
- Amusement Rides
- Agriculture
And that's the short list. While it is possible to use other solutions, in the case of such a critical task, using a quality name gives that additional level of security.
Today we are introducing the Manometer click and with it a library that is sure to induce feelings of joy. Mainly because we have made it so easy to use. The Manometer click as is, supports 0 - 60 psi. A fair, middle ground range that is the most common. Ranges for the Honeywell sensor line goes from 0 to 250 psi ( 0 bar to 17.24 bar ) in the surface mounted flavors.
Some of the other benefits to high accuracy pressure sensors are:
- Accuracy of .25%
- Temperature compensation
- Large pressure range
- No need for calibration
As a side benefit, since this is a completely compensated unit, you also have the ability to read the temperature originating at the sensor itself. Let's dive into some code and see how easy they are to use.
Library
Code and examples can be found on Libstock or Github:
// Initialize manometer, type 3 with min 0 max 60 psi if( manometer_init( MANOMETER_ADDRESS_TYPE_3, 0, 60 ) ) while(1);
There are 6 different "types" of sensors supported by the library.
MANOMETER_ADDRESS_TYPE_2 = 0x28, MANOMETER_ADDRESS_TYPE_3 = 0x38, MANOMETER_ADDRESS_TYPE_4 = 0x48, MANOMETER_ADDRESS_TYPE_5 = 0x58, MANOMETER_ADDRESS_TYPE_6 = 0x68, MANOMETER_ADDRESS_TYPE_7 = 0x78
All of them are based on the same principle but different part numbers. For the Manometer it is a Type 3 part number. You can also get more information about the series here.
How to use them is greatly simplified with the library:
/** * @brief manometer get status */ status_t manometer_get_status( void ); /** * @brief manometer_reset */ void manometer_reset( void ); /** * @brief manometer_get_pressure * @return pressure */ float manometer_get_pressure( void ); /** * @brief manometer_get_temp * @param units of measure CELSIUS or FAHRENHEIT * @return float - temperature */ float manometer_get_temp( temp_units_t unit );
The manometer has 4 states that are self managed, but if you need to see the status of your sensor, you can. If there is an issue with the sensor, you can reset it. The crown jewels are what we can get from the sensor: manometer_get_pressure and manometer_get_temp .
You have a choice of CELSIUS or FAHRENHEIT when calling manometer_get_temp() .
Example
/****************************************************************************** * Includes *******************************************************************************/ #include#include #include "manometer_hw.h" #include "resources.h" /****************************************************************************** * Module Preprocessor Constants *******************************************************************************/ #define INNER_RADIUS 20.0f #define OUTER_RADIUS 60.0f #define X_CENTER 160.0f #define Y_CENTER 110.0f #define PI 3.14159265f /****************************************************************************** * Module Preprocessor Macros *******************************************************************************/ /****************************************************************************** * Module Typedefs *******************************************************************************/ /** * @struct Line beginning and end points in X and Y */ typedef struct { int x1; int y1; int x2; int y2; } line_t; /****************************************************************************** * Module Variable Definitions *******************************************************************************/ // TFT module connections unsigned int TFT_DataPort at GPIOE_ODR; sbit TFT_RST at GPIOE_ODR.B8; sbit TFT_RS at GPIOE_ODR.B12; sbit TFT_CS at GPIOE_ODR.B15; sbit TFT_RD at GPIOE_ODR.B10; sbit TFT_WR at GPIOE_ODR.B11; sbit TFT_BLED at GPIOE_ODR.B9; // End TFT module connections static volatile bool update_flag; /****************************************************************************** * Function Prototypes *******************************************************************************/ void display_init( void ); void system_init( void ); void update_display( void ); /****************************************************************************** * Private Function Definitions *******************************************************************************/ /****************************************************************************** * Public Function Definitions *******************************************************************************/ void init_timer2() { RCC_APB1ENR.TIM2EN = 1; TIM2_CR1.CEN = 0; TIM2_PSC = 575; TIM2_ARR = 62499; NVIC_IntEnable(IVT_INT_TIM2); TIM2_DIER.UIE = 1; TIM2_CR1.CEN = 1; } void display_init() { TFT_Init_ILI9341_8bit( 320, 280 ); TFT_BLED = 1; TFT_Set_Default_Mode(); TFT_Set_Pen( CL_WHITE, 1 ); TFT_Set_Brush( 1, CL_WHITE, 0, 0, 0, 0 ); TFT_Set_Font( TFT_defaultFont, CL_BLACK, FO_HORIZONTAL ); TFT_Fill_Screen( CL_WHITE ); TFT_Set_Pen( CL_BLACK, 1 ); TFT_Line( 20, 222, 300, 222 ); TFT_Write_Text( "EasyMx PRO v7 for STM32", 19, 223 ); TFT_Write_Text( "www.mikroe.com", 200, 223 ); TFT_Image( ( 320 - 220 ) / 2, 1, &pressure3_bmp, 1 ); TFT_Set_Font( TFT_defaultFont, CL_BLACK, FO_HORIZONTAL ); } void update_display() { float temp, pressure; static float old_temp, old_pressure; static line_t last_line; char txt[80]; line_t current_line; temp = manometer_get_temp( CELSIUS ); pressure = manometer_get_pressure(); sprintf( txt, "Temp: %frn", temp ); UART_Write_Text( txt ); sprintf( txt, "Pressure: %frn", pressure ); UART_Write_Text( txt ); TFT_Set_Font( TFT_defaultFont, CL_WHITE, FO_HORIZONTAL ); sprintf( txt, "%3.1f PSI", old_pressure ); TFT_Write_Text( txt, 160, 138 ); sprintf( txt, "%3.1f C", old_temp ); TFT_Write_Text( txt, 160, 160 ); TFT_Set_Font( TFT_defaultFont, CL_BLACK, FO_HORIZONTAL ); sprintf( txt, "%3.1f PSI", pressure ); TFT_Write_Text( txt, 160, 138 ); sprintf( txt, "%3.1f C", temp ); TFT_Write_Text( txt, 160, 160 ); old_pressure = pressure; old_temp = temp; TFT_Set_Pen( CL_WHITE, 4 ); TFT_Line( last_line.x1, last_line.y1, last_line.x2, last_line.y2 ); TFT_Set_Pen( CL_RED, 4 ); if( old_pressure <= 15.0f ) { current_line.x1 = ( int )( X_CENTER + ( INNER_RADIUS * sin( 270.0f * ( PI / 180.0f ) ) ) ); current_line.y1 = ( int )( Y_CENTER + ( INNER_RADIUS * -cos( 270.0f * ( PI / 180.0f ) ) ) ); current_line.x2 = ( int )( X_CENTER + ( OUTER_RADIUS * sin( 270.0f * ( PI / 180.0f ) ) ) ); current_line.y2 = ( int )( Y_CENTER + ( OUTER_RADIUS * -cos( 270.0f * ( PI / 180.0f ) ) ) ); } else if( old_pressure >= 42.0f ) { current_line.x1 = ( int )( X_CENTER + ( INNER_RADIUS * sin( 90.0f * ( PI / 180.0f ) ) ) ); current_line.y1 = ( int )( Y_CENTER + ( INNER_RADIUS * -cos( 90.0f * ( PI / 180.0f ) ) ) ); current_line.x2 = ( int )( X_CENTER + ( OUTER_RADIUS * sin( 90.0f * ( PI / 180.0f ) ) ) ); current_line.y2 = ( int )( Y_CENTER + ( OUTER_RADIUS * -cos( 90.0f * ( PI / 180.0f ) ) ) ); } else { current_line.x1 = ( int )( X_CENTER + ( INNER_RADIUS * sin( old_pressure * ( PI / 180.0f ) ) ) ); current_line.y1 = ( int )( Y_CENTER + ( INNER_RADIUS * -cos( old_pressure * ( PI / 180.0f ) ) ) ); current_line.x2 = ( int )( X_CENTER + ( OUTER_RADIUS * sin( old_pressure * ( PI / 180.0f ) ) ) ); current_line.y2 = ( int )( Y_CENTER + ( OUTER_RADIUS * -cos( old_pressure * ( PI / 180.0f ) ) ) ); } TFT_Line( current_line.x1, current_line.y1, current_line.x2, current_line.y2 ); memcpy( &last_line, ¤t_line, sizeof( line_t ) ); } void system_init() { // UART UART1_Init_Advanced( 115200, _UART_8_BIT_DATA, _UART_NOPARITY, _UART_ONE_STOPBIT, &_GPIO_MODULE_USART1_PA9_10 ); Delay_ms(100); UART_Write_Text( "**** Manometer ****rn" ); I2C1_Init_Advanced( 400000, &_GPIO_MODULE_I2C1_PB67 ); Delay_ms(100); // Stabilization time if( manometer_init( MANOMETER_ADDRESS_TYPE_3, 0, 60 ) ) while(1); display_init(); init_timer2(); EnableInterrupts(); } void main() { system_init(); while(1) { if( update_flag ) { update_display(); update_flag = false; } } } void Timer2_interrupt() iv IVT_INT_TIM2 { TIM2_SR.UIF = 0; update_flag = true; }
References
Honeywell High Accuracy Sensors Honeywell 2016