Using Grove Barometic sensor and Grove Digital Light sensor with GrovePi


#1

I’m trying to use the Grove Barometic sensor and the Grove Digital Light sensor with GrovePi but I don’t know how to write the Python code.

It seems I have to use write_i2c_block(address,value[] +specific data), read_i2c_byte(address) and read_i2c_block(address) functions from grovepi.py. The address is 0x77, but wich value[] should I use to let the GrovePi access the Barometic sensor (which is connected to I2C-2) or the Digital Light sensor (which is connected to I2C-1). It can’t be [1], [2], [3], [4], [5], [7], [20], [30] or [40] because grovepi.py defines these values[] for writing to other devices. Can I just use any value[] unused so far or should it have a link to the internal I2C-adress of the Barometic sensor (which is 0x77) or the Digital Light sensor (which is 0x29)?


#2

Hi,
Both the sensors that you want to run are I2C. If you connect them to GrovePi and run the i2cdetect -y 0 or `i2cdetect -y 1’ on the Raspberry Pi then you’ll see the I2C devices connected to the Raspberry Pi. You use these I2C sensors directly from the Raspberry Pi. The GrovePi does not play any role here and is just there to connect the sensors and do level conversion on the I2C line.

You’ll have to go through the Arduino library for the pressure sensor and figure out how it works and port that to a python library. We have something similar to Grove Oled. You can look that up as a reference on how to send I2C data
https://github.com/DexterInd/GrovePi/blob/master/Software/Python/grove_i2c_oled_96x96_hello_world.py and https://github.com/DexterInd/GrovePi/blob/master/Software/Python/grove_i2c_oled_96x96.py .

Please let me know if you are able to make it work.

-karan


#3

Karan,

If I run i2cdetect -y 1 (my Raspberry Pi is a rev. B so the I2C port is 1) I see only these addresses:

  • 04 -> This is my GrovePi
  • 18 -> This is my RPI2 I2C 1-Wire host adaptor for Raspberry Pi from Sheepwalker Electronics (which I use to read my DS18B20 one-wire digital temperature sensors)
  • UU on the crossing of row 30: and collumn b -> Some device not detected. Looking at /sys/class/i2c-adapters/i2c-1/1-003b, told me it was a device named wm8804.
  • UU on the crossing of row 50: and collumn 1 -> Some device not detected, it is my RTC Alarm Pi real time Clock Module from ABelectronicsUK because it's address is 0x51.
The Barometic sensor should be address 0x77 and the Digital Light sensor should be address 0x29 but neither of them is shown.

If I use the Adafruit_BMP085_example.py written for the BMP085 module (which is used in the Grove Barometic sensor) it shows me an error: Error accessing 0x77: Check your I2C address.

So the main problem is that neither the GrovePi nor the Raspberry Pi see the sensors and therefore they can’t communicate with them. Could this be solved by adding these devices manually under /sys/class/i2c-adapter/i2c-1 ?


#4

Hi Johan,
Can you remove all the other sensors and just attach the pressure sensor on the I2C port and try runnin I2Cdectect again.

Have you tried out the pressure sensor on an arduino or any other platform. It can be broken too because the Pi is clearly able to detect other sensors and just has the problem with the pressure sensor.

-Karan


#5

Karan,

I can’t test the sensor on another platform. I only have a Raspberry Pi and PC’s.

Remoing all the other sensors (the 6 one-wire DS18B20 on the RPI I2C 1-Wire host adaptor, the Grove Sound sensor on GrovePi analog port 1, the Grove Temp-humidity sensor Pro on GrovePi digital port 4, the Grove Dust sensor on GrovePi digital port 8 and the 1/2" Water flow meter on the GrovePi digital port 2), I still got the same results. No devices are found on port 0x77 or port 0x29. When I run the Adafruit_BMP085_example.py, I got the same error: Error accessing 0×77: Check your I2C address.

It would be very strange that both sensors are defective. I ordered them form Seeedstudio.com toghether with the GrovePi and the Grove Dust sensor on may 21 2014 and they arrived on may 23 2014 at home. I was never able to get both sensors working but the Dust Sensor worked without a problem. If the are broken, it would have been prior to delivery. Should I be entitled on a free replacement or should I order new ones?


#6

Hi Johan,
If you think that the sensors are broken and you received them in that condition, then you should contact the guys at Seeed and ask them about the problem. They’ll surely help you out.

Thanks,
Karan


#7

Karan,

Since I wasn’t sure the sensors were broken because all the sensors are mounted in a sensorbox on a pool on my roof and 2 UTP cat6 cables ensure the connection with the GrovePi (wich is on the RaspberryPi) in my cellar. One of these UTP-cables is used for the Grove analog Sound Sensor, the Grove Temp. & Humidity Sensor Pro and the Grove Dust Sensor and these seem to work (but neither of these sensors is I2C, there analog or digital). The other UTP-cable is used for connecting all the I2C-sensors (e.g. the Grove Barometic Sensor and the Grove Digital Light Sensor) and neither of them is detected by sudo i2cdetect -y 1.

So it could be broken sensors or a wrong wiring on the second UTP-cable. To check the wrong wiring I need to get up the roof again and we had a full week of heavy rain, so that wasn’t on option. I therefore ordered a new Grove Barometic sensor and a new Grove Digital Light sensor from Seeds Technology. They arrived yesterday.

I then unplugged the Grove-wires in the GrovePi I2C-ports (making sure both I2C-sensors on the roof and the UTP-cable are’t connected anymore) and plugged in the new Grove Digital Light Sensor in the GrovePi I2C-1 port and the Grove Barometic Sensor in the GrovePi I2C-2 port. Then I ran the sudo i2cdetect -y 1 command and got this result:

pi@raspberrypi ~ $ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- 04 -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- 18 -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- 29 -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77
pi@raspberrypi ~ $

All sensors are detected:

  • 0x04 is the GrovePi.
  • 0x18 is my RPI2 I2C 1-Wire host adaptor for Raspberry Pi from Sheepwalker Electronics (which I use to read my DS18B20 one-wire digital temperature sensors).
  • 0x029 is the Grove Digital Light Sensor (whose sensor is a TSL2561, so it's NOT 0x039 as was mentioned in the libraries I found for the TSL2561).
  • 0x077 is the Grove Barometic Sensor (whose sensor is the BMP085).

I then just had to addapt the Adafruit_I2C.py (change the bus to smbus.SMBus(1) in stead of smbus.SMBus(0) since my sensors are on I2C 1 bus) and correct the altitude by setting the barometic pressure at sea level in Belgium (you can find this on line at the KMI website, look at the value of “Middelkerke” which is situated at the shore. Today at 10 AM the pressure at sea level is 1019,0 hPa so in the Adafruit_BMP085_example.py the code should be altitude = bmp.readAltitude(101900) in stead of altitude = bmp.readAltitude().

And in the Adafruit_BMP085.py the code should be def readAltitude(self, seaLevelPressure=101900): in stead of def readAltitude(self, seaLevelPressure=101325):.

The full script of adapted Adafruit_BMP085_example.py is here:

#!/usr/bin/python

import smbus
import grovepi
from Adafruit_BMP085 import BMP085

# ===========================================================================
# Example Code
# ===========================================================================

# Initialise the BMP085 and use STANDARD mode (default value)
# bmp = BMP085(0x77, debug=True)
bmp = BMP085(0x77, 1)

# To specify a different operating mode, uncomment one of the following:
# bmp = BMP085(0x77, 0)  # ULTRALOWPOWER Mode
# bmp = BMP085(0x77, 1)  # STANDARD Mode
# bmp = BMP085(0x77, 2)  # HIRES Mode
# bmp = BMP085(0x77, 3)  # ULTRAHIRES Mode

bus = smbus.SMBus(1)

temp = bmp.readTemperature()

# Read the current barometric pressure level
pressure = bmp.readPressure()

# To calculate altitude based on an estimated mean sea level pressure
# (1013.25 hPa) call the function as follows, but this won't be very accurate
# altitude = bmp.readAltitude()

# To specify a more accurate altitude, enter the correct mean sea level
# pressure level.  For example, if the current pressure level is 1018.70 hPa
# enter 101870 since we include two decimal places in the integer value
altitude = bmp.readAltitude(101900)

print "Temperature: %.2f C" % temp
print "Pressure:    %.2f hPa" % (pressure / 100.0)
print "Altitude:    %.2f" % altitude

The full script of the adapted Adafruit_BMP085.py is here:

#!/usr/bin/python

import time
from Adafruit_I2C import Adafruit_I2C

# ===========================================================================
# BMP085 Class
# ===========================================================================

class BMP085 :
  i2c = None

  # Operating Modes
  __BMP085_ULTRALOWPOWER     = 0
  __BMP085_STANDARD          = 1
  __BMP085_HIGHRES           = 2
  __BMP085_ULTRAHIGHRES      = 3

  # BMP085 Registers
  __BMP085_CAL_AC1           = 0xAA  # R   Calibration data (16 bits)
  __BMP085_CAL_AC2           = 0xAC  # R   Calibration data (16 bits)
  __BMP085_CAL_AC3           = 0xAE  # R   Calibration data (16 bits)
  __BMP085_CAL_AC4           = 0xB0  # R   Calibration data (16 bits)
  __BMP085_CAL_AC5           = 0xB2  # R   Calibration data (16 bits)
  __BMP085_CAL_AC6           = 0xB4  # R   Calibration data (16 bits)
  __BMP085_CAL_B1            = 0xB6  # R   Calibration data (16 bits)
  __BMP085_CAL_B2            = 0xB8  # R   Calibration data (16 bits)
  __BMP085_CAL_MB            = 0xBA  # R   Calibration data (16 bits)
  __BMP085_CAL_MC            = 0xBC  # R   Calibration data (16 bits)
  __BMP085_CAL_MD            = 0xBE  # R   Calibration data (16 bits)
  __BMP085_CONTROL           = 0xF4
  __BMP085_TEMPDATA          = 0xF6
  __BMP085_PRESSUREDATA      = 0xF6
  __BMP085_READTEMPCMD       = 0x2E
  __BMP085_READPRESSURECMD   = 0x34

  # Private Fields
  _cal_AC1 = 0
  _cal_AC2 = 0
  _cal_AC3 = 0
  _cal_AC4 = 0
  _cal_AC5 = 0
  _cal_AC6 = 0
  _cal_B1 = 0
  _cal_B2 = 0
  _cal_MB = 0
  _cal_MC = 0
  _cal_MD = 0

  # Constructor
  def __init__(self, address=0x77, mode=1, debug=False):
    self.i2c = Adafruit_I2C(address)

    self.address = address
    self.debug = debug
    # Make sure the specified mode is in the appropriate range
    if ((mode < 0) | (mode > 3)):
      if (self.debug):
        print "Invalid Mode: Using STANDARD by default"
      self.mode = self.__BMP085_STANDARD
    else:
      self.mode = mode
    # Read the calibration data
    self.readCalibrationData()

  def readS16(self, register):
    "Reads a signed 16-bit value"
    hi = self.i2c.readS8(register)
    lo = self.i2c.readU8(register+1)
    return (hi << 8) + lo

  def readU16(self, register):
    "Reads an unsigned 16-bit value"
    hi = self.i2c.readU8(register)
    lo = self.i2c.readU8(register+1)
    return (hi << 8) + lo

  def readCalibrationData(self):
    "Reads the calibration data from the IC"
    self._cal_AC1 = self.readS16(self.__BMP085_CAL_AC1)   # INT16
    self._cal_AC2 = self.readS16(self.__BMP085_CAL_AC2)   # INT16
    self._cal_AC3 = self.readS16(self.__BMP085_CAL_AC3)   # INT16
    self._cal_AC4 = self.readU16(self.__BMP085_CAL_AC4)   # UINT16
    self._cal_AC5 = self.readU16(self.__BMP085_CAL_AC5)   # UINT16
    self._cal_AC6 = self.readU16(self.__BMP085_CAL_AC6)   # UINT16
    self._cal_B1 = self.readS16(self.__BMP085_CAL_B1)     # INT16
    self._cal_B2 = self.readS16(self.__BMP085_CAL_B2)     # INT16
    self._cal_MB = self.readS16(self.__BMP085_CAL_MB)     # INT16
    self._cal_MC = self.readS16(self.__BMP085_CAL_MC)     # INT16
    self._cal_MD = self.readS16(self.__BMP085_CAL_MD)     # INT16
    if (self.debug):
      self.showCalibrationData()

  def showCalibrationData(self):
      "Displays the calibration values for debugging purposes"
      print "DBG: AC1 = %6d" % (self._cal_AC1)
      print "DBG: AC2 = %6d" % (self._cal_AC2)
      print "DBG: AC3 = %6d" % (self._cal_AC3)
      print "DBG: AC4 = %6d" % (self._cal_AC4)
      print "DBG: AC5 = %6d" % (self._cal_AC5)
      print "DBG: AC6 = %6d" % (self._cal_AC6)
      print "DBG: B1  = %6d" % (self._cal_B1)
      print "DBG: B2  = %6d" % (self._cal_B2)
      print "DBG: MB  = %6d" % (self._cal_MB)
      print "DBG: MC  = %6d" % (self._cal_MC)
      print "DBG: MD  = %6d" % (self._cal_MD)

  def readRawTemp(self):
    "Reads the raw (uncompensated) temperature from the sensor"
    self.i2c.write8(self.__BMP085_CONTROL, self.__BMP085_READTEMPCMD)
    time.sleep(0.005)  # Wait 5ms
    raw = self.readU16(self.__BMP085_TEMPDATA)
    if (self.debug):
      print "DBG: Raw Temp: 0x%04X (%d)" % (raw & 0xFFFF, raw)
    return raw

  def readRawPressure(self):
    "Reads the raw (uncompensated) pressure level from the sensor"
    self.i2c.write8(self.__BMP085_CONTROL, self.__BMP085_READPRESSURECMD + (self.mode << 6))
    if (self.mode == self.__BMP085_ULTRALOWPOWER):
      time.sleep(0.005)
    elif (self.mode == self.__BMP085_HIGHRES):
      time.sleep(0.014)
    elif (self.mode == self.__BMP085_ULTRAHIGHRES):
      time.sleep(0.026)
    else:
      time.sleep(0.008)
    msb = self.i2c.readU8(self.__BMP085_PRESSUREDATA)
    lsb = self.i2c.readU8(self.__BMP085_PRESSUREDATA+1)
    xlsb = self.i2c.readU8(self.__BMP085_PRESSUREDATA+2)
    raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self.mode)
    if (self.debug):
      print "DBG: Raw Pressure: 0x%04X (%d)" % (raw & 0xFFFF, raw)
    return raw

  def readTemperature(self):
    "Gets the compensated temperature in degrees celcius"
    UT = 0
    X1 = 0
    X2 = 0
    B5 = 0
    temp = 0.0

    # Read raw temp before aligning it with the calibration values
    UT = self.readRawTemp()
    X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15
    X2 = (self._cal_MC << 11) / (X1 + self._cal_MD)
    B5 = X1 + X2
    temp = ((B5 + 8) >> 4) / 10.0
    if (self.debug):
      print "DBG: Calibrated temperature = %f C" % temp
    return temp

  def readPressure(self):
    "Gets the compensated pressure in pascal"
    UT = 0
    UP = 0
    B3 = 0
    B5 = 0
    B6 = 0
    X1 = 0
    X2 = 0
    X3 = 0
    p = 0
    B4 = 0
    B7 = 0

    UT = self.readRawTemp()
    UP = self.readRawPressure()

    # You can use the datasheet values to test the conversion results
    # dsValues = True
    dsValues = False

    if (dsValues):
      UT = 27898
      UP = 23843
      self._cal_AC6 = 23153
      self._cal_AC5 = 32757
      self._cal_MB = -32768;
      self._cal_MC = -8711
      self._cal_MD = 2868
      self._cal_B1 = 6190
      self._cal_B2 = 4
      self._cal_AC3 = -14383
      self._cal_AC2 = -72
      self._cal_AC1 = 408
      self._cal_AC4 = 32741
      self.mode = self.__BMP085_ULTRALOWPOWER
      if (self.debug):
        self.showCalibrationData()

    # True Temperature Calculations
    X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15
    X2 = (self._cal_MC << 11) / (X1 + self._cal_MD)
    B5 = X1 + X2
    if (self.debug):
      print "DBG: X1 = %d" % (X1)
      print "DBG: X2 = %d" % (X2)
      print "DBG: B5 = %d" % (B5)
      print "DBG: True Temperature = %.2f C" % (((B5 + 8) >> 4) / 10.0)

    # Pressure Calculations
    B6 = B5 - 4000
    X1 = (self._cal_B2 * (B6 * B6) >> 12) >> 11
    X2 = (self._cal_AC2 * B6) >> 11
    X3 = X1 + X2
    B3 = (((self._cal_AC1 * 4 + X3) << self.mode) + 2) / 4
    if (self.debug):
      print "DBG: B6 = %d" % (B6)
      print "DBG: X1 = %d" % (X1)
      print "DBG: X2 = %d" % (X2)
      print "DBG: X3 = %d" % (X3)
      print "DBG: B3 = %d" % (B3)

    X1 = (self._cal_AC3 * B6) >> 13
    X2 = (self._cal_B1 * ((B6 * B6) >> 12)) >> 16
    X3 = ((X1 + X2) + 2) >> 2
    B4 = (self._cal_AC4 * (X3 + 32768)) >> 15
    B7 = (UP - B3) * (50000 >> self.mode)
    if (self.debug):
      print "DBG: X1 = %d" % (X1)
      print "DBG: X2 = %d" % (X2)
      print "DBG: X3 = %d" % (X3)
      print "DBG: B4 = %d" % (B4)
      print "DBG: B7 = %d" % (B7)

    if (B7 < 0x80000000):
      p = (B7 * 2) / B4
    else:
      p = (B7 / B4) * 2

    if (self.debug):
      print "DBG: X1 = %d" % (X1)
      
    X1 = (p >> 8) * (p >> 8)
    X1 = (X1 * 3038) >> 16
    X2 = (-7357 * p) >> 16
    if (self.debug):
      print "DBG: p  = %d" % (p)
      print "DBG: X1 = %d" % (X1)
      print "DBG: X2 = %d" % (X2)

    p = p + ((X1 + X2 + 3791) >> 4)
    if (self.debug):
      print "DBG: Pressure = %d Pa" % (p)

    return p

  def readAltitude(self, seaLevelPressure=101900):
    "Calculates the altitude in meters"
    altitude = 0.0
    pressure = float(self.readPressure())
    altitude = 44330.0 * (1.0 - pow(pressure / seaLevelPressure, 0.1903))
    if (self.debug):
      print "DBG: Altitude = %d" % (altitude)
    return altitude

    return 0

This is the result:

pi@raspberrypi ~ $ sudo python Adafruit_BMP085_example.py
Error accessing 0x77: Check your I2C address
Temperature: 19.50 C
Pressure:    1011.83 hPa
Altitude:    3.56
pi@raspberrypi ~ $

For some reason I don’t understand, it first gives an error about the I2C address, but the rest of the script is performed correctly and the results are good. The sensor is actualy 0.57m below the street level and the altitude at street level is here 5.16m. The correct level is 4.59m and the measurement gives me 3.56m, wich is 1.03m lower. Since 1 hPa pressure means an altitude change of 8.5m (or 1m change in altitude give a pressure difference of 0,12 hPa), this difference is can be neglected.

But when I run the script again, it gives multiple times the same error:

pi@raspberrypi ~ $ sudo python Adafruit_BMP085_example.py
Error accessing 0x77: Check your I2C address
Error accessing 0x77: Check your I2C address
Error accessing 0x77: Check your I2C address
Temperature: 19.70 C
Pressure:    -231.96 hPa
Altitude:    -15.89

And when I ran it again it even stopt during an error:

pi@raspberrypi ~ $ sudo python Adafruit_BMP085_example.py
Error accessing 0x77: Check your I2C address
Error accessing 0x77: Check your I2C address
Error accessing 0x77: Check your I2C address
Error accessing 0x77: Check your I2C address
Error accessing 0x77: Check your I2C address
Error accessing 0x77: Check your I2C address
Traceback (most recent call last):
  File "Adafruit_BMP085_example.py", line 35, in <module>
    altitude = bmp.readAltitude(101870)
  File "/home/pi/Adafruit_BMP085.py", line 254, in readAltitude
    altitude = 44330.0 * (1.0 - pow(pressure / seaLevelPressure, 0.1903))
ValueError: negative number cannot be raised to a fractional power

After waiting some time, the scripts works again like the first time giving sensible Temperature and Pressure readings, although the Altitude has lowered to 2.48 m in stead of 3.56 m.

Problaby the sensor isn’t allways responding to some calls of the Adafruit_I2C.py. Maybe there need some delays between following commands for the time the sensors needs to do it’s calculations before it can respond, but I don’t know where and how long these delays need to be.

The Grove Digital Light Sensor on the other hand is working OK without any problems, although I needed to write a full script (using some parts of an existing script). I’ll do some more fine tuning and will post it here when it’s ready.


#8

Hi Johan,
The problem might indeed be related to timing but can be something else too. Since you are using a few functions of the Adafruit library, it might be better to create a small library for you application and fine tune it so that it works good for you.

The second problem which causes the program to crash is a math problem. In the bmp.readAltitude() function you get the pressure value and convert it to altitude. If the pressure value is incorrect and not in the range it should be in, then it is unable to convert it to altitude and gives out the error. You can simply put a check on the pressure value to make sure that you are returned a good value or a error code like -1 instead of the program crashing. You can also simply use exception handling to solve this problem.

I also noticed that you are using long wires for the I2C bus. This could also be a big problem. I2C is supposed to be used as a chip to chip interface and does not work well with length over a feet. There is a problem of bus capacitance with the increasing length. There is a lot of information around this that you can find. I’ll recommend you to avoid using I2C over long wires if possible.

-Karan


#9

Karan,

I’ll make up my own library based on the Adafruit library (but only with the functions I need) and try to fine tune it (I have to read the datasheet of the sensor more in detail to find out which timing issues must be dealed with).

The second problem I had figured out myself all ready. It is indeed because the returned value becomes negative that there accurs a math problem. This is indeed easy to solve with exception handling.

The use of long wiring is the only way I can achieve it. I use the Raspberry Pi for both logging my solar heating system (solar collector panels on the roof and a solar boiler in the cellar) and for my environmental quality monitoring system. The Raspberry Pi is located in the cellar near the solar boiler. See this photo:

. For the solar logging system I use 1 Water Flow Meter (which I connected now directly to free GPIO-pins) and 5 DS18B20 1-wire temperature sensors. 2 of them are in the solar boiler (immersed under water, one near the top, the other near the bottom), 1 is on the return pipe from the solar collector to the solar boiler just above the boiler, 1 is in the solar collector panels on the roof and 1 outside on the roof (in the shade near the solar collector panels). The 5 DS18B20 sensors are connected through a 1-Wire passive hub (on the photo on the left next to the Raspberry Pi wit different colored RJ-45-plugs) I use a cat6 UTP cable (about 15m long) tot connect both DS18B20 sensor on the roof) and they work fine. The 3 DS18B20 in or near the boiler and the Water Flow Meter are connected with short cat6 UTP cables (max 2 m) and they work fine as well, but neither of them uses the GrovePi (although the 1-wire DS18B20 sensors are connected to a RPI2 I2C 1-Wire host adaptor for Raspberry Pi from Sheepwalker Electronics, which, just as the Grove Pi, uses the I2C port of the Raspberry Pi through pins 3 and 5.

All of the Grove Sensor I need for my environmental quality monitoring system are mounted in a sensor box wich is on a pole on top of the roof (about 2 m above the roof, wich is about 10 m above the street level) (

). The wiring is done using 2 cat6 UTP cables of 15 m each.

In the sensor box I made a PCB with two RJ45-connectors and 6 Grove connectors (

). The analog sensor (the Grove Sound Sensor) and digital sensors (the Grove Temperature and Humidity Sensor Pro and the Grove Dust Sensor) use the first UTP-cable (with the blue connector). The GND and +5V of the different Grove connectors are placed in parallel (so I only need 1 pair of the 4 pair wires to give GND and +5V), the white and yellow wires of each sensor use one pair wires each. The second utp-cable (with the yellox connector) is use for the I2C-sensors and I use only 2 pairs of wires (one for white and yellow, the other for GND and +5V) and the 2 Grove connectors are placed in parallel on the PCB. As a backup, the GND and +5V of the analog and digital sensors are placed in parallel with the GND and +5V of the I2C as well.

On top of the Grove Pi a made a similar connection-PCB with 2 RJ45-connectors and 5 small Grove Cables (one side has Grove connectors to be able to plug them into the Grove Pi, the other side is soldered directly on the PCB to link them to the RJ45-connectors. On this PCB I also placed all GND and +5V wires in parallel (to make sure the pairs of GND and +5V on both RJ-45 connectors get power in case one of the Grove wires might not be good). On the same connection-PCB a placed 4 3-position screw connectors the connect the Water Flow Meter (3 in reserve for later expanding the system). The grey cable coming in from the top of the first picture connects the Water Flow Meter.

So you see I simple can’t put the Raspberry Pi and GrovePi closer to the sensors (one of the reasons is that I don’t have power on the roof, and that would main I had to get an extra power cable tot the roof and build a waterproof casing for the Raspberry Pi, Grove Pi, powered USB-hub and adaptor) unless I put it further away from the solar boiler (and the Water Flow Meter) causing cable length problems as well.

Could the problem be caused because I have now different devices using the I2C-port of the Raspberry Pi?

  1. The GrovePi while communicating the date of the analog Grove Sound Sensor and the digital Grove Dust Sensor and Grove Temp. & Humidity Sensor Pro to the Raspberry Pi.
  2. The RPI2 I2C 1-Wire host adaptor while communciating the data from the 5 DS18B20 1-wire sensors to the Raspberry Pi.
  3. The Raspberry Pi itself while communicating with the Grove Barometic Sensor and the Grove Digital Light Sensor through the GrovePi.

If so could this be solved by building time laps in the script so that al the different sensors aren’t being asked at the same time. So something like this schematic:

1. reset GPIO-pins for Water Flow Sensor
2. read value from Water Flow Sensor during 1 second, do calculations and store values
3. reset GPIO-pins for Water Flow Sensor
4. wait 5 seconds
5. read 5 values from DS18B20 sensors from RPI I2C 1-Ware host adaptor and store values
6. wait 5 seconds
7. read values from Grove Analog Sound Sensor, Grove Digital Temp. and Humidity Sensor Pro and Grove Dust Sensor through the GrovePi and store values
8. wait 5 seconds
9. read values from Grove Barometic Sensor directly from Raspberry Pi over I2C (making sure the script has sufficiant timing to get the data without false readings), do calculations and store values
10. wait 5 seconds
11. read values from Grove Digital Light sensor directly from Raspberry Pi over I2C, do calculations and store values.
12. wait 5 minutes and start over again (or use a cron job to run the script every 5 minutes)

#10

Hi Johan,
If the only problem that you are facing is when reading the Digital light sensor and the barometric sensor then the problem must be with the cables attached. I2C is not suitable to be used with long cables. You might be able to get it to work upto 2m cables after experimenting a lot with pullups and I2C buffer chips. (Please have a look here: http://www.esacademy.com/en/library/technical-articles-and-documents/miscellaneous/i2c-bus/frequently-asked-questions/i2c-faq.html and http://www.nxp.com/documents/application_note/AN10658.pdf ). I cannot say for sure whether this will work or not.

In situations like this, you should use RS485 to transfer data using long wires. You can have an Arduino close to the I2C sensors which reads the data from the I2C sensors. The you can use a RS485 shield on the arduino to send the data to the Raspberry Pi. You’ll also need a RS485 shield on the Raspberry Pi to receive the data. You should be able to find RS485 shield on Sparkfun or Seeed.

-Karan