简体   繁体   中英

How to get data of BH1750 (light sensor) via on I2C interface using i2c-tools

I am trying to use BH170FVI sensor via on I²C interface on Ubuntu-16.04. My board is UpSquared not Raspberry.

To be able to use i2c interface, I installed i2c-tools . I also controlled BMI160 sensor with this tool before without meeting a problem.

When I tried to detect my sensor via on terminal with the command:

i2cdetect -r -y 5

This command detects my sensor correctly as shown below:

在此处输入图片说明

As it seems my device adress is 0x23 .

After this when I tried to read all the register map data by the command:

i2cdump -y -f 5 0x23

The result is:

在此处输入图片说明

The problem is all map adresses are zero. At least one of them should read light amount. I thought the sensor power may off but I tried to use command i2cset for power-on but still nothing change.

Note: My sensor has no problem because I tried it with Arduino and also with below code:

#!/usr/bin/python
import smbus
import time
 
# Define some constants from the datasheet
DEVICE     = 0x23 # Default device I2C address
POWER_DOWN = 0x00 # No active state
POWER_ON   = 0x01 # Power on
RESET      = 0x07 # Reset data register value
ONE_TIME_HIGH_RES_MODE = 0x20
 
bus = smbus.SMBus(1)  # Rev 2 Pi uses 1
 
def convertToNumber(data):
  # Simple function to convert 2 bytes of data
  # into a decimal number
  return ((data[1] + (256 * data[0])) / 1.2)
 
def readLight(addr=DEVICE):
  data = bus.read_i2c_block_data(addr,ONE_TIME_HIGH_RES_MODE)
  return convertToNumber(data)
 
def main():
 
  while True:
    print "Light Level : " + str(readLight()) + " lux"
    time.sleep(0.5)
 
if __name__=="__main__":
   main()

My question is that why I cant control my sensor via on i2c-tools .

I think @0andriy is right. You need a driver, a library to interface it (more details in the "official" user documentation for libiio ), with python bindings in your case and some configuration. In user space you could use mraa/upm, but it's not in your Ubuntu so you would need to build that.

The suggested answer is to use the driver in the kernel, create a small ACPI table that tells the kernel which device to find on address 0x23 on bus 5. And then you use python-libiio or libiio C++ bindings to access the device. Examples of ACPI tables that can be loaded into the kernel (hint: through ConfigFS) are here https://github.com/westeri/meta-acpi/tree/master/recipes-bsp/acpi-tables/samples .

In your case it will be something like:

DefinitionBlock ("bh1750.aml", "SSDT", 5, "", "BH1750", 1)
{
    External (_SB_.PCI0.I2C5, DeviceObj) // Define Correct I2C controller
    Scope (\_SB.PCI0.I2C5)
    {
        Device (ALS0)
        {
            Name (_HID, "PRP0001")
            Name (_DDN, "ROHM BH1750FVI ambient light sensor")
            Name (_CRS, ResourceTemplate () {
                    I2cSerialBus (
                            0x23,                   // I2C Address
                            ControllerInitiated, 
                            400000,                 // Bus Speed
                            AddressingMode7Bit,     
                            "\\_SB.PCI0.I2C5",
                            0x00,
                            ResourceConsumer,,)
            }
            Name (_DSD, Package () {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package () {
                    Package () {"compatible", "rohm,bh1750"},
                }
            })
        }
    }
}

...assuming the path to the controller is \\\\_SB_.PCI0.I2C5 (you may find it in DSDT).

The links @0andriy gave in comments, ie adding i2c client devices on x86_64 , Building a i2c device controller and spidev Linux driver on Intel Atom board have additional information how to compile and attach the above table to your system.

To my knowledge it is not possible doing that with i2c-tools. The problem is the way you need to read the measurement results from BH1750. See datasheet:

S Adr Rd (A) (Data) A (Data) NA P

You cannot create such a sequence with i2c-tools:

  • either one byte without register address
  • n bytes, but you have to provide a register address

Both will result in I2C command sequences which are not what the chip wants.

It worked for me in C from userspace. See my question here:

Read a word (2 byte) without providing a register address from userspace

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM