Tutorial suggestion

Moderators: adafruit_support_bill, adafruit

Forum rules
Talk about Adafruit Raspberry Pi® accessories! Please do not ask for Linux support, this is for Adafruit products only! For Raspberry Pi help please visit: http://www.raspberrypi.org/phpBB3/
Locked
bryand
 
Posts: 6
Joined: Sat Nov 03, 2012 7:55 pm

Tutorial suggestion

Post by bryand »

I'm trying to build up a weather station using Adafruit sensors and a Pi.
Some of the sensors, like the TSL2561 don't have Pi/Python software but do have Arduino code.
Although I've tried using code for other sensors as a template, I'm still having no luck getting the TSL running on the Pi, though it works fine from an Arduino.

How about a tutorial showing how to convert Arduino C code to Pi Python?

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Tutorial suggestion

Post by adafruit_support_rick »

Thanks for the idea! I'll pass it on up.

Meanwhile, we are working hard at bringing out more and more sensor libraries for Pi, so please try to be patient with us while we get things moving!

bryand
 
Posts: 6
Joined: Sat Nov 03, 2012 7:55 pm

Re: Tutorial suggestion

Post by bryand »

OK well to reply to my own query, I managed to get some sensible readings from a pair of TLS2561s on a very extended i2c bus (basically the RPi is in the middle of a 9.5 metre long ribbon cable).
For what it's worth, here's my python code. The program is running on a headless RPi, logging the light hitting my roof, to see what I might expect from solar panels. Apologies for what may be poor coding - I learnt my computing a long time ago, in Pascal!

Code: Select all

#!/usr/bin/python

import sys
import smbus
import time
import datetime
import gspread
from Adafruit_I2C import Adafruit_I2C

# ===========================================================================
# Program to log the output of two TLS2561 Luxmeters on the same extended i2c bus.
# i2c bus is 4-way 20 AWG ribbon cable with SDA and SCL on the outside cores. 
# Each sensor is 4.5 metres from the RPi.  i2c bus has its own 3v3 power supply.
#
# Automatically switches from high gain to low gain as brightness increases.
# 
# Uses lots of ideas from Adafruit code, and their I2C & gspread libraries
#
# Google Account Details
# ===========================================================================

# Account details for google docs
email       = '[email protected]'
password    = 'somesecret'
spreadsheet = 'Rooftop_Lux'

####################################
# address param for Luxmeter instance is set by ADDR pin connection: 
#  0x29 = ADDR tied to 0v
#  0x49 = ADDR tied to 3v3
#  0x39 = ADDR left floating (default, but not used here)
#
# Param is gain and integration timing - only 0x01 and 0x11 are used here
#  0x00 = no gain, 13 mSec  (brightest)
#  0x01 = no gain, 101 mSec
#  0x02 = no gain, 402 mSec
#  0x10 = 16X gain, 13 mSec
#  0x11 = 16X gain, 101 mSec
#  0x12 = 16X gain, 402 mSec (darkest)
#######################################
#
# Login with your Google account
try:
  gc = gspread.login(email, password)
except:
  print "Unable to log in.  Check your email address/password"
  sys.exit()

# Open a worksheet from your spreadsheet using the filename
try:
  worksheet = gc.open(spreadsheet).sheet1
  # Alternatively, open a spreadsheet using the spreadsheet's key
  # worksheet = gc.open_by_key('0ApwDUb5fnx_XdENOV1Rncmpac25jMkd3d1lEM1RKUnc')
except:
  print "Unable to open the spreadsheet.  Check your filename: %s" % spreadsheet
  sys.exit()

class Luxmeter :
  i2c = None

  def __init__(self, address=0x39, debug=0):
    self.i2c = Adafruit_I2C(address)
    self.address = address
    self.debug = debug

    self.i2c.write8(0x80, 0x03)  	# enable the device
    self.i2c.write8(0x81, 0x11)  	# set gain = 16X and timing = 101 mSec

  def readfull(self, reg=0x8C):
    "Reads visible + IR value from the I2C device"
    try:
      fullval = self.i2c.readU16(reg)
      newval = self.i2c.reverseByteOrder(fullval)
      if (self.debug):
        print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, fullval & 0xFFFF, reg)
      return newval
    except IOError, err:
      print "Error accessing 0x%02X: Check your I2C address" % self.address
      return -1

  def readIR(self, reg=0x8E):
    "Reads IR value from the I2C device"
    try:
      IRval = self.i2c.readU16(reg)
      newIR = self.i2c.reverseByteOrder(IRval)
      if (self.debug):
        print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, IRval & 0xFFFF, reg)
      return newIR
    except IOError, err:
      print "Error accessing 0x%02X: Check your I2C address" % self.address
      return -1

# Continuously append data from East- and West-facing sensors
while(True):
  eastlux = Luxmeter(0x29,False)    	# create instance with 0v i2c address and no debug messages
  eastlux.i2c.write8(0x80, 0x03)  	# enable the device
  eastlux.i2c.write8(0x81, 0x11)  	# set gain = 16X and timing = 101 mSec

  egainsetting = "High gain"
  eambient = eastlux.readfull()
  if eambient >= 37177:			# sensor is maxed out, so remove the 16X gain
    eastlux.i2c.write8(0x81,0x01)
    egainsetting = "Low gain"
    time.sleep(0.41)
    eambient = eastlux.readfull()	# try again

  time.sleep(0.41)			# allow for slowest A2D conversion
  einfra = eastlux.readIR()
  time.sleep(0.41)			# allow for slowest A2D conversion

# the RPi has floating point, so these calculations are MUCH easier than they are
# for an Arduino! - taken from TAOS datasheet

  ratio = (float) (einfra / eambient)

  if ((ratio >= 0) & (ratio <= 0.52)):
	elux = (0.0315 * eambient) - (0.0593 * eambient * (ratio**1.4))
  elif (ratio <= 0.65):
	elux = (0.0229 * eambient) - (0.0291 * einfra)
  elif (ratio <= 0.80):
 	elux = (0.0157 * eambient) - (0.018 + einfra)
  elif (ratio <= 1.3):
 	elux = (0.00338 * eambient) - (0.0026 * einfra)
  elif (ratio > 1.3):
        elux = 0

  westlux = Luxmeter(0x49,False)   	# create instance with 3v3 i2c address and no debug messages
  westlux.i2c.write8(0x80, 0x03)  	# enable the device
  westlux.i2c.write8(0x81, 0x11)  	# set gain = 16X and timing = 101 mSec

  wgainsetting = "High gain"
  wambient = westlux.readfull()
  if wambient >= 37177:			# sensor is maxed out, so remove the 16X gain
    westlux.i2c.write8(0x81,0x01)
    wgainsetting = "Low gain"
    time.sleep(0.41)
    wambient = westlux.readfull() 	# try again

#  wambient = wambient + fudgefactor	# add offset to match up the two sensors

  time.sleep(0.41)			# allow for slowest A2D conversion
  winfra = westlux.readIR()
  time.sleep(0.41)			# allow for slowest A2D conversion

  ratio = (float) (winfra / wambient)

  if ((ratio >= 0) & (ratio <= 0.52)):
	wlux = (0.0315 * wambient) - (0.0593 * wambient * (ratio**1.4))
  elif (ratio <= 0.65):
	wlux = (0.0229 * wambient) - (0.0291 * winfra)
  elif (ratio <= 0.80):
 	wlux = (0.0157 * wambient) - (0.018 + winfra)
  elif (ratio <= 1.3):
 	wlux = (0.00338 * wambient) - (0.0026 * winfra)
  elif (ratio > 1.3):
        wlux = 0

  if (elux + wlux) > 10:		# don't log in the dark!
    # Append the data to the spreadsheet, including a timestamp
    try:
      values = [datetime.datetime.now(), egainsetting, eambient, einfra, elux, wgainsetting, wambient, winfra, wlux]
      worksheet.append_row(values)
    except:
      print "Unable to append data.  Check your connection?"
      sys.exit()

    print "East Lux = %.2f, West Lux = %.2f. Wrote a row to %s" % (elux, wlux, spreadsheet)

  # Get one set of readings every three minutes
  time.sleep(173)

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Tutorial suggestion

Post by adafruit_support_rick »

Cool - You've already generated some interest

User avatar
jgilbert
 
Posts: 18
Joined: Mon Jan 14, 2013 1:25 pm

Re: Tutorial suggestion

Post by jgilbert »

First of all, let me say that Adafruit rocks. I have ordered a ton of gear for RPI and Arduino in the last 2 weeks and found it to be the best documented and best supported from any of the retailers I've worked with.

+1 to the python code, and the request for more python libraries.

Like the OP, I have a TSL2561 that I've successfully integrated on Arduino and now I'm trying to move my project over to the RPI so I can take advantage of the full stack. Will post more if I get it working.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Tutorial suggestion

Post by adafruit_support_rick »

jgilbert wrote:First of all, let me say that Adafruit rocks. I have ordered a ton of gear for RPI and Arduino in the last 2 weeks and found it to be the best documented and best supported from any of the retailers I've worked with.
Thanks!! :D

User avatar
static
 
Posts: 188
Joined: Thu Dec 23, 2010 6:21 pm

Re: Tutorial suggestion

Post by static »

bryand,
I'm a very novice programmer. I'm trying to learn a lot of Python after a single college course 6 years ago.

In your code you have a function to check the light. Then, in the main program, you have a loop to check for saturation of the sensor and if it is maxed out, you have it drop the gain and recheck the light values. Is there a reason not to do that in the function? I'm going to play with it, but it seemed like an easier way to do it.

Thanks for commenting your code. It made it very easy to understand and start working with it.

bryand
 
Posts: 6
Joined: Sat Nov 03, 2012 7:55 pm

Re: Tutorial suggestion

Post by bryand »

Hi static,
Tha adjustment of the gain was an afterthought, which is why it is awkwardly placed.
Yes, it would be more elegant to put it in the Read functions.

In fact I have been logging my two sensors for a couple of days now, and have abandoned the gain-switching because it seems unnecessary at the moment (may need it in the summer).

Image
(I'm using broadband + IR rather than Lux because the combined value more closely approximates the spectral response of a silicon PV panel)

scortier
 
Posts: 13
Joined: Mon Jan 14, 2013 2:47 pm

Re: Tutorial suggestion

Post by scortier »

Bryand,

I am new to using the Raspberry Pi. I used your code in Python 2 with the sensor. But I also tried comparing values obtained from the code with a handheld lux meter. The values seem to be off. I'm not sure what the problem is.

Just in an ambient lighted room, the sensors read about 85-92 lux, but the lux meter reads ~275 lux. Have you tried comparing your values? I am not sure which is accurate.

scortier
 
Posts: 13
Joined: Mon Jan 14, 2013 2:47 pm

Re: Tutorial suggestion

Post by scortier »

Hi Bryand,

That's a neat graph you've come up with. I'm wondering if the vertical axis is lux values. I am shining a very bright LED that should be reading in the tens of thousands of lux on the sensor and the output is reading 1171 lux.

bryand
 
Posts: 6
Joined: Sat Nov 03, 2012 7:55 pm

Re: Tutorial suggestion

Post by bryand »

Hi scortier,
If you have a handheld lux meter, use it - I make no claims as to accuracy of my routines (ymmv etc).
What is important to me is the relative values from two sensors (one front and one back of the house) and for that absolute accuracy isn't important.
However. comparing my lux results to what Wikipedia says I ought to expect from different sources, I'm not far off. And we all know of wikipedia's fabled
precision (if not it's accuracy).
The numbers on the graph I posted are raw data values which are the sum of the broadband and IR sensors. I am trying to emulate a PV solar call, and our specialists reckon that because PV cells are more sensitive to IR than visible, adding the two sensors is the closest approximation to what a solar panel sees. Again, the actual numbers don't matter, it's the comparison of the two sensors that does.

User avatar
static
 
Posts: 188
Joined: Thu Dec 23, 2010 6:21 pm

Re: Tutorial suggestion

Post by static »

Great looking project. That's for the updates. Still watching and learning.

Locked
Forum rules
Talk about Adafruit Raspberry Pi® accessories! Please do not ask for Linux support, this is for Adafruit products only! For Raspberry Pi help please visit: http://www.raspberrypi.org/phpBB3/

Return to “Adafruit Raspberry Pi® accessories”