Things used in this project

Hardware components:
475267 240424 01 front zoom kankcmvqdh
Raspberry Pi Zero Wireless
×1
Nova icon lijwm6pmk7
Hologram Nova
×1
Hologram%20dash
Hologram Global IoT SIM Card
×1
Ambient%20light
TinyCircuits TinyShield Ambient Light Sensor
×1
09264 1
RGB Diffused Common Cathode
×1
Software apps and online services:
Avatar light%402x
Hologram Data Router
Hand tools and fabrication machines:
Beer

Schematics

I am using a raspberry Pi but the idea is the same
Shine a photon toward ale and let magic happen.
Sensor wkzgb9ruwh
Testing the sensor.
I inverted the logic here. Normally the LED is always on and the program measures the amount of reflected light. Once the reflected light falls below a certain threshold an SMS is sent.
Vid 20171227 110152 sl5dtchqsu

Code

Beer Sensor With Hologram Io Nova Modem and SwishPi pHAT shieldPython
Issue : sudo python App.py
#!/usr/bin/sudo /usr/bin/python

import math
import time 
import sys
import APDS9300 as LuxSens
import RPi.GPIO as GPIO
import subprocess
import json
from time import sleep
import time
import datetime
from Hologram.HologramCloud import HologramCloud ## Import Hologram cloud library

print "=== Beer Sensor demo test  ===" 
print "********************************"

R = 11 # LED pin
G = 13
B = 15

"""
	Setups the pins in BCM mode
		
		
	:param none: 
	:returns none : 
"""
def InitLeds():
	GPIO.setwarnings(True) # suppress GPIO used message
	GPIO.setmode(GPIO.BOARD) # use BCM pin numbers
	GPIO.setup(R, GPIO.OUT) # set LED pin as output
	GPIO.setup(G, GPIO.OUT) # set LED pin as output
	GPIO.setup(B, GPIO.OUT) # set LED pin as output
	GPIO.output(R, GPIO.HIGH)
	GPIO.output(G, GPIO.HIGH)
	GPIO.output(B, GPIO.HIGH)

def RedLEDon():
    GPIO.output(R, GPIO.LOW)

def RedLEDoff():
    GPIO.output(R, GPIO.HIGH)

def GreenLEDon():
    GPIO.output(G, GPIO.LOW)
	
def GreenLEDoff():
    GPIO.output(G, GPIO.HIGH)
	
def BlueLEDon():
    GPIO.output(B, GPIO.LOW)

def BlueLEDoff():
    GPIO.output(B, GPIO.HIGH)
	
DEVICE_ID = 1

# send data to Hologram's cloud through WiFi
with open('../credentials.json') as key_file:
    devicekey = json.load(key_file)
# hologram = HologramCloud(devicekey, enable_inbound=False)
hologram = HologramCloud(devicekey, network='cellular', enable_inbound=False)

result = hologram.network.connect()
if result == False:
    print ' Failed to connect to cell network'
	
THRESHOLD = 10
global count 
TRANSMIT_CYCLE = 10

def main(argv):
	print "=== Beer Sensor First test  ===" 
	print "********************************"
	InitLeds()
	AmbientLight = LuxSens.APDS9300()					#Setup Ambient light sensor 
	id = AmbientLight.chipID()
	print "Chip ID: 0x%02X. \r\n" % id
	count = 0
	
	while (count < TRANSMIT_CYCLE):
		time.sleep(3)
		channel1 = AmbientLight.readChannel(1)				#Take a reading from channel one
		print "Channel 1 value: %d." % channel1		
		channel2 = AmbientLight.readChannel(0)				#Take a reading from channel two
		print "Channel 2 value: %d" % channel2
		Lux = AmbientLight.getLuxLevel(channel1,channel2)
		print "Lux output: %d." % Lux
		if(Lux > THRESHOLD):
			BlueLEDon()
			RedLEDon()
			beerCount = 0
			subprocess.call (["hologram","send","--sms","--destination","+1xxxxxxxxxx","'Message from Hologram.io : Out of Beer bro!'","--devicekey","xxxxxxx"])
			# message = json.dumps({'beer': beerCount,"source_device": DEVICE_ID,   "datetime": time.time()}) 
			# response_code = hologram.sendMessage(message)
			# print hologram.getResultString(response_code) # Prints 'Message sent successfully'.
			print("out of beer message sent\r\n")
			hologram.network.disconnect()
			count = TRANSMIT_CYCLE		  #get out of here
		else:
			BlueLEDoff()
			GreenLEDon()
			RedLEDon()
			beerCount = 1


if __name__ == '__main__':
	try:
		main(sys.argv[1:])
		time.sleep(2)
	except KeyboardInterrupt:
		print("")



# /* Hologram IO Nova Contest Beer Sensor
 # * Copyright (C) 2017 (almost 2018) by Dimiter Kendri
 # *
 # *
 # * This Library is free software: you can redistribute it and/or modify
 # * it under the terms of the GNU General Public License as published by
 # * the Free Software Foundation, either version 3 of the License, or
 # * (at your option) any later version.
 # *
 # * This Library is distributed in the hope that it will be useful,
 # * but WITHOUT ANY WARRANTY; without even the implied warranty of
 # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # * GNU General Public License for more details.
 # *
 # * You should have received a copy of the GNU General Public License
 # * along with the code.  If not, see
 # * <http://www.gnu.org/licenses/>.
 # */
APDS9300.pyPython
Ambient light sensor
#!/usr/bin/python
import sys
import smbus
import time
bus = smbus.SMBus(1)

APDS9300ADDR = 0x29					#Address of ambient light sensor

#Register definitions
CONTROL           = 0x00			#Control of basic functions
TIMING            = 0x01
THRESHLOWLOW      = 0x02
THRESHLOWHIGH     = 0x03
THRESHHIGHLOW     = 0x04
THRESHHIGHHIGH    = 0x05
INTERRUPT         = 0x06			#Interrupt control 
CRC               = 0x08
ID                = 0x0A
DATA0LOW          = 0x0C
DATA0HIGH         = 0x0D
DATA1LOW          = 0x0E
DATA1HIGH         = 0x0F

#COMMAND REG
COMMAND           = 0x80
CMD_CLEAR_INT     = 0x40
CMD_WORD          = 0x20

#CONTROL REG
POWERON 		  = 0x03
POWEROFF          = 0x00

#Timing Reg
GAIN              = 0x10
MANUAL            = 0x08
INTEG13_7MS       = 0x00
INTEG101MS        = 0x01
INTEG402MS        = 0x02

#INTERRUPT REG
INTERR_THRSHOLD   = 0x01
INTERR_DIS        = 0x00
INTERR_EN         = 0x10

class APDS9300(object):
	""" 
	Ambient Light Sensor. Class functions for the APDS9300 ambient light sensor. 
	"""
	
	def __init__(self):
		"""
		Powers on the sensor 
		
		
		:param none: 
		:returns: none
		"""
		self._address = APDS9300ADDR
		self.setpowerState(POWERON)				#Power on sensor
		self.setGain(1)
		self.setSamplingTime(0x02)

	def setpowerState(self,state):
		"""
		Configures the power state of the chip.
		
		
		:param state:  Denotes the power state of the sensor ,set to 0/1 to turn off/on.
		:returns: none
		"""
		self.writeRegister(CONTROL|CMD_CLEAR_INT|CONTROL,state)		#Turn on or off the sensor

	def setGain(self,gain):
		"""
		Set the gain of the internal photodiode sensors, can be 1x or 16x.
		
		
		:param gain: Gain type can be GAIN_1 or GAIN_16 for gain of 1 or 16x
		:returns: none
		"""
		value = 0
		if (gain == 1):
			value  = self.readByte(COMMAND|TIMING)      #Write to TIMING register
			value &= 0b11101111
			self.writeByte(COMMAND|TIMING)       		#Write to TIMING register
			self.writeByte(value)
		elif (gain == 16):
			self.writeByte(COMMAND|TIMING)				#Write to TIMING register
			self.writeByte(GAIN)
		else :
			self.writeByte(COMMAND|TIMING)				#Write to TIMING register
			self.writeByte(GAIN)

	def setSamplingTime(self,sampling_time):
		"""
		Configure the sampling time of the sensor.
		
		
		:param sampling_time: Can be 0x00,0x01,0x02
		:returns: none
		"""
		self.writeByte(TIMING|COMMAND)
		self.writeByte(sampling_time)

	def readChannel(self,channel):
		"""
		Read raw data from channel 0 or channel 1
		
		
		:param channel: Value of 0 or 1.
		:returns data : Channel data as raw number.
		"""
		if(channel == 1):
			self.writeByte(COMMAND|CMD_CLEAR_INT|CMD_WORD|DATA0LOW)
			channel = self.readWord(0x00)
		else :
			self.writeByte(COMMAND|CMD_CLEAR_INT|CMD_WORD|DATA1LOW)
			channel = self.readWord(0x00)
		return channel

	def getLuxLevel(self,ch0, ch1):
		"""
		Returns LUX output from the raw sensor data.
		
		
		:param ch0: Channel 0 value 
		:param ch1: Channel 1 value 
		:returns: Lux Float value of light intensity
		"""
		k = 0
		if(ch0 !=0):
			k = float(ch1/ch0)
			
		Lux=0

		if((k>=0) and (k<=0.52)):
			Lux=(0.0315*ch0)-(0.0593*ch0*pow(k,1.4))
		elif( (k>0.52) and (k<=0.65)):
			Lux=(0.0229*ch0)-(0.0291*ch1)
		elif((k>0.65) and (k<=0.80)): 
			Lux=(0.0157*ch0)-(0.0180*ch1)
		elif((k>0.80) and (k<=1.30)):
			Lux=(0.00338*ch0)-(0.00260*ch1)
		else :
			Lux=0
		return Lux
		
	def setIntLowThreshold(self,lowvalue):
		"""
		Set the low level data threshold for the interrupt.
		
		
		:param lowvalue: Low interrupt threshold value 
		:returns: none
		"""
		self.writeWord((THRESHLOWLOW|COMMAND|CMD_WORD),lowvalue)	#use the write word protocol to write these 16 bit values

	def setIntHighThreshold(self,highvalue):
		"""
		Set the high level data threshold for the interrupt.
		
		
		:param highvalue: High interrupt threshold value 
		:returns: none
		"""
		self.writeWord((THRESHHIGHLOW| COMMAND | CMD_WORD),highvalue)

	def clearInterrupt(self):
		"""
		Clear any active interrupts.
		
		
		:param: none
		:returns: none 
		"""
		self.writeByte(COMMAND|CMD_CLEAR_INT)			#Set clear bit to 1

	def setInterruptState(self,enable=False):
		"""
		Enable or disable the interrupts on the sensor.
		
		
		:param enable: Enables or diable interrupt. Default is False.
		:returns: none 
		"""
		if enable == True:
			self.writeRegister(COMMAND|INTERRUPT,INTERR_EN)
		else:
			self.writeRegister(COMMAND|INTERRUPT,INTERR_DIS)

	def chipID(self):
		"""
		Read the unique chip ID.
		
		
		:param none: 
		:returns: partID ID of chip
		"""
		partID = self.readByte(COMMAND|ID)
		return partID
		
	def writeByte(self,data):
		"""
		Write a byte value. Assumes the register pointer is predefined.
		
		
		:param data: Data byte to write on the I2C bus 
		:returns: none
		"""
		bus.write_byte(self._address,data)
		return 0

	def writeRegister(self,reg,data):
		"""
		Write a byte value to a register.
		
		
		:param reg: Register  address
		:param data: Data byte to be written on register. 
		:returns: none
		"""
		bus.write_byte_data(self._address,reg,data)

	def writeWord(self,reg, data):
		"""
		Write a word value to a register.
		
		
		:param reg: Register  address
		:param data: Data word to be written on the register. 
		:returns: none
		"""
		buffer = [(data >> 8) & 0xFF, data & 0xFF]
		bus.write_i2c_block_data(self._address, reg, buffer)

	def readByte(self,reg):
		"""
		Read a byte value from a register.
		
		
		:param reg: Register  address
		:returns: Register byte content
		"""
		x = bus.read_byte_data(self._address, reg)
		return x

	def readWord(self,reg):
		"""
		Read a word value from a register.
		
		
		:param reg: Register  address
		:returns: Register word content
		"""
		x = bus.read_word_data(self._address, reg)
		return x
		

Credits

5f6d42b1c3309b2560dc8d48b9f071dd
Dimiter Kendri
1 project β€’ 8 followers
Blah blah blah yatzeeee...
Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Add projectSign up / Login