All Downloads are FREE. Search and download functionalities are using the official Maven repository.

one.microproject.rpi.hardware.gpio.sensors.BMP180 Maven / Gradle / Ivy

package one.microproject.rpi.hardware.gpio.sensors;

import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;

import com.pi4j.system.SystemInfo;

import java.io.IOException;

import java.text.DecimalFormat;
import java.text.NumberFormat;

/**
 * BMP-180 I2C
 * 3.3V Bosch temperature and barometric pressure sensor.
 * @author gergej
 *
 */
public class BMP180 {
		  public final static int LITTLE_ENDIAN = 0;
		  public final static int BIG_ENDIAN    = 1;
		  private final static int BMP180_ENDIANNESS = BIG_ENDIAN;
		  /*
		  Prompt> sudo i2cdetect -y 1
		       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
		  00:          -- -- -- -- -- -- -- -- -- -- -- -- --
		  10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
		  20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
		  30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
		  40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
		  50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
		  60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
		  70: -- -- -- -- -- -- -- 77
		   */
		  // This next addresses is returned by "sudo i2cdetect -y 1", see above.
		  public final static int BMP180_ADDRESS = 0x77; 
		  // Operating Modes
		  public final static int BMP180_ULTRALOWPOWER     = 0;
		  public final static int BMP180_STANDARD          = 1;
		  public final static int BMP180_HIGHRES           = 2;
		  public final static int BMP180_ULTRAHIGHRES      = 3;

		  // BMP180 Registers
		  public final static int BMP180_CAL_AC1           = 0xAA;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_AC2           = 0xAC;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_AC3           = 0xAE;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_AC4           = 0xB0;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_AC5           = 0xB2;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_AC6           = 0xB4;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_B1            = 0xB6;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_B2            = 0xB8;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_MB            = 0xBA;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_MC            = 0xBC;  // R   Calibration data (16 bits)
		  public final static int BMP180_CAL_MD            = 0xBE;  // R   Calibration data (16 bits)
		  
		  public final static int BMP180_CONTROL           = 0xF4;
		  public final static int BMP180_TEMPDATA          = 0xF6;
		  public final static int BMP180_PRESSUREDATA      = 0xF6;
		  public final static int BMP180_READTEMPCMD       = 0x2E;
		  public final static int BMP180_READPRESSURECMD   = 0x34;

		  private int cal_AC1 = 0;
		  private int cal_AC2 = 0;
		  private int cal_AC3 = 0;
		  private int cal_AC4 = 0;
		  private int cal_AC5 = 0;
		  private int cal_AC6 = 0;
		  private int cal_B1  = 0;
		  private int cal_B2  = 0;
		  private int cal_MB  = 0;
		  private int cal_MC  = 0;
		  private int cal_MD  = 0;

		  private static boolean verbose = "true".equals(System.getProperty("i2c.verbose", "false"));
		  
		  private I2CBus bus;
		  private I2CDevice bmp180;
		  private int mode = BMP180_STANDARD;
		  
		  public BMP180()
		  {
		    this(BMP180_ADDRESS);
		  }
		  
		  public BMP180(int address)
		  {
		    try
		    {
		      // Get i2c bus
		      bus = I2CFactory.getInstance(I2CBus.BUS_1); // Depends onthe RasPI version
		      if (verbose)
		        System.out.println("Connected to bus. OK.");

		      // Get device itself
		      bmp180 = bus.getDevice(address);
		      if (verbose)
		        System.out.println("Connected to device. OK.");
		      
		      try { this.readCalibrationData(); }
		      catch (Exception ex)
		      { ex.printStackTrace(); }            
		    }
		    catch (IOException e)
		    {
		      System.err.println(e.getMessage());
		    } catch (I2CFactory.UnsupportedBusNumberException e) {
		      System.err.println(e.getMessage());
		    }
		  }
		  
		  private int readU8(int reg) throws Exception
		  {
		    // "Read an unsigned byte from the I2C device"
		    int result = 0;
		    try
		    {
		      result = this.bmp180.read(reg);
		      if (verbose)
		        System.out.println("I2C: Device " + BMP180_ADDRESS + " returned " + result + " from reg " + reg);
		    }
		    catch (Exception ex)
		    { ex.printStackTrace(); }
		    return result;
		  }
		  
		  private int readS8(int reg) throws Exception
		  {
		    // "Reads a signed byte from the I2C device"
		    int result = 0;
		    try
		    {
		      result = this.bmp180.read(reg);
		      if (result > 127)
		        result -= 256;
		      if (verbose)
		        System.out.println("I2C: Device " + BMP180_ADDRESS + " returned " + result + " from reg " + reg);
		    }
		    catch (Exception ex)
		    { ex.printStackTrace(); }
		    return result;
		  }
		  
		  private int readU16(int register) throws Exception
		  {
		    int hi = this.readU8(register);
		    int lo = this.readU8(register + 1);
		    return (BMP180_ENDIANNESS == BIG_ENDIAN) ? (hi << 8) + lo : (lo << 8) + hi; // Big Endian
		  }

		  private int readS16(int register) throws Exception
		  {
		    int hi = 0, lo = 0;
		    if (BMP180_ENDIANNESS == BIG_ENDIAN)
		    {
		      hi = this.readS8(register);
		      lo = this.readU8(register + 1);
		    }
		    else
		    {
		      lo = this.readS8(register);
		      hi = this.readU8(register + 1);
		    }
		    return (hi << 8) + lo;
		  }

		  public void readCalibrationData() throws Exception
		  {
		    // Reads the calibration data from the IC
		    cal_AC1 = readS16(BMP180_CAL_AC1);   // INT16
		    cal_AC2 = readS16(BMP180_CAL_AC2);   // INT16
		    cal_AC3 = readS16(BMP180_CAL_AC3);   // INT16
		    cal_AC4 = readU16(BMP180_CAL_AC4);   // UINT16
		    cal_AC5 = readU16(BMP180_CAL_AC5);   // UINT16
		    cal_AC6 = readU16(BMP180_CAL_AC6);   // UINT16
		    cal_B1 =  readS16(BMP180_CAL_B1);    // INT16
		    cal_B2 =  readS16(BMP180_CAL_B2);    // INT16
		    cal_MB =  readS16(BMP180_CAL_MB);    // INT16
		    cal_MC =  readS16(BMP180_CAL_MC);    // INT16
		    cal_MD =  readS16(BMP180_CAL_MD);    // INT16
		    if (verbose)
		      showCalibrationData();
		  }
		        
		  private void showCalibrationData()
		  {
		    // Displays the calibration values for debugging purposes
		    System.out.println("DBG: AC1 = " + cal_AC1);
		    System.out.println("DBG: AC2 = " + cal_AC2);
		    System.out.println("DBG: AC3 = " + cal_AC3);
		    System.out.println("DBG: AC4 = " + cal_AC4);
		    System.out.println("DBG: AC5 = " + cal_AC5);
		    System.out.println("DBG: AC6 = " + cal_AC6);
		    System.out.println("DBG: B1  = " + cal_B1);
		    System.out.println("DBG: B2  = " + cal_B2);
		    System.out.println("DBG: MB  = " + cal_MB);
		    System.out.println("DBG: MC  = " + cal_MC);
		    System.out.println("DBG: MD  = " + cal_MD);
		  }
		              
		  public int readRawTemp() throws Exception
		  {
		    // Reads the raw (uncompensated) temperature from the sensor
		    bmp180.write(BMP180_CONTROL, (byte)BMP180_READTEMPCMD);
		    waitfor(5);  // Wait 5ms
		    int raw = readU16(BMP180_TEMPDATA);
		    if (verbose)
		      System.out.println("DBG: Raw Temp: " + (raw & 0xFFFF) + ", " + raw);
		    return raw;
		  }
		      
		  public int readRawPressure() throws Exception
		  {
		    // Reads the raw (uncompensated) pressure level from the sensor
		    bmp180.write(BMP180_CONTROL, (byte)(BMP180_READPRESSURECMD + (this.mode << 6)));
		    if (this.mode == BMP180_ULTRALOWPOWER)
		      waitfor(5);
		    else if (this.mode == BMP180_HIGHRES)
		      waitfor(14);
		    else if (this.mode == BMP180_ULTRAHIGHRES)
		      waitfor(26);
		    else
		      waitfor(8);
		    int msb = bmp180.read(BMP180_PRESSUREDATA);
		    int lsb = bmp180.read(BMP180_PRESSUREDATA + 1);
		    int xlsb = bmp180.read(BMP180_PRESSUREDATA + 2);
		    int raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - this.mode);
		    if (verbose)
		      System.out.println("DBG: Raw Pressure: " + (raw & 0xFFFF) + ", " + raw);
		    return raw;
		  }
		      
		  public float readTemperature() throws Exception
		  {
		    // Gets the compensated temperature in degrees celcius
		    int UT = 0;
		    int X1 = 0;
		    int X2 = 0;
		    int B5 = 0;
		    float temp = 0.0f;

		    // Read raw temp before aligning it with the calibration values
		    UT = this.readRawTemp();
		    X1 = ((UT - this.cal_AC6) * this.cal_AC5) >> 15;
		    X2 = (this.cal_MC << 11) / (X1 + this.cal_MD);
		    B5 = X1 + X2;
		    temp = ((B5 + 8) >> 4) / 10.0f;
		    if (verbose)
		      System.out.println("DBG: Calibrated temperature = " + temp + " C");
		    return temp;
		  }

		  public float readPressure() throws Exception
		  {
		    // Gets the compensated pressure in pascal
		    int UT = 0;
		    int UP = 0;
		    int B3 = 0;
		    int B5 = 0;
		    int B6 = 0;
		    int X1 = 0;
		    int X2 = 0;
		    int X3 = 0;
		    int p = 0;
		    int B4 = 0;
		    int B7 = 0;

		    UT = this.readRawTemp();
		    UP = this.readRawPressure();

		    // You can use the datasheet values to test the conversion results
		    // boolean dsValues = true;
		    boolean dsValues = false;

		    if (dsValues)
		    {
		      UT = 27898;
		      UP = 23843;
		      this.cal_AC6 = 23153;
		      this.cal_AC5 = 32757;
		      this.cal_MB = -32768;
		      this.cal_MC = -8711;
		      this.cal_MD = 2868;
		      this.cal_B1 = 6190;
		      this.cal_B2 = 4;
		      this.cal_AC3 = -14383;
		      this.cal_AC2 = -72;
		      this.cal_AC1 = 408;
		      this.cal_AC4 = 32741;
		      this.mode = BMP180_ULTRALOWPOWER;
		      if (verbose)
		        this.showCalibrationData();
		    }
		    // True Temperature Calculations
		    X1 = (int)((UT - this.cal_AC6) * this.cal_AC5) >> 15;
		    X2 = (this.cal_MC << 11) / (X1 + this.cal_MD);
		    B5 = X1 + X2;
		    if (verbose)
		    {
		      System.out.println("DBG: X1 = " + X1);
		      System.out.println("DBG: X2 = " + X2);
		      System.out.println("DBG: B5 = " + B5);
		      System.out.println("DBG: True Temperature = " + (((B5 + 8) >> 4) / 10.0)  + " C");
		    } 
		    // Pressure Calculations
		    B6 = B5 - 4000;
		    X1 = (this.cal_B2 * (B6 * B6) >> 12) >> 11;
		    X2 = (this.cal_AC2 * B6) >> 11;
		    X3 = X1 + X2;
		    B3 = (((this.cal_AC1 * 4 + X3) << this.mode) + 2) / 4;
		    if (verbose)
		    {
		      System.out.println("DBG: B6 = " + B6);
		      System.out.println("DBG: X1 = " + X1);
		      System.out.println("DBG: X2 = " + X2);
		      System.out.println("DBG: X3 = " + X3);
		      System.out.println("DBG: B3 = " + B3);
		    }
		    X1 = (this.cal_AC3 * B6) >> 13;
		    X2 = (this.cal_B1 * ((B6 * B6) >> 12)) >> 16;
		    X3 = ((X1 + X2) + 2) >> 2;
		    B4 = (this.cal_AC4 * (X3 + 32768)) >> 15;
		    B7 = (UP - B3) * (50000 >> this.mode);
		    if (verbose)
		    {
		      System.out.println("DBG: X1 = " + X1);
		      System.out.println("DBG: X2 = " + X2);
		      System.out.println("DBG: X3 = " + X3);
		      System.out.println("DBG: B4 = " + B4);
		      System.out.println("DBG: B7 = " + B7);
		    }
		    if (B7 < 0x80000000)
		      p = (B7 * 2) / B4;
		    else
		      p = (B7 / B4) * 2;

		    if (verbose)
		      System.out.println("DBG: X1 = " + X1);
		      
		    X1 = (p >> 8) * (p >> 8);
		    X1 = (X1 * 3038) >> 16;
		    X2 = (-7357 * p) >> 16;
		    if (verbose)
		    {
		      System.out.println("DBG: p  = " + p);
		      System.out.println("DBG: X1 = " + X1);
		      System.out.println("DBG: X2 = " + X2);
		    }
		    p = p + ((X1 + X2 + 3791) >> 4);
		    if (verbose)
		      System.out.println("DBG: Pressure = " + p + " Pa");

		    return p;
		  }
		      
		  private int standardSeaLevelPressure = 101325;

		  public void setStandardSeaLevelPressure(int standardSeaLevelPressure)
		  {
		    this.standardSeaLevelPressure = standardSeaLevelPressure;
		  }

		  public double readAltitude() throws Exception
		  {
		    // "Calculates the altitude in meters"
		    double altitude = 0.0;
		    float pressure = readPressure();
		    altitude = 44330.0 * (1.0 - Math.pow(pressure / standardSeaLevelPressure, 0.1903));
		    if (verbose)
		      System.out.println("DBG: Altitude = " + altitude);
		    return altitude;
		  }
		      
		  protected static void waitfor(long howMuch)
		  {
		    try { Thread.sleep(howMuch); } catch (InterruptedException ie) { ie.printStackTrace(); }
		  }
		  
		  public static void main(String[] args)
		  {
		    final NumberFormat NF = new DecimalFormat("##00.00");
		    BMP180 sensor = new BMP180();
		    float press = 0;
		    float temp  = 0;
		    double alt  = 0;

		    try { press = sensor.readPressure(); } 
		    catch (Exception ex) 
		    { 
		      System.err.println(ex.getMessage()); 
		      ex.printStackTrace();
		    }
		    sensor.setStandardSeaLevelPressure((int)press); // As we ARE at the sea level (in San Francisco).
		    try { alt = sensor.readAltitude(); } 
		    catch (Exception ex) 
		    { 
		      System.err.println(ex.getMessage()); 
		      ex.printStackTrace();
		    }
		    try { temp = sensor.readTemperature(); } 
		    catch (Exception ex) 
		    { 
		      System.err.println(ex.getMessage()); 
		      ex.printStackTrace();
		    }
		    
		    System.out.println("Temperature: " + NF.format(temp) + " C");
		    System.out.println("Pressure   : " + NF.format(press / 100) + " hPa");
		    System.out.println("Altitude   : " + NF.format(alt) + " m");
		    // Bonus : CPU Temperature
		    try
		    {
		      System.out.println("CPU Temperature   :  " + SystemInfo.getCpuTemperature());
		      System.out.println("CPU Core Voltage  :  " + SystemInfo.getCpuVoltage());
		    }
		    catch (InterruptedException ie)
		    {
		      ie.printStackTrace();
		    }
		    catch (IOException e)
		    {
		      e.printStackTrace();
		    }
		  }
		}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy