BMP180/BMP280 i2c nodes.. can't figure it out!

#1

Hello,

I have i2c sensors on my RPi and downloaded all the BMP180 / BME280 / BMP280 i2c nodes but they all lack instructions and are all asking for a "command" which seems to be an integer. I tried sending various integers in there but keep getting "invalid command". Even tried hooking it to a timer to try one integer after another but still get the same error.

What is that command? I checked the BMP180 datasheet, nothing about commands there. Also searched Google, cannot find anything useful, just people using pre-made libraries.

For the record, I tried with both BMP180 and BMP280 but none work.

Thanks all!

0 Likes

#2

Please tell us which node you are using. Probably node-red-contrib-something.

0 Likes

#3

Look up "device tree" on the RPI, I don't have the link at the moment. You can enable various sensors connected to the RPi and read the values directly from the file system.

0 Likes

#4

I am reading from a BMP180 using this method from the following file:
/sys/devices/platform/soc/20804000.i2c/i2c-1/1-0077/iio:device0/in_pressure_input

0 Likes

#5

I just got a BMP280 and it seems to work OK

I used the node-red-contrib-bme280 node

[{"id":"9dfe3beb.19da28","type":"Bme280","z":"c0cf297.f9d51d8","name":"","bus":"1","address":"0x76","topic":"bme280","extra":false,"x":880,"y":180,"wires":[["2360c09e.8b35d"]]},{"id":"2360c09e.8b35d","type":"debug","z":"c0cf297.f9d51d8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1130,"y":180,"wires":[]},{"id":"c090494e.d03398","type":"inject","z":"c0cf297.f9d51d8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":680,"y":180,"wires":[["9dfe3beb.19da28"]]}]

I made sure it was connected OK using i2cdetect - y 1
image

and ran this python prog as well to make sure everything worked outside of Node-RED first

#!/usr/bin/python
#--------------------------------------
#    ___  ___  _ ____
#   / _ \/ _ \(_) __/__  __ __
#  / , _/ ___/ /\ \/ _ \/ // /
# /_/|_/_/  /_/___/ .__/\_, /
#                /_/   /___/
#
#           bme280.py
#  Read data from a digital pressure sensor.
#
#  Official datasheet available from :
#  https://www.bosch-sensortec.com/bst/products/all_products/bme280
#
# Author : Matt Hawkins
# Date   : 25/07/2016
#
# http://www.raspberrypi-spy.co.uk/
#
#--------------------------------------
import smbus
import time
from ctypes import c_short
from ctypes import c_byte
from ctypes import c_ubyte

DEVICE = 0x76 # Default device I2C address


bus = smbus.SMBus(1) # Rev 2 Pi, Pi 2 & Pi 3 uses bus 1
                     # Rev 1 Pi uses bus 0

def getShort(data, index):
  # return two bytes from data as a signed 16-bit value
  return c_short((data[index+1] << 8) + data[index]).value

def getUShort(data, index):
  # return two bytes from data as an unsigned 16-bit value
  return (data[index+1] << 8) + data[index]

def getChar(data,index):
  # return one byte from data as a signed char
  result = data[index]
  if result > 127:
    result -= 256
  return result

def getUChar(data,index):
  # return one byte from data as an unsigned char
  result =  data[index] & 0xFF
  return result

def readBME280ID(addr=DEVICE):
  # Chip ID Register Address
  REG_ID     = 0xD0
  (chip_id, chip_version) = bus.read_i2c_block_data(addr, REG_ID, 2)
  return (chip_id, chip_version)

def readBME280All(addr=DEVICE):
  # Register Addresses
  REG_DATA = 0xF7
  REG_CONTROL = 0xF4
  REG_CONFIG  = 0xF5

  REG_CONTROL_HUM = 0xF2
  REG_HUM_MSB = 0xFD
  REG_HUM_LSB = 0xFE

  # Oversample setting - page 27
  OVERSAMPLE_TEMP = 2
  OVERSAMPLE_PRES = 2
  MODE = 1

  # Oversample setting for humidity register - page 26
  OVERSAMPLE_HUM = 2
  bus.write_byte_data(addr, REG_CONTROL_HUM, OVERSAMPLE_HUM)

  control = OVERSAMPLE_TEMP<<5 | OVERSAMPLE_PRES<<2 | MODE
  bus.write_byte_data(addr, REG_CONTROL, control)

  # Read blocks of calibration data from EEPROM
  # See Page 22 data sheet
  cal1 = bus.read_i2c_block_data(addr, 0x88, 24)
  cal2 = bus.read_i2c_block_data(addr, 0xA1, 1)
  cal3 = bus.read_i2c_block_data(addr, 0xE1, 7)

  # Convert byte data to word values
  dig_T1 = getUShort(cal1, 0)
  dig_T2 = getShort(cal1, 2)
  dig_T3 = getShort(cal1, 4)

  dig_P1 = getUShort(cal1, 6)
  dig_P2 = getShort(cal1, 8)
  dig_P3 = getShort(cal1, 10)
  dig_P4 = getShort(cal1, 12)
  dig_P5 = getShort(cal1, 14)
  dig_P6 = getShort(cal1, 16)
  dig_P7 = getShort(cal1, 18)
  dig_P8 = getShort(cal1, 20)
  dig_P9 = getShort(cal1, 22)

  dig_H1 = getUChar(cal2, 0)
  dig_H2 = getShort(cal3, 0)
  dig_H3 = getUChar(cal3, 2)

  dig_H4 = getChar(cal3, 3)
  dig_H4 = (dig_H4 << 24) >> 20
  dig_H4 = dig_H4 | (getChar(cal3, 4) & 0x0F)

  dig_H5 = getChar(cal3, 5)
  dig_H5 = (dig_H5 << 24) >> 20
  dig_H5 = dig_H5 | (getUChar(cal3, 4) >> 4 & 0x0F)

  dig_H6 = getChar(cal3, 6)

  # Wait in ms (Datasheet Appendix B: Measurement time and current calculation)
  wait_time = 1.25 + (2.3 * OVERSAMPLE_TEMP) + ((2.3 * OVERSAMPLE_PRES) + 0.575) + ((2.3 * OVERSAMPLE_HUM)+0.575)
  time.sleep(wait_time/1000)  # Wait the required time  

  # Read temperature/pressure/humidity
  data = bus.read_i2c_block_data(addr, REG_DATA, 8)
  pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
  temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
  hum_raw = (data[6] << 8) | data[7]

  #Refine temperature
  var1 = ((((temp_raw>>3)-(dig_T1<<1)))*(dig_T2)) >> 11
  var2 = (((((temp_raw>>4) - (dig_T1)) * ((temp_raw>>4) - (dig_T1))) >> 12) * (dig_T3)) >> 14
  t_fine = var1+var2
  temperature = float(((t_fine * 5) + 128) >> 8);

  # Refine pressure and adjust for temperature
  var1 = t_fine / 2.0 - 64000.0
  var2 = var1 * var1 * dig_P6 / 32768.0
  var2 = var2 + var1 * dig_P5 * 2.0
  var2 = var2 / 4.0 + dig_P4 * 65536.0
  var1 = (dig_P3 * var1 * var1 / 524288.0 + dig_P2 * var1) / 524288.0
  var1 = (1.0 + var1 / 32768.0) * dig_P1
  if var1 == 0:
    pressure=0
  else:
    pressure = 1048576.0 - pres_raw
    pressure = ((pressure - var2 / 4096.0) * 6250.0) / var1
    var1 = dig_P9 * pressure * pressure / 2147483648.0
    var2 = pressure * dig_P8 / 32768.0
    pressure = pressure + (var1 + var2 + dig_P7) / 16.0

  # Refine humidity
  humidity = t_fine - 76800.0
  humidity = (hum_raw - (dig_H4 * 64.0 + dig_H5 / 16384.0 * humidity)) * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * humidity * (1.0 + dig_H3 / 67108864.0 * humidity)))
  humidity = humidity * (1.0 - dig_H1 * humidity / 524288.0)
  if humidity > 100:
    humidity = 100
  elif humidity < 0:
    humidity = 0

  return temperature/100.0,pressure/100.0,humidity

def main():

  (chip_id, chip_version) = readBME280ID()
  print "Chip ID     :", chip_id
  print "Version     :", chip_version

  temperature,pressure,humidity = readBME280All()

  print "Temperature : ", temperature, "C"
  print "Pressure : ", pressure, "hPa"
  print "Humidity : ", humidity, "%"

if __name__=="__main__":
   main()

Simon

1 Like

#6

Just yesterday, I did exactly what @cymplecy did and had exactly the same success. I wanted to take it a step farther and manage the data and number of digits I passed along to Watson IoT.

First, if you check the Extra Data box in the BME node, you get the full "data set" from the sensor:

temperature_C: 24.54
humidity: 48.00285972066518
pressure_hPa: 1008.9618686461673
model: "BME280"
heatIndex: 25.624424558111855
dewPoint_C: 12.810600563041554
altitude_M: 35.74196949170104
temperature_F: 76.172
pressure_Hg: 29.79463137918758

Follow the BME node with a function node containing something like this:

msg.payload = {
BarPress: msg.payload.pressure_hPa.toFixed(2),
TempC : msg.payload.temperature_C.toFixed(2),
TempF : msg.payload.temperature_F.toFixed(2),
Humid : msg.payload.humidity.toFixed(2)
};
return msg;

I couldn't see why I needed more than two places to the right of the decimal...

Jeff

0 Likes

#7

Hello,

Thanks for your reply, sorry for the delay I had no internet.

Here are 2 nodes I tried for example, both asking for "commands":


0 Likes

#8

Those are generic nodes for advanced users to communicate with i2c devices that don't have a specialist node already made.

Try this one out on your BMP/BME280 devices

I haven't got a 180 device but if I did - I try out this one on it

0 Likes

#9

Here is a known-good flow that uses the BME280.


Note that the reformat function node simplifies the format of the data for display or passing to another system.

[{"id":"a9e889ba.6422f8","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"9a2db7f1.dd5a18","type":"debug","z":"a9e889ba.6422f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":730,"y":160,"wires":[]},{"id":"e6ccffec.3de5a","type":"function","z":"a9e889ba.6422f8","name":"reformat for IBM Watson","func":"//var pres = msg.payload.pressure_hPa.toFixed(2);\n//var tempC = msg.payload.temperature_C;\n//var tempF = msg.payload.temperature_F;\n//var humidity = msg.payload.humidity;\n\nmsg.payload = {\n BarPress: msg.payload.pressure_hPa.toFixed(2),\n TempC : msg.payload.temperature_C.toFixed(2),\n TempF : msg.payload.temperature_F.toFixed(2),\n Humid : msg.payload.humidity.toFixed(2),\n Status : msg.payload.switch\n};\n\n//test with a constant string\n//msg.payload = {BarPress: \"1000.00\"};\n\nreturn msg;\n//\n// temperature_C: 24.54\n// humidity: 48.00285972066518\n// pressure_hPa: 1008.9618686461673\n// model: \"BME280\" \n// heatIndex: 25.624424558111855 \n// dewPoint_C: 12.810600563041554 \n// altitude_M: 35.74196949170104\n// temperature_F: 76.172 \n// pressure_Hg: 29.79463137918758","outputs":1,"noerr":0,"x":530,"y":160,"wires":[["9a2db7f1.dd5a18"]]},{"id":"dbed9420.59b608","type":"Bme280","z":"a9e889ba.6422f8","name":"BME280","bus":"1","address":"0x76","topic":"bme280","extra":true,"x":329,"y":200,"wires":[["e6ccffec.3de5a","f6fc599a.dcb008"]]},{"id":"bf205802.36d808","type":"inject","z":"a9e889ba.6422f8","name":"Trigger BME data","topic":"","payload":"","payloadType":"date","repeat":"10","crontab":"","once":true,"onceDelay":0.1,"x":150,"y":200,"wires":[["dbed9420.59b608"]]},{"id":"f6fc599a.dcb008","type":"debug","z":"a9e889ba.6422f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":730,"y":200,"wires":[]}]

0 Likes