joan2937 / pigpio

pigpio is a C library for the Raspberry which allows control of the General Purpose Input Outputs (GPIO).
The Unlicense
1.43k stars 404 forks source link

Handle for I2C Devices #73

Closed Joey-1970 closed 7 years ago

Joey-1970 commented 7 years ago

Hello Joan,

here I again... ;-)

I try two I2C-Devices on the bus (BME280, BH1750). I expected one Handle for each I2C-device. But i get only one for them (or the same for each...). If I try only one to read, it works for both of them, but when I try to read from two, one dosen't work...

How does it work correct?

Joachim

joan2937 commented 7 years ago

I can't tell without seeing the code you are using.

Joey-1970 commented 7 years ago

Hello Joan,

thank you for your answer. My projekt ist here: https://github.com/Joey-1970/SymconModules

Let me explain you what I mean in principle: For example I take two BME280. I can choice the Device Address between 67H or 77H, but the register for measurementdata and calibratedata are the same! So when I "ask" for Handle with command, I need the Device Address for it. If I want to read or write I only need the handle and the register - not the device address! So, I wondering, how it can be possible to read with the same handle the same register...so I expeted one handle for each Device on the bus.

In my project I make a "interface" between a distant Raspberry pi with some devices and IP-Symcon, a software for smart home...

Joachim

joan2937 commented 7 years ago

You need to post a complete example script which shows the problem. I need to see how you are opening the I2C devices.

Joey-1970 commented 7 years ago

..the complete code is linked... ;-)

In the projekt, there are to Client Sockets, one only for commands, one for Notifications. For the next steps., I only use the Command-Client Socket I try to explaine it:

  1. If some add a new device, he has to give so informations, for example the device address
  2. I catch the handle for this device: CommandClientSocket(pack("LLLLL", 54, 0, $data->DeviceAddress, 4, 0), 16); and give it back reserved for this device
  3. I read something CommandClientSocket(pack("LLLL", 61, $data->Handle, $data->Register, 0), 16); or write something CommandClientSocket(pack("LLLLL", 62, $data->Handle, $data->Register, 4, $data->Value), 16);
  4. If someone add a new I2C-Device I do it the same way --> 1. But if I do it in this way, I get for each Device the same Handle...

Maybe it is because I use the Command-ClientSocket which is closed after data-transmission?

Joachim

joan2937 commented 7 years ago

You need to prepare a small complete example I can run which demonstrates the problem. I'm not prepared to spend a lot of effort on something unless there is a demonstrated problem.

Joey-1970 commented 7 years ago

...send two times a Command 54 to get a free handle with differnt device address?? CommandClientSocket(pack("LLLLL", 54, 0, 67H, 4, 0) CommandClientSocket(pack("LLLLL", 54, 0, 77H, 4, 0)

joan2937 commented 7 years ago

I don't know what you are doing wrong. I can do the same from the command line without error.

$ sudo pigpiod
$ pigs i2co 1 0x67 0
0
$ pigs i2co 1 0x77 0
1
$ pigs i2co 1 0x78 0
2
$ pigs i2co 1 0x79 0
3
$ pigs i2co 1 0x7a 0
4
$ pigs i2co 1 0x66 0
5
$ cat /dev/pigerr&
[1] 1847
$ pigs csi 4
$ pigs i2co 1 0x60 0
6
$ 2016-08-04 20:08:46 i2cOpen: i2cBus=1 i2cAddr=96 flags=0x0

$ pigs i2co 1 0x50 0
7
$ 2016-08-04 20:08:59 i2cOpen: i2cBus=1 i2cAddr=80 flags=0x0
SlySven commented 7 years ago

You say you have two of each of these devices - are all their I2C addresses configured correctly? Looking at the data-sheet for the BME280 on page 31 it says that the I2C address is 0x76 if the SDO pin is tied to ground and 0x77 if the pin is tied to VDDIO. Similarly from the BH1750 data-sheet (:thought_balloon: Humm, I think I have a strip of 5 of those somewhere... ) on page 10 it says that with the ADDR pin grounded ( < 0.3 * Vcc ) the address is 0100011 or 0x23 and with it at a high level ( > 0.7 * Vcc ) the address is 1011100 or 0x5C.

Now if you are using two BME280 at the same time on the same bus they must be set to have different I2C address - one must have the SDO pin pulled low and the other pulled high - then the one with the low SDO pin will appear at address 0x76 and the other one with it high will be at 0x77. It doesn't matter from a circuit point of view which is which (the same is true for the other pair of devices)...

{Though you or your system's user will want to know where the module with each configuration is - so they can tell whether the cold dark place with no atmosphere is somewhere outside or in your front room :laughing: }

Joey-1970 commented 7 years ago

Hello SlySven,

thanks for your answer, but I know this and this is not the problem.

Hello Joan, your are right! I make a simply test-code, where I only want to catch two different handle for two device. I look in my code again and I can fix the problem - but I don't understand why this cause this error. I do this: Every time the user change some settings and press "Apply" the code catch a new handle. So the number of handle went higher and higher - but it works. So I think, it will be a good idea to delete curent handle (is there a guilty one) and get a new one. But if I have more then one I2C-device it won't work. Both devices get back a "0" as handle. Maybe this is an timing problem, At this time I don't know ist. For now, I don't delete the current handle and it works. Here, special thanks for your patience!;-)

The BME280 works in my code, I now work on implented the PCS8591 and the Nextion NX4832K035 Touchdisplay on the serial port.

It is possible and meaningful in your opinion to make a function like "I2cdetect" do?

Joachim

joan2937 commented 7 years ago

You can have many handles to the same device at the same I2C address. There is no point in doing so though. Generally you should get a handle for a device just once at the start of your program and release the handle at the end of the program.

The following script does a simple I2C device detect.

#!/usr/bin/env python

# 2015-06-30
# i2c_detect.py
# Public Domain

import pigpio

pi = pigpio.pi() # connect to local Pi

for device in range(128):

      h = pi.i2c_open(1, device)
      try:
         pi.i2c_read_byte(h)
         print(hex(device))
      except: # exception if i2c_read_byte fails
         pass
      pi.i2c_close(h)

pi.stop # disconnect from Pi