[UNICON] [BMP085] วัดความกดอากาศ with UNICON

ตรวจสอบสภาพอากาศกับ Unicon และ BMP085

<อ้างอิงจากวารสาร The Prototype Electronics ฉบับที่ 40>

UniconProject03-fig13

 

เกี่ยวกับโมดูลวัดความกดอากาศ BMP085

 

    BMP085 เป็นตัวตรวจจับปริมาณของสภาพแวดล้อมที่พัฒนาขึ้นจากเทคโนโลยีเปียโซ-รีซิสตีฟ (Piezo-resistive technology) เป็นผลงานของ BOSCH หนึ่งในผู้ผลิตตัวตรวจจับคุณภาพสูงในวงการอุตสาหกรรมระดับโลก ใช้ไฟเลี้ยงในย่าน +1.8 ถึง +3.6V เชื่อมต่อกับไมโครคอนโทรลเลอร์ผ่านทางบัส I2C มีคุณสมบัติที่น่าสนใจดังนี้    

 

    • วัดความกดอากาศได้ในช่วง 300 ถึง 1100 hPa (hPa คือหน่วย hecto Pascal โดยที่ hecto หมายถึง 100)
    • มีความผิดพลาดในการวัดต่ำสุด +2.5hPa
    • ไฟเลี้ยงย่าน 1.8 ถึง 3.6V กินกระแสไฟฟ้าเฉลี่ย 3mA ที่อัตราการเปลี่ยนแปลงของข้อมูล 1Hz
    • ติดต่อกับไมโครคอนโทรลเลอร์ผ่านบัส I2C
    • ให้ค่าของอุณหภูมิในพื้นที่ที่ตรวจวัดสัมพันธ์กับค่าความกดอากาศในช่วงเวลาและสภาพแวดล้อมเดียวกัน ทำให้นำผลการตรวจจับไปคำนวณเพื่อหาค่าตำแหน่งความสูงจากระดับน้ำทะเล (altitude) ของสถานที่ที่ติดตั้งตัวตรวจจับนี้ได้
    • มีจุดต่อ 6 จุด มีระยะห่าง 0.1 นิ้ว หรือ 2.54 มม.
    • ขนาด 0.65 x 0.65 นิ้วหรือ 16.5 x 16.5 มม

        ในรูปข้างล่างนี้จะแสดงหน้าตาของโมดูล BMP085 และบอร์ดเชื่อมต่อ ADX-BMP085 ที่นำมาใช้เชื่อมต่อกับบอร์ด Unicon สำหรับบอร์ด ADX-BMP085 ได้เคยแนะนำให้สร้างและตีพิมพ์ใน TPE ฉบับที่ 23 บทความการใช้งานแผงวงจรเชื่อมต่อ BMP085 ตัวตรวจจับความกดดันอากาศ

รูปที่ 1โมดูล BMP085 และบอร์ดเชื่อมต่อ ADX-BMP085 พร้อมสายสัญญาณ JST3AA-8 สำหรับเชื่อมต่อกับบอร์ด Unicon

การต่อวงจรเพื่อใช้งานกับบอร์ด Unicon

 

        การเชื่อมต่อกับบอร์ด Unicon ของ BMP085 ทำได้ไม่ยาก เพียงต่อขา SDA ของ BMP085 เข้าที่ขา 2 (SDA) และขา SCL เข้าที่ขา 3 (SCL) ของบอร์ด Unicon โดยติดตั้งโมดูล BMP085 ลงบนบอร์ด ADX-BMP085 จะทำให้การเชื่อมต่อง่ายขึ้นมาก อีกทั้งยังช่วยให้ใช้งาน BMP085 กับบอร์ด Unicon ที่ใช้ไฟเลี้ยง +5V ได้ เนื่องจากบอร์ด ADX-BMP085 มีวงจรควบคุมไฟเลี้ยงคงที่ +3.3V เมื่อได้ไฟเลี้ยง +5V จากบอร์ด Unicon ก็จะควบคุมให้เหลือคงที่ที่ +3.3V สำหรับเลี้ยงโมดูล BMP085 ได้

รูปที่ 2การเชื่อมต่อเพื่อทดลองใช้งานโมดูล BMP085 กับบอร์ด Unicon

        สำหรับวงจรของบอร์ด ADX-BMP085 แสดงในรูป ท่านที่มีโมดูล BMP085 อยู่แล้ว ก็สามารถต่อวงจรขึ้นมาเองได้เลย

รูปที่ 3วงจรของบอร์ดเชื่อมต่อ ADX-BMP085

 

เรื่องที่ควรทราบเกี่ยวกับรีจิสเตอร์ของ BMP085

 

        โมดูลวัดความกดอากาศ BMP085 มีรีจิสเตอร์เพื่อใช้ในการปรับแต่งตัวตรวจจับให้สามารถวัดค่าได้แม่นยำอยู่หลายตัวจะต้องนำค่ามาคำนวณร่วมกันเพื่ออ่านค่าอุณหภูมิและความกดอากาศ ดังมีข้อมูลโดยสรุปตามตาราง

ตารางที่ 1 ตารางแอดเดรสของรีจิสเตอร์ค่าสัมประสิทธิ์ที่ใช้ในการปรับแต่งสำหรับโมดูล BMP085

        สำหรับการอ่านค่าความกดอากาศจะอ่านค่าแบบ Oversampling (osrs) ได้ จึงเลือกอ่านค่าจากรีจิสเตอร์ควบคุมที่เกี่ยวข้องกับการอ่านค่าแบบ Oversampling ที่ต้องการได้ โดยเลือกได้ตั้งแต่ osrs0 ถึง osrs3 ดังแสดงในตารางโดยจะต้องอ่านค่าที่ได้จาก Oversampling 4 ระดับแล้วนำมาคำนวณเพื่อให้ค่าความกดอากาศออกมา

ตารางที่ 2 ตารางแสดงค่าของรีจิสเตอร์ควบคุมการอ่านค่าจากโมดูล BMP085 ค่าระยะเวลาที่ปรากฏใหน่วยเป็นวินาที

        สำหรับการใช้งานโมดูล BMP085 จะต้องมีการปรับแต่งตัวตรวจจับก่อนทุกครั้ง เพื่อให้ค่าที่วัดได้มีความแม่นยำ

 

 

เกี่ยวกับโปรแกรมควบคุม

 

       โปรแกรมควบคุมเพื่ออ่านค่าจากโมดูล BMP085 ของบอร์ด Unicon จะทำการอ่านค่าจากเซ็นเซอร์ BMP085 โดยจะนำค่าอุณหภูมิและความกดอากาศที่วัดได้มาแสดงบนจอ GLCD ของบอร์ด Unicon ตอนต้นของโปรแกรมในส่วนของ setup() จะต้องเรียกฟังก์ชั่น bmp085Calibration(); ก่อนเพื่อทำการปรับแต่งตัวตรวจจับให้พร้อมใช้งาน ในส่วนของการคำนวณค่าความกดดอากาศนั้นจะเป็นหน้าที่ของฟังก์ชั่น bmp085GetPressure() ที่นำค่าของ รีจิสเตอร์ทั้งหมดของ BMP085 ที่อ่านค่าจากฟังก์ชั่น bmp085ReadUP(); มาทำการคำนวณ จนกระทั่งได้ค่าความกดอากาศมาเก็บไว้ในตัวแปร P เพื่อนำไปแสดงผลต่อไป

/*****************************************************
 * 
 *   TITLE : TEMPERATURE AND PRESSURE
 *   CATAGORIES : I2C
 *   CREATED DATE : DECEMBER 9, 2013
 *   AUTHOR : INNOVATIVE EXPERIMENT CO., LTD. (INEX)
 *   WEBSITE : HTTP://WWW.INEX.CO.TH
 *   DESCRIPTION : Measure temperature and pressure with BMP085
 *                 and show value on Unicon board's GLCD
 *                 โปรแกรมวัดอุณหภูมิและความกดอากาศด้วย BMP085
 *                 โดยแสดงค่าอุณหภูมิและความกดอากาศมาแสดงบน GLCD
 *
 ******************************************************/

#include <unicon.h>

// Define BMP085 Address
#define DEVICE_ADDRESS 0xEE >> 1 

// Set oversampling to ultra low power
// 0 : Ultra low poewr
// 1 : Standard
// 2 : High resolution
// 3 : Ultra high resolution
const unsigned char OSS = 0;

// Declare calibration coefficient values
int ac1;
int ac2; 
int ac3; 
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1; 
int b2;
int mb;
int mc;
int md;
long b5; 

// Declare variable for temperature and pressure
float temperature;
long pressure;

void setup()
{
  // Initiate I2C
  Wire.begin();
  
  // Call calibration function
  bmp085Calibration();
}

void loop()
{
  // Get temperature
  temperature = bmp085GetTemperature(bmp085ReadUT());
  
  // Get pressure
  pressure = bmp085GetPressure(bmp085ReadUP());
  
  // Write temperature at line 2 column 0 
  glcd(0, 0, "%f C  ", temperature);  
  
  // Write pressure at line 5 column 0 
  glcd(1, 0, "%l Pa  ", pressure);
  
  // Delay time 1 second
  delay(1000);
}

// Get calibration coefficient values
void bmp085Calibration()
{
  // Get calibration coefficient values from BMP085
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}

// Get temperature function
float bmp085GetTemperature(unsigned int ut){
  // Declare variable for calculate date
  long x1, x2;

  // Calculate temperature
  x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  x2 = ((long)mc << 11)/(x1 + md);
  b5 = x1 + x2;
  float temp = ((b5 + 8)>>4);
  temp = temp /10;

 // Return calculated temperature 
  return temp;
}

long bmp085GetPressure(unsigned long up)
{
  // Declare variable for calculate date
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;
  
  // Calculate pressure
  b6 = b5 - 4000;
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
  x1 = (ac3 * b6)>>13;
  x2 = (b1 * ((b6 * b6)>>12))>>16;
  x3 = ((x1 + x2) + 2)>>2;
  b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
  b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  if (b7 < 0x80000000)
    p = (b7<<1)/b4;
  else
    p = (b7/b4)<<1;
  x1 = (p>>8) * (p>>8);
  x1 = (x1 * 3038)>>16;
  x2 = (-7357 * p)>>16;
  p += (x1 + x2 + 3791)>>4;
  
  // Return calculated pressure 
  return p;
}

// Get char data from BMP085
char bmp085Read(unsigned char address)
{
  // Declare variable to get data
  unsigned char data;
  
  // Begin I2C transmission with BMP085 address 
  Wire.beginTransmission(DEVICE_ADDRESS);
  
  // Send register address
  Wire.write(address);
  
  // End I2C trasmission
  Wire.endTransmission();
  
  // Request next register address
  Wire.requestFrom(DEVICE_ADDRESS, 1);
  
  // Get data until all data
  while(!Wire.available());
  
  // Return data from 
  return Wire.read();
}

// Get int data from BMP085
int bmp085ReadInt(unsigned char address)
{
  // Declare variable to get data
  unsigned char msb, lsb;
  
  // Begin I2C transmission with BMP085 address 
  Wire.beginTransmission(DEVICE_ADDRESS);
  
  // Send register address
  Wire.write(address);
  
  // End I2C trasmission
  Wire.endTransmission();
  
  // Request next 2 register address
  Wire.requestFrom(DEVICE_ADDRESS, 2);
  
  // Get data until all data
  while(Wire.available()<2);
  
  // Get most significant bit 
  msb = Wire.read();
  
  // Get least significant bit 
  lsb = Wire.read();
  
  // Return data from BMP085
  return (int) msb<<8 | lsb;
}

// Get temperature data from BMP085
unsigned int bmp085ReadUT()
{
  // Declare variable to get data
  unsigned int ut;
  
  // Begin I2C transmission with BMP085 address 
  Wire.beginTransmission(DEVICE_ADDRESS);
  
  // Send register address
  Wire.write(0xF4);
  Wire.write(0x2E);
  
  // End I2C trasmission
  Wire.endTransmission();
  
  // Delay time 5 milliseconds
  delay(5);
  
  // Get data from 0xF6
  ut = bmp085ReadInt(0xF6);
  
  // Return temperature data
  return ut;
}

// Get pressure data from BMP085
unsigned long bmp085ReadUP()
{
  // Declare variable to get data
  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;
 
  // Begin I2C transmission with BMP085 address 
  Wire.beginTransmission(DEVICE_ADDRESS);
  
  // Send register address
  Wire.write(0xF4);
  Wire.write(0x34 + (OSS<<6));
  
  // End I2C trasmission
  Wire.endTransmission();
  
  // Delay time by depending on OSS
  delay(2 + (3<<OSS));
 
  // Begin I2C transmission with BMP085 address 
  Wire.beginTransmission(DEVICE_ADDRESS);
  
  // Send register address
  Wire.write(0xF6);
  
  // End I2C trasmission
  Wire.endTransmission();
  
  // Request next 3 register address
  Wire.requestFrom(DEVICE_ADDRESS, 3);
  
  // Get data until all data
  while(Wire.available() < 3);
  
  // Get most significant bit 
  msb = Wire.read();
  
  // Get least significant bit 
  lsb = Wire.read();
  
  // Get extra least significant bit 
  xlsb = Wire.read();
  
  // Calculate pressure data 
  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
  
  // Return pressure data
  return up;
}

    โปรแกรมสำหรับอ่านค่าจากโมดูล BMP085 ของบอร์ด Unicon

 

 

ทดสอบวัดความกดอากาศ

 

        สำหรับการทดสอบ BMP085 จะให้ได้ผลแบบชัดเจน ต้องวัดเปรียบเทียบระหว่างพื้นที่ที่มีความกดอากาศต่างกันมากๆ เช่น บนอาคารสูงกับห้องใต้ดิน จึงอาจทดสอบให้เห็นได้ไม่ง่ายนัก เนื่องจากโดยปกติพื้นที่ของประเทศไทยจะอยู่สูงจากระดับน้ำทะเลประมาณ 1.44 เมตร และภูมิประเทศเป็นที่ราบเสียส่วนใหญ่ ส่งผลให้ความกดอากาศปกติจึงไม่ต่างกันมากนักในแต่ละพื้นที่ จากการทดสอบในพื้นที่กรุงเทพมหานครโดยใช้โมดูล BMP085 วัดได้ 100,676 Pa หรือ 100.676 kPa (กิโลปาสคาล) เนื่องจากอยู่สูงกว่าระกับน้ำทะเลประมาณ 1 เมตร ค่าความกดอากาศจะลดลงเมื่ออยู่สูงจากระดับน้ำทะเล โดยที่ระดับน้ำทะเลจะมีค่าความกดอากาศ 1 atm หรือหนึ่งหน่วยบรรยากาศ หรือเท่ากับ 101.325 kPa หรือ 760 mmHg (มิลลิเมตรปรอท)

รูปที่ 4

ผลการทำงานของการวัดอุณหภูมิและค่าความกดอากาศด้วยโมดูล BMP085 และบอร์ด Unicon

Facebook Comments