Базовые способы работы с моторами в Python были рассмотрены в прошлой заметке - теперь настало время осветить, какие API (applications programming interface) доступны для работы со стандартными LEGO NXT датчиками. |
nxt.sensor
, который предоставляет классы по работе с датчиками. Для этого в Python Shell запросим справку по модулю:import nxt.sensor help(nxt.sensor)Небольшая информационная страничка расскажет, что данный модуль предоставляет доступ к следующим под-модулям:
- analog
- common
- digital
- generic
- hitechnic
- mindsensors
Сразу можно раскрыть нюансы использования модуля
nxt.sensor
- в большинстве случаев не нужно импортировать каждый отдельный под-модуль, чтобы получить доступ к классам, отвечающим за работу того или иного датчика, - эти классы уже импортированы в пространство имен этого модуля. Но для того, чтобы посмотреть каждый отдельный класс можно, тем не менее, воспользоваться справкой по каждому отдельному под-модулю. Например, чтобы получить информацию по API, работающим со стандартными NXT датчиками, нужно выполнить help(nxt.sensor.generic)
.Теперь, глядя на полученную таким образом документацию, приступаем к изучению механизмов работы.
Датчик касания
Доступ к данному датчику осуществляется через класс
Touch
:from nxt.sensor import Touch, PORT_1 SensorTouch = Touch(brick, PORT_1)У данного класса полезен только один метод:
is_pressed()
, который возвращает True
, если датчик в соответствующем порту нажат, иначе False. Метод может использоваться, например, вот так:engine.run(90) while(not SensorTouch.is_pressed()): pass engine.brake()
Датчик расстояния
За работу с ультрасоник датчиком отвечает класс
Ultrasonic
.from nxt.sensor import Ultrasonic, PORT_4 USSensor = Ultrasonic(brick, PORT_4)Судя по документации, в классе заявляется поддержка работы со всеми пятью режимами (о режимах в частности и о работе US Senor вообще можно почитать на английском языке вот здесь), которые поддерживает датчик расстояния NXT:
OFF, SINGLE_SHOT, CONTINUOUS_MEASUREMENT, EVENT_CAPTURE, REQUEST_WARM_RESET
. На самом деле, скорее всего все зависит от того, поддерживает ли firmware блока эти команды в полном объеме.В реальной жизни, скорее всего, будет использоваться стандартный (
CONTINUOUS_MEASUREMENT
?) режим. Который включается по умолчанию. Поэтому расстояние до ближайшего предмета можно получить с помощью метода get_distance(). Возвращаемое значение метода будет принимать числовое значение от 0 до 255 - расстояние в сантиметрах (фактически от 7 до 255). engine.reset_position(False) engine.run(50) for i in range(0, 100): print "Angle:", engine.get_tacho().rotation_count, print "Distance:", USSensor.get_distance() engine.brake()
Датчик освещенности
Класс
Light
предоставляет средства для получения замеров отраженного или окружающего света.from nxt.sensor import Light, PORT_3 eye = Light(brick, PORT_3)При инициализации класса подсветка светодиодом включена не будет. Т.е. замеры освещенности будут производиться для окружающего света. Позднее, подсветка может быть как включена, так и выключена (при необходимости) с использованием метода
set_illuminated()
, который в качестве параметра принимает логическое значение, обозначающее включить или выключить светодиод.FREQ_D = 587 FREQ_E = 659 brick.play_tone_and_wait(FREQ_E, 500) eye.set_illuminated(False) brick.play_tone_and_wait(FREQ_D, 500) eye.set_illuminated(True)Замер освещенности происходит в режиме считывания сырых данных, т.е. результатом будет число из диапазона от 0 до 1023. За это отвечает метод
get_lightness()
:TRIGGER_POINT=510 while True: if eye.get_lightness() < TRIGGER_POINT: engineLeft.run(100) engineRight.run(10) else: engineLeft.run(10) engineRight.run(100)
Датчик цвета
Инициализация класса
Color20
- датчика цвета практически не отличается от остальных датчиков.import nxt.sensor camera = Color20(brick, PORT_2)При этом автоматически включается режим, когда горят все три светодиода: красный, зеленый и синий - датчик в этом режиме готов к определению цвета через вызов метода
get_color()
:view = camera.get_color() if view == 6: print "White" elif view == 1: print "Black" else print "Too colorful!"Метод возвращает число, характеризующее цвет под датчиком:
1 | Черный |
2 | Синий |
3 | Зеленый |
4 | Желтый |
5 | Красный |
6 | Белый |
Из программы на языке Python датчик также можно использовать в режиме определения освещенности, как для отраженного цвета, так и для окружающего . Для этого можно воспользоваться методом
get_reflected_light()
. Метод в качестве параметра принимает значение, каким светодиодом производить подсветку (Type.COLORRED, Type.COLORGREEN, Type.COLORBLUE
) или вообще не производить (Type.COLORNONE
):TARGET_POINT = 510 while True: err = TARGET_POINT - camera.get_reflected_light(Type.COLORRED) P = err * 0.5 engineLeft.run(50 + P) engineRight.run(50 - P)Существует также способ отдельно манипулировать светодиодами посредством метода
set_light_color()
. Например, робот может помигать своими светодиодами и в конце выключить их вообще:from time import sleep for color in (Type.COLORRED, Type.COLORGREEN, Type.COLORBLUE): camera.set_light_color(color) sleep(0.5) camera.set_light_color(Type.COLORNONE)В заключение, можно также сказать, что опрос цветового датчика в режиме освещенности не выглядит оптимальным, если взглянуть на исходный код модуля
gereric.py
:def get_reflected_light(self, color): self.set_light_color(color) return self.get_input_values().scaled_valueВидно, что перед каждым опросом метод тратит время на вызов метода, включающего светодиод. А ведь в большинстве случаев он уже включен. Поэтому использовать
get_reflected_light()
, например, в цикле не выглядит оптимальным. Вместо этого, нужно воспользоваться знанием того, что помимо родных методов класса Color20
, можно вызывать унаследованные методы. В данном случае полезным будет метод get_input_values()
, возвращающий кортеж различных данных о датчике, в том числе и величину отраженного света. Теперь если светодиод включить только один раз перед циклом, то программа будет выглядеть следующим образом:TARGET_POINT = 510 camera.set_light_color(Type.COLORRED) while True: err = TARGET_POINT - camera.get_input_values().scaled_value P = err * 0.5 engineLeft.run(50 + P) engineRight.run(50 - P)
а как записовать речь и передовать ее на нхт?
ОтветитьУдалить