diff --git a/Adafruit_CharLCD/Adafruit_CharLCD.py b/Adafruit_CharLCD/Adafruit_CharLCD.py index a4bb9a93..c05b6a64 100755 --- a/Adafruit_CharLCD/Adafruit_CharLCD.py +++ b/Adafruit_CharLCD/Adafruit_CharLCD.py @@ -7,7 +7,7 @@ # from time import sleep - +import Adafruit_BBIO.GPIO as GPIO class Adafruit_CharLCD(object): @@ -53,18 +53,12 @@ class Adafruit_CharLCD(object): LCD_5x10DOTS = 0x04 LCD_5x8DOTS = 0x00 - def __init__(self, pin_rs=25, pin_e=24, pins_db=[23, 17, 21, 22], GPIO=None): - # Emulate the old behavior of using RPi.GPIO if we haven't been given - # an explicit GPIO interface to use - if not GPIO: - import RPi.GPIO as GPIO - GPIO.setwarnings(False) + def __init__(self, pin_rs="P8_31", pin_e="P8_32", pins_db=["P8_27","P8_28","P8_29","P8_30"]): self.GPIO = GPIO self.pin_rs = pin_rs self.pin_e = pin_e self.pins_db = pins_db - self.GPIO.setmode(GPIO.BCM) self.GPIO.setup(self.pin_e, GPIO.OUT) self.GPIO.setup(self.pin_rs, GPIO.OUT) @@ -137,7 +131,7 @@ def blink(self): self.displaycontrol |= self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - def DisplayLeft(self): + def scrollDisplayLeft(self): """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) @@ -206,5 +200,6 @@ def message(self, text): if __name__ == '__main__': lcd = Adafruit_CharLCD() + lcd.begin(16,2) lcd.clear() lcd.message(" Adafruit 16x2\n Standard LCD") diff --git a/Adafruit_HMC5883L/Adafruit_HMC5883L.py b/Adafruit_HMC5883L/Adafruit_HMC5883L.py new file mode 100755 index 00000000..62c8019f --- /dev/null +++ b/Adafruit_HMC5883L/Adafruit_HMC5883L.py @@ -0,0 +1,195 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Python library for HMC5883L magnetometer. + +# Code based on: +# * http://think-bowl.com/i2c-python-libraries-for-the-raspberry-pi/ +# License: http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_US +# +# * https://github.com/adafruit/Adafruit_HMC5883_Unified +# License: +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +from Adafruit_I2C import Adafruit_I2C +import math + +class Adafruit_HMC5883L(object): + +# Default device address + HMC5883_ADDRESS = (0x3C >> 1) + +# REGISTERS + HMC5883_REGISTER_MAG_CRA_REG_M = 0x00 + HMC5883_REGISTER_MAG_CRB_REG_M = 0x01 + HMC5883_REGISTER_MAG_MR_REG_M = 0x02 + HMC5883_REGISTER_MAG_OUT_X_H_M = 0x03 + HMC5883_REGISTER_MAG_OUT_X_L_M = 0x04 + HMC5883_REGISTER_MAG_OUT_Z_H_M = 0x05 + HMC5883_REGISTER_MAG_OUT_Z_L_M = 0x06 + HMC5883_REGISTER_MAG_OUT_Y_H_M = 0x07 + HMC5883_REGISTER_MAG_OUT_Y_L_M = 0x08 + HMC5883_REGISTER_MAG_SR_REG_Mg = 0x09 + HMC5883_REGISTER_MAG_IRA_REG_M = 0x0A + HMC5883_REGISTER_MAG_IRB_REG_M = 0x0B + HMC5883_REGISTER_MAG_IRC_REG_M = 0x0C + HMC5883_REGISTER_MAG_TEMP_OUT_H_M = 0x31 + HMC5883_REGISTER_MAG_TEMP_OUT_L_M = 0x32 + +# MAGNETOMETER GAIN SETTINGS +# See http://www.adafruit.com/datasheets/HMC5883L_3-Axis_Digital_Compass_IC.pdf +# (Reg , factor) + HMC5883_MAGGAIN_0_88 = (0x00, 0.73) # +/- 0.88 + HMC5883_MAGGAIN_1_3 = (0x20, 0.92) # +/- 1.3 + HMC5883_MAGGAIN_1_9 = (0x40, 1.22) # +/- 1.9 + HMC5883_MAGGAIN_2_5 = (0x60, 1.52) # +/- 2.5 + HMC5883_MAGGAIN_4_0 = (0x80, 2.27) # +/- 4.0 + HMC5883_MAGGAIN_4_7 = (0xA0, 2.56) # +/- 4.7 + HMC5883_MAGGAIN_5_6 = (0xC0, 3.03) # +/- 5.6 + HMC5883_MAGGAIN_8_1 = (0xE0, 4.35) # +/- 8.1 + + HMC5883_MODE_CONTINUOUS = 0x00 + HMC5883_MODE_SINGLE = 0x01 + HMC5883_MODE_IDLE = 0x10 + + def __init__(self, busnum=-1, debug=False, declination=(0,0)): + self.bus = Adafruit_I2C(self.HMC5883_ADDRESS, busnum, debug) + self.setDeclination(declination[0], declination[1]) + # Set initial scaling factor + self.gain=self.HMC5883_MAGGAIN_1_3 + self.setScale(self.gain) + # Set measurement mode to continuous intially + self.setMode(self.HMC5883_MODE_CONTINUOUS) + + self.debug = debug + + def __str__(self): + ret_str = "" + (x, y, z) = self.getAxes() + ret_str += "Axis X: "+str(x)+"\n" + ret_str += "Axis Y: "+str(y)+"\n" + ret_str += "Axis Z: "+str(z)+"\n" + ret_str += "Declination: "+ self.getDeclinationString() +"\n" + ret_str += "Heading: " + self.getHeadingString() + "\n" + return ret_str + + def setMode(self, mode=None): + if mode == None: + self.mode = self.HMC5883_MODE_SINGLE + else: + self.mode = mode + self.bus.write8(self.HMC5883_REGISTER_MAG_MR_REG_M, self.mode) + + def setScale(self, gain): + self.gain = gain + self.setOption(self.HMC5883_REGISTER_MAG_CRB_REG_M, self.gain[0]) + + def setOption(self, register, *function_set): + options = 0x00 + for function in function_set: + options = options | function + self.bus.write8(register, options) + + # Adds to existing options of register + def addOption(self, register, *function_set): + options = self.bus.read_byte(register) + for function in function_set: + options = options | function + self.bus.write8(register, options) + + # Removes options of register + def removeOption(self, register, *function_set): + options = self.bus.read_byte(register) + for function in function_set: + options = options & (function ^ 0b11111111) + self.bus.write8(register, options) + + def setDeclination(self, degree, min = 0): + self.declinationDeg = degree + self.declinationMin = min + self.declination = (degree+min/60) * (math.pi/180) + + def getDeclination(self): + return (self.declinationDeg, self.declinationMin) + + def getDeclinationString(self): + return str(self.declinationDeg)+"° "+str(self.declinationMin)+"'" + + # Returns heading + def getHeading(self, DMS=False): + (scaled_x, scaled_y, scaled_z) = self.getAxes() + + headingRad = math.atan2(scaled_y, scaled_x) + headingRad += self.declination + + # Correct for reversed heading + if(headingRad < 0): + headingRad += 2*math.pi + + # Check for wrap and compensate + if(headingRad > 2*math.pi): + headingRad -= 2*math.pi + + # Convert to degrees from radians + headingDeg = headingRad * 180/math.pi + degrees = math.floor(headingDeg) + minutes = round(((headingDeg - degrees) * 60)) + if DMS: + return (degrees, minutes) + else: + return headingDeg + + def getHeadingString(self): + (degrees, minutes) = self.getHeading(True) + return str(degrees)+"° "+str(minutes)+"'" + + def getAxes(self): + (magno_x, magno_z, magno_y) = ( self.bus.readS16(self.HMC5883_REGISTER_MAG_OUT_X_H_M, False), + self.bus.readS16(self.HMC5883_REGISTER_MAG_OUT_Z_H_M, False), + self.bus.readS16(self.HMC5883_REGISTER_MAG_OUT_Y_H_M, False) ) + + if (magno_x == -4096): + magno_x = None + else: + magno_x = round(magno_x * self.gain[1], 4) + + if (magno_y == -4096): + magno_y = None + else: + magno_y = round(magno_y * self.gain[1], 4) + + if (magno_z == -4096): + magno_z = None + else: + magno_z = round(magno_z * self.gain[1], 4) + + return (magno_x, magno_y, magno_z) + +# Simple example prints heading and x, y & z data once per second: +if __name__ == '__main__': + + from time import sleep + + # Set declination for your location as (degrees, minutes) + # See http://magnetic-declination.com + mag = Adafruit_HMC5883L(declination=(11,35)) + + while True: + print mag + sleep(1) # Output is fun to watch if this is commented out diff --git a/Adafruit_HMC5883L/Adafruit_I2C.py b/Adafruit_HMC5883L/Adafruit_I2C.py new file mode 120000 index 00000000..77f06164 --- /dev/null +++ b/Adafruit_HMC5883L/Adafruit_I2C.py @@ -0,0 +1 @@ +../Adafruit_I2C/Adafruit_I2C.py \ No newline at end of file diff --git a/Adafruit_PFC8547LCD/Adafruit_I2C.py b/Adafruit_PFC8547LCD/Adafruit_I2C.py new file mode 120000 index 00000000..77f06164 --- /dev/null +++ b/Adafruit_PFC8547LCD/Adafruit_I2C.py @@ -0,0 +1 @@ +../Adafruit_I2C/Adafruit_I2C.py \ No newline at end of file diff --git a/Adafruit_PFC8547LCD/Adafruit_PFC8547LCD.py b/Adafruit_PFC8547LCD/Adafruit_PFC8547LCD.py new file mode 100755 index 00000000..9f27dc16 --- /dev/null +++ b/Adafruit_PFC8547LCD/Adafruit_PFC8547LCD.py @@ -0,0 +1,305 @@ +from time import sleep +from Adafruit_I2C import Adafruit_I2C + +# Code based on https://gist.github.com/ufux/6094977 +# Massaged to use Adafruit_I2C library and commands. +# Communication from expander to display: high nibble first, then low nibble +# Communication via i2c to the PCF 8547: bits are processed from highest to lowest (send P7 bit first) + +class Adafruit_PCF8547LCD: + #initializes objects and lcd + + # LCD Commands + LCD_CLEARDISPLAY = 0x01 + LCD_RETURNHOME = 0x02 + LCD_ENTRYMODESET = 0x04 + LCD_DISPLAYCONTROL = 0x08 + LCD_CURSORSHIFT = 0x10 + LCD_FUNCTIONSET = 0x20 + LCD_SETCGRAMADDR = 0x40 + LCD_SETDDRAMADDR = 0x80 + + # Flags for display on/off control + LCD_DISPLAYON = 0x04 + LCD_DISPLAYOFF = 0x00 + LCD_CURSORON = 0x02 + LCD_CURSOROFF = 0x00 + LCD_BLINKON = 0x01 + LCD_BLINKOFF = 0x00 + + # Flags for display entry mode + LCD_ENTRYRIGHT = 0x00 + LCD_ENTRYLEFT = 0x02 + LCD_ENTRYSHIFTINCREMENT = 0x01 + LCD_ENTRYSHIFTDECREMENT = 0x00 + + # Flags for display/cursor shift + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + LCD_MOVERIGHT = 0x04 + LCD_MOVELEFT = 0x00 + + # flags for function set + LCD_8BITMODE = 0x10 + LCD_4BITMODE = 0x00 + LCD_2LINE = 0x08 + LCD_1LINE = 0x00 + LCD_5x10DOTS = 0x04 + LCD_5x8DOTS = 0x00 + + # flags for backlight control + LCD_BACKLIGHT = 0x08 + LCD_NOBACKLIGHT = 0x00 + + EN = 0b00000100 # Enable bit + RW = 0b00000010 # Read/Write bit + RS = 0b00000001 # Register select bit + + ''' + new pinout: + ----------- ----------- + 0x80 P7 - - D7 + 0x40 P6 - - D6 + 0x20 P5 - - D5 + 0x10 P4 - - D4 + ----------- ----------- + 0x08 P3 - - BL Backlight ??? + 0x04 P2 - - EN Starts Data read/write + 0x02 P1 - - RW low: write, high: read + 0x01 P0 - - RS Register Select: 0: Instruction Register (IR) (AC when read), 1: data register (DR) + ''' + + def __init__(self, addr=0x3f, busnum=-1, withBacklight=True, withOneTimeInit=False): + ''' + device writes! + crosscheck also http://www.monkeyboard.org/tutorials/81-display/70-usb-serial-to-hd44780-lcd + here a sequence is listed + ''' + self.addr = addr + self.busnum = busnum + + self.bus = Adafruit_I2C(self.addr, self.busnum) + + self.displayshift = (self.LCD_CURSORMOVE | + self.LCD_MOVERIGHT) + self.displaymode = (self.LCD_ENTRYLEFT | + self.LCD_ENTRYSHIFTDECREMENT) + self.displaycontrol = (self.LCD_DISPLAYON | + self.LCD_CURSOROFF | + self.LCD_BLINKOFF) + + self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS + self.displayfunction |= self.LCD_2LINE + + if withBacklight: + self.blFlag=self.LCD_BACKLIGHT + else: + self.blFlag=self.LCD_NOBACKLIGHT + + # we can initialize the display only once after it had been powered on + if(withOneTimeInit): + self.bus.writeRaw8(0x3f) + self.pulseEnable() + sleep(0.0100) # TODO: Not clear if we have to wait that long + self.write(self.displayfunction) # 0x28 + + self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol) # 0x08 + 0x4 = 0x0C + self.write(self.LCD_ENTRYMODESET | self.displaymode) # 0x06 + self.clear() # 0x01 + self.home() + + def begin(self, cols, lines): + if (lines > 1): + self.numlines = lines + self.displayfunction |= self.LCD_2LINE + + def home(self): + self.write(self.LCD_RETURNHOME) # set cursor position to zero + self.delayMicroseconds(3000) # this command takes a long time! + + def clear(self): + self.write(self.LCD_CLEARDISPLAY) # command to clear display + self.delayMicroseconds(3000) # 3000 microsecond sleep, clearing the display takes a long time + + def setCursor(self, col, row): + self.row_offsets = [0x00, 0x40, 0x14, 0x54] + if row > self.numlines: + row = self.numlines + row -= 1 # row_offsets is zero indexed + self.write(self.LCD_SETDDRAMADDR | (col - 1 + self.row_offsets[row])) + + def noDisplay(self): + """ Turn the display off (quickly) """ + self.displaycontrol &= ~self.LCD_DISPLAYON + self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def display(self): + """ Turn the display on (quickly) """ + self.displaycontrol |= self.LCD_DISPLAYON + self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def noCursor(self): + """ Turns the underline cursor off """ + self.displaycontrol &= ~self.LCD_CURSORON + self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def cursor(self): + """ Turns the underline cursor on """ + self.displaycontrol |= self.LCD_CURSORON + self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def noBlink(self): + """ Turn the blinking cursor off """ + self.displaycontrol &= ~self.LCD_BLINKON + self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def blink(self): + """ Turn the blinking cursor on """ + self.displaycontrol |= self.LCD_BLINKON + self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def DisplayLeft(self): + """ These commands scroll the display without changing the RAM """ + self.write(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) + + def scrollDisplayRight(self): + """ These commands scroll the display without changing the RAM """ + self.write(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT) + + def leftToRight(self): + """ This is for text that flows Left to Right """ + self.displaymode |= self.LCD_ENTRYLEFT + self.write(self.LCD_ENTRYMODESET | self.displaymode) + + def rightToLeft(self): + """ This is for text that flows Right to Left """ + self.displaymode &= ~self.LCD_ENTRYLEFT + self.write(self.LCD_ENTRYMODESET | self.displaymode) + + def autoscroll(self): + """ This will 'right justify' text from the cursor """ + self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT + self.write(self.LCD_ENTRYMODESET | self.displaymode) + + def noAutoscroll(self): + """ This will 'left justify' text from the cursor """ + self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT + self.write(self.LCD_ENTRYMODESET | self.displaymode) + + def delayMicroseconds(self, microseconds): + seconds = microseconds / float(1000000) # divide microseconds by 1 million for seconds + sleep(seconds) + + # clocks EN to latch command + def pulseEnable(self): + # uses underlying + self.bus.writeRaw8((self.bus.bus.read_byte(self.addr) | self.EN | self.blFlag)) # | 0b0000 0100 # set "EN" high + self.bus.writeRaw8(((self.bus.bus.read_byte(self.addr) | self.blFlag) & 0xFB)) # & 0b1111 1011 # set "EN" low + + # write data to lcd in 4 bit mode, 2 nibbles + # high nibble is sent first + def write(self, cmd): + #write high nibble first + self.bus.writeRaw8( (cmd & 0xF0) | self.blFlag ) + hi= self.bus.bus.read_byte(self.addr) + self.pulseEnable() + + # write low nibble second ... + self.bus.writeRaw8( (cmd << 4) | self.blFlag ) + lo= self.bus.bus.read_byte(self.addr) + self.pulseEnable() + self.bus.writeRaw8(self.blFlag) + + # write a character to lcd (or character rom) 0x09: backlight | RS=DR + def write_char(self, charvalue): + controlFlag = self.blFlag | self.RS + + # write high nibble + self.bus.writeRaw8((controlFlag | (charvalue & 0xF0))) + self.pulseEnable() + + # write low nibble + self.bus.writeRaw8((controlFlag | (charvalue << 4))) + self.pulseEnable() + self.bus.writeRaw8(self.blFlag) + + # put char function + def putc(self, char): + self.write_char(ord(char)) + + def _setDDRAMAdress(self, line, col): + # we write to the Data Display RAM (DDRAM) + # TODO: Factor line offsets for other display organizations; this is for 20x4 only + if line == 1: + self.write(self.LCD_SETDDRAMADDR | (0x00 + col) ) + if line == 2: + self.write(self.LCD_SETDDRAMADDR | (0x40 + col) ) + if line == 3: + self.write(self.LCD_SETDDRAMADDR | (0x14 + col) ) + if line == 4: + self.write(self.LCD_SETDDRAMADDR | (0x54 + col) ) + + # put string function + def message(self, string, line=1): + """ Send string to LCD. Newline wraps to next line. + Starts at line 1 unless passed starting line """ + self._setDDRAMAdress(line, 0) + for char in string: + if char == '\n': + line = 1 if line > 4 else line + 1 + self._setDDRAMAdress(line, 0) + else: + self.putc(char) + + def putString(self, string): + """ Sends a string to LCD starting at current cursor position + Doesn't handle newline character + """ + for char in string: + self.putc(char) + + # add custom characters (0 - 7) + def lcd_load_custon_chars(self, fontdata): + self.lcd_device.bus.write(0x40); + for char in fontdata: + for line in char: + self.write_char(line) + +if __name__ == '__main__': + from time import localtime, strftime + + initFlag=False + debug=False + backlight=True + + lcd = Adafruit_PCF8547LCD(0x3f,1,backlight, initFlag) + lcd.begin(20,4) + msg = "+" + "=" * 18 + "+\n" + msg += "| 20x4 LCD |\n" + msg += "| w/ PCF8547 |\n" + msg += "+" + "=" * 18 + "+" + + lcd.message(msg) + sleep(3) + + lcd.clear() + lcd.cursor() + lcd.message("Cursor Positioning") + lcd.setCursor(2,4) + lcd.putString(". <- (2,4)") + lcd.setCursor(6,2) + lcd.putString(". <- (6,2)") + lcd.setCursor(11,3) + lcd.putString(".") + lcd.setCursor(1,3) + lcd.putString("(11,3) -> ") + + sleep(5) + + lcd.clear() + lcd.noCursor() + lcd.message(" Simple Clock ",1) + lcd.message("CTRL-C to quit",4) + while True: + lcd.message(strftime("%Y-%m-%d %H:%M:%S ", localtime()),3) + sleep(1) diff --git a/Adafruit_SharpIR/Adafruit_I2C.py b/Adafruit_SharpIR/Adafruit_I2C.py new file mode 120000 index 00000000..77f06164 --- /dev/null +++ b/Adafruit_SharpIR/Adafruit_I2C.py @@ -0,0 +1 @@ +../Adafruit_I2C/Adafruit_I2C.py \ No newline at end of file diff --git a/Adafruit_SharpIR/Adafruit_SharpIR.py b/Adafruit_SharpIR/Adafruit_SharpIR.py new file mode 100644 index 00000000..74a0d475 --- /dev/null +++ b/Adafruit_SharpIR/Adafruit_SharpIR.py @@ -0,0 +1,126 @@ +#!/usr/bin/python +import Adafruit_BBIO.ADC as ADC +from time import sleep +import sys +""" +For the BeagleBone Black the input voltage has to be 0-1.8V +The easiest way is with a voltage divider + + Ra Rb +Vin -->--[== 1K ==]--+--[== 560 ==]----+ + | | + V | + | | + Vout === Gnd + - + Rb +Vout = --------- x Vin + Ra + Rb + +Scale factor for voltage divider to get original Vin: (Ra+Rb)/Rb + +Requires numpy and scipy.optimize for the calibration calculations + +""" + +class Adafruit_SharpIR(object): + + def __init__(self, AIN="AIN1", min=10, max=80, scale=2.5, coeff=28, power=-1): + """ + min/max: minimum and maximum distances for the sensor + scale: scaling factor to apply to measured voltages to convert + measured voltage to actual voltage. If sampled voltage is + coming from a voltage divider then scale = (Ra+Rb)/Rb + coeff: coefficient determined from calibration + power: powerterm determined from calibration + """ + self.AIN = AIN + self.min = min + self.max = max + self.scale = scale + self.coeff = coeff + self.power = power + ADC.setup(AIN) + return + + def calibrate(self, numsteps): + """ + Calculates the coefficient and power terms for the sensor by recording + voltage measurements at known distances and then performing an + exponential curve fit on the data. + + numsteps: the number of measurements to take from min to max distance + more steps will give a more accurate curve + """ + import numpy as np + from scipy.optimize import curve_fit + + distances = range(self.min, self.max+1, (self.max-self.min)/numsteps) + voltages = [] + + def func(x, a, b): + """ + Curve fitting function. Used to fit data points to the curve + y = a * x ^ b + """ + return a * x ** b + + print('IR Calibration') + print('\nThe calibration process requires you to place an object ' \ + '(a flat piece of card is good) at a variety of distances from ' \ + 'the minumum distance to the maximum distance.\n\n' \ + 'Voltage readings will be taken at (cm):') + print distances + + for d in distances: + print("Measure @ %d cm" % (d)) + sleep(3) + for x in range(5): + sys.stdout.write("%d " % (5-x)) + sys.flush() + sleep(1) + + print("\nReading @ %d cm" % (d)) + value = 0.0 + total = 0.0 + for x in range(5): + value = ADC.read(self.AIN) * 1.8 * self.scale + total = total + value + print("#%d - %2.4f" % (x+1, value)) + sleep(1) + print("%d cm Average: %2.4f" % (d, total/5)) + print"=" * 15 + voltages.append(total/5) + + # fits measured voltages to y = a * x ^ B curve + popt, pcov = curve_fit(func, np.array(voltages), np.array(distances)) + self.coeff = popt[0] + self.power = popt[1] + print "Calibration Data" + print "-" * 15 + print "Coefficient :", self.coeff + print "Power :", self.power + print "Err 1 std dev:", np.sqrt(np.diag(pcov)) + print "\nEquation : distance = %2.2f * scaled_voltage ** %2.2f" % (self.coeff, self.power) + print "-" * 15 + print "Example use:" + print ' IR = Adafruit_SharpIR("P9_36", scale=1560.0/560.0, coeff=%2.6f, power=%2.6f)' % (self.coeff, self.power) + print "-" * 15 + + def distance(self): + """ + Returns the distance in cm using the calibration data + """ + distance = self.coeff * (ADC.read(self.AIN) * 1.8 * self.scale) ** self.power + if distance < self.min: + distance = -1 # invalid distance + elif distance > self.max: + distance = self.max + return distance + +if __name__ == '__main__': + IR = Adafruit_SharpIR("P9_36", scale=1560.0/560.0) + IR.calibrate(10) + while 1: + print IR.distance() + sleep(1) \ No newline at end of file