Saturday, September 3, 2016

IOError Exception Handling for a BMP180 Temperature & Barometric Sensor


THE PROJECT:

I recently set up a mini 'weather' recorder to make inside and outside temps, inside humidity and general barometric pressure readings available on an SSD1306 .96" yellow-blue OLED. The project uses a Raspberry Pi Zero, BMP280, OLED, and cheap Homeless Despot plastic junction box for the inside 'monitor.' In the garage, attached to a wall next to the washer and dryer, a Raspberry Pi 3 with an 18" i2c cable fed outside through the concrete, reads data from a BMP180 housed in a cut piece of reinforced tubing for protection from rain.

The BMP180 data is read every 10 minutes and logged to a file published via a lighttpd Web page on the 192.168.1.XX network. The inside junction box monitor strips off temperature and barometric pressure readings from the Web server, then combines the data with data from a BME280 via i2C off the Zero.

The result is a nice little display with date and time, along with inside and outside temps, humidity and barometric pressure.

THE PROBLEM:

So far I've had two BME280s fail when used outside. I do not know if they are Bosch Sensortec units (I doubt they are as the sensors are of Asian origin). Both have 'come back to life' when used inside. I'm guessing that the sensors are not tolerant of either high temps (90F+) or high humidity (90%+). I have ordered a set of four more, along with a 'supposed' 'real' Bosch unit from Adafruit. We shall see.

The problem is that I also had the BMP180 (installed outside) fail once or twice. Due to my n00b Python skills and the piss-poor example code on the Internet for these sensors, once a read hits an I/O error in Python, game over for the monitoring code - the script bombs and the process halts.

What to do?

Well, I put in place some error-checking, and we'll see if some Python exception handling might do the trick. I first looked for the very first instance in the logging script in which the i2c device (i.e., the sensor) is being accessed, then put in a piece of exception handling. I found that with the BMP180, simply rebooting the RPi3 worked to restore functionality. The code tests a write (or read), and if not successful, waits 10 minutes before rebooting. This *should* allow SSH access to fix or replace the sensor or shut down the script.

The first part is to use Python's 'try':

 try:
        cal = bus.read_i2c_block_data(addr, REG_CALIB, 22)
  except IOError:
        reboot()


NOTE: the below reboot() function does not work! see a later posting regarding how to properly initiate a reboot process!

 The next is to call a reboot function:

def reboot():
  text_file = open("/home/pi/Downloads/ssd1306-master/error.txt", "a")
  text_file.write(str(datetime.now().strftime('%F %H:%M ')))
  text_file.write("error reading sensor - rebooting\n")
  text_file.close()
  time.sleep(600)
  cmd = "sudo reboot"
  err = os.popen(cmd).read()
  strerr = str(err)
  return  "%s" % strerr.rstrip('\r\n')


 I use the Python try in the first instance of reading or writing the sensor. There are multiple instances in my script, so I guess I should sprinkle these liberally at each instance?

Anyway, ever since I modified my script, guess what? That's right, no problems. Rock solid readings every 10 minutes for nearly a week. Perhaps the problem is voltage related? Who knows?



No comments:

Post a Comment