aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Schodet2023-06-28 23:03:13 +0200
committerNicolas Schodet2024-01-03 01:28:36 +0100
commit86ca27f8490be3e332f8e0b15e92b0cab5faa335 (patch)
treef87641e9223b01315642be777ac6e2141dba410e
parente64e020afa308ddb37b319ea8a9f4c1af8750992 (diff)
Ran isort, black and flake8 on digital sensors
There is still a large amount of work to do on documentation and cleanup.
-rw-r--r--.pre-commit-config.yaml14
-rw-r--r--nxt/sensor/digital.py183
-rw-r--r--nxt/sensor/hitechnic.py589
-rw-r--r--nxt/sensor/mindsensors.py853
4 files changed, 927 insertions, 712 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index cee6751..5b06e0a 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -15,24 +15,10 @@ repos:
rev: 23.1.0
hooks:
- id: black
- # Exclude files not cleaned up yet.
- exclude: |
- (?x)^(
- nxt/sensor/digital\.py|
- nxt/sensor/hitechnic\.py|
- nxt/sensor/mindsensors\.py|
- )$
- repo: https://github.com/pycqa/flake8
rev: 5.0.4
hooks:
- id: flake8
- # Exclude files not cleaned up yet.
- exclude: |
- (?x)^(
- nxt/sensor/digital\.py|
- nxt/sensor/hitechnic\.py|
- nxt/sensor/mindsensors\.py|
- )$
- repo: local
hooks:
- id: pytest
diff --git a/nxt/sensor/digital.py b/nxt/sensor/digital.py
index 4cc33e6..9f7f223 100644
--- a/nxt/sensor/digital.py
+++ b/nxt/sensor/digital.py
@@ -2,6 +2,7 @@
# Copyright (C) 2006,2007 Douglas P Lau
# Copyright (C) 2009 Marcus Wanner, Paulo Vieira, rhn
# Copyright (C) 2010,2011,2012 Marcus Wanner
+# Copyright (C) 2023 Nicolas Schodet
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -30,51 +31,58 @@ class SensorInfo:
self.sensor_type = sensor_type
def clarifybinary(self, instr, label):
- outstr = ''
- outstr += (label + ': `' + instr + '`\n')
+ outstr = ""
+ outstr += label + ": `" + instr + "`\n"
for char in instr:
- outstr += (hex(ord(char))+', ')
- outstr += ('\n')
+ outstr += hex(ord(char)) + ", "
+ outstr += "\n"
return outstr
def __str__(self):
- outstr = ''
- outstr += (self.clarifybinary(str(self.version), 'Version'))
- outstr += (self.clarifybinary(str(self.product_id), 'Product ID'))
- outstr += (self.clarifybinary(str(self.sensor_type), 'Type'))
+ outstr = ""
+ outstr += self.clarifybinary(str(self.version), "Version")
+ outstr += self.clarifybinary(str(self.product_id), "Product ID")
+ outstr += self.clarifybinary(str(self.sensor_type), "Type")
return outstr
+
class BaseDigitalSensor(nxt.sensor.Sensor):
- """Object for digital sensors. I2C_ADDRESS is the dictionary storing name
- to i2c address mappings. It should be updated in every subclass. When
- subclassing this class, make sure to call add_compatible_sensor to add
- compatible sensor data.
+ """Object for digital sensors.
+
+ :param bool check_compatible: Check sensor class match the connected sensor.
+
+ If `check_compatible` is ``True``, queries the sensor for its name and print
+ a warning if the wrong sensor class is used.
+
+ `I2C_ADDRESS` is the dictionary storing name to I2C address mappings. It should be
+ updated in every subclass. When subclassing this class, make sure to call
+ :func:`add_compatible_sensor` to add compatible sensor data.
"""
+
I2C_DEV = 0x02
- I2C_ADDRESS = {'version': (0x00, '8s'),
- 'product_id': (0x08, '8s'),
- 'sensor_type': (0x10, '8s'),
-# 'factory_zero': (0x11, 1), # is this really correct?
- 'factory_scale_factor': (0x12, 'B'),
- 'factory_scale_divisor': (0x13, 'B'),
+ I2C_ADDRESS = {
+ "version": (0x00, "8s"),
+ "product_id": (0x08, "8s"),
+ "sensor_type": (0x10, "8s"),
+ # "factory_zero": (0x11, 1), # is this really correct?
+ "factory_scale_factor": (0x12, "B"),
+ "factory_scale_divisor": (0x13, "B"),
}
def __init__(self, brick, port, check_compatible=True):
- """Creates a BaseDigitalSensor. If check_compatible is True, queries
- the sensor for its name, and if a wrong sensor class was used, prints
- a warning.
- """
super().__init__(brick, port)
self.set_input_mode(nxt.sensor.Type.LOW_SPEED_9V, nxt.sensor.Mode.RAW)
self.last_poll = time.time()
self.poll_delay = 0.01
time.sleep(0.1) # Give I2C time to initialize
- #Don't do type checking if this class has no compatible sensors listed.
- try: self.compatible_sensors
- except AttributeError: check_compatible = False
+ # Don't do type checking if this class has no compatible sensors listed.
+ try:
+ self.compatible_sensors
+ except AttributeError:
+ check_compatible = False
if check_compatible:
sensor = self.get_sensor_info()
- if not sensor in self.compatible_sensors:
+ if sensor not in self.compatible_sensors:
logger.warning(
"wrong sensor class chosen for sensor %s on port %s",
sensor.product_id,
@@ -91,37 +99,43 @@ class BaseDigitalSensor(nxt.sensor.Sensor):
)
def _ls_get_status(self, size):
- for n in range(30): #https://code.google.com/p/nxt-python/issues/detail?id=35
+ for n in range(30): # https://code.google.com/p/nxt-python/issues/detail?id=35
try:
b = self._brick.ls_get_status(self._port)
if b >= size:
return b
except I2CPendingError:
pass
- raise I2CError('ls_get_status timeout')
+ raise I2CError("ls_get_status timeout")
def _i2c_command(self, address, value, format):
- """Writes an i2c value to the given address. value must be a string. value is
- a tuple of values corresponding to the given format.
+ """Write one or several values to an I2C register.
+
+ :param int address: I2C register address.
+ :param tuple value: Tuple of values to write.
+ :param str format: Format string using :mod:`struct` syntax.
"""
value = struct.pack(format, *value)
msg = bytes((self.I2C_DEV, address)) + value
now = time.time()
- if self.last_poll+self.poll_delay > now:
+ if self.last_poll + self.poll_delay > now:
diff = now - self.last_poll
time.sleep(self.poll_delay - diff)
self.last_poll = time.time()
self._brick.ls_write(self._port, msg, 0)
def _i2c_query(self, address, format):
- """Reads an i2c value from given address, and returns a value unpacked
- according to the given format. Format is the same as in the struct
- module. See http://docs.python.org/library/struct.html#format-strings
+ """Read one or several values from an I2C register.
+
+ :param int address: I2C register address.
+ :param str format: Format string using :mod:`struct` syntax.
+ :return: Read values in a tuple.
+ :rtype: tuple
"""
size = struct.calcsize(format)
msg = bytes((self.I2C_DEV, address))
now = time.time()
- if self.last_poll+self.poll_delay > now:
+ if self.last_poll + self.poll_delay > now:
diff = now - self.last_poll
time.sleep(self.poll_delay - diff)
self.last_poll = time.time()
@@ -129,19 +143,22 @@ class BaseDigitalSensor(nxt.sensor.Sensor):
try:
self._ls_get_status(size)
finally:
- #we should clear the buffer no matter what happens
+ # we should clear the buffer no matter what happens
data = self._brick.ls_read(self._port)
if len(data) < size:
- raise I2CError('Read failure: Not enough bytes')
+ raise I2CError("Read failure: Not enough bytes")
data = struct.unpack(format, data[-size:])
return data
def read_value(self, name):
- """Reads a value from the sensor. Name must be a string found in
- self.I2C_ADDRESS dictionary. Entries in self.I2C_ADDRESS are in the
- name: (address, format) form, with format as in the struct module.
- Be careful on unpacking single variables - struct module puts them in
- tuples containing only one element.
+ """Read one or several values from the sensor.
+
+ :param str name: Name of the values to read.
+ :return: Read values in a tuple.
+ :rtype: tuple
+
+ The `name` parameter is an index inside `I2C_ADDRESS` dictionary, which gives
+ the corresponding I2C register address and format string.
"""
address, fmt = self.I2C_ADDRESS[name]
for n in range(3):
@@ -152,62 +169,78 @@ class BaseDigitalSensor(nxt.sensor.Sensor):
raise I2CError("read_value timeout")
def write_value(self, name, value):
- """Writes value to the sensor. Name must be a string found in
- self.I2C_ADDRESS dictionary. Entries in self.I2C_ADDRESS are in the
- name: (address, format) form, with format as in the struct module.
- value is a tuple of values corresponding to the format from
- self.I2C_ADDRESS dictionary.
+ """Write one or several values to the sensor.
+
+ :param str name: Name of the values to write.
+ :param tuple value: Tuple of values to write.
+
+ The `name` parameter is an index inside `I2C_ADDRESS` dictionary, which gives
+ the corresponding I2C register address and format string.
"""
address, fmt = self.I2C_ADDRESS[name]
self._i2c_command(address, value, fmt)
def get_sensor_info(self):
- version = self.read_value('version')[0].decode('windows-1252').split('\0')[0]
- product_id = self.read_value('product_id')[0].decode('windows-1252').split('\0')[0]
- sensor_type = self.read_value('sensor_type')[0].decode('windows-1252').split('\0')[0]
+ version = self.read_value("version")[0].decode("windows-1252").split("\0")[0]
+ product_id = (
+ self.read_value("product_id")[0].decode("windows-1252").split("\0")[0]
+ )
+ sensor_type = (
+ self.read_value("sensor_type")[0].decode("windows-1252").split("\0")[0]
+ )
return SensorInfo(version, product_id, sensor_type)
@classmethod
def add_compatible_sensor(cls, version, product_id, sensor_type):
- """Adds an entry in the compatibility table for the sensor. If version
- is None, then it's the default class for this model. If product_id is
- None, then this is the default class for this vendor.
+ """Adds an entry in the compatibility table for the sensor.
+
+ :param version: Sensor version, or ``None`` for default class.
+ :type version: str or None
+ :param product_id: Product identifier, or ``None`` for default class.
+ :type product_id: str or None
+ :param str sensor_type: Sensor type
"""
try:
cls.compatible_sensors
except AttributeError:
cls.compatible_sensors = []
finally:
- cls.compatible_sensors.append(SCompatibility(version, product_id,
- sensor_type))
- add_mapping(cls, version, product_id, sensor_type)
+ cls.compatible_sensors.append(
+ _SCompatibility(version, product_id, sensor_type)
+ )
+ _add_mapping(cls, version, product_id, sensor_type)
-class SCompatibility(SensorInfo):
- """An object that helps manage the sensor mappings"""
+class _SCompatibility(SensorInfo):
+ """An object that helps manage the sensor mappings."""
+
def __eq__(self, other):
if self.product_id is None:
return self.product_id == other.product_id
elif self.version is None:
- return (self.product_id == other.product_id and
- self.sensor_type == other.sensor_type)
+ return (
+ self.product_id == other.product_id
+ and self.sensor_type == other.sensor_type
+ )
else:
- return (self.version == other.version and
- self.product_id == other.product_id and
- self.sensor_type == other.sensor_type)
+ return (
+ self.version == other.version
+ and self.product_id == other.product_id
+ and self.sensor_type == other.sensor_type
+ )
+
sensor_mappings = {}
-def add_mapping(cls, version, product_id, sensor_type):
- "None means any other value"
+def _add_mapping(cls, version, product_id, sensor_type):
if product_id not in sensor_mappings:
sensor_mappings[product_id] = {}
models = sensor_mappings[product_id]
if sensor_type is None:
if sensor_type in models:
- raise ValueError('Already registered!')
+ raise ValueError("Already registered!")
models[sensor_type] = cls
return
@@ -216,7 +249,7 @@ def add_mapping(cls, version, product_id, sensor_type):
versions = models[sensor_type]
if version in versions:
- raise ValueError('Already registered!')
+ raise ValueError("Already registered!")
else:
versions[version] = cls
@@ -226,14 +259,22 @@ class SearchError(Exception):
def find_class(info):
- """Returns an appropriate class for the given SensorInfo"""
+ """Returns an appropriate class.
+
+ :param SensorInfo info: Information read from the sensor.
+ :return: Class corresponding to sensor.
+ :rtype: BaseDigitalSensor
+ :raises SearchError: When no class found.
+ """
dic = sensor_mappings
- for val, msg in zip((info.product_id, info.sensor_type, info.version),
- ('Vendor', 'Model', 'Version')):
+ for val, msg in zip(
+ (info.product_id, info.sensor_type, info.version),
+ ("Vendor", "Model", "Version"),
+ ):
if val in dic:
dic = dic[val]
elif None in dic:
dic = dic[None]
else:
- raise SearchError(msg + ' not found')
+ raise SearchError(msg + " not found")
return dic[info.sensor_type][None]
diff --git a/nxt/sensor/hitechnic.py b/nxt/sensor/hitechnic.py
index f35d62f..b9c48d8 100644
--- a/nxt/sensor/hitechnic.py
+++ b/nxt/sensor/hitechnic.py
@@ -24,11 +24,15 @@ from nxt.sensor.digital import BaseDigitalSensor
class Compass(BaseDigitalSensor):
"""Hitechnic compass sensor."""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'mode': (0x41, 'B'),
- 'heading': (0x42, 'B'),
- 'adder': (0x43, 'B'),
- })
+ I2C_ADDRESS.update(
+ {
+ "mode": (0x41, "B"),
+ "heading": (0x42, "B"),
+ "adder": (0x43, "B"),
+ }
+ )
class Modes:
MEASUREMENT = 0x00
@@ -37,9 +41,8 @@ class Compass(BaseDigitalSensor):
def get_heading(self):
"""Returns heading from North in degrees."""
-
- two_degree_heading = self.read_value('heading')[0]
- adder = self.read_value('adder')[0]
+ two_degree_heading = self.read_value("heading")[0]
+ adder = self.read_value("adder")[0]
heading = two_degree_heading * 2 + adder
return heading
@@ -47,7 +50,7 @@ class Compass(BaseDigitalSensor):
get_sample = get_heading
def get_relative_heading(self, target=0):
- rheading = self.get_sample()-target
+ rheading = self.get_sample() - target
if rheading > 180:
rheading -= 360
elif rheading < -180:
@@ -68,38 +71,38 @@ class Compass(BaseDigitalSensor):
inverted = False
heading = self.get_sample()
in_range = (heading > minval) and (heading < maxval)
- """
- an xor handles the reversal
- a faster, more compact way of saying
- if !reversed return in_range
- if reversed return !in_range
- """
return bool(inverted) ^ bool(in_range)
def get_mode(self):
- return self.read_value('mode')[0]
+ return self.read_value("mode")[0]
def set_mode(self, mode):
if mode != self.Modes.MEASUREMENT and mode != self.Modes.CALIBRATION:
- raise ValueError('Invalid mode specified: ' + str(mode))
- self.write_value('mode', (mode, ))
+ raise ValueError("Invalid mode specified: " + str(mode))
+ self.write_value("mode", (mode,))
-Compass.add_compatible_sensor(None, 'HiTechnc', 'Compass ') # Tested with version '\xfdV1.23 '
-Compass.add_compatible_sensor(None, 'HITECHNC', 'Compass ') # Tested with version '\xfdV2.1 '
+Compass.add_compatible_sensor(
+ None, "HiTechnc", "Compass "
+) # Tested with version '\xfdV1.23 '
+Compass.add_compatible_sensor(
+ None, "HITECHNC", "Compass "
+) # Tested with version '\xfdV2.1 '
class Accelerometer(BaseDigitalSensor):
- """
- Object for Accelerometer sensors. Thanks to Paulo Vieira.
- """
+ """Object for Accelerometer sensors. Thanks to Paulo Vieira."""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'x_axis_high': (0x42, 'b'),
- 'y_axis_high': (0x43, 'b'),
- 'z_axis_high': (0x44, 'b'),
- 'xyz_short': (0x42, '3b'),
- 'all_data': (0x42, '3b3B')
- })
+ I2C_ADDRESS.update(
+ {
+ "x_axis_high": (0x42, "b"),
+ "y_axis_high": (0x43, "b"),
+ "z_axis_high": (0x44, "b"),
+ "xyz_short": (0x42, "3b"),
+ "all_data": (0x42, "3b3B"),
+ }
+ )
class Acceleration:
def __init__(self, x, y, z):
@@ -109,10 +112,8 @@ class Accelerometer(BaseDigitalSensor):
super().__init__(brick, port, check_compatible)
def get_acceleration(self):
- """
- Returns the acceleration along x, y, z axes. 200 => 1g.
- """
- xh, yh, zh, xl, yl, zl = self.read_value('all_data')
+ """Returns the acceleration along x, y, z axes. 200 => 1g."""
+ xh, yh, zh, xl, yl, zl = self.read_value("all_data")
x = xh << 2 | xl
y = yh << 2 | yl
z = zh << 2 | zl
@@ -121,35 +122,46 @@ class Accelerometer(BaseDigitalSensor):
get_sample = get_acceleration
-Accelerometer.add_compatible_sensor(None, 'HiTechnc', 'Accel. ')
-Accelerometer.add_compatible_sensor(None, 'HITECHNC', 'Accel. ') # Tested with version '\xfdV1.1 '
+Accelerometer.add_compatible_sensor(None, "HiTechnc", "Accel. ")
+Accelerometer.add_compatible_sensor(
+ None, "HITECHNC", "Accel. "
+) # Tested with version '\xfdV1.1 '
-# noinspection PyPep8Naming
class IRReceiver(BaseDigitalSensor):
"""
Object for HiTechnic IRReceiver sensors for use with LEGO Power Functions IR
Remotes. Coded to HiTechnic's specs for the sensor but not tested. Please report
whether this worked for you or not!
"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({
- 'm1A': (0x42, 'b'),
- 'm1B': (0x43, 'b'),
- 'm2A': (0x44, 'b'),
- 'm2B': (0x45, 'b'),
- 'm3A': (0x46, 'b'),
- 'm3B': (0x47, 'b'),
- 'm4A': (0x48, 'b'),
- 'm4B': (0x49, 'b'),
- 'all_data': (0x42, '8b')
- })
-
- # noinspection PyPep8Naming
+ I2C_ADDRESS.update(
+ {
+ "m1A": (0x42, "b"),
+ "m1B": (0x43, "b"),
+ "m2A": (0x44, "b"),
+ "m2B": (0x45, "b"),
+ "m3A": (0x46, "b"),
+ "m3B": (0x47, "b"),
+ "m4A": (0x48, "b"),
+ "m4B": (0x49, "b"),
+ "all_data": (0x42, "8b"),
+ }
+ )
+
class SpeedReading:
def __init__(self, m1A, m1B, m2A, m2B, m3A, m3B, m4A, m4B):
- self.m1A, self.m1B, self.m2A, self.m2B, self.m3A, self.m3B, self.m4A, self.m4B = \
- m1A, m1B, m2A, m2B, m3A, m3B, m4A, m4B
+ (
+ self.m1A,
+ self.m1B,
+ self.m2A,
+ self.m2B,
+ self.m3A,
+ self.m3B,
+ self.m4A,
+ self.m4B,
+ ) = (m1A, m1B, m2A, m2B, m3A, m3B, m4A, m4B)
self.channel_1 = (m1A, m1B)
self.channel_2 = (m2A, m2B)
self.channel_3 = (m3A, m3B)
@@ -165,14 +177,14 @@ class IRReceiver(BaseDigitalSensor):
and 100. -128 specifies motor brake mode. Note that no motors are actually
being controlled here!
"""
- m1A, m1B, m2A, m2B, m3A, m3B, m4A, m4B = self.read_value('all_data')
+ m1A, m1B, m2A, m2B, m3A, m3B, m4A, m4B = self.read_value("all_data")
return self.SpeedReading(m1A, m1B, m2A, m2B, m3A, m3B, m4A, m4B)
get_sample = get_speeds
-IRReceiver.add_compatible_sensor(None, 'HiTechnc', 'IRRecv ')
-IRReceiver.add_compatible_sensor(None, 'HITECHNC', 'IRRecv ')
+IRReceiver.add_compatible_sensor(None, "HiTechnc", "IRRecv ")
+IRReceiver.add_compatible_sensor(None, "HITECHNC", "IRRecv ")
class IRSeekerv2(BaseDigitalSensor):
@@ -180,25 +192,28 @@ class IRSeekerv2(BaseDigitalSensor):
Object for HiTechnic IRSeeker sensors. Coded to HiTechnic's specs for the sensor
but not tested. Please report whether this worked for you or not!
"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({
- 'dspmode': (0x41, 'B'),
- 'DC_direction': (0x42, 'B'),
- 'DC_sensor_1': (0x43, 'B'),
- 'DC_sensor_2': (0x44, 'B'),
- 'DC_sensor_3': (0x45, 'B'),
- 'DC_sensor_4': (0x46, 'B'),
- 'DC_sensor_5': (0x47, 'B'),
- 'DC_sensor_mean': (0x48, 'B'),
- 'all_DC': (0x42, '7B'),
- 'AC_direction': (0x49, 'B'),
- 'AC_sensor_1': (0x4A, 'B'),
- 'AC_sensor_2': (0x4B, 'B'),
- 'AC_sensor_3': (0x4C, 'B'),
- 'AC_sensor_4': (0x4D, 'B'),
- 'AC_sensor_5': (0x4E, 'B'),
- 'all_AC': (0x49, '6B')
- })
+ I2C_ADDRESS.update(
+ {
+ "dspmode": (0x41, "B"),
+ "DC_direction": (0x42, "B"),
+ "DC_sensor_1": (0x43, "B"),
+ "DC_sensor_2": (0x44, "B"),
+ "DC_sensor_3": (0x45, "B"),
+ "DC_sensor_4": (0x46, "B"),
+ "DC_sensor_5": (0x47, "B"),
+ "DC_sensor_mean": (0x48, "B"),
+ "all_DC": (0x42, "7B"),
+ "AC_direction": (0x49, "B"),
+ "AC_sensor_1": (0x4A, "B"),
+ "AC_sensor_2": (0x4B, "B"),
+ "AC_sensor_3": (0x4C, "B"),
+ "AC_sensor_4": (0x4D, "B"),
+ "AC_sensor_5": (0x4E, "B"),
+ "all_AC": (0x49, "6B"),
+ }
+ )
I2C_DEV = 0x10 # different from standard 0x02
class DSPModes:
@@ -206,26 +221,57 @@ class IRSeekerv2(BaseDigitalSensor):
AC_DSP_1200Hz = 0x00
AC_DSP_600Hz = 0x01
- # noinspection PyPep8Naming
class _data:
def get_dir_brightness(self, direction):
"""Gets the brightness of a given direction (1-9)."""
if direction % 2 == 1: # if it's an odd number
- val = getattr(self, "sensor_%d" % ((direction-1)//2+1))
+ val = getattr(self, "sensor_%d" % ((direction - 1) // 2 + 1))
else:
- val = (getattr(self, f"sensor_{direction // 2}")
- + getattr(self, f"sensor_{direction // 2 + 1}")) / 2
+ val = (
+ getattr(self, f"sensor_{direction // 2}")
+ + getattr(self, f"sensor_{direction // 2 + 1}")
+ ) / 2
return val
class DCData(_data):
- def __init__(self, direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5, sensor_mean):
- self.direction, self.sensor_1, self.sensor_2, self.sensor_3, self.sensor_4, self.sensor_5, self.sensor_mean\
- = direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5, sensor_mean
+ def __init__(
+ self,
+ direction,
+ sensor_1,
+ sensor_2,
+ sensor_3,
+ sensor_4,
+ sensor_5,
+ sensor_mean,
+ ):
+ (
+ self.direction,
+ self.sensor_1,
+ self.sensor_2,
+ self.sensor_3,
+ self.sensor_4,
+ self.sensor_5,
+ self.sensor_mean,
+ ) = (
+ direction,
+ sensor_1,
+ sensor_2,
+ sensor_3,
+ sensor_4,
+ sensor_5,
+ sensor_mean,
+ )
class ACData(_data):
def __init__(self, direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5):
- self.direction, self.sensor_1, self.sensor_2, self.sensor_3, self.sensor_4, self.sensor_5 =\
- direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5
+ (
+ self.direction,
+ self.sensor_1,
+ self.sensor_2,
+ self.sensor_3,
+ self.sensor_4,
+ self.sensor_5,
+ ) = (direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5)
def __init__(self, brick, port, check_compatible=True):
super().__init__(brick, port, check_compatible)
@@ -234,28 +280,40 @@ class IRSeekerv2(BaseDigitalSensor):
"""
Returns the unmodulated (DC) values.
"""
- direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5, sensor_mean = self.read_value('all_DC')
- return self.DCData(direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5, sensor_mean)
+ (
+ direction,
+ sensor_1,
+ sensor_2,
+ sensor_3,
+ sensor_4,
+ sensor_5,
+ sensor_mean,
+ ) = self.read_value("all_DC")
+ return self.DCData(
+ direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5, sensor_mean
+ )
def get_ac_values(self):
"""
Returns the modulated (AC) values. 600Hz and 1200Hz modes can be selected
between by using the set_dsp_mode() function.
"""
- direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5 = self.read_value('all_AC')
+ direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5 = self.read_value(
+ "all_AC"
+ )
return self.ACData(direction, sensor_1, sensor_2, sensor_3, sensor_4, sensor_5)
def get_dsp_mode(self):
- return self.read_value('dspmode')[0]
+ return self.read_value("dspmode")[0]
def set_dsp_mode(self, mode):
- self.write_value('dspmode', (mode, ))
+ self.write_value("dspmode", (mode,))
get_sample = get_ac_values
-IRSeekerv2.add_compatible_sensor(None, 'HiTechnc', 'NewIRDir')
-IRSeekerv2.add_compatible_sensor(None, 'HITECHNC', 'NewIRDir')
+IRSeekerv2.add_compatible_sensor(None, "HiTechnc", "NewIRDir")
+IRSeekerv2.add_compatible_sensor(None, "HITECHNC", "NewIRDir")
class EOPD(BaseAnalogSensor):
@@ -272,6 +330,7 @@ class EOPD(BaseAnalogSensor):
def __init__(self, brick, port):
super().__init__(brick, port)
from math import sqrt
+
self.sqrt = sqrt
def set_range_long(self):
@@ -323,43 +382,59 @@ class Colorv2(BaseDigitalSensor):
Object for HiTechnic Color v2 Sensors. Coded to HiTechnic's specs for the sensor
but not tested. Please report whether this worked for you or not!
"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({
- 'mode': (0x41, 'B'),
- 'number': (0x42, 'B'),
- 'red': (0x43, 'B'),
- 'green': (0x44, 'B'),
- 'blue': (0x45, 'B'),
- 'white': (0x46, 'B'),
- 'index': (0x47, 'B'),
- 'normred': (0x48, 'B'),
- 'normgreen': (0x49, 'B'),
- 'normblue': (0x4A, 'B'),
- 'all_data': (0x42, '9B'),
- 'rawred': (0x42, '<H'),
- 'rawgreen': (0x44, '<H'),
- 'rawblue': (0x46, '<H'),
- 'rawwhite': (0x48, '<H'),
- 'all_raw_data': (0x42, '<4H')
- })
+ I2C_ADDRESS.update(
+ {
+ "mode": (0x41, "B"),
+ "number": (0x42, "B"),
+ "red": (0x43, "B"),
+ "green": (0x44, "B"),
+ "blue": (0x45, "B"),
+ "white": (0x46, "B"),
+ "index": (0x47, "B"),
+ "normred": (0x48, "B"),
+ "normgreen": (0x49, "B"),
+ "normblue": (0x4A, "B"),
+ "all_data": (0x42, "9B"),
+ "rawred": (0x42, "<H"),
+ "rawgreen": (0x44, "<H"),
+ "rawblue": (0x46, "<H"),
+ "rawwhite": (0x48, "<H"),
+ "all_raw_data": (0x42, "<4H"),
+ }
+ )
class Modes:
ACTIVE = 0x00 # get measurements using get_active_color
PASSIVE = 0x01 # get measurements using get_passive_color
RAW = 0x03 # get measurements using get_passive_color
BLACK_CALIBRATION = 0x42 # hold away from objects, results saved in EEPROM
- WHITE_CALIBRATION = 0x43 # hold in front of white surface, results saved in EEPROM
+ WHITE_CALIBRATION = (
+ 0x43 # hold in front of white surface, results saved in EEPROM
+ )
LED_POWER_LOW = 0x4C # saved in EEPROM, must calibrate after using
LED_POWER_HIGH = 0x48 # saved in EEPROM, must calibrate after using
RANGE_NEAR = 0x4E # saved in EEPROM, only affects active mode
- RANGE_FAR = 0x46 # saved in EEPROM, only affects active mode, more susceptible to noise
+ RANGE_FAR = (
+ 0x46 # saved in EEPROM, only affects active mode, more susceptible to noise
+ )
FREQ_50 = 0x35 # saved in EEPROM, use when local wall power is 50Hz
FREQ_60 = 0x36 # saved in EEPROM, use when local wall power is 60Hz
class ActiveData:
- def __init__(self, number, red, green, blue, white, index, normred, normgreen, normblue):
- self.number, self.red, self.green, self.blue, self.white, self.index, self.normred, self.normgreen, \
- self.normblue = number, red, green, blue, white, index, normred, normgreen, normblue
+ def __init__(
+ self, number, red, green, blue, white, index, normred, normgreen, normblue
+ ):
+ self.number = number
+ self.red = red
+ self.green = green
+ self.blue = blue
+ self.white = white
+ self.index = index
+ self.normred = normred
+ self.normgreen = normgreen
+ self.normblue = normblue
class PassiveData:
# also holds raw mode data
@@ -371,27 +446,39 @@ class Colorv2(BaseDigitalSensor):
def get_active_color(self):
"""Returns color values when in active mode."""
- number, red, green, blue, white, index, normred, normgreen, normblue = self.read_value('all_data')
- return self.ActiveData(number, red, green, blue, white, index, normred, normgreen, normblue)
+ (
+ number,
+ red,
+ green,
+ blue,
+ white,
+ index,
+ normred,
+ normgreen,
+ normblue,
+ ) = self.read_value("all_data")
+ return self.ActiveData(
+ number, red, green, blue, white, index, normred, normgreen, normblue
+ )
get_sample = get_active_color
def get_passive_color(self):
"""Returns color values when in passive or raw mode."""
- red, green, blue, white = self.read_value('all_raw_data')
+ red, green, blue, white = self.read_value("all_raw_data")
return self.PassiveData(red, green, blue, white)
def get_mode(self):
- return self.read_value('mode')[0]
+ return self.read_value("mode")[0]
def set_mode(self, mode):
- self.write_value('mode', (mode, ))
+ self.write_value("mode", (mode,))
-Colorv2.add_compatible_sensor(None, 'HiTechnc', 'ColorPD')
-Colorv2.add_compatible_sensor(None, 'HITECHNC', 'ColorPD')
-Colorv2.add_compatible_sensor(None, 'HiTechnc', 'ColorPD ')
-Colorv2.add_compatible_sensor(None, 'HITECHNC', 'ColorPD ')
+Colorv2.add_compatible_sensor(None, "HiTechnc", "ColorPD")
+Colorv2.add_compatible_sensor(None, "HITECHNC", "ColorPD")
+Colorv2.add_compatible_sensor(None, "HiTechnc", "ColorPD ")
+Colorv2.add_compatible_sensor(None, "HITECHNC", "ColorPD ")
class Gyro(BaseAnalogSensor):
@@ -423,26 +510,29 @@ class Gyro(BaseAnalogSensor):
class Prototype(BaseDigitalSensor):
"""Object for HiTechnic sensor prototype boards."""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({
- 'A0': (0x42, '<H'),
- 'A1': (0x44, '<H'),
- 'A2': (0x46, '<H'),
- 'A3': (0x48, '<H'),
- 'A4': (0x4A, '<H'),
- 'all_analog': (0x42, '<5H'),
- 'digital_in': (0x4C, 'B'),
- 'digital_out': (0x4D, 'B'),
- 'digital_cont': (0x4E, 'B'),
- 'sample_time': (0x4F, 'B'),
- })
-
- # noinspection PyPep8Naming
+ I2C_ADDRESS.update(
+ {
+ "A0": (0x42, "<H"),
+ "A1": (0x44, "<H"),
+ "A2": (0x46, "<H"),
+ "A3": (0x48, "<H"),
+ "A4": (0x4A, "<H"),
+ "all_analog": (0x42, "<5H"),
+ "digital_in": (0x4C, "B"),
+ "digital_out": (0x4D, "B"),
+ "digital_cont": (0x4E, "B"),
+ "sample_time": (0x4F, "B"),
+ }
+ )
+
class Digital_Data:
"""
Container for 6 bits of digital data. Takes an integer or a list of six bools
and can be converted into a list of bools or an integer.
"""
+
def __init__(self, pins):
if isinstance(pins, int):
self.dataint = pins
@@ -452,14 +542,12 @@ class Prototype(BaseDigitalSensor):
self.datalst = pins
self.d0, self.d1, self.d2, self.d3, self.d4, self.d5 = self.datalst
- # noinspection PyMethodMayBeStatic
def tolist(self, val):
lst = []
for i in range(6):
lst.append(bool(val & 2**i))
return lst
- # noinspection PyMethodMayBeStatic
def toint(self, lst):
val = 0
for i in range(6):
@@ -475,54 +563,56 @@ class Prototype(BaseDigitalSensor):
def __getitem__(self, i):
return self.datalst[i]
- # noinspection PyPep8Naming
class Analog_Data:
def __init__(self, a0, a1, a2, a3, a4):
self.a0, self.a1, self.a2, self.a3, self.a4 = a0, a1, a2, a3, a4
def get_analog(self):
- return self.Analog_Data(*self.read_value('all_analog'))
+ return self.Analog_Data(*self.read_value("all_analog"))
def get_digital(self):
- return self.Digital_Data(self.read_value('digital_in')[0])
+ return self.Digital_Data(self.read_value("digital_in")[0])
def set_digital(self, pins):
"""Can take a Digital_Data() object"""
- self.write_value('digital_out', (int(pins), ))
+ self.write_value("digital_out", (int(pins),))
def set_digital_modes(self, modes):
"""Sets input/output mode of digital pins. Can take a Digital_Data() object."""
- self.write_value('digital_cont', (int(modes), ))
+ self.write_value("digital_cont", (int(modes),))
-Prototype.add_compatible_sensor(None, 'HiTechnc', 'Proto ')
+Prototype.add_compatible_sensor(None, "HiTechnc", "Proto ")
class SuperPro(BaseDigitalSensor):
"""
Object for HiTechnic sensor SuperPro boards.
"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({
- "version": (0x00, "8s"),
- "manufacturer": (0x08, "8s"),
- "sensor_type": (0x10, "8s"),
- "analog_a0": (0x42, "<H"),
- "analog_a1": (0x44, "<H"),
- "analog_a2": (0x46, "<H"),
- "analog_a3": (0x48, "<H"),
- "digital_in": (0x4C, "<B"),
- "digital_out": (0x4D, "<B"),
- "digital_dir": (0x4E, "<B"),
- "strobe_out": (0x50, "B"),
- "led_out": (0x51, "B"),
- "analog_out0_mode": (0x52, "B"),
- "analog_out0_freq": (0x53, "<H"),
- "analog_out0_volts": (0x55, "H"),
- "analog_out1_mode": (0x57, "B"),
- "analog_out1_freq": (0x58, "<H"),
- "analog_out1_volts": (0x5A, "H")
- })
+ I2C_ADDRESS.update(
+ {
+ "version": (0x00, "8s"),
+ "manufacturer": (0x08, "8s"),
+ "sensor_type": (0x10, "8s"),
+ "analog_a0": (0x42, "<H"),
+ "analog_a1": (0x44, "<H"),
+ "analog_a2": (0x46, "<H"),
+ "analog_a3": (0x48, "<H"),
+ "digital_in": (0x4C, "<B"),
+ "digital_out": (0x4D, "<B"),
+ "digital_dir": (0x4E, "<B"),
+ "strobe_out": (0x50, "B"),
+ "led_out": (0x51, "B"),
+ "analog_out0_mode": (0x52, "B"),
+ "analog_out0_freq": (0x53, "<H"),
+ "analog_out0_volts": (0x55, "H"),
+ "analog_out1_mode": (0x57, "B"),
+ "analog_out1_freq": (0x58, "<H"),
+ "analog_out1_volts": (0x5A, "H"),
+ }
+ )
I2C_DEV = 0x10
@@ -536,7 +626,8 @@ class SuperPro(BaseDigitalSensor):
UPWARDS_SAWTOOTH = 3
DOWNWARDS_SAWTOOTH = 4
TRIANGLE = 5
- PWM = 6 # TODO: Test. Documentation seems to imply this should work, but it wasn't for me.
+ PWM = 6 # TODO: Test. Documentation seems to imply this should work, but it
+ # wasn't for me.
def get_analog(self) -> Dict[str, int]:
"""
@@ -544,7 +635,12 @@ class SuperPro(BaseDigitalSensor):
:return: Map of pin name, pin value (bits)
"""
- analog_in_pin_name_map = [("analog_a0", "a0"), ("analog_a1", "a1"), ("analog_a2", "a2"), ("analog_a3", "a3")]
+ analog_in_pin_name_map = [
+ ("analog_a0", "a0"),
+ ("analog_a1", "a1"),
+ ("analog_a2", "a2"),
+ ("analog_a3", "a3"),
+ ]
analog_raw_map = {}
for pin in analog_in_pin_name_map:
raw = self.read_value(pin[0])[0]
@@ -556,20 +652,25 @@ class SuperPro(BaseDigitalSensor):
def get_analog_volts(self, voltage_reference: float = 3.3) -> Dict[str, float]:
"""
- Get analog input pins (A0-A3) results in volts. Resolution to ~3mV (voltage reference * (1/1023) volts)
+ Get analog input pins (A0-A3) results in volts. Resolution to ~3mV (voltage
+ reference * (1/1023) volts)
- :param voltage_reference: optionally provide measured voltage from 3.3V regulator for more accurate calculations
+ :param voltage_reference: optionally provide measured voltage from 3.3V
+ regulator for more accurate calculations
:return: Map of pin name, pin voltage (in volts)
"""
analog_raw_map = self.get_analog()
analog_voltage_map = {}
for item in analog_raw_map:
- analog_voltage_map[item] = analog_raw_map[item] * self.ANALOG_LSB * voltage_reference
+ analog_voltage_map[item] = (
+ analog_raw_map[item] * self.ANALOG_LSB * voltage_reference
+ )
return analog_voltage_map
@staticmethod
def _byte_to_boolean_list(integer: int, reverse=False) -> List[bool]:
- # Converts byte to boolean string, inverts string to correct bit order if needed, converts chars to boolean list
+ # Converts byte to boolean string, inverts string to correct bit order if
+ # needed, converts chars to boolean list
if reverse:
return [bit == "1" for bit in "{0:08b}".format(integer)[::-1]]
return [bit == "1" for bit in "{0:08b}".format(integer)]
@@ -582,7 +683,7 @@ class SuperPro(BaseDigitalSensor):
boolean_list.reverse()
output_byte = 0
for bit in range(0, 8):
- output = (2 ** bit) * boolean_list[bit]
+ output = (2**bit) * boolean_list[bit]
output_byte += output
return output_byte
@@ -643,10 +744,14 @@ class SuperPro(BaseDigitalSensor):
def set_strobe_output(self, mode_int: int):
"""
- Strobe output - behaves like any other output, but has strobe signal sent whenever a digital read/write sent.
- When a digital read is done, it will send a spike on RD (inverse of the current RD pin state),
- when a digital write is done, it will send a spike on WR (inverse of the current WR pin state)
- This 'digital read' and 'digital write' actions causing a spike applies to the B0-7 pins
+ Strobe output - behaves like any other output, but has strobe signal sent
+ whenever a digital read/write sent.
+ When a digital read is done, it will send a spike on RD (inverse of the current
+ RD pin state),
+ when a digital write is done, it will send a spike on WR (inverse of the current
+ WR pin state)
+ This 'digital read' and 'digital write' actions causing a spike applies to the
+ B0-7 pins
Bits to write: S0 = 1, S1 = 2 S2 = 4 S3 = 8 RD = 16 WR = 32
:param mode_int: mode_int: Byte (0-63 inclusive)
@@ -665,7 +770,9 @@ class SuperPro(BaseDigitalSensor):
output_byte = (red * 0x01) + (blue * 0x02)
self.write_value("led_out", [output_byte])
- def analog_out(self, pin: int, mode: AnalogOutputMode, freq: int, voltage_bits: int):
+ def analog_out(
+ self, pin: int, mode: AnalogOutputMode, freq: int, voltage_bits: int
+ ):
"""
Analog Output Pins
@@ -676,7 +783,7 @@ class SuperPro(BaseDigitalSensor):
"""
if not 0 <= pin <= 1:
raise RuntimeError("Pin must be 0 or 1")
- if not 0 <= voltage_bits <= ((2 ** 10) - 1):
+ if not 0 <= voltage_bits <= ((2**10) - 1):
raise RuntimeError("Integer must be in range of 0 and (2^10)-1 inclusive")
low = voltage_bits & 0b0000000000000011
low_shifted = low << 8
@@ -694,7 +801,14 @@ class SuperPro(BaseDigitalSensor):
self.write_value("analog_out0_freq", [freq_swapped])
self.write_value("analog_out0_volts", [actual_voltage_bits])
- def analog_out_voltage(self, pin: int, mode: AnalogOutputMode, freq: int, voltage: float, voltage_reference=3.3):
+ def analog_out_voltage(
+ self,
+ pin: int,
+ mode: AnalogOutputMode,
+ freq: int,
+ voltage: float,
+ voltage_reference=3.3,
+ ):
"""
Analog Output Pins
@@ -702,7 +816,8 @@ class SuperPro(BaseDigitalSensor):
:param mode: 0-5 for various modes, see AnalogOutputMode class
:param freq: 0 to 2^13Hz (~8kHz) Note: if 0 provided for wave, will get 1Hz
:param voltage: The desired voltage (between 0 and the voltage reference)
- :param voltage_reference: Output 1023 in the analog_out mode to find the maximum voltage, enter it here.
+ :param voltage_reference: Output 1023 in the analog_out mode to find the maximum
+ voltage, enter it here.
"""
if not 0 <= pin <= 1:
raise RuntimeError("Pin must be 0 or 1")
@@ -711,7 +826,7 @@ class SuperPro(BaseDigitalSensor):
self.analog_out(pin, mode, freq, voltage_bits)
-SuperPro.add_compatible_sensor(None, 'HiTechnc', 'SuperPro')
+SuperPro.add_compatible_sensor(None, "HiTechnc", "SuperPro")
class ServoCon(BaseDigitalSensor):
@@ -719,18 +834,21 @@ class ServoCon(BaseDigitalSensor):
Object for HiTechnic FIRST Servo Controllers. Coded to HiTechnic's specs for
the sensor but not tested. Please report whether this worked for you or not!
"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({
- 'status': (0x40, 'B'),
- 'steptime': (0x41, 'B'),
- 's1pos': (0x42, 'B'),
- 's2pos': (0x43, 'B'),
- 's3pos': (0x44, 'B'),
- 's4pos': (0x45, 'B'),
- 's5pos': (0x46, 'B'),
- 's6pos': (0x47, 'B'),
- 'pwm': (0x48, 'B'),
- })
+ I2C_ADDRESS.update(
+ {
+ "status": (0x40, "B"),
+ "steptime": (0x41, "B"),
+ "s1pos": (0x42, "B"),
+ "s2pos": (0x43, "B"),
+ "s3pos": (0x44, "B"),
+ "s4pos": (0x45, "B"),
+ "s5pos": (0x46, "B"),
+ "s6pos": (0x47, "B"),
+ "pwm": (0x48, "B"),
+ }
+ )
class Status:
STOPPED = 0x00 # all motors stopped
@@ -744,57 +862,59 @@ class ServoCon(BaseDigitalSensor):
Returns the status of the motors. 0 for all stopped, 1 for
some running.
"""
- return self.read_value('status')[0]
+ return self.read_value("status")[0]
def set_step_time(self, time):
"""Sets the step time (0-15)."""
- self.write_value('steptime', (time, ))
+ self.write_value("steptime", (time,))
def set_pos(self, num, pos):
"""
Sets the position of a server. num is the servo number (1-6),
pos is the position (0-255).
"""
- self.write_value('s%dpos' % num, (pos, ))
+ self.write_value("s%dpos" % num, (pos,))
def get_pwm(self):
"""
Gets the "PWM enable" value. The function of this value is
nontrivial and can be found in the documentation for the sensor.
"""
- return self.read_value('pwm')[0]
+ return self.read_value("pwm")[0]
def set_pwm(self, pwm):
"""
Sets the "PWM enable" value. The function of this value is
nontrivial and can be found in the documentation for the sensor.
"""
- self.write_value('pwm', (pwm, ))
+ self.write_value("pwm", (pwm,))
-ServoCon.add_compatible_sensor(None, 'HiTechnc', 'ServoCon')
+ServoCon.add_compatible_sensor(None, "HiTechnc", "ServoCon")
class MotorCon(BaseDigitalSensor):
"""Object for HiTechnic FIRST Motor Controllers."""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({
- 'm1enctarget': (0x40, '>l'),
- 'm1mode': (0x44, 'B'),
- 'm1power': (0x45, 'b'),
- 'm2power': (0x46, 'b'),
- 'm2mode': (0x47, 'B'),
- 'm2enctarget': (0x48, '>l'),
- 'm1enccurrent': (0x4c, '>l'),
- 'm2enccurrent': (0x50, '>l'),
- 'batteryvoltage': (0x54, '2B'),
- 'm1gearratio': (0x56, 'b'),
- 'm1pid': (0x57, '3B'),
- 'm2gearratio': (0x5a, 'b'),
- 'm2pid': (0x5b, '3B'),
- })
-
- # noinspection PyPep8Naming
+ I2C_ADDRESS.update(
+ {
+ "m1enctarget": (0x40, ">l"),
+ "m1mode": (0x44, "B"),
+ "m1power": (0x45, "b"),
+ "m2power": (0x46, "b"),
+ "m2mode": (0x47, "B"),
+ "m2enctarget": (0x48, ">l"),
+ "m1enccurrent": (0x4C, ">l"),
+ "m2enccurrent": (0x50, ">l"),
+ "batteryvoltage": (0x54, "2B"),
+ "m1gearratio": (0x56, "b"),
+ "m1pid": (0x57, "3B"),
+ "m2gearratio": (0x5A, "b"),
+ "m2pid": (0x5B, "3B"),
+ }
+ )
+
class PID_Data:
def __init__(self, p, i, d):
self.p, self.i, self.d = p, i, d
@@ -804,85 +924,88 @@ class MotorCon(BaseDigitalSensor):
def set_enc_target(self, mot, val):
"""Set the encoder target (-2147483648-2147483647) for a motor"""
- self.write_value('m%denctarget' % mot, (val, ))
+ self.write_value("m%denctarget" % mot, (val,))
def get_enc_target(self, mot):
"""Get the encoder target for a motor"""
- return self.read_value('m%denctarget' % mot)[0]
+ return self.read_value("m%denctarget" % mot)[0]
def get_enc_current(self, mot):
"""Get the current encoder value for a motor"""
- return self.read_value('m%denccurrent' % mot)[0]
+ return self.read_value("m%denccurrent" % mot)[0]
def set_mode(self, mot, mode):
"""
Set the mode for a motor. This value is a bit mask, and you can
find details about it in the sensor's documentation.
"""
- self.write_value('m%dmode' % mot, (mode, ))
+ self.write_value("m%dmode" % mot, (mode,))
def get_mode(self, mot):
"""
Get the mode for a motor. This value is a bit mask, and you can
find details about it in the sensor's documentation.
"""
- return self.read_value('m%dmode' % mot)[0]
+ return self.read_value("m%dmode" % mot)[0]
def set_power(self, mot, power):
"""Set the power (-100-100) for a motor"""
- self.write_value('m%dpower' % mot, (power, ))
+ self.write_value("m%dpower" % mot, (power,))
def get_power(self, mot):
"""Get the power for a motor"""
- return self.read_value('m%dpower' % mot)[0]
+ return self.read_value("m%dpower" % mot)[0]
def set_gear_ratio(self, mot, ratio):
"""Set the gear ratio for a motor"""
- self.write_value('m%dgearratio' % mot, (ratio, ))
+ self.write_value("m%dgearratio" % mot, (ratio,))
def get_gear_ratio(self, mot):
"""Get the gear ratio for a motor"""
- return self.read_value('m%dgearratio' % mot)[0]
+ return self.read_value("m%dgearratio" % mot)[0]
def set_pid(self, mot, piddata):
"""
Set the PID coefficients for a motor. Takes data in
MotorCon.PID_Data(p, i, d) format.
"""
- self.write_value('m%dpid' % mot, (piddata.p, piddata.i, piddata.d))
+ self.write_value("m%dpid" % mot, (piddata.p, piddata.i, piddata.d))
def get_pid(self, mot):
"""
Get the PID coefficients for a motor. Returns a PID_Data() object.
"""
- p, i, d = self.read_value('m%dpid' % mot)
+ p, i, d = self.read_value("m%dpid" % mot)
return self.PID_Data(p, i, d)
def get_battery_voltage(self):
"""
Gets the battery voltage (in millivolts/20)
"""
- data = self.read_value('batteryvoltage')
+ data = self.read_value("batteryvoltage")
high = data[0]
low = data[1]
return high << 2 | low
-MotorCon.add_compatible_sensor(None, 'HiTechnc', 'MotorCon')
+MotorCon.add_compatible_sensor(None, "HiTechnc", "MotorCon")
class Angle(BaseDigitalSensor):
"""HiTechnic Angle Sensor."""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({
- 'mode': (0x41, 'c'),
- 'angle': (0x42, '2B'),
- 'angle_acc': (0x44, '>l'),
- 'rpm': (0x48, '>h'),
- })
+ I2C_ADDRESS.update(
+ {
+ "mode": (0x41, "c"),
+ "angle": (0x42, "2B"),
+ "angle_acc": (0x44, ">l"),
+ "rpm": (0x48, ">h"),
+ }
+ )
def get_angle(self):
- v = self.read_value('angle')
+ v = self.read_value("angle")
return v[0] * 2 + v[1]
get_sample = get_angle
@@ -894,7 +1017,7 @@ class Angle(BaseDigitalSensor):
return self.read_value("rpm")[0]
def calibrate(self): # Current angle will be zero degrees written in EEPROM
- self.write_value('mode', b'C')
+ self.write_value("mode", b"C")
def reset(self): # Reset accumulated angle
- self.write_value('mode', b'R')
+ self.write_value("mode", b"R")
diff --git a/nxt/sensor/mindsensors.py b/nxt/sensor/mindsensors.py
index a599c65..5aead02 100644
--- a/nxt/sensor/mindsensors.py
+++ b/nxt/sensor/mindsensors.py
@@ -17,23 +17,26 @@ import logging
from nxt.sensor import Mode, Type
from nxt.sensor.analog import BaseAnalogSensor
-from nxt.sensor.digital import BaseDigitalSensor, SensorInfo
+from nxt.sensor.digital import BaseDigitalSensor
logger = logging.getLogger(__name__)
+
class SumoEyes(BaseAnalogSensor):
"""The class to control Mindsensors Sumo sensor. Warning: long range not
working for my sensor.
"""
- #range: 5-10cm
+
+ # range: 5-10cm
class Reading:
"""Contains the reading of SumoEyes sensor. left and right can be True or
False. If True, then there is something there, if False, then it's empty
there.
"""
+
def __init__(self, raw_reading):
self.raw = raw_reading
- val = raw_reading.normalized_value # FIXME: make it rely on raw_value
+ val = raw_reading.normalized_value # FIXME: make it rely on raw_value
right = 600 < val < 700
both = 700 <= val < 900
left = 300 < val < 400
@@ -41,7 +44,7 @@ class SumoEyes(BaseAnalogSensor):
self.right = right or both
def __str__(self):
- return '(left: ' + str(self.left) + ', right: ' + str(self.right) + ')'
+ return "(left: " + str(self.left) + ", right: " + str(self.right) + ")"
def __init__(self, brick, port, long_range=False):
super().__init__(brick, port)
@@ -64,31 +67,35 @@ class SumoEyes(BaseAnalogSensor):
class Compassv2(BaseDigitalSensor):
"""Class for the now-discontinued CMPS-Nx sensor. Also works with v1.1 sensors.
-Note that when using a v1.x sensor, some of the commands are not supported!
-To determine your sensor's version, use get_sensor_info().version"""
+ Note that when using a v1.x sensor, some of the commands are not supported!
+ To determine your sensor's version, use get_sensor_info().version"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'command': (0x41, '<B'),
- 'heading': (0x42, '<H'),
- 'x_offset': (0x44, '<h'), #unsure about signedness for this one
- 'y_offset': (0x46, '<h'), #and this one
- 'x_range': (0x48, '<H'),
- 'y_range': (0x4A, '<H'),
- 'x_raw': (0x4C, '<H'), #and this one
- 'y_raw': (0x4E, '<H'), #and this one
- })
+ I2C_ADDRESS.update(
+ {
+ "command": (0x41, "<B"),
+ "heading": (0x42, "<H"),
+ "x_offset": (0x44, "<h"), # unsure about signedness for this one
+ "y_offset": (0x46, "<h"), # and this one
+ "x_range": (0x48, "<H"),
+ "y_range": (0x4A, "<H"),
+ "x_raw": (0x4C, "<H"), # and this one
+ "y_raw": (0x4E, "<H"), # and this one
+ }
+ )
class Commands:
- AUTO_TRIG_ON = 'A'
- AUTO_TRIG_OFF = 'S'
- MAP_HEADING_BYTE = 'B' # map heading to 0-255 range
- MAP_HEADING_INTEGER = 'I' # map heading to 0-36000 (or 3600) range
- SAMPLING_50_HZ = 'E' # set sampling frequency to 50 Hz
- SAMPLING_60_HZ = 'U' # set sampling frequency to 60 Hz
- SET_ADPA_MODE_ON = 'N' # set ADPA mode on
- SET_ADPA_MODE_OFF = 'O' # set ADPA mode off
- BEGIN_CALIBRATION = 'C' # begin calibration
- DONE_CALIBRATION = 'D' # done with calibration
- LOAD_USER_CALIBRATION = 'L' # load user calibration value
+ AUTO_TRIG_ON = "A"
+ AUTO_TRIG_OFF = "S"
+ MAP_HEADING_BYTE = "B" # map heading to 0-255 range
+ MAP_HEADING_INTEGER = "I" # map heading to 0-36000 (or 3600) range
+ SAMPLING_50_HZ = "E" # set sampling frequency to 50 Hz
+ SAMPLING_60_HZ = "U" # set sampling frequency to 60 Hz
+ SET_ADPA_MODE_ON = "N" # set ADPA mode on
+ SET_ADPA_MODE_OFF = "O" # set ADPA mode off
+ BEGIN_CALIBRATION = "C" # begin calibration
+ DONE_CALIBRATION = "D" # done with calibration
+ LOAD_USER_CALIBRATION = "L" # load user calibration value
def __init__(self, brick, port, check_compatible=True):
super().__init__(brick, port, check_compatible)
@@ -96,125 +103,135 @@ To determine your sensor's version, use get_sensor_info().version"""
def command(self, command):
value = ord(command)
- self.write_value('command', (value, ))
+ self.write_value("command", (value,))
def get_heading(self):
- return self.read_value('heading')[0]
+ return self.read_value("heading")[0]
get_sample = get_heading
-Compassv2.add_compatible_sensor(None, 'mndsnsrs', 'CMPS')
+
+Compassv2.add_compatible_sensor(None, "mndsnsrs", "CMPS")
class DIST(BaseDigitalSensor):
"""Class for the Distance Infrared Sensor"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'command': (0x41, '<B'),
- 'distance': (0x42, '<H'),
- 'voltage': (0x44, '<H'),
- 'type': (0x50, '<B'),
- 'no_of_data_points': (0x51, '<B'),
- 'min_distance': (0x52, '<H'),
- 'max_distance': (0x54, '<H'),
- })
+ I2C_ADDRESS.update(
+ {
+ "command": (0x41, "<B"),
+ "distance": (0x42, "<H"),
+ "voltage": (0x44, "<H"),
+ "type": (0x50, "<B"),
+ "no_of_data_points": (0x51, "<B"),
+ "min_distance": (0x52, "<H"),
+ "max_distance": (0x54, "<H"),
+ }
+ )
class Commands:
- TYPE_GP2D12 = '1' #GP2D12 sensor Module
- TYPE_GP2D120 = '2' #Short range sensor Module
- TYPE_GP2Y0A21YK = '3' #Medium range sensor Module
- TYPE_GP2Y0A02YK = '4' #Long range sensor Module
- TYPE_CUSTOM = '5' #Custom sensor Module
- POWER_ON = 'E' #Sensor module power on
- POWER_OFF = 'D' #Sensor module power offset
- ADPA_ON = 'N' #ADPA mode on
- ADPA_OFF = 'O' #ADPA mode off (default)
+ TYPE_GP2D12 = "1" # GP2D12 sensor Module
+ TYPE_GP2D120 = "2" # Short range sensor Module
+ TYPE_GP2Y0A21YK = "3" # Medium range sensor Module
+ TYPE_GP2Y0A02YK = "4" # Long range sensor Module
+ TYPE_CUSTOM = "5" # Custom sensor Module
+ POWER_ON = "E" # Sensor module power on
+ POWER_OFF = "D" # Sensor module power offset
+ ADPA_ON = "N" # ADPA mode on
+ ADPA_OFF = "O" # ADPA mode off (default)
def command(self, command):
value = ord(command)
- self.write_value('command', (value, ))
+ self.write_value("command", (value,))
def get_distance(self):
- return self.read_value('distance')[0]
+ return self.read_value("distance")[0]
get_sample = get_distance
def get_type(self):
- return self.read_value('type')[0]
+ return self.read_value("type")[0]
def get_voltage(self):
- return self.read_value('voltage')[0]
+ return self.read_value("voltage")[0]
def get_min_distance(self):
- return self.read_value('min_distance')[0]
+ return self.read_value("min_distance")[0]
def get_max_distance(self):
- return self.read_value('max_distance')[0]
+ return self.read_value("max_distance")[0]
+
-DIST.add_compatible_sensor(None, 'mndsnsrs', 'DIST')
+DIST.add_compatible_sensor(None, "mndsnsrs", "DIST")
class RTC(BaseDigitalSensor):
"""Class for the RealTime Clock sensor (DS1307)"""
- #TODO: Create a function to set the clock
- #Has no identification
+
+ # TODO: Create a function to set the clock
+ # Has no identification
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'seconds': (0x00, '<B'),
- 'minutes': (0x01, '<B'),
- 'hours': (0x02, '<B'),
- 'day': (0x03, '<B'),
- 'date': (0x04, '<B'),
- 'month': (0x05, '<B'),
- 'year': (0x06, '<B'),
- })
+ I2C_ADDRESS.update(
+ {
+ "seconds": (0x00, "<B"),
+ "minutes": (0x01, "<B"),
+ "hours": (0x02, "<B"),
+ "day": (0x03, "<B"),
+ "date": (0x04, "<B"),
+ "month": (0x05, "<B"),
+ "year": (0x06, "<B"),
+ }
+ )
I2C_DEV = 0xD0
def __init__(self, brick, port):
super().__init__(brick, port, check_compatible=False)
def get_seconds(self):
- gs = self.read_value('seconds')[0]
- gs2 = gs & 0xf # bitmasks
+ gs = self.read_value("seconds")[0]
+ gs2 = gs & 0xF # bitmasks
gs3 = gs & 0x70
gs3 = gs3 >> 4
return str(gs3) + str(gs2)
def get_minutes(self):
- gm = self.read_value('minutes')[0]
- gm2 = gm & 0xf
+ gm = self.read_value("minutes")[0]
+ gm2 = gm & 0xF
gm3 = gm & 0x70
gm3 = gm3 >> 4
return str(gm3) + str(gm2)
def get_hours(self):
- gh = self.read_value('hours')[0]
- gh2 = gh & 0xf
+ gh = self.read_value("hours")[0]
+ gh2 = gh & 0xF
gh3 = gh & 0x30
gh3 = gh3 >> 4
return str(gh3) + str(gh2)
def get_day(self):
- gwd = self.read_value('day')[0]
+ gwd = self.read_value("day")[0]
gwd = gwd & 0x07
return gwd
def get_month(self):
- gmo = self.read_value('month')[0]
- gmo2 = gmo & 0xf
+ gmo = self.read_value("month")[0]
+ gmo2 = gmo & 0xF
gmo3 = gmo & 0x10
gmo3 = gmo3 >> 4
return str(gmo3) + str(gmo2)
def get_year(self):
"""Last two digits (10 for 2010)"""
- gy = self.read_value('year')[0]
- gy2 = gy & 0xf
+ gy = self.read_value("year")[0]
+ gy2 = gy & 0xF
gy3 = gy & 0xF0
- gy3 = gy3 >> 4
+ gy3 = gy3 >> 4
return str(gy3) + str(gy2)
def get_date(self):
- gd = self.read_value('date')[0]
- gd2 = gd & 0xf
+ gd = self.read_value("date")[0]
+ gd2 = gd & 0xF
gd3 = gd & 0x60
gd3 = gd3 >> 4
return str(gd3) + str(gd2)
@@ -222,20 +239,20 @@ class RTC(BaseDigitalSensor):
def hour_mode(self, mode):
"""Writes mode bit and re-enters hours, which is required"""
if mode == 12 or 24:
- hm = self.read_value('hours')[0]
+ hm = self.read_value("hours")[0]
hm2 = hm & 0x40
hm2 = hm2 >> 6
- if mode == 12 and hm2 == 0: #12_HOUR = 1
+ if mode == 12 and hm2 == 0: # 12_HOUR = 1
hm3 = hm + 64
- self.write_value('hours', (hm3, ))
- elif mode == 24 and hm2 == 1: #24_HOUR = 0
+ self.write_value("hours", (hm3,))
+ elif mode == 24 and hm2 == 1: # 24_HOUR = 0
hm3 = hm - 64
- self.write_value('hours', (hm3, ))
+ self.write_value("hours", (hm3,))
else:
- raise ValueError('Must be 12 or 24!')
+ raise ValueError("Must be 12 or 24!")
def get_mer(self):
- mer = self.read_value('hours')[0]
+ mer = self.read_value("hours")[0]
mer2 = mer & 0x40
mer2 = mer2 >> 6
if mer2 == 1:
@@ -243,122 +260,130 @@ class RTC(BaseDigitalSensor):
mer3 = mer3 >> 0x10
return mer3
else:
- logger.error('cannot get mer in 24-hour mode')
+ logger.error("cannot get mer in 24-hour mode")
def get_sample(self):
"""Returns a struct_time() tuple which can be processed by the time module."""
import time
- return time.struct_time((
- int(self.get_year())+2000,
- int(self.get_month()),
- int(self.get_date()),
- int(self.get_hours()),
- int(self.get_minutes()),
- int(self.get_seconds()),
- int(self.get_day()),
- 0, #Should be the Julian Day, but computing that is hard.
- 0 #No daylight savings time to worry about here.
- ))
+
+ return time.struct_time(
+ (
+ int(self.get_year()) + 2000,
+ int(self.get_month()),
+ int(self.get_date()),
+ int(self.get_hours()),
+ int(self.get_minutes()),
+ int(self.get_seconds()),
+ int(self.get_day()),
+ 0, # Should be the Julian Day, but computing that is hard.
+ 0, # No daylight savings time to worry about here.
+ )
+ )
class ACCL(BaseDigitalSensor):
"""Class for Accelerometer sensor"""
- I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'sensitivity': (0x19, 'B'),
- 'command': (0x41, 'B'),
- 'x_tilt': (0x42, 'b'),
- 'y_tilt': (0x43, 'b'),
- 'z_tilt': (0x44, 'b'),
- 'all_tilt': (0x42, '3b'),
-
- 'x_accel': (0x45, '<h'),
- 'y_accel': (0x47, '<h'),
- 'z_accel': (0x49, '<h'),
- 'all_accel': (0x45, '<3h'),
- 'x_offset': (0x4B, '<h'),
- 'x_range': (0x4D, '<h'),
-
- 'y_offset': (0x4F, '<h'),
- 'y_range': (0x51, '<h'),
-
- 'z_offset': (0x53, '<h'),
- 'z_range': (0x55, '<h'),
- })
+ I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
+ I2C_ADDRESS.update(
+ {
+ "sensitivity": (0x19, "B"),
+ "command": (0x41, "B"),
+ "x_tilt": (0x42, "b"),
+ "y_tilt": (0x43, "b"),
+ "z_tilt": (0x44, "b"),
+ "all_tilt": (0x42, "3b"),
+ "x_accel": (0x45, "<h"),
+ "y_accel": (0x47, "<h"),
+ "z_accel": (0x49, "<h"),
+ "all_accel": (0x45, "<3h"),
+ "x_offset": (0x4B, "<h"),
+ "x_range": (0x4D, "<h"),
+ "y_offset": (0x4F, "<h"),
+ "y_range": (0x51, "<h"),
+ "z_offset": (0x53, "<h"),
+ "z_range": (0x55, "<h"),
+ }
+ )
class Commands:
- SENS_15G = '1' #that's 1.5...Alt. 2.5G (sensors older than V3.20)
- SENS_2G = '2' #Alt .3.3G
- SENS_4G = '3' #Alt. 6.7G
- SENS_6G = '4' #Alt. 10G
- X_CALIBRATION = 'X' #Acquire X point calibration
- X_CAL_AND_END = 'x' #X point calibration and end calibration
- Y_CALIBRATION = 'Y' #Acquire Y point calibration
- Y_CAL_AND_END = 'y' #Y point calibration and end calibration
- Z_CALIBRATION = 'Z' #Acquire Z point calibration
- Z_CAL_AND_END = 'z' #Z point calibration and end calibration
- CAL_RESET = 'R' #Reset to factory set calibration
- ADPA_ON = 'N' #Set ADPA mode On
- ADPA_OFF = 'O' #Set ADPA mode Off (default)
+ SENS_15G = "1" # that's 1.5...Alt. 2.5G (sensors older than V3.20)
+ SENS_2G = "2" # Alt .3.3G
+ SENS_4G = "3" # Alt. 6.7G
+ SENS_6G = "4" # Alt. 10G
+ X_CALIBRATION = "X" # Acquire X point calibration
+ X_CAL_AND_END = "x" # X point calibration and end calibration
+ Y_CALIBRATION = "Y" # Acquire Y point calibration
+ Y_CAL_AND_END = "y" # Y point calibration and end calibration
+ Z_CALIBRATION = "Z" # Acquire Z point calibration
+ Z_CAL_AND_END = "z" # Z point calibration and end calibration
+ CAL_RESET = "R" # Reset to factory set calibration
+ ADPA_ON = "N" # Set ADPA mode On
+ ADPA_OFF = "O" # Set ADPA mode Off (default)
def __init__(self, brick, port, check_compatible=True):
super().__init__(brick, port, check_compatible)
def command(self, command):
value = ord(command)
- self.write_value('command', (value, ))
+ self.write_value("command", (value,))
def get_sensitivity(self):
- return chr(self.read_value('sensitivity')[0])
+ return chr(self.read_value("sensitivity")[0])
def get_tilt(self, axis):
- xyz = str(axis) + '_tilt'
+ xyz = str(axis) + "_tilt"
return self.read_value(xyz)[0]
def get_all_tilt(self):
- return self.read_value('all_tilt')
+ return self.read_value("all_tilt")
def get_accel(self, axis):
- xyz = str(axis) + '_accel'
+ xyz = str(axis) + "_accel"
return self.read_value(xyz)[0]
def get_all_accel(self):
- return self.read_value('all_accel')
+ return self.read_value("all_accel")
get_sample = get_all_accel
def get_offset(self, axis):
- xyz = str(axis) + '_offset'
+ xyz = str(axis) + "_offset"
return self.read_value(xyz)[0]
def get_range(self, axis):
- xyz = str(axis) + '_range'
+ xyz = str(axis) + "_range"
return self.read_value(xyz)[0]
def set_offset(self, axis, value):
- xyz = str(axis) + '_offset'
- self.write_value(xyz, (value, ))
+ xyz = str(axis) + "_offset"
+ self.write_value(xyz, (value,))
def set_range(self, axis, value):
- xyz = str(axis) + '_range'
- self.write_value(xyz, (value, ))
+ xyz = str(axis) + "_range"
+ self.write_value(xyz, (value,))
-ACCL.add_compatible_sensor(None, 'mndsnsrs', 'ACCL-NX') #Tested with version 'V3.20'
+
+ACCL.add_compatible_sensor(None, "mndsnsrs", "ACCL-NX") # Tested with version 'V3.20'
class MTRMUX(BaseDigitalSensor):
"""Class for RCX Motor Multiplexer sensor"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'command' : (0x41, '<B'),
- 'direction_m1': (0x42, '<B'),
- 'speed_m1': (0x43, '<B'),
- 'direction_m2': (0x44, '<B'),
- 'speed_m2': (0x45, '<B'),
- 'direction_m3': (0x46, '<B'),
- 'speed_m3': (0x47, '<B'),
- 'direction_m4': (0x48, '<B'),
- 'speed_m4': (0x49, '<B'),
- })
+ I2C_ADDRESS.update(
+ {
+ "command": (0x41, "<B"),
+ "direction_m1": (0x42, "<B"),
+ "speed_m1": (0x43, "<B"),
+ "direction_m2": (0x44, "<B"),
+ "speed_m2": (0x45, "<B"),
+ "direction_m3": (0x46, "<B"),
+ "speed_m3": (0x47, "<B"),
+ "direction_m4": (0x48, "<B"),
+ "speed_m4": (0x49, "<B"),
+ }
+ )
I2C_DEV = 0xB4
class Commands:
@@ -371,324 +396,335 @@ class MTRMUX(BaseDigitalSensor):
super().__init__(brick, port, check_compatible)
def command(self, command):
- self.write_value('command', (command, ))
+ self.write_value("command", (command,))
def set_direction(self, number, value):
- addressname = 'direction_m' + str(number)
- self.write_value(addressname, (value, ))
+ addressname = "direction_m" + str(number)
+ self.write_value(addressname, (value,))
def set_speed(self, number, value):
- addressname = 'speed_m' + str(number)
- self.write_value(addressname, (value, ))
+ addressname = "speed_m" + str(number)
+ self.write_value(addressname, (value,))
def get_direction(self, number):
- addressname = 'direction_m' + str(number)
+ addressname = "direction_m" + str(number)
return self.read_value(addressname)[0]
def get_speed(self, number):
- addressname = 'speed_m' + str(number)
+ addressname = "speed_m" + str(number)
return self.read_value(addressname)[0]
-MTRMUX.add_compatible_sensor(None, 'mndsnsrs', 'MTRMUX') #Tested with version 'V2.11'
+
+MTRMUX.add_compatible_sensor(None, "mndsnsrs", "MTRMUX") # Tested with version 'V2.11'
class LineLeader(BaseDigitalSensor):
"""Class for Line Sensor Array"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'command': (0x41, '<B'),
- 'steering': (0x42, '<b'),
- 'average': (0x43, '<B'),
- 'result': (0x44, '<B'),
- 'set_point': (0x45, '<B'),
-
- 'kp': (0x46, '<B'),
- 'ki': (0x47, '<B'),
- 'kd': (0x48, '<B'),
- 'kp_divisor':(0x61, '<B'),
- 'ki_divisor':(0x62, '<B'),
- 'kd_divisor':(0x63, '<B'),
- #One byte for each sensor, so byte# = sensor#
- 'calibrated_reading_byte1': (0x49, '<B'),
- 'calibrated_reading_byte2': (0x4A, '<B'),
- 'calibrated_reading_byte3': (0x4B, '<B'),
- 'calibrated_reading_byte4': (0x4C, '<B'),
- 'calibrated_reading_byte5': (0x4D, '<B'),
- 'calibrated_reading_byte6': (0x4E, '<B'),
- 'calibrated_reading_byte7': (0x4F, '<B'),
- 'calibrated_reading_byte8': (0x50, '<B'),
- 'all_calibrated_readings': (0x49, '<8B'),
-
- 'w_read_limit':(0x51, '<H'),
- 'b_read_limit':(0x59, '<B'),
- 'w_cal_data1':(0x64, '<B'),
- 'b_cal_data':(0x6C, '<B'),
-
- 'uncal_sensor1_voltage_byte1':(0x74, '<B'),
- 'uncal_sensor2_voltage_byte1':(0x76, '<B'),
- 'uncal_sensor3_voltage_byte1':(0x78, '<B'),
- 'uncal_sensor4_voltage_byte1':(0x7A, '<B'),
- 'uncal_sensor5_voltage_byte1':(0x7C, '<B'),
- 'uncal_sensor6_voltage_byte1':(0x7E, '<B'),
- 'uncal_sensor7_voltage_byte1':(0x80, '<B'),
- 'uncal_sensor8_voltage_byte1':(0x82, '<B'),
- 'all_uncal_readings': (0x74, '<8B'),
- })
+ I2C_ADDRESS.update(
+ {
+ "command": (0x41, "<B"),
+ "steering": (0x42, "<b"),
+ "average": (0x43, "<B"),
+ "result": (0x44, "<B"),
+ "set_point": (0x45, "<B"),
+ "kp": (0x46, "<B"),
+ "ki": (0x47, "<B"),
+ "kd": (0x48, "<B"),
+ "kp_divisor": (0x61, "<B"),
+ "ki_divisor": (0x62, "<B"),
+ "kd_divisor": (0x63, "<B"),
+ # One byte for each sensor, so byte# = sensor#
+ "calibrated_reading_byte1": (0x49, "<B"),
+ "calibrated_reading_byte2": (0x4A, "<B"),
+ "calibrated_reading_byte3": (0x4B, "<B"),
+ "calibrated_reading_byte4": (0x4C, "<B"),
+ "calibrated_reading_byte5": (0x4D, "<B"),
+ "calibrated_reading_byte6": (0x4E, "<B"),
+ "calibrated_reading_byte7": (0x4F, "<B"),
+ "calibrated_reading_byte8": (0x50, "<B"),
+ "all_calibrated_readings": (0x49, "<8B"),
+ "w_read_limit": (0x51, "<H"),
+ "b_read_limit": (0x59, "<B"),
+ "w_cal_data1": (0x64, "<B"),
+ "b_cal_data": (0x6C, "<B"),
+ "uncal_sensor1_voltage_byte1": (0x74, "<B"),
+ "uncal_sensor2_voltage_byte1": (0x76, "<B"),
+ "uncal_sensor3_voltage_byte1": (0x78, "<B"),
+ "uncal_sensor4_voltage_byte1": (0x7A, "<B"),
+ "uncal_sensor5_voltage_byte1": (0x7C, "<B"),
+ "uncal_sensor6_voltage_byte1": (0x7E, "<B"),
+ "uncal_sensor7_voltage_byte1": (0x80, "<B"),
+ "uncal_sensor8_voltage_byte1": (0x82, "<B"),
+ "all_uncal_readings": (0x74, "<8B"),
+ }
+ )
class Commands:
- CALIBRATE_WHITE = 'W'
- CALIBRATE_BLACK = 'B'
- SENSOR_SLEEP = 'D'
- US_CONFIG = 'A'
- EU_CONFIG = 'E'
- UNI_CONFIG = 'U'
- SENSOR_WAKE = 'P'
- COLOR_INVERT = 'I'
- COLOR_INVERT_REVERSE = 'R'
- SNAPSHOT = 'S'
+ CALIBRATE_WHITE = "W"
+ CALIBRATE_BLACK = "B"
+ SENSOR_SLEEP = "D"
+ US_CONFIG = "A"
+ EU_CONFIG = "E"
+ UNI_CONFIG = "U"
+ SENSOR_WAKE = "P"
+ COLOR_INVERT = "I"
+ COLOR_INVERT_REVERSE = "R"
+ SNAPSHOT = "S"
def __init__(self, brick, port, check_compatible=True):
super().__init__(brick, port, check_compatible)
def command(self, command):
value = ord(command)
- self.write_value('command', (value, ))
+ self.write_value("command", (value,))
def get_steering(self):
- 'Value to add to the left and subtract from the right motor\'s power.'
- return self.read_value('steering')[0]
+ "Value to add to the left and subtract from the right motor's power."
+ return self.read_value("steering")[0]
def get_average(self):
- 'Weighted average; greater as line is closer to right edge. 0 for no line.'
- return self.read_value('average')[0]
+ "Weighted average; greater as line is closer to right edge. 0 for no line."
+ return self.read_value("average")[0]
def get_result(self):
- 'Bitmap, one bit for each sensor'
- return self.read_value('result')[0]
+ "Bitmap, one bit for each sensor"
+ return self.read_value("result")[0]
def set_set_point(self, value):
- 'Average value for steering to gravitate to. 10 (left) to 80 (right).'
- self.write_value('set_point', (value, ))
+ "Average value for steering to gravitate to. 10 (left) to 80 (right)."
+ self.write_value("set_point", (value,))
def set_pid(self, pid, value):
- addressname = 'k' + str(pid)
- self.write_value(addressname, (value, ))
+ addressname = "k" + str(pid)
+ self.write_value(addressname, (value,))
def set_pid_divisor(self, pid, value):
- addressname = 'k' + str(pid) + '_divisor'
- self.write_value(addressname, (value, ))
+ addressname = "k" + str(pid) + "_divisor"
+ self.write_value(addressname, (value,))
def get_reading(self, number):
- addressname = 'calibrated_reading_byte' + str(number)
+ addressname = "calibrated_reading_byte" + str(number)
return self.read_value(addressname)[0]
def get_reading_all(self):
- return self.read_value('all_calibrated_readings')
+ return self.read_value("all_calibrated_readings")
get_sample = get_reading_all
def get_uncal_reading(self, number):
- addressname = 'uncal_sensor' + str(number) + '_voltage_byte1'
+ addressname = "uncal_sensor" + str(number) + "_voltage_byte1"
return self.read_value(addressname)[0]
def get_uncal_all(self):
- return self.read_value('all_uncal_readings')
+ return self.read_value("all_uncal_readings")
-LineLeader.add_compatible_sensor(None, 'mndsnsrs', 'LineLdr') #Tested with version 'V1.16'
+
+LineLeader.add_compatible_sensor(
+ None, "mndsnsrs", "LineLdr"
+) # Tested with version 'V1.16'
class Servo(BaseDigitalSensor):
"""Class for Servo sensors"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'command' : (0x41, '<B'),
-
- 'servo_1_pos': (0x42, '<H'),
- 'servo_2_pos': (0x44, '<H'),
- 'servo_3_pos': (0x46, '<H'),
- 'servo_4_pos': (0x48, '<H'),
- 'servo_5_pos': (0x4A, '<H'),
- 'servo_6_pos': (0x4C, '<H'),
- 'servo_7_pos': (0x4E, '<H'),
- 'servo_8_pos': (0x50, '<H'),
-
- 'servo_1_speed': (0x52, '<B'),
- 'servo_2_speed': (0x53, '<B'),
- 'servo_3_speed': (0x54, '<B'),
- 'servo_4_speed': (0x55, '<B'),
- 'servo_5_speed': (0x56, '<B'),
- 'servo_6_speed': (0x57, '<B'),
- 'servo_7_speed': (0x58, '<B'),
- 'servo_8_speed': (0x59, '<B'),
-
- 'servo_1_quick': (0x5A, '<B'),
- 'servo_2_quick': (0x5B, '<B'),
- 'servo_3_quick': (0x5C, '<B'),
- 'servo_4_quick': (0x5D, '<B'),
- 'servo_5_quick': (0x5E, '<B'),
- 'servo_6_quick': (0x5F, '<B'),
- 'servo_7_quick': (0x60, '<B'),
- 'servo_8_quick': (0x61, '<B'),
- })
+ I2C_ADDRESS.update(
+ {
+ "command": (0x41, "<B"),
+ "servo_1_pos": (0x42, "<H"),
+ "servo_2_pos": (0x44, "<H"),
+ "servo_3_pos": (0x46, "<H"),
+ "servo_4_pos": (0x48, "<H"),
+ "servo_5_pos": (0x4A, "<H"),
+ "servo_6_pos": (0x4C, "<H"),
+ "servo_7_pos": (0x4E, "<H"),
+ "servo_8_pos": (0x50, "<H"),
+ "servo_1_speed": (0x52, "<B"),
+ "servo_2_speed": (0x53, "<B"),
+ "servo_3_speed": (0x54, "<B"),
+ "servo_4_speed": (0x55, "<B"),
+ "servo_5_speed": (0x56, "<B"),
+ "servo_6_speed": (0x57, "<B"),
+ "servo_7_speed": (0x58, "<B"),
+ "servo_8_speed": (0x59, "<B"),
+ "servo_1_quick": (0x5A, "<B"),
+ "servo_2_quick": (0x5B, "<B"),
+ "servo_3_quick": (0x5C, "<B"),
+ "servo_4_quick": (0x5D, "<B"),
+ "servo_5_quick": (0x5E, "<B"),
+ "servo_6_quick": (0x5F, "<B"),
+ "servo_7_quick": (0x60, "<B"),
+ "servo_8_quick": (0x61, "<B"),
+ }
+ )
I2C_DEV = 0xB0
- COMMANDVALUES = {'R': (0x52), #Resume macro execution
- 'S': (0x53), #reset initial position and speed
- 'I1': (0x4931), #store initial position motor 1
- 'I2': (0x4932), #store initial position motor 2
- 'I3': (0x4933), #etc...
- 'I4': (0x4934),
- 'I5': (0x4935),
- 'I6': (0x4936),
- 'I7': (0x4937),
- 'I8': (0x4938),
- 'H': (0x48), #Halt macro
- 'Gx': (0x4778), #not going to work yet x = variable
- 'EM': (0x454d), #Edit Macro
- 'P': (0x50), #Pause Macro
- }
+ COMMANDVALUES = {
+ "R": (0x52), # Resume macro execution
+ "S": (0x53), # reset initial position and speed
+ "I1": (0x4931), # store initial position motor 1
+ "I2": (0x4932), # store initial position motor 2
+ "I3": (0x4933), # etc...
+ "I4": (0x4934),
+ "I5": (0x4935),
+ "I6": (0x4936),
+ "I7": (0x4937),
+ "I8": (0x4938),
+ "H": (0x48), # Halt macro
+ "Gx": (0x4778), # not going to work yet x = variable
+ "EM": (0x454D), # Edit Macro
+ "P": (0x50), # Pause Macro
+ }
class Commands:
- RESUME_MACRO = 'R'
- RESET_POS_SPEED = 'S'
- STORE_MOTOR_POS_1 = 'I1'
- STORE_MOTOR_POS_2 = 'I2'
- STORE_MOTOR_POS_3 = 'I3'
- STORE_MOTOR_POS_4 = 'I4'
- STORE_MOTOR_POS_5 = 'I5'
- STORE_MOTOR_POS_6 = 'I6'
- STORE_MOTOR_POS_7 = 'I7'
- STORE_MOTOR_POS_8 = 'I8'
- HALT_MACRO = 'H'
- X_TO_VAR = 'Gx' #not going to work yet
- EDIT_MACRO = 'EM'
- PAUSE_MACRO = 'P'
+ RESUME_MACRO = "R"
+ RESET_POS_SPEED = "S"
+ STORE_MOTOR_POS_1 = "I1"
+ STORE_MOTOR_POS_2 = "I2"
+ STORE_MOTOR_POS_3 = "I3"
+ STORE_MOTOR_POS_4 = "I4"
+ STORE_MOTOR_POS_5 = "I5"
+ STORE_MOTOR_POS_6 = "I6"
+ STORE_MOTOR_POS_7 = "I7"
+ STORE_MOTOR_POS_8 = "I8"
+ HALT_MACRO = "H"
+ X_TO_VAR = "Gx" # not going to work yet
+ EDIT_MACRO = "EM"
+ PAUSE_MACRO = "P"
def __init__(self, brick, port, check_compatible=True):
super().__init__(brick, port, check_compatible)
def command(self, command):
value = self.COMMANDVALUES[command]
- self.write_value('command', (value, ))
+ self.write_value("command", (value,))
def get_bat_level(self):
- return self.read_value('command')[0]
+ return self.read_value("command")[0]
def set_position(self, number, value):
- addressname = 'servo_' + str(number) + '_pos'
- self.write_value(addressname, (value, ))
+ addressname = "servo_" + str(number) + "_pos"
+ self.write_value(addressname, (value,))
def get_position(self, number):
- return self.read_value('servo_' + str(number) + '_pos')[0]
+ return self.read_value("servo_" + str(number) + "_pos")[0]
def set_speed(self, number, value):
- addressname = 'servo_' + str(number) + '_speed'
- self.write_value(addressname, (value, ))
+ addressname = "servo_" + str(number) + "_speed"
+ self.write_value(addressname, (value,))
def get_speed(self, number):
- return self.read_value('servo_' + str(number) + '_speed')[0]
+ return self.read_value("servo_" + str(number) + "_speed")[0]
def set_quick(self, number, value):
- addressname = 'servo_' + str(number) + '_quick'
- self.write_value(addressname, (value, ))
+ addressname = "servo_" + str(number) + "_quick"
+ self.write_value(addressname, (value,))
+
-Servo.add_compatible_sensor(None, 'mndsnsrs', 'NXTServo') #Tested with version 'V1.20'
+Servo.add_compatible_sensor(None, "mndsnsrs", "NXTServo") # Tested with version 'V1.20'
class MMX(BaseDigitalSensor):
"""Class for MMX sensors"""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'command' : (0x41, '<B'),
- #Motor Writes
- 'encoder_1_target': (0x42, '<l'),
- 'speed_1': (0x46, '<B'),
- 'seconds_to_run_1': (0x47, '<B'),
- 'command_b_1': (0x48, '<B'),
- 'command_a_1': (0x49, '<B'),
-
- 'encoder_2_target': (0x4A, '<l'),
- 'speed_2': (0x4E, '<B'),
- 'seconds_to_run_2': (0x4F, '<B'),
- 'command_b_2': (0x50, '<B'),
- 'command_a_2': (0x51, '<B'),
- #Motor reads
- 'encoder_1_pos': (0x62, '<H'),
- 'encoder_2_pos': (0x66, '<H'),
- 'status_m1': (0x72, '<B'),
- 'status_m2': (0x73, '<B'),
- 'tasks_running_m1': (0x76, '<H'),
- 'tasks_running_m2': (0x77, '<H'),
- #PID Control
- 'p_encoder': (0x7A, '<H'),
- 'i_encoder': (0x7C, '<H'),
- 'd_encoder': (0x7E, '<H'),
- 'p_speed': (0x80, '<H'),
- 'i_speed': (0x82, '<H'),
- 'd_speed': (0x84, '<H'),
- 'pass_count': (0x86, '<B'),
- 'tolerance': (0x87, '<B'),
- })
+ I2C_ADDRESS.update(
+ {
+ "command": (0x41, "<B"),
+ # Motor Writes
+ "encoder_1_target": (0x42, "<l"),
+ "speed_1": (0x46, "<B"),
+ "seconds_to_run_1": (0x47, "<B"),
+ "command_b_1": (0x48, "<B"),
+ "command_a_1": (0x49, "<B"),
+ "encoder_2_target": (0x4A, "<l"),
+ "speed_2": (0x4E, "<B"),
+ "seconds_to_run_2": (0x4F, "<B"),
+ "command_b_2": (0x50, "<B"),
+ "command_a_2": (0x51, "<B"),
+ # Motor reads
+ "encoder_1_pos": (0x62, "<H"),
+ "encoder_2_pos": (0x66, "<H"),
+ "status_m1": (0x72, "<B"),
+ "status_m2": (0x73, "<B"),
+ "tasks_running_m1": (0x76, "<H"),
+ "tasks_running_m2": (0x77, "<H"),
+ # PID Control
+ "p_encoder": (0x7A, "<H"),
+ "i_encoder": (0x7C, "<H"),
+ "d_encoder": (0x7E, "<H"),
+ "p_speed": (0x80, "<H"),
+ "i_speed": (0x82, "<H"),
+ "d_speed": (0x84, "<H"),
+ "pass_count": (0x86, "<B"),
+ "tolerance": (0x87, "<B"),
+ }
+ )
I2C_DEV = 0x06
class Commands:
- RESET_PARAMS_ENCODERS = 'R'
- ISSUE_SYNCED_COMMANDS = 'S'
- MOTOR_1_FLOAT_STOP = 'a'
- MOTOR_2_FLOAT_STOP = 'b'
- BOTH_FLOAT_STOP = 'c'
- MOTOR_1_BRAKE_STOP = 'A'
- MOTOR_2_BRAKE_STOP = 'B'
- BOTH_BRAKE_STOP = 'C'
- MOTOR_1_ENC_RESET = 'r'
- MOTOR_2_ENC_RESET = 's'
+ RESET_PARAMS_ENCODERS = "R"
+ ISSUE_SYNCED_COMMANDS = "S"
+ MOTOR_1_FLOAT_STOP = "a"
+ MOTOR_2_FLOAT_STOP = "b"
+ BOTH_FLOAT_STOP = "c"
+ MOTOR_1_BRAKE_STOP = "A"
+ MOTOR_2_BRAKE_STOP = "B"
+ BOTH_BRAKE_STOP = "C"
+ MOTOR_1_ENC_RESET = "r"
+ MOTOR_2_ENC_RESET = "s"
def __init__(self, brick, port, check_compatible=True):
super().__init__(brick, port, check_compatible)
def command(self, command):
value = ord(command)
- self.write_value('command', (value, ))
+ self.write_value("command", (value,))
def get_bat_level(self):
- return self.read_value('command')[0]
+ return self.read_value("command")[0]
def set_encoder_target(self, motor_number, value):
- addressname = 'encoder_' + str(motor_number) + '_target'
- self.write_value(addressname, (value, ))
+ addressname = "encoder_" + str(motor_number) + "_target"
+ self.write_value(addressname, (value,))
def set_speed(self, motor_number, value):
- addressname = 'speed_' + str(motor_number)
- self.write_value(addressname, (value, ))
+ addressname = "speed_" + str(motor_number)
+ self.write_value(addressname, (value,))
def set_time_run(self, motor_number, seconds):
- addressname = 'seconds_to_run_' + str(motor_number)
- self.write_value(addressname, (seconds, ))
+ addressname = "seconds_to_run_" + str(motor_number)
+ self.write_value(addressname, (seconds,))
def command_b(self, motor_number, value):
- addressname = 'command_b_' + str(motor_number)
- self.write_value(addressname, (value, ))
+ addressname = "command_b_" + str(motor_number)
+ self.write_value(addressname, (value,))
def command_a(self, motor_number, bit_num, bit_val):
- addressname = 'command_a_' + str(motor_number)
+ addressname = "command_a_" + str(motor_number)
s = self.read_value(addressname)[0]
- #I feel like there must be an easier way to write one bit...
+ # I feel like there must be an easier way to write one bit...
val = bit_val << bit_num
if bit_val == 1:
value = val | s
- self.write_value(addressname, (value, ))
- return value #testing purposes
+ self.write_value(addressname, (value,))
+ return value # testing purposes
elif bit_val == 0:
val = 1
val = val << bit_num
val = val ^ 0xFF
value = val & s
- self.write_value(addressname, (value, ))
+ self.write_value(addressname, (value,))
return value
def get_encoder_pos(self, motor_number):
- addressname = 'encoder_' +str(motor_number) +'_pos'
+ addressname = "encoder_" + str(motor_number) + "_pos"
return self.read_value(addressname)[0]
def get_motor_status(self, motor_number, bit_num):
- addressname = 'status_m' + str(motor_number)
+ addressname = "status_m" + str(motor_number)
s = self.read_value(addressname)[0]
x = 1
x = x << bit_num
@@ -697,68 +733,95 @@ class MMX(BaseDigitalSensor):
return value
def get_tasks(self, motor_number):
- addressname = 'tasks_running_m' + str(motor_number)
+ addressname = "tasks_running_m" + str(motor_number)
return self.read_value(addressname)[0]
def set_pid(self, pid, target, value):
- addressname = str(pid) + '_' + str(target)
- self.write_value(addressname, (value, ))
+ addressname = str(pid) + "_" + str(target)
+ self.write_value(addressname, (value,))
def set_pass_count(self, value):
- self.write_value('pass_count', (value, ))
+ self.write_value("pass_count", (value,))
def set_tolerance(self, value):
- self.write_value('tolerance', (value, ))
+ self.write_value("tolerance", (value,))
+
-MMX.add_compatible_sensor(None, 'mndsnsrs', 'NxTMMX') #Tested with version 'V1.01'
+MMX.add_compatible_sensor(None, "mndsnsrs", "NxTMMX") # Tested with version 'V1.01'
class HID(BaseDigitalSensor):
"""Class for Human Interface Device sensors.
-These are connected to a computer and look like a keyboard to it."""
+ These are connected to a computer and look like a keyboard to it."""
+
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'command' : (0x41, '<B'),
- 'modifier' : (0x42, '<B'),
- 'keyboard_data' : (0x43, '<B'),
- })
+ I2C_ADDRESS.update(
+ {
+ "command": (0x41, "<B"),
+ "modifier": (0x42, "<B"),
+ "keyboard_data": (0x43, "<B"),
+ }
+ )
I2C_DEV = 0x04
class Commands:
- TRANSMIT = 'T'
- ASCII_MODE = 'A'
- DIRECT_MODE = 'D'
+ TRANSMIT = "T"
+ ASCII_MODE = "A"
+ DIRECT_MODE = "D"
def __init__(self, brick, port, check_compatible=True):
super().__init__(brick, port, check_compatible)
def command(self, command):
value = ord(command)
- self.write_value('command', (value, ))
+ self.write_value("command", (value,))
def set_modifier(self, mod):
- self.write_value('modifier', (mod, ))
+ self.write_value("modifier", (mod,))
def write_data(self, data):
data = ord(data)
- self.write_value('keyboard_data', (data, ))
+ self.write_value("keyboard_data", (data,))
-HID.add_compatible_sensor(None, 'mndsnsrs', 'NXTHID') #Tested with version 'V1.02'
+
+HID.add_compatible_sensor(None, "mndsnsrs", "NXTHID") # Tested with version 'V1.02'
class PS2(BaseDigitalSensor):
I2C_ADDRESS = BaseDigitalSensor.I2C_ADDRESS.copy()
- I2C_ADDRESS.update({'command' : (0x41, '<B'),
- 'button_set_1': (0x42, '<B'),
- 'button_set_2': (0x43, '<B'),
- 'x_left_joystick': (0x44, '<b'),
- 'y_left_joystick': (0x45, '<b'),
- 'x_right_joystick': (0x46, '<b'),
- 'y_right_joystick': (0x47, '<b'),
- })
+ I2C_ADDRESS.update(
+ {
+ "command": (0x41, "<B"),
+ "button_set_1": (0x42, "<B"),
+ "button_set_2": (0x43, "<B"),
+ "x_left_joystick": (0x44, "<b"),
+ "y_left_joystick": (0x45, "<b"),
+ "x_right_joystick": (0x46, "<b"),
+ "y_right_joystick": (0x47, "<b"),
+ }
+ )
class ControllerState:
class Buttons:
- left, down, right, up, square, cross, circle, triangle, r1, r2, r3, l1, l2, l3 = [0 for i in range(14)] #14 zeros
+ (
+ left,
+ down,
+ right,
+ up,
+ square,
+ cross,
+ circle,
+ triangle,
+ r1,
+ r2,
+ r3,
+ l1,
+ l2,
+ l3,
+ ) = [
+ 0 for i in range(14)
+ ] # 14 zeros
+
def __init__(self, buttons_1, buttons_2, left_x, left_y, right_x, right_y):
self.leftstick = (left_x, left_y)
self.rightstick = (right_x, right_y)
@@ -781,35 +844,37 @@ class PS2(BaseDigitalSensor):
self.buttons.l3 = bool(buttons_1 & 0x02)
class Commands:
- POWER_ON = 'E'
- POWER_OFF = 'D'
- DIGITAL_MODE = 'A'
- ANALOG_MODE = 's'
- ADPA_ON = 'N'
- ADPA_OFF = 'O'
+ POWER_ON = "E"
+ POWER_OFF = "D"
+ DIGITAL_MODE = "A"
+ ANALOG_MODE = "s"
+ ADPA_ON = "N"
+ ADPA_OFF = "O"
def __init__(self, brick, port, check_compatible=True):
super().__init__(brick, port, check_compatible)
def command(self, command):
value = ord(command)
- self.write_value('command', (value, ))
+ self.write_value("command", (value,))
def get_joystick(self, xy, lr):
- addressname = str(xy) + '_' + str(lr) + '_joystick'
+ addressname = str(xy) + "_" + str(lr) + "_joystick"
return self.read_value(addressname)[0]
def get_buttons(self, setnum):
- addressname = 'button_set_' + str(setnum)
+ addressname = "button_set_" + str(setnum)
return self.read_value(addressname)[0]
def get_sample(self):
return self.ControllerState(
self.get_buttons(1),
self.get_buttons(2),
- self.get_joystick('x', 'left'),
- self.get_joystick('y', 'left'),
- self.get_joystick('x', 'right'),
- self.get_joystick('y', 'right'))
+ self.get_joystick("x", "left"),
+ self.get_joystick("y", "left"),
+ self.get_joystick("x", "right"),
+ self.get_joystick("y", "right"),
+ )
+
-PS2.add_compatible_sensor(None, 'mndsnsrs', 'PSPNX') #Tested with version 'V2.00'
+PS2.add_compatible_sensor(None, "mndsnsrs", "PSPNX") # Tested with version 'V2.00'