Merge branch 'master' of github.com:jamesbowman/i2cdriver
This commit is contained in:
commit
651dec5ac2
|
@ -5,8 +5,9 @@
|
|||
I2CDriver is a tool for controlling any I2C device from your PC's USB port,
|
||||
and can also monitor and capture I2C traffic.
|
||||
It connects as a standard USB serial device, so there are no drivers to install.
|
||||
The serial protocol is [very simple](/protocol.md),
|
||||
and there are included drivers for
|
||||
On the main site
|
||||
[i2cdriver.com](https://i2cdriver.com),
|
||||
there are drivers for
|
||||
|
||||
* Windows/Mac/Linux GUI
|
||||
* Windows/Mac/Linux command-line
|
||||
|
|
|
@ -4,13 +4,11 @@ import time
|
|||
import struct
|
||||
from collections import OrderedDict
|
||||
|
||||
__version__ = '0.0.2'
|
||||
__version__ = '0.0.3'
|
||||
|
||||
PYTHON2 = (sys.version_info < (3, 0))
|
||||
|
||||
from lm75b import *
|
||||
import EDS
|
||||
import bargraph
|
||||
|
||||
class I2CTimeout(Exception):
|
||||
pass
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
"""
|
||||
Example for Bi-Color (Red/Green) 24-Bar Bargraph, based on HT16K33.
|
||||
Available from Adafruit.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import serial
|
||||
import time
|
||||
import struct
|
||||
import random
|
||||
|
||||
from i2cdriver import I2CDriver
|
||||
|
||||
from ht16k33 import HT16K33
|
||||
|
||||
class bargraph(HT16K33):
|
||||
def image(self, bb):
|
||||
def swiz(b):
|
||||
bs = [str((b >> n) & 1) for n in range(8)]
|
||||
return int(bs[7] + bs[0] + bs[1] + bs[2] + bs[3] + bs[4] + bs[5] + bs[6], 2)
|
||||
bb = [swiz(b) for b in bb]
|
||||
self.load([b for s in zip(bb,bb) for b in s])
|
||||
|
||||
def char(self, c):
|
||||
n = ord(c)
|
||||
ch = font[n * 8:n * 8 + 8]
|
||||
self.image(ch)
|
||||
|
||||
def set(self, pix):
|
||||
rr = pix
|
||||
def paint(r, i):
|
||||
|
@ -33,3 +26,12 @@ class bargraph(HT16K33):
|
|||
[paint(red, i) for i in range(24) if (pix[i] & 1)]
|
||||
[paint(grn, i) for i in range(24) if (pix[i] & 2)]
|
||||
self.load([red[0], grn[0], red[1], grn[1], red[2], grn[2]])
|
||||
|
||||
if __name__ == '__main__':
|
||||
i2 = I2CDriver(sys.argv[1])
|
||||
|
||||
d0 = bargraph(i2)
|
||||
|
||||
for i in range(60):
|
||||
d0.set([random.choice((0,1,2,3)) for i in range(24)])
|
||||
time.sleep(.08)
|
|
@ -0,0 +1,210 @@
|
|||
"""
|
||||
Example for BNO080 integrated IMU.
|
||||
Available from Sparkfun.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import serial
|
||||
import time
|
||||
import struct
|
||||
import random
|
||||
import math
|
||||
|
||||
from i2cdriver import I2CDriver
|
||||
def hexdump(s):
|
||||
def toprint(c):
|
||||
if 32 <= c < 127:
|
||||
return chr(c)
|
||||
else:
|
||||
return "."
|
||||
def hexline(s):
|
||||
return (" ".join(["%02x" % c for c in s]).ljust(49) +
|
||||
"|" +
|
||||
"".join([toprint(c) for c in s]).ljust(16) +
|
||||
"|")
|
||||
return "\n".join([hexline(s[i:i+16]) for i in range(0, len(s), 16)])
|
||||
|
||||
CHANNEL_COMMAND = 0
|
||||
CHANNEL_EXECUTABLE = 1
|
||||
CHANNEL_CONTROL = 2
|
||||
CHANNEL_REPORTS = 3
|
||||
CHANNEL_WAKE_REPORTS = 4
|
||||
CHANNEL_GYRO = 5
|
||||
|
||||
# All the ways we can configure or talk to the BNO080, figure 34, page 36 reference manual
|
||||
# These are used for low level communication with the sensor, on channel 2
|
||||
SHTP_REPORT_COMMAND_RESPONSE = 0xF1
|
||||
SHTP_REPORT_COMMAND_REQUEST = 0xF2
|
||||
SHTP_REPORT_FRS_READ_RESPONSE = 0xF3
|
||||
SHTP_REPORT_FRS_READ_REQUEST = 0xF4
|
||||
SHTP_REPORT_PRODUCT_ID_RESPONSE = 0xF8
|
||||
SHTP_REPORT_PRODUCT_ID_REQUEST = 0xF9
|
||||
SHTP_REPORT_BASE_TIMESTAMP = 0xFB
|
||||
SHTP_REPORT_SET_FEATURE_COMMAND = 0xFD
|
||||
|
||||
# All the different sensors and features we can get reports from
|
||||
# These are used when enabling a given sensor
|
||||
SENSOR_REPORTID_ACCELEROMETER = 0x01
|
||||
SENSOR_REPORTID_GYROSCOPE = 0x02
|
||||
SENSOR_REPORTID_MAGNETIC_FIELD = 0x03
|
||||
SENSOR_REPORTID_LINEAR_ACCELERATION = 0x04
|
||||
SENSOR_REPORTID_ROTATION_VECTOR = 0x05
|
||||
SENSOR_REPORTID_GRAVITY = 0x06
|
||||
SENSOR_REPORTID_GAME_ROTATION_VECTOR = 0x08
|
||||
SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR = 0x09
|
||||
SENSOR_REPORTID_TAP_DETECTOR = 0x10
|
||||
SENSOR_REPORTID_STEP_COUNTER = 0x11
|
||||
SENSOR_REPORTID_STABILITY_CLASSIFIER = 0x13
|
||||
SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER = 0x1E
|
||||
|
||||
# Record IDs from figure 29, page 29 reference manual
|
||||
# These are used to read the metadata for each sensor type
|
||||
FRS_RECORDID_ACCELEROMETER = 0xE302
|
||||
FRS_RECORDID_GYROSCOPE_CALIBRATED = 0xE306
|
||||
FRS_RECORDID_MAGNETIC_FIELD_CALIBRATED = 0xE309
|
||||
FRS_RECORDID_ROTATION_VECTOR = 0xE30B
|
||||
|
||||
# Command IDs from section 6.4, page 42
|
||||
# These are used to calibrate, initialize, set orientation, tare etc the sensor
|
||||
COMMAND_ERRORS = 1
|
||||
COMMAND_COUNTER = 2
|
||||
COMMAND_TARE = 3
|
||||
COMMAND_INITIALIZE = 4
|
||||
COMMAND_DCD = 6
|
||||
COMMAND_ME_CALIBRATE = 7
|
||||
COMMAND_DCD_PERIOD_SAVE = 9
|
||||
COMMAND_OSCILLATOR = 10
|
||||
COMMAND_CLEAR_DCD = 11
|
||||
|
||||
CALIBRATE_ACCEL = 0
|
||||
CALIBRATE_GYRO = 1
|
||||
CALIBRATE_MAG = 2
|
||||
CALIBRATE_PLANAR_ACCEL = 3
|
||||
CALIBRATE_ACCEL_GYRO_MAG = 4
|
||||
CALIBRATE_STOP = 5
|
||||
|
||||
def normalize(v, tolerance=0.00001):
|
||||
mag2 = sum(n * n for n in v)
|
||||
if abs(mag2 - 1.0) > tolerance:
|
||||
mag = math.sqrt(mag2)
|
||||
v = tuple(n / mag for n in v)
|
||||
return v
|
||||
|
||||
class BNO080:
|
||||
def __init__(self, i2, a = 0x4b):
|
||||
self.i2 = i2
|
||||
self.a = a
|
||||
self.seqno = [0] * 8
|
||||
|
||||
if 1:
|
||||
self.sendPacket(CHANNEL_EXECUTABLE, [1])
|
||||
time.sleep(0.150)
|
||||
while True:
|
||||
if not self.receivePacket():
|
||||
break
|
||||
|
||||
self.setFeature(SENSOR_REPORTID_ROTATION_VECTOR, 50000)
|
||||
|
||||
def read_quaternion(self):
|
||||
while True:
|
||||
r = self.receivePacket()
|
||||
while r:
|
||||
tag = r[0]
|
||||
r = r[1:]
|
||||
if tag == 0xfb:
|
||||
# print("Time %d" % struct.unpack("I", r[:4]))
|
||||
r = r[4:]
|
||||
elif tag == SHTP_REPORT_COMMAND_RESPONSE:
|
||||
r = r[16:]
|
||||
elif tag == 0xfc:
|
||||
# print("Get Feature Response")
|
||||
r = r[17:]
|
||||
elif tag == SENSOR_REPORTID_ACCELEROMETER:
|
||||
r = r[10:]
|
||||
elif tag == SENSOR_REPORTID_ROTATION_VECTOR:
|
||||
(_,_,_,i,j,k,w,_) = struct.unpack("<BBBhhhhh", r[:14])
|
||||
Q14 = 2 ** -14
|
||||
# print((i * Q14, j * Q14, k * Q14, w * Q14))
|
||||
return (w * Q14, i * Q14, j * Q14, k * Q14)
|
||||
r = r[14:]
|
||||
else:
|
||||
assert 0, "Bad tag %#x" % tag
|
||||
|
||||
def setFeature(self, reportID, timeBetweenReports, specificConfig = 0):
|
||||
p = struct.pack("<BBBHIII",
|
||||
SHTP_REPORT_SET_FEATURE_COMMAND,
|
||||
reportID,
|
||||
0, 0,
|
||||
timeBetweenReports,
|
||||
0, specificConfig)
|
||||
# print(hexdump(p))
|
||||
|
||||
self.sendPacket(CHANNEL_CONTROL, p)
|
||||
|
||||
def sendPacket(self, channel, data):
|
||||
# print('send on', channel, 'seq', self.seqno[channel])
|
||||
self.i2.start(self.a, 0)
|
||||
self.i2.write(struct.pack("<HBB", 4 + len(data), channel, self.seqno[channel]))
|
||||
self.i2.write(data)
|
||||
self.i2.stop()
|
||||
self.seqno[channel] += 1
|
||||
|
||||
def receivePacket(self):
|
||||
if not self.i2.start(self.a, 1):
|
||||
self.i2.stop()
|
||||
return None
|
||||
hdr = self.i2.read(4)
|
||||
self.i2.stop()
|
||||
length, channel, sequence = (struct.unpack("<HBB", hdr))
|
||||
length &= 0x7fff
|
||||
# print()
|
||||
# print('length', length)
|
||||
# print('channel', channel)
|
||||
# print('sequence', sequence)
|
||||
if length == 0 or channel not in range(8):
|
||||
return None
|
||||
|
||||
# self.seqno[channel] = sequence + 1
|
||||
|
||||
self.i2.start(self.a, 1)
|
||||
data = self.i2.read(length)
|
||||
self.i2.stop()
|
||||
# print(len(data), repr(data))
|
||||
# print(hexdump(data[4:]))
|
||||
return data[4:]
|
||||
|
||||
def showpacket(self, data):
|
||||
tag = data[0]
|
||||
print('tag', tag)
|
||||
r = data[1:]
|
||||
if tag == 0:
|
||||
self.showpacket_00(r)
|
||||
else:
|
||||
assert False, "Cannot show packet %02x" % tag
|
||||
|
||||
def showpacket_00(self, ad):
|
||||
while ad:
|
||||
(T, L) = struct.unpack("BB", ad[:2])
|
||||
V = ad[2:2+L]
|
||||
decoder = {
|
||||
1: lambda: ("GUID", struct.unpack("I", V)),
|
||||
2: lambda: ("MaxCargoPlusHeaderWrite", struct.unpack("H", V)),
|
||||
3: lambda: ("MaxCargoPlusHeaderRead", struct.unpack("H", V)),
|
||||
4: lambda: ("MaxTransferWrite", struct.unpack("H", V)),
|
||||
5: lambda: ("MaxTransferRead", struct.unpack("H", V)),
|
||||
6: lambda: ("NormalChannel", struct.unpack("B", V)),
|
||||
7: lambda: ("WakeChannel", struct.unpack("B", V)),
|
||||
8: lambda: ("AppName", (V[:-1].decode(), )),
|
||||
9: lambda: ("ChannelName", (V[:-1].decode(), )),
|
||||
0x80: lambda: ("SHTP Version", (V[:-1].decode(), )),
|
||||
}.get(T, lambda: (str(T), (V,)))
|
||||
(nm,f) = decoder()
|
||||
print("%5d %-26s: %r" % ((len(ad), nm, ) + f))
|
||||
ad = ad[2+L:]
|
||||
|
||||
if __name__ == '__main__':
|
||||
i2 = I2CDriver(sys.argv[1])
|
||||
|
||||
d = BNO080(i2)
|
||||
while True:
|
||||
print('quaternion:', d.read_quaternion())
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
python led8x8.py /dev/ttyUSB0
|
||||
# python EDS-take-a-ticket.py /dev/ttyUSB0
|
||||
# python i2cgui.py
|
|
@ -240,7 +240,6 @@ class Frame(wx.Frame):
|
|||
def read(self, e):
|
||||
n = int(self.rxCount.GetValue())
|
||||
if self.addr is not None:
|
||||
print("read", n)
|
||||
self.start(1)
|
||||
r = self.sd.read(n)
|
||||
bb = struct.unpack("B"*n, r)
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
"""
|
||||
Example for LCD1602, in which a PCF8574 I/O expander drives a HD44780.
|
||||
Available from various vendors.
|
||||
|
||||
Note that the modules require a 5V VCC; they don't function using the
|
||||
3.3V VCC of I2CDriver.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
import struct
|
||||
|
||||
from i2cdriver import I2CDriver
|
||||
|
||||
class HD44780:
|
||||
|
||||
def __init__(self, i2, a = 0x27):
|
||||
self.i2 = i2
|
||||
self.a = a
|
||||
|
||||
self.nybble(3) # Enter 4-bit mode
|
||||
self.nybble(3)
|
||||
self.nybble(3)
|
||||
self.nybble(2)
|
||||
|
||||
self.cmd(0x28) # 2 lines, 5x8 dot matrix
|
||||
self.cmd(0x0c) # display on
|
||||
self.cmd(0x06) # inc cursor to right when writing and don't scroll
|
||||
self.cmd(0x80) # set cursor to row 1, column 1
|
||||
|
||||
self.clear()
|
||||
|
||||
def clear(self):
|
||||
""" Clear the screen """
|
||||
self.cmd(0x01)
|
||||
time.sleep(.003)
|
||||
|
||||
def show(self, line, text):
|
||||
""" Send string to LCD. Newline wraps to second line"""
|
||||
self.cmd({0:0x80, 1:0xc0}[line])
|
||||
for c in text:
|
||||
self.data(ord(c))
|
||||
|
||||
def cmd(self, b):
|
||||
self.nybble(b >> 4)
|
||||
self.nybble(b & 0xf)
|
||||
time.sleep(.000053)
|
||||
|
||||
def data(self, b):
|
||||
self.nybble(b >> 4, 1)
|
||||
self.nybble(b & 0xf, 1)
|
||||
|
||||
# The PCF8574 outputs are connected to the HD44780
|
||||
# pins as follows:
|
||||
|
||||
# P0 RS (0: command, 1: data)
|
||||
# P1 R/W (0: write, 1: read)
|
||||
# P2 Enable/CLK
|
||||
# P3 Backlight control
|
||||
# P4-7 D4-D7
|
||||
|
||||
def nybble(self, n, rs = 0):
|
||||
bl = 8 | rs
|
||||
self.port(
|
||||
bl | (n << 4),
|
||||
bl | (n << 4) | 4,
|
||||
bl | (n << 4)
|
||||
)
|
||||
|
||||
def port(self, *bb):
|
||||
# Write bytes to port, setting the PCF8574 outputs
|
||||
self.i2.start(self.a, 0)
|
||||
self.i2.write(bb)
|
||||
self.i2.stop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
i2 = I2CDriver(sys.argv[1])
|
||||
d = HD44780(i2)
|
||||
d.show(0, "HELLO WORLD")
|
||||
time.sleep(.5)
|
||||
d.show(1, "0123456789012345")
|
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
Example for 8x8 LED Matrix modules, based on HT16K33.
|
||||
Available from multiple vendors.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
from i2cdriver import I2CDriver
|
||||
|
||||
font = open("cp437-8x8", "rb").read()
|
||||
|
||||
from ht16k33 import HT16K33
|
||||
|
||||
class led8x8(HT16K33):
|
||||
def image(self, bb):
|
||||
""" Set the pixels to the bytes bb """
|
||||
def swiz(b):
|
||||
bs = [str((b >> n) & 1) for n in range(8)]
|
||||
return int(bs[7] + bs[0] + bs[1] + bs[2] + bs[3] + bs[4] + bs[5] + bs[6], 2)
|
||||
bb = [swiz(b) for b in bb]
|
||||
self.load([b for s in zip(bb,bb) for b in s])
|
||||
|
||||
def char(self, c):
|
||||
""" Set the pixels to character c """
|
||||
n = ord(c)
|
||||
ch = font[n * 8:n * 8 + 8]
|
||||
self.image(ch)
|
||||
|
||||
if __name__ == '__main__':
|
||||
i2 = I2CDriver(sys.argv[1])
|
||||
|
||||
d = led8x8(i2)
|
||||
|
||||
for c in "I2C":
|
||||
d.char(c)
|
||||
time.sleep(1)
|
Binary file not shown.
After Width: | Height: | Size: 342 B |
|
@ -0,0 +1,35 @@
|
|||
"""
|
||||
Example Xtrinsic MAG3110 Three-Axis Digital Magnetometer
|
||||
Breakout available from Sparkfun.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import struct
|
||||
import time
|
||||
|
||||
from i2cdriver import I2CDriver, EDS
|
||||
|
||||
class MAG3110:
|
||||
def __init__(self, i2, a = 0x0e):
|
||||
self.i2 = i2
|
||||
self.a = a
|
||||
self.i2.regwr(self.a, 0x10, 0b00000001) # CTRL_REG1. ACTIVE mode, 80 Hz conversions
|
||||
|
||||
def rd(self):
|
||||
""" Read the measurement STATUS_REG and OUT_X,Y,Z """
|
||||
return self.i2.regrd(self.a, 0x00, ">B3h")
|
||||
|
||||
def measurement(self):
|
||||
""" Wait for a new field reading, return the (x,y,z) """
|
||||
while True:
|
||||
(status, x, y, z) = self.rd()
|
||||
if status & 8:
|
||||
return (x, y, z)
|
||||
|
||||
if __name__ == '__main__':
|
||||
i2 = I2CDriver(sys.argv[1])
|
||||
i2.scan()
|
||||
|
||||
d = MAG3110(i2)
|
||||
while 1:
|
||||
print(d.measurement())
|
|
@ -0,0 +1,107 @@
|
|||
"""
|
||||
Example for 128X64OLED Module
|
||||
Available from multiple vendors, e.g. DIYMall
|
||||
|
||||
This example loads the I2CDriver logo onto the display,
|
||||
and flashes it four times.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
from PIL import Image, ImageChops
|
||||
|
||||
from i2cdriver import I2CDriver
|
||||
|
||||
SETCONTRAST = 0x81
|
||||
DISPLAYALLON_RESUME = 0xA4
|
||||
DISPLAYALLON = 0xA5
|
||||
NORMALDISPLAY = 0xA6
|
||||
INVERTDISPLAY = 0xA7
|
||||
DISPLAYOFF = 0xAE
|
||||
DISPLAYON = 0xAF
|
||||
SETDISPLAYOFFSET = 0xD3
|
||||
SETCOMPINS = 0xDA
|
||||
SETVCOMDETECT = 0xDB
|
||||
SETDISPLAYCLOCKDIV = 0xD5
|
||||
SETPRECHARGE = 0xD9
|
||||
SETMULTIPLEX = 0xA8
|
||||
SETLOWCOLUMN = 0x00
|
||||
SETHIGHCOLUMN = 0x10
|
||||
SETSTARTLINE = 0x40
|
||||
MEMORYMODE = 0x20
|
||||
COLUMNADDR = 0x21
|
||||
PAGEADDR = 0x22
|
||||
COMSCANINC = 0xC0
|
||||
COMSCANDEC = 0xC8
|
||||
SEGREMAP = 0xA0
|
||||
CHARGEPUMP = 0x8D
|
||||
|
||||
class OLED:
|
||||
def __init__(self, i2, a = 0x3c):
|
||||
self.i2 = i2
|
||||
self.a = a
|
||||
|
||||
self.command(DISPLAYOFF)
|
||||
self.command(SETDISPLAYCLOCKDIV, 0x80) # the suggested ratio 0x80
|
||||
|
||||
self.command(SETMULTIPLEX, 0x3f)
|
||||
|
||||
self.command(SETDISPLAYOFFSET, 0)
|
||||
self.command(SETSTARTLINE | 0x0)
|
||||
self.command(CHARGEPUMP, 0x14)
|
||||
self.command(MEMORYMODE, 0)
|
||||
self.command(SEGREMAP | 0x1)
|
||||
self.command(COMSCANDEC)
|
||||
|
||||
self.command(SETCOMPINS, 0x12)
|
||||
self.command(SETCONTRAST, 0xcf)
|
||||
|
||||
self.command(SETVCOMDETECT, 0x40)
|
||||
self.command(DISPLAYALLON_RESUME)
|
||||
self.command(NORMALDISPLAY)
|
||||
|
||||
self.im = Image.new("1", (128,64), 1)
|
||||
self.cls()
|
||||
|
||||
def command(self, *c):
|
||||
assert(self.i2.start(self.a, 0))
|
||||
assert(self.i2.write((0,) + c))
|
||||
self.i2.stop()
|
||||
|
||||
def image(self, im):
|
||||
for p in range(8):
|
||||
pr = self.im.crop((0,8*p,128,8*p+8)).transpose(Image.ROTATE_270)
|
||||
bb = im.crop((0,8*p,128,8*p+8)).transpose(Image.ROTATE_270)
|
||||
diff = ImageChops.difference(pr, bb)
|
||||
di = diff.getbbox()
|
||||
if di is not None:
|
||||
(x0, y0, x1, y1) = di
|
||||
self.command(COLUMNADDR)
|
||||
self.command(y0)
|
||||
self.command(y1 - 1)
|
||||
self.command(PAGEADDR)
|
||||
self.command(p)
|
||||
self.command(p + 1)
|
||||
self.i2.start(self.a, 0)
|
||||
self.i2.write([0x40])
|
||||
self.i2.write(bb.tobytes()[y0:y1])
|
||||
self.i2.stop()
|
||||
self.im = im
|
||||
self.command(DISPLAYON)
|
||||
|
||||
def cls(self):
|
||||
self.image(Image.new("1", (128,64), 0))
|
||||
|
||||
if __name__ == '__main__':
|
||||
i2 = I2CDriver(sys.argv[1])
|
||||
d = OLED(i2)
|
||||
|
||||
d.image(Image.open("logo.png").convert("1"))
|
||||
|
||||
for i in range(4):
|
||||
d.command(INVERTDISPLAY)
|
||||
time.sleep(.5)
|
||||
d.command(NORMALDISPLAY)
|
||||
time.sleep(.5)
|
|
@ -0,0 +1,43 @@
|
|||
"""
|
||||
Example for Qwiic Joystick
|
||||
Available from Sparkfun.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
import struct
|
||||
|
||||
from i2cdriver import I2CDriver
|
||||
|
||||
class Joystick:
|
||||
def __init__(self, i2, a = 0x20):
|
||||
self.i2 = i2
|
||||
self.a = a
|
||||
|
||||
def axis(self, i):
|
||||
self.i2.start(self.a, 0)
|
||||
self.i2.write([i])
|
||||
self.i2.stop() # Note: their firmware cannot handle an I2C restart
|
||||
self.i2.start(self.a, 1)
|
||||
(r,) = struct.unpack(">H", self.i2.read(2))
|
||||
self.i2.stop()
|
||||
return r
|
||||
|
||||
def read(self):
|
||||
"""
|
||||
return the joystick (x,y) position. The range is 0-1023.
|
||||
The center position of the joystick is approximately 512.
|
||||
"""
|
||||
|
||||
# Note: their firmware requires two separate reads
|
||||
|
||||
return (self.axis(0), self.axis(2))
|
||||
|
||||
if __name__ == '__main__':
|
||||
i2 = I2CDriver(sys.argv[1])
|
||||
|
||||
d = Joystick(i2)
|
||||
|
||||
while 1:
|
||||
print(d.read())
|
||||
time.sleep(.1)
|
|
@ -0,0 +1,44 @@
|
|||
"""
|
||||
Example for Qwiic Keypad
|
||||
Available from Sparkfun.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
import struct
|
||||
|
||||
from i2cdriver import I2CDriver
|
||||
|
||||
class Keypad:
|
||||
def __init__(self, i2, a = 0x4b):
|
||||
self.i2 = i2
|
||||
self.a = a
|
||||
|
||||
def read_ts(self):
|
||||
"""
|
||||
Return (key, timestamp) if pressed, or None.
|
||||
"""
|
||||
|
||||
self.i2.start(self.a, 1)
|
||||
(k, age_in_ms) = struct.unpack(">BH", self.i2.read(3))
|
||||
self.i2.stop()
|
||||
if k != 0:
|
||||
return (chr(k), time.time() - age_in_ms * .001)
|
||||
else:
|
||||
return None
|
||||
|
||||
def read(self):
|
||||
r = self.read_ts()
|
||||
if r:
|
||||
return r[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
if __name__ == '__main__':
|
||||
i2 = I2CDriver(sys.argv[1])
|
||||
|
||||
d = Keypad(i2)
|
||||
|
||||
while 1:
|
||||
print(d.read())
|
||||
time.sleep(.1)
|
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Example for MPR121 Capacitive Touch Sensor.
|
||||
Available from multiple vendors.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import serial
|
||||
import time
|
||||
import struct
|
||||
import random
|
||||
|
||||
from i2cdriver import I2CDriver
|
||||
|
||||
class MPR121:
|
||||
def __init__(self, i2, a = 0x5a):
|
||||
self.i2 = i2
|
||||
self.a = a
|
||||
self.i2.regwr(self.a, 0x5e, 0x0c)
|
||||
|
||||
def read(self):
|
||||
""" Return 12 touch detection flags """
|
||||
(tb,) = struct.unpack("<H", self.i2.regrd(0x5a, 0, 2))
|
||||
return [((tb >> i) & 1) for i in range(12)]
|
||||
|
||||
if __name__ == '__main__':
|
||||
i2 = I2CDriver(sys.argv[1])
|
||||
|
||||
i2.reset()
|
||||
|
||||
d = MPR121(i2)
|
||||
while 1:
|
||||
print(d.read())
|
||||
time.sleep(.1)
|
|
@ -19,9 +19,6 @@ setup(name='i2cdriver',
|
|||
install_requires=['pyserial'],
|
||||
py_modules = [
|
||||
'i2cdriver',
|
||||
'lm75b',
|
||||
'EDS',
|
||||
'ht16k33',
|
||||
'bargraph',
|
||||
],
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue