BMP180 and Orange Pi Zero

BAROMETER AND TEMPERATURE

Barometric pressure measurement is possible with the BMP180 or GY-68 sensor which also provides the ambient temperature via an I2c bus.

Connection

Connect as shown in the diagram, the BMP180 module to the I2c0 bus.

Activation of the I2c bus

You have to configure the system by running ‘armbian-config’, the equivalent of ‘raspiconfig’ on Raspberry.

$ armbian-config

Go to the “system” section and select “Hardware” then activate i2c0.

Install the I2c utilities.

apt install i2c-tools

Test the response of the BMP180.

i2cdetect -y 0
Reply address 77

Installation Libraries

Installation of the i2c bus access library with python3:

apt install python-smbus python3-smbus

With nano, create the python3 testbmp.py file and copy the source here below. Each sensor has its own set of calibration coefficients which must not be zero. They are read and displayed by the program.

#!/usr/bin/python3          

import smbus
import time
import math

address = 0x77  #I2c device BMP180
mode = 1 # mode Standard

# BMP180 registers
CONTROL_REG = 0xF4
DATA_REG = 0xF6
# Calibration data registers
CAL_AC1_REG = 0xAA
CAL_AC2_REG = 0xAC
CAL_AC3_REG = 0xAE
CAL_AC4_REG = 0xB0
CAL_AC5_REG = 0xB2
CAL_AC6_REG = 0xB4
CAL_B1_REG = 0xB6
CAL_B2_REG = 0xB8
CAL_MB_REG = 0xBA
CAL_MC_REG = 0xBC
CAL_MD_REG = 0xBE


def read_signed_16_bit( register): #Lit valeur signée 16 bits        
        msb = bus.read_byte_data(address, register)
        lsb = bus.read_byte_data(address, register + 1)
        if msb > 127:
            msb -= 256
        return (msb << 8) + lsb
def read_unsigned_16_bit( register):  #Lit valeur non signée 16 bits
        msb = bus.read_byte_data(address, register)
        lsb = bus.read_byte_data(address, register + 1)
        return (msb << 8) + lsb

# Temperature (see BMP180 datasheet)

def get_raw_temp():    
        # Start the measurement
        bus.write_byte_data(address, CONTROL_REG, 0x2E)
        # Wait 5 ms
        time.sleep(0.005)
        # Read the raw data from the DATA_REG, 0xF6
        raw_data = read_unsigned_16_bit(DATA_REG)
        # Return the raw data
        return raw_data
def get_temp():
        UT = get_raw_temp()
        X1 = ((UT - calAC6) * calAC5) / math.pow(2, 15)
        X2 = calMC*math.pow(2, 11)/(X1+calMD)
        B5 = X1 + X2
        temperature = ((B5 + 8) / math.pow(2, 4)) / 10
        return temperature

# Pressure
def get_raw_pressure():        
        bus.write_byte_data(address, CONTROL_REG, 0x34 + (mode << 6))
        # Sleep for 8 ms.
        time.sleep(0.008)
        # Read the raw data from the DATA_REG, 0xF6
        MSB = bus.read_byte_data(address, DATA_REG)
        LSB = bus.read_byte_data(address, DATA_REG + 1)
        XLSB = bus.read_byte_data(address, DATA_REG + 2)
        raw_data = ((MSB << 16) + (LSB << 8) + XLSB) >> (8 - mode)
        return raw_data
def get_pressure():     
        UP = get_raw_pressure()
        UT = get_raw_temp()
        #calculation idem temperature
        X1 = ((UT - calAC6) * calAC5) / math.pow(2, 15)
        X2 = (calMC * math.pow(2, 11)) / (X1 + calMD)
        B5 = X1 + X2      
        B6 = B5 - 4000
        X1 = (calB2 * (B6 * B6 / math.pow(2, 12))) / math.pow(2, 11)
        X2 = calAC2 * B6 / math.pow(2, 11)
        X3 = X1 + X2
        B3 = (((calAC1 * 4 + int(X3)) << mode) + 2) / 4
        X1 = calAC3 * B6 / math.pow(2, 13)
        X2 = (calB1 * (B6 * B6 / math.pow(2, 12))) / math.pow(2, 16)
        X3 = ((X1 + X2) + 2) / math.pow(2, 2)
        B4 = calAC4 * (X3 + 32768) / math.pow(2,15)
        B7 = (UP - B3) * (50000 >> mode)
        if B7 < 0x80000000:
            pressure = (B7 * 2) / B4
        else:
            pressure = (B7 / B4) * 2
        X1 = (pressure / math.pow(2, 8)) * (pressure / math.pow(2, 8))
        X1 = (X1 * 3038) / math.pow(2, 16)
        X2 = (-7357 * pressure) / math.pow(2, 16)
        pressure = pressure + (X1 + X2 + 3791) / math.pow(2, 4)
        pressure=pressure/100 #hPa
        return pressure 

        
# I2C bus 0

bus = smbus.SMBus(0)

# Calibration data variables
calAC1 = read_signed_16_bit(CAL_AC1_REG)
calAC2 = read_signed_16_bit(CAL_AC2_REG)
calAC3 = read_signed_16_bit(CAL_AC3_REG)
calAC4 = read_unsigned_16_bit(CAL_AC4_REG)
calAC5 = read_unsigned_16_bit(CAL_AC5_REG)
calAC6 = read_unsigned_16_bit(CAL_AC6_REG)
calB1 = read_signed_16_bit(CAL_B1_REG)
calB2 = read_signed_16_bit(CAL_B2_REG)
calMB = read_signed_16_bit(CAL_MB_REG)
calMC = read_signed_16_bit(CAL_MC_REG)
calMD = read_signed_16_bit(CAL_MD_REG)

print("Calibration:",calAC1,calAC2,calAC3,calAC4,calAC5,calAC6,calB1,calB2,calMB,calMC,calMD)
while True:
    print("Temperature: {0:0.1f} C".format(get_temp()))
    print('Pressure = {0:0.1f} hPa'.format(get_pressure()))   
    time.sleep(2)

The pressure is given in hecto Pascal (hPa) and the temperature in degrees Celsius (° C).