Звук
Чтобы воспроизвести звуки, вы должны сначала импортировать класс Sound и создать экземпляр этого класса, чтобы каждый приведенный ниже сценарий включал
from ev3dev2.sound import Sound
sound = Sound()

все описанные здесь звуковые функции, имеющие параметр play_type , который по умолчанию равен 0. Вот значения трех возможных значений play_type:
0: воспроизвести звук и заблокировать программу до ее завершения. Это значение по умолчанию.1: Воспроизведение звука без блокировки программы.2: Воспроизвести звук как петлю , блокируя программу. Цикл можно завершить, только уничтожив программу, так что эта опция не очень полезна.Воспроизвести стандартный звуковой сигналИспользовать   звуковой сигнал ( play_type=0 )
Пример: 
#!/usr/bin/env python3from ev3dev2.sound import Sound
sound = Sound()
sound.beep()
Обратите внимание, что по умолчанию команда beep() блокирует (приостанавливает) выполнение программы до тех пор, пока не завершится воспроизведение звука. Для получения дополнительной информации см. официальную документацию .
Воспроизвести ОДИН тонЧтобы воспроизвести ОДИН тон заданной частоты n (Гц) и длительности (секунды), используйтеplay_tone ( частота, продолжительность,  play_type=0 )
Пример: Чтобы воспроизвести один тон частотой 1500 Гц в течение 2 секунд (2000 миллисекунд):
#!/usr/bin/env python3from ev3dev2.sound import Sound
sound = Sound()
sound.play_tone(1500, 2)Официальная документация .
Воспроизведение ПОСЛЕДОВАТЕЛЬНОСТИ тоновВ настоящее время (октябрь 2018 г.) новая функция play_tone() не может воспроизводить последовательность тонов, а старая функция tone() может. Поэтому, чтобы воспроизвести ПОСЛЕДОВАТЕЛЬНОСТЬ тонов, используйте    тон( tone_sequence )
Параметр tone_sequence представляет собой список кортежей, где каждый кортеж содержит до трех чисел. Вы уже должны знать, что кортеж похож на список, за исключением того, что список можно изменить, а кортеж — нет. Первое число — это частота в Гц, второе — продолжительность в миллисекундах, а третье — задержка в миллисекундах между этим и следующим тоном в последовательности.
#!/usr/bin/env python3

from ev3dev2.sound import Sound

sound = Sound()

# Play a 200Hz tone for 2 seconds and then wait 0.4 seconds
# before playing the next tone, 800Hz for 1 second
# followed by a 3 second delay
sound.tone([(200, 2000, 400),(800, 1000, 3000)])
Официальная документация.

Воспроизведение звукового файла WAVЧтобы воспроизвести звуковой файл WAV, используйте      play_file( wav_file,  play_type=0 )  .  Вы не можете использовать файлы mp3 с командой  воспроизведения  , а также звуковые файлы Lego в формате RSF или RSO. Внизу этой страницы я разместил ZIP-файл, содержащий все звуки Lego в формате WAV . Все звуки находятся в одной папке, а не разнесены по разным папкам, как в EV3-G. Все сценарии на этом сайте, использующие эти звуки, предполагают, что вы поместили их в папку «звуки» внутри папки «робот». Поэтому адрес папки «звуки» будет  /home/robot/sounds/ . Самый простой способ сделать это — открыть папку звуков в VS Code, а затем щелкнуть значок «Отправить проект на устройство» в заголовке браузера устройств EV3. Это так просто! Мои сценарии предполагают, что вы загрузили звуки EV3 в EV3, как только что было описано. Это похоже на то, как мои сценарии предполагают, что вы поместили все изображения Lego в формате BMP в папку с именем «pics» в папке «robot», как описано на  этой странице . Если вы прошьете новый образ Stretch на свою SD-карту, папки «звуки» и «изображения» (и все ваши сценарии) будут удалены, поэтому вам нужно будет снова загрузить их на EV3.
Вот список звуков EV3 без расширений файлов .wav:

Хорошим источником дополнительных бесплатных звуковых файлов WAV является  Wavsource.com . Однако у меня была проблема с файлом WAV, который я скачал оттуда — я получил сообщение об ошибке «недостаточное выполнение», когда запускал свой скрипт, что предполагает, что звуковой файл был поврежден. Если вы получите такое же сообщение, удалите этот звуковой файл и попробуйте другой. Если вы хотите добавить дополнительные звуковые файлы WAV в папку «звуки», которую вы уже создали, как было предложено выше, просто добавьте файлы WAV к существующим файлам в папке «звуки» на вашем ПК, а затем снова загрузите всю папку в EV3. как описано выше.
Если у вас есть папка «sounds», содержащая, среди прочего, файл «Dog bark 1.wav» внутри папки «robot» на EV3, вы сможете запустить следующий скрипт. Звуковой сигнал включен, чтобы доказать вам, что программа приостанавливается (блокируется) до тех пор, пока собака не перестанет лаять перед воспроизведением звукового сигнала:
#!/usr/bin/env python3
from ev3dev2.sound import Sound
from time import sleep

sound = Sound()

sound.play_file('/home/robot/sounds/Dog bark 1.wav')
sound.beep()
Официальная документация .

Текст в речьИспользовать   говорить ( текст,  play_type=0 )
Попробуйте этот сценарий ниже, который не требует пояснений. Обратите внимание, что вы можете контролировать амплитуду (громкость), скорость и язык, и что вы можете каркать и шептать, если хотите! Функция speak() на самом деле управляет основной функцией espeak() . Функция espeak() имеет значения по умолчанию для амплитуды и скорости 100 и 175, но они переопределяются значениями по умолчанию speak() , которые равны 200 и 130. Для получения дополнительной информации см  . espeak.sourceforge.net  . Обратите внимание, как немного деформирован английский текст, чтобы он звучал лучше. Попробуйте изменить комментарий/раскомментировать, чтобы услышать неизмененный текст.

#!/usr/bin/env python3из ev3dev2.sound импорт звука
звук = звук()# см. http://espeak.sourceforge.net/# значения -a 200 -s 130 ДОЛЖНЫ БЫТЬ ВКЛЮЧЕНЫ при указании любых других параметров# a = амплитуда (макс. 200, по умолчанию 100), s = скорость 80-500, по умолчанию = 175)
опции = ‘-a 200 -s 130 -v’# str_en = «Я думаю, вы должны знать, я чувствую себя очень подавленным»str_en = «Думаю, вам следует знать, они очень подавлены»# Голос по умолчанию = английский, мужскойзвук.говорить(str_en)# Английский, male1 (самый низкий мужской тон)sound.speak(str_en, espeak_opts=’-a 200 -s 130 -v en+m1 ‘) # длинная форма# английский, мужской7 (самый высокий мужской тон)sound.speak(str_en, espeak_opts=opts+’ en+m7 ‘) # используя мою переменную ‘opts’# английский, женский1 (самый низкий женский тон)sound.speak(str_en, espeak_opts=opts+’ en+f1 ‘)# английский, женский5 (самый высокий женский тон)sound.speak(str_en, espeak_opts=opts+’ en+f5 ‘)# квакатьsound.speak(str_en, espeak_opts=opts+’ en+croak ‘)# шепотsound.speak(str_en, espeak_opts=opts+’ en+whisper ‘)# en-us = американский английскийsound.speak(str_en, espeak_opts=opts+’ en-us ‘)# en-rp = Полученное произношение («BBC English»)sound.speak(str_en, espeak_opts=opts+’ en-rp ‘)# s = 80 — самая низкая возможная скоростьsound.speak(str_en, espeak_opts=’-a 200 -s 80 ‘)# s = 300 — высокая скоростьsound.speak(str_en, espeak_opts=’-a 200 -s 300 ‘)
# Французскийstr_fr = ‘Le chat est sous la chaise! Le singe est sur la branche!sound.speak(str_fr, espeak_opts=opts+’ fr ‘)# Французский, высокий мужской тонsound.speak(str_fr, espeak_opts=opts+’ fr+m7 ‘)# француженка, женщина довольно низкого тонаsound.speak(str_fr, espeak_opts=opts+’ fr+f2 ‘)# См. http://espeak.sourceforge.net/languages.html# для других языков
См. также пример в нижней части комбинированного примера ниже. Кажется, есть (по состоянию на октябрь 2018 года) небольшая ошибка: если ваша строка заканчивается точкой, то произносимые слова будут заканчиваться словом «точка». Решение: либо опустить последнюю точку, либо поставить после нее пробел.
Комбинированный примерПример программы для демонстрации воспроизведения звуковых сигналов, тонов и преобразования текста в речь:#!/usr/bin/env python3
from ev3dev2.sound import Sound
from time import sleep

sound = Sound()

#play a standard beep
sound.beep()

sleep(2) # pause for 2 seconds

# Play a SINGLE 2000 Hz tone for 1.5 seconds
sound.play_tone(2000, 1.5)

sleep(2)

# Play a SEQUENCE of tones
sound.tone([(200, 2000, 400),(800, 1800, 2000)])

sleep(2)

# Play a 500 Hz tone for 1 second and then wait 0.4 seconds
# before playing the next tone
# Play the tone three times
sound.tone([(500, 1000, 400)] * 3)

sleep(2)

#text to speech
sound.speak('Hello, my name is E V 3!')
Использование двигателей

Использование двигателей

На этой странице описаны не все доступные двигательные функции, а только те, которые представляют наибольший интерес для начинающих программистов EV3 Python. Полное описание смотрите в официальной документации .
В новой (версия 2) библиотеке EV3 Python реализованы значительные улучшения моторных функций. Улучшения включают в себя:введение классов MoveSteering и  MoveTank , которые имитируют функциональность блоков Move Steering и Move Tank в стандартной системе на основе значков Lego EV3, иногда называемой EV3-G.

целый ряд новых on-функций, похожих на run-функции библиотеки v1, но лучше. Поскольку функции «on» лучше, вы должны использовать их, а не функции «run», даже если функции «run» все еще доступны (по крайней мере, на данный момент…). Поскольку функции «запуска» неполноценны, они не будут использоваться на этом сайте, хотя на старом сайте, посвященном библиотеке EV3 Python v1 , функции «запуска» описаны.

С помощью новых функций можно задавать значения угла в градусах и оборотах, а значения времени в минутах и ​​секундах. Например, вы можете запросить, чтобы двигатель вращался со скоростью 10 оборотов в минуту.

В новой библиотеке есть функция wait_until_not_moving() для одиночных моторов, которая может быть полезна, например, для определения того, прекратили ли движение захватные рычаги, которые смыкаются вокруг объекта (вы не будете точно знать, какое значение угла или времени использовать, чтобы заставить руки смыкаются).

Новые функции «включения» делают программу «блокировкой» (паузой) до тех пор, пока движение не завершится, прежде чем продолжить, что является тем же поведением  , что и блокировка двигателя в EV-G, и почти всегда  то, что вам нужно. Если вы не хотите, чтобы функция  блокировала программу, это тоже  вариант  .Общие параметры, используемые функциями onскоростьБольшинство методов, использующих двигатели, принимают  аргумент скорости . скорость представляет собой целое число, которое представляет собой  процент от номинальной максимальной скорости двигателя . Например, если вы установите скорость  на 50, то двигатель будет работать на 50% от его номинальной максимальной скорости (для функций, которые управляют двумя двигателями, скорость относится к более быстрому двигателю).Номинальная максимальная скорость большого двигателя Lego EV3 составляет 1050 градусов в секунду .Номинальная  максимальная скорость среднего двигателя Lego EV3 составляет 1560 градусов в секунду .Двигатели обычно не способны надежно и точно достигать своей номинальной максимальной скорости, поэтому не следует использовать значения скорости выше 90 .В официальной документации  вы часто будете видеть ссылки на «количество тахометров в секунду», но для двигателей  Lego EV3 это просто то же самое, что и градусы в секунду.Как указывалось ранее,  скорость представляет собой  процент от номинальной максимальной скорости двигателя . Следовательно , если для большого и среднего двигателей установлена ​​скорость = 50 , то они будут работать с разными скоростями (в градусах в секунду). Большой двигатель будет работать со скоростью 50% x 1050 = 525 градусов в секунду, а средний двигатель будет работать со скоростью 50% x 1560 = 780 градусов в секунду. Также можно указать скорость в градусах в секунду или оборотах в секунду , или градусах в минуту , или оборотах в минуту — во всех этих случаях большие и средние двигатели будут вращаться с одинаковой скоростью, если вы зададите им одинаковое значение, например, 100 градусов в минуту. второй       . Это работает следующим образом: вы вводите желаемое значение, например, в градусах в секунду, а функция преобразует его в соответствующее значение скорости  . Например , SpeedDPS() преобразует значение в градусах в секунду в соответствующее значение скорости  . Следующий сценарий демонстрирует использование этих функций преобразования. Обратите внимание, что эти функции преобразования должны быть импортированы , прежде чем их можно будет использовать в скрипте, как показано ниже. #!/usr/bin/env python3из ev3dev2.motor импортировать LargeMotorиз ev3dev2.motor импортировать SpeedDPS, SpeedRPM, SpeedRPS, SpeedDPMиз времени импортировать сон
лм = большой двигатель ()
»’Это запустит большой двигатель на 50% его мощности.расчетная максимальная скорость 1050 град/с.50% х 1050 = 525 град/с»’lm.on_for_seconds (скорость = 50, секунды = 3)спать(1)
»’скорость и секунды являются ПОЗИЦИОННЫМИаргументы, что означаетвам не нужно включать имена параметров какпока вы ставите аргументы в этом порядке (скорость, затем секунды), так что это то же самое, что ипредыдущая команда:»’lm.on_for_seconds(50, 3)спать(1)
»’Это будет работать со скоростью 500 градусов в секунду (DPS).Вы должны быть в состоянии услышать, что двигатель работаетнемного медленнее, чем раньше.»’lm.on_for_seconds (скорость = SpeedDPS (500) , секунды = 3)спать(1)
# 36000 градусов в минуту (DPM) (редко полезно!)lm.on_for_seconds (скорость = SpeedDPM (36000) , секунды = 3)спать(1)
# 2 оборота в секунду (RPS)lm.on_for_seconds (скорость = SpeedRPS (2) , секунды = 3)спать(1)
# 100 оборотов в минуту (об/мин)lm.on_for_seconds (скорость = SpeedRPM (100) , секунды = 3)
тормозтормоз является булевым параметром, что означает, что он может принимать  значения True или False . Если это правда, то, как только двигатель завершит свое движение, двигатель будет активно пытаться удерживать двигатель в фиксированном положении. Если тормоз равен False, то  , как только двигатель завершит свое движение, двигатель постепенно остановится, замедляясь только за счет трения. тормоз всегда имеет значение True по умолчанию. тормоз является аргументом ключевого слова  («kwarg»), поэтому вам не нужно включать его в команду двигателя, но если вы включаете, вы должны указать имя, а также значение, например, rake=False . блокировать«Блокировка» программы означает приостановку выполнения программы до тех пор, пока текущая команда не будет завершена. Многие моторные команды v2 имеют аргумент ‘ block ‘, и почти в каждом случае block=True по умолчанию. Исключением является функция on( ), для которой block=False по умолчанию. block является  аргументом ключевого слова, и поэтому вам не обязательно включать его в свой код для запуска команды. Если вы не включите  block=False , то будет использоваться значение по умолчанию block=True (за исключением функции on() , для которой block=False  по умолчанию ). функции включения для управления одним двигателемВы можете заставить один или несколько двигателей вращаться с заданной скоростью.через заданный уголна определенное время’навсегда’ (пока двигатель не будет остановлен командой off () и позднее во время выполнения программы)пока он не перестанет двигаться (например, когда захват закрывает объект)на заданную позициюпока не будет достигнуто другое состояние
Поверните один двигатель на заданный уголИспользуйте либо on_for_rotations() , либо on_for_degrees() :
on_for_rotations(speed, rotations, brake=True, block=True)Вращайте двигатель на скорости  для оборотов.Пример: включить один двигатель на 5 оборотов при 50% его номинальной максимальной скорости:on_for_rotations(speed=50, rotations=5)
Имена позиционных аргументов указывать не нужно, если аргументы указаны в правильном порядке и вы никогда не ставите безымянный аргумент после именованного аргумента, так что это то же самое, что и выше:on_for_rotations(50, 5)
Чтобы сделать ваши скрипты максимально понятными, вероятно, будет хорошей идеей включить имена, как я обычно делаю на этом сайте.
Как объяснялось ранее, скорость  представляет собой целое число в процентах от номинальной максимальной скорости двигателя. Функции преобразования доступны для преобразования таких единиц, как градусы в секунду, в соответствующее значение скорости  , как описано выше. Пример: чтобы повернуть один двигатель на 5 оборотов со скоростью 500 градусов в секунду:on_for_ вращений (скорость = SpeedDPS (500) ,  вращений = 5 )Не забудьте импортировать функцию преобразования, прежде чем использовать ее, как показано в первом скрипте на этой странице.
Как упоминалось ранее, вам не нужно включать аргументы ключевого слова « тормоз » и « блок» , если вы хотите использовать их значения по умолчанию «Истина» и «Истина», как это обычно бывает.

on_for_degrees(speed, degrees, brake=True, block=True)
Поверните двигатель на скорости  на градусы .
Пример: поверните один двигатель на 90 градусов при 80% номинальной максимальной скорости:on_for_grades (скорость = 80, градусы = 90)
Запуск одного двигателя в течение заданного времениon_for_seconds(speed, seconds, brake=True, block=True)
Вращайте двигатель на скорости в  течение нескольких секунд
Пример: двигатель должен работать на 40 % от  номинальной максимальной скорости в течение 3 секунд: on_for_seconds (скорость = 40, секунды = 3)

Запустите один двигатель «навсегда»on(speed, brake=True, block=False)Вращайте двигатель на скорости  «навсегда»Пример: для включения двигателя на 45% от номинальной максимальной скорости:вкл(скорость=45)Остановить один двигательВам часто понадобится это, чтобы выключить двигатель, который вы включили «навсегда» с помощью  on() .off()
Запустите один двигатель, пока он не перестанет двигатьсяХорошим примером может быть ситуация, когда руки захвата смыкаются вокруг какого-либо объекта. Вы не можете точно знать, какому углу или какому времени соответствует это движение.
wait_until_not_moving()
Эта команда обычно выдается после команды on() , как в этом примере. Просто возьмите движущееся колесо, чтобы остановить его, и скрипт прекратит работу.#!/usr/bin/env python3from ev3dev2.motor import LargeMotor, OUTPUT_B
large_motor = LargeMotor(OUTPUT_B)
large_motor.on(speed=50)large_motor.wait_until_not_moving()
Поверните один двигатель в заданное положениеПо состоянию на декабрь 2018 года в этой команде может быть ошибка, которая может привести к зависанию программы. В частности, если двигателю приказано переместиться в положение, которое находится в пределах примерно 10 градусов от его текущего положения, это может привести к сбою, что приведет к зависанию программы. Поэтому я советую вам пока избегать использования этой функции .
on_to_position(speed, position, brake=True, block=True)Эта функция игнорирует знак скорости, что имеет смысл, поскольку всегда будет только одно возможное направление вращения двигателя для достижения запрошенного положения. Важно понимать, что положение (угол) имеет бесконечную шкалу, и поэтому двигатель будет вращаться предсказуемым образом. Например, если двигатель находится в положении 1° и получает указание перейти в положение 359°, то он повернется в положительном направлении на 358°. Не утверждайте, что начальная и конечная позиции разделены всего на 2° — они разделены на 358°. Если двигатель находится в положении 180° и вы даете ему указание перейти на -540°, то он повернется на 720° (два оборота) в отрицательном направлении — он окажется в том же физическом положении, что и до его перемещения, но теперь он «официально» в новой позиции -540°.
Запустите один двигатель, пока не будет достигнуто какое-то другое состояниеДругие функции для одиночных двигателей см. в официальной документации .
Используйте двигатель в качестве датчикаПоскольку вы можете прочитать положение двигателя, вы можете использовать двигатель в качестве датчика. Например, вы можете вручную повернуть двигатель, а затем иметь код, который может управлять скоростью второго двигателя или воспроизводить звуки, например, в зависимости от положения двигателя. Для двигателей Lego EV3 position возвращает текущее положение двигателя в градусах. Когда двигатель вращается по часовой стрелке (как видно, если держать двигатель таким образом, что красная ось двигателя находится внизу справа), положение увеличится. Аналогично, вращение против часовой стрелки приводит к уменьшению положения. Запись установит позицию на это значение.функции «вкл.» для управления парой двигателейВ эту группу функций входят очень важные функции MoveSteering и MoveTank .
Так же, как и в системе на основе значков Lego EV3,  функции MoveTank управляют двумя двигателями на основе  значений левой_скорости  и  правой_скорости  .
Как и в системе на основе значков Lego EV3,  функции  MoveSteering  управляют двумя двигателями на основе значения рулевого управления и значения скорости (EV3-G называет скорость «мощностью»). Немного сложнее объяснить значение этих параметров по сравнению с параметрами MoveTank . Значение рулевого управления управляет траекторией движения робота и может быть любым значением в диапазоне от -100 до +100.-100 означает поворот налево на месте-50 означает поворот налево с не вращающимся левым колесом0 означает идти прямо+50 означает поворот направо с не вращающимся правым колесом+100 означает поворот направо на местеЗначение скорости относится к скорости более быстрого колеса (иногда колеса могут быть одинаково быстрыми, например, когда рулевое управление = 0). Скорость более медленного колеса рассчитывается автоматически на основе значений рулевого управления и скорости .
Эта диаграмма может помочь вам понять взаимосвязь между MoveTank и MoveSteering . Он предназначен для того, чтобы показать, какие значения left_speed и right_speed ( параметры MoveTank ) соответствуют всем возможным значениям рулевого управления и значению скорости 40 ( параметры MoveSteering ).

Для всех значений рулевого управления (от -100 до +100) всегда есть хотя бы один двигатель со скоростью, равной значению скорости 40.Когда рулевое управление =0, мы замечаем, что и left_speed , и right_speed равны скорости , равной 40.При  рулевом управлении =25 мы отмечаем, что left_speed=40  и right_speed=20  При  рулевом управлении =50 мы отмечаем, что left_speed=40  и right_speed=0  При  рулевом управлении =100 мы отмечаем, что left_speed=40  и right_speed=-40  Прежде чем вы сможете использовать эти функции MoveTank и MoveSteering , вы должны импортировать их и определить пару двигателей. По умолчанию эти функции будут работать с большими двигателями Lego EV3, и вам не нужно импортировать LargeMotor , чтобы использовать эти функции с парой больших двигателей. Ниже используются разумные имена для сопряжения больших двигателей:steer_pair = MoveSteering(OUTPUT_B, OUTPUT_C)tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)Я рекомендую вам не использовать имена типа drive_pair, иначе когда вы столкнетесь с кодом типа drive_pair.on_for_seconds(50,50,3)  , вы не узнаете из него, является ли это командой рулевого управления или командой танка — движения будут очень разные.
Вы также можете использовать эти функции с парой средних двигателей, но в этом случае вам необходимо импортировать MediumMotor . Вам также необходимо указать в сопряжении, что вы используете средние двигатели, например :tank_pair= MoveTank(OUTPUT_B, OUTPUT_C, motor_class=MediumMotor)
Вот полный скрипт с использованием пары средних моторов:#!/usr/bin/env python3from ev3dev2.motor import MediumMotor, MoveSteering, OUTPUT_A, OUTPUT_Dfrom time import sleep
steer_pair = MoveSteering(OUTPUT_A, OUTPUT_D, motor_class=MediumMotor)
steer_pair.on_for_seconds(steering=0, speed=50, seconds=2)

Вы должны использовать подходящую пару двигателей, поэтому вы не можете соединить большой двигатель со средним двигателем.
Переместить танк на заданный уголИспользуйте либо on_for_rotations() , либо on_for_degrees().on_for_rotations(left_speed, right_speed, rotations, brake=True, block=True)Вращайте моторы со скоростью left_speed и right_speed для вращения . Как и для параметра скорости  , который используется с одиночными двигателями, левая_скорость и правая_скорость представляют собой целые проценты от  номинальной максимальной скорости двигателя. Как и в случае со скоростью , вы можете использовать функции преобразования, такие как SpeedDPS()  , которые преобразуют градусы в секунду в соответствующие  значения left_speed или right_speed . 
Если левая_скорость не равна правой_скорости (т. е. робот будет вращаться), двигатель снаружи поворота (тот, у которого более высокая скорость) будет вращаться на полные обороты , в то время как для двигателя внутри будет рассчитано количество оборотов. в соответствии с ожидаемым оборотом.
Пример:tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)# drive in a turn for 10 rotations of the outer (faster) motortank_pair.on_for_rotations(left_speed=50, right_speed=75, rotations=10)
Поскольку это позиционные аргументы, имена необязательны, поэтому можно написать одну и ту же командуtank_pair.on_for_rotations(50, 75, 10)но, вероятно, лучше включить имена для ясности.
on_for_degrees(left_speed, right_speed, degrees, brake=True, block=True)Вращайте моторы на left_speed и right_speed на градусы . Единственная разница между  on_for_rotations() и  on_for_degrees() заключается в том, что в одном используются повороты, а в другом — градусы.Переместить танк на заданное времяon_for_seconds(left_speed, right_speed, seconds, brake=True, block=True)Вращайте моторы со скоростью left_speed и right_speed в течение секунд .Переместить танк «навсегда»на (левая_скорость, правая_скорость)Начните вращать двигатели в соответствии с левой_скоростью и правой_скоростью навсегда.Остановить моторыoff(brake=True)Немедленно остановите оба двигателя.Пример скриптаЗаставьте робота двигаться вперед по прямой до тех пор, пока не будет нажат сенсорный датчик, прикрепленный к бамперу, затем остановите оба двигателя. Обратите внимание, что ‘ is_pressed ‘ не является функцией, поэтому ей не нужны круглые скобки. Обратите внимание, что здесь неуместно использовать ts.wait_for_bump() , потому что, когда бампер сталкивается с объектом, это «нажатие» на датчик касания, а не «удар» (нажатие и отпускание). Наконец, заметьте также, что после выключения двигателей тормоз будет действовать на них в течение 5 секунд, в течение которых их будет очень трудно провернуть вручную, тогда как после завершения программы  их будет намного легче провернуть.
#!/usr/bin/env python3from ev3dev2.motor import MoveTank, OUTPUT_B, OUTPUT_Cfrom ev3dev2.sensor.lego import TouchSensorfrom time import sleep
ts = TouchSensor()tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
tank_pair.on(left_speed=30, right_speed=30)
while not ts.is_pressed:  # while touch sensor is not pressed    sleep(0.01)
tank_pair.off()sleep(5)Переместить руль на заданный уголИспользуйте либо  on_for_rotations() , либо on_for_degrees().  on_for_rotations(steering, speedrotations, brake=True, block=True)Вращайте моторы так, чтобы робот двигался по траектории, определяемой рулевым управлением , и чтобы более быстрый мотор имел скорость, равную скорости, и двигался на угол, заданный поворотами . Скорость и угол поворота более медленного двигателя вычисляются автоматически на основе значений рулевого управления и скорости .
скорость представляет собой целое число в процентах от  номинальной максимальной скорости двигателя. Вы можете использовать функции преобразования, такие как  SpeedDPS()  , которые преобразуют градусы в секунду в соответствующее  значение скорости . 
Пример:steer_pair = MoveSteering (OUTPUT_B, OUTPUT_C)# заезжаем в оборот на 10 оборотов внешнего мотораsteer_pair.on_for_rotations(рулевое управление=-20, скорость=75, обороты=10)
Поскольку это позиционные аргументы, имена необязательны, поэтому можно написать одну и ту же командуsteer_pair.on_for_rotations(-20, 75, 10)но, вероятно, лучше включить имена для ясности.
on_for_degrees(steering, speed, degrees, brake=True, block=True)Вращайте моторы так, чтобы робот двигался по траектории, определяемой рулевым управлением , и чтобы более быстрый мотор имел скорость, равную скорости , и двигался на угол, заданный в градусах . Скорость  и угол поворота более медленного двигателя вычисляются автоматически на основе значений рулевого управления и скорости . Единственная разница между on_for_rotations() и on_for_degrees() заключается в том, что в одном используются повороты, а в другом — градусы. Переместить рулевое управление  на заданное времяon_for_seconds(steering, speed, seconds, brake=True, block=True)Вращайте моторы так, чтобы робот двигался по длинному пути, определяемому рулевым управлением , со скоростью, определяемой скоростью . Более быстрый двигатель будет иметь скорость, равную скорости , а скорость более медленного двигателя будет рассчитываться как функция значения скорости и значения рулевого управления . (Иногда двигатели работают одинаково быстро, например, когда рулевое управление = 0.)Переместить рулевое управление «навсегда»вкл(рулевое управление, скорость)Начните вращать двигатели в соответствии с  рулевым управлением  и  скоростью  навсегда.Остановить моторыoff(brake=True)Немедленно остановите оба двигателя.
Регулировка скорости и  синхронизацияEV3 Python обычно использует функцию под названием « регулирование скорости » при использовании двигателей.  Когда регулирование скорости включено, контроллер двигателя будет изменять мощность, подаваемую на двигатель, чтобы поддерживать требуемую скорость . Это сравнимо с тем, как круиз-контроль вашего автомобиля пытается поддерживать постоянную скорость, даже если ваш автомобиль движется вверх или вниз по склону.
Хотя EV3 Python использует регулировку скорости, в настоящее время он не предлагает синхронизацию  двигателей для пар двигателей, так что если один двигатель замедляется ниже требуемой скорости, другой двигатель замедляется, чтобы соответствовать. Синхронизация двигателей — это функция EV3-G, и однажды она может быть доступна в EV3 Python.
Другие примечанияОбратите внимание: если к EV3 подключен только один большой двигатель, вам не нужно указывать, к какому порту двигателя он подключен. То же самое верно для среднего двигателя, а также для каждого типа датчика.

Если у вас есть два двигателя одного типа, подключенные к EV3, и вы запускаете команду для перемещения одного двигателя этого типа без указания буквы порта, то порт, который находится первым в алфавитном порядке, будет тем, который получает команду. Самый первый скрипт на этой странице является примером этого. В этом скрипте нет ничего, что говорило бы о том, какой мотор должен двигаться, поэтому скрипт будет использовать первый большой мотор, который он найдет при сканировании портов мотора в алфавитном порядке. Если у вас есть большие двигатели на портах B и C, двигатель B будет двигаться. Если вы хотите, чтобы двигатель C двигался, вы можете изменить начало скрипта следующим образом:#!/usr/bin/env python3from ev3dev2.motor import LargeMotor, OUTPUT_Cfrom ev3dev2.motor import SpeedDPS, SpeedRPM, SpeedRPS, SpeedDPMfrom time import sleep
lm = LargeMotor(OUTPUT_C)
Кнопки

Buttons

Эта страница посвящена кнопкам на интеллектуальном блоке EV3, а не кнопке сенсорного датчика. Официальная документация находится ЗДЕСЬ . Вот несколько коротких сценариев, демонстрирующих использование класса Button().Подождите, пока ударВ новой библиотеке EV3 Python (v2) есть несколько замечательных новых функций кнопок, таких как wait_for_bump(buttons) . «Удар» — это нажатие и отпускание кнопки. Существуют также функции wait_for_pressed(кнопки) и wait_for_released(кнопки) , которые работают аналогичным образом. Вот сценарий, демонстрирующий использование новых функций. Он ждет, пока не будет нажата левая кнопка, затем издает звуковой сигнал, затем ждет, пока не будет нажата кнопка вверх или вниз, затем издает звуковой сигнал, затем ждет, пока правая кнопка не будет (нажата и) не отпущена, затем издает звуковой сигнал.    
По состоянию на октябрь 2018 года эти функции не работают должным образом — они будут исправлены в следующем выпуске.
#!/usr/bin/env python3
from ev3dev2.button import Button
from ev3dev2.sound import Sound

btn = Button()
sound = Sound()

btn.wait_for_bump(‘слева’)звук.бип()btn.wait_for_pressed([‘вверх’, ‘вниз’])звук.бип()btn.wait_for_released(‘правильно’)звук.бип()
Нажмите любую кнопку, чтобы выйтиЦикл проверяет, нажата ли какая-либо кнопка, и если да, то издает звуковой сигнал и выходит из сценария. Скрипт проверяет состояние кнопки каждые 0,01 секунды.
#!/usr/bin/env python3from ev3dev2.button import Buttonfrom ev3dev2.sound import Soundfrom time import sleep
btn = Button()sound = Sound()
while True:    if btn.any():    # Checks if any button is pressed.        sound.beep()  # Wait for the beep to finish.        exit()  # Stop the program.    else:        sleep(0.01)  # Wait 0.01 second
Вот гораздо более аккуратная версия приведенного выше скрипта:
#!/usr/bin/env python3from ev3dev2.button import Buttonfrom ev3dev2.sound import Soundfrom time import sleep
btn = Button()sound = Sound()
while not btn.any(): # While no (not any) button is pressed.    sleep(0.01)  # Wait 0.01 second
sound.beep()
Вы можете подумать, что это плохие примеры, потому что функцию wait_for_bump() можно было бы использовать для создания более короткого и ясного сценария, но на самом деле второй приведенный выше сценарий — это хороший способ использовать нажатие кнопки для выхода из цикла и, возможно, завершения программы.
Реагировать на нажатия и отпускания кнопокВ цикле этого скрипта выделенная команда btn.process() проверяет любое изменение состояния кнопок. Если он обнаруживает изменение, он запускает соответствующие «события». Например, если он обнаруживает, что левая кнопка только что была нажата, он запускает событие «изменение состояния левой кнопки», называемое on_left, а также событие «изменения кнопки», называемое on_change . Он также присваивает состоянию параметра значение True , если кнопка нажата, и False , если кнопка отпущена. Обработчики событий реагируют на события. Например, если нажата левая кнопка, то событие «изменение состояния левой кнопки» вызовет выделенный элемент on_left.обработчик события, который вызовет выделенную функцию ‘ left ‘ (функция не обязательно должна иметь это имя).
#!/usr/bin/env python3from ev3dev2.button import Buttonfrom time import sleep
btn = Button()
# Do something when state of any button changes:  def left(state):    if state:        print('Left button pressed')    else:        print('Left button released')    def right(state):  # neater use of 'if' follows:    print('Right button pressed' if state else 'Right button released')    def up(state):    print('Up button pressed' if state else 'Up button released')    def down(state):    print('Down button pressed' if state else 'Down button released')    def enter(state):    print('Enter button pressed' if state else 'Enter button released')    btn.on_left = leftbtn.on_right = rightbtn.on_up = upbtn.on_down = downbtn.on_enter = enter
# This loop checks button states continuously (every 0.01s). Если новое состояние отличается от старого, то соответствующее#  Вызываются обработчики событий кнопок.while True:    btn.process()    sleep(0.01)
Если вы запускаете этот скрипт из VS Code, нажмите кнопку остановки, чтобы выйти. если вы работаете из Brickman, нажмите и удерживайте кнопку возврата, чтобы выйти.
Получить список измененных состояний кнопокФункциональность этого скрипта аналогична предыдущему, но он использует обработчик событий on_change(changed_buttons) для получения гораздо более лаконичного сценария. Он не только отображает измененные состояния кнопок, но и реагирует на нажатие определенной кнопки. Нажмите кнопку остановки (VS Code) или нажмите и удерживайте кнопку возврата (Brickman), чтобы завершить сценарий.
#!/usr/bin/env python3from ev3dev2.button import Buttonfrom time import sleep
btn = Button()
def change(changed_buttons):   # changed_buttons is a list of # tuples of changed button names and their states.    print('These buttons changed state: ' + str(changed_buttons))    if ('left', True) in changed_buttons:        print('You pressed the left button')
btn.on_change = change
# This loop checks button states# continuously and calls appropriate event handlerswhile True:    btn.process()    sleep(0.01)
Проверить состояния кнопокВ предыдущем сценарии было показано, как можно использовать process() и соответствующие ему обработчики событий для обнаружения и реагирования на ИЗМЕНЕНИЯ состояния. Существуют также функции ( вниз , влево , ввод и т. д.), которые просто определяют СОСТОЯНИЕ кнопок. Состояние True, если кнопка нажата, и False в противном случае. Сценарий ниже проверяет и отображает состояние левой кнопки раз в секунду. Вы можете завершить сценарий односекундным нажатием на кнопку Backspace.
#!/usr/bin/env python3# prints the state of the left button (True or False) every second# When left button is pressed the string '^[[D' is also printedfrom ev3dev2.button import Buttonfrom time import sleep
btn = Button()
while not btn.backspace:    print(btn.left)    sleep(1)
Другие функции кнопокСледующий скрипт демонстрирует еще две функции: buttons_pressed и check_buttons() . Функция  check_buttons() проверяет, соответствуют ли в данный момент нажатые кнопки заданному списку, а затем возвращает True или False. Каждую секунду печатается список нажатых кнопок, и  вы можете закончить скрипт, нажав ТОЛЬКО левую и правую кнопки одновременно.
#!/usr/bin/env python3# Every second a list of the pressed buttons is printed# and you can end the script by pressing# ONLY the left and right buttons simultaneously.from ev3dev2.button import Buttonfrom time import sleep
btn = Button()
while True:    print(btn.buttons_pressed)    if btn.check_buttons(buttons=['left','right']):        exit()    sleep(1)
ЖК-экран
Смотрите также официальную документацию ЗДЕСЬ .
EV3 оснащен монохромным ЖК-экраном с разрешением 178 x 128 пикселей (оттенки серого). Координаты верхнего левого пикселя — (0, 0), а координаты нижнего правого пикселя — (177, 127).
Отображение текста с помощью функции print()
Функцию print() очень легко использовать, так как она не требует от вас создания объекта Display() и выполнения команды update() для применения ожидающих изменений на экране. Поэтому ее проще использовать, чем функции text_pixels() и text_grid()  , описанные ниже. Когда вы используете функцию print() , текст автоматически обтекает правый край экрана и при необходимости автоматически прокручивается вверх. Вы можете изменить шрифт, как показано в следующем примере. Когда вы устанавливаете шрифт, эта настройка будет запоминаться до тех пор, пока вы не выключите кирпич.
Сценарий ниже показывает, как установить нужный шрифт. Вы можете получить список доступных шрифтов, запустив   ls /usr/share/consolefonts  в терминале SSH. В VS Code вы можете открыть терминал SSH, щелкнув правой кнопкой мыши зеленую точку, указывающую на успешное подключение к EV3, и выбрав «Открыть терминал SSH». Обратите внимание, что шрифты, используемые  функцией print()  , и процедура их указания отличаются от  шрифтов, используемых   функциями text_pixels()  и  text_grid() ,  и процедуры их указания. Сценарий ниже a также показывает, как вы можете запретить функции  print()  начинать новую строку после печати. 
#!/usr/bin/env python3from time import sleepimport osos.system('setfont Lat15-TerminusBold14')# os.system('setfont Lat15-TerminusBold32x16')  # Try this larger font
print('EV3 Python rules!')print()  # print a blank line
print('EV3', 'Python rules!')  # comma means continue on same line
# print() has a parameter 'end' which by# default is the new line character:print('EV3')    # A new line will be started after thisprint('Python rules!')
# Here the 'end' parameterновая строка по умолчанию# character argument is replaced# by an empty string so no new line is begunprint('EV3', end='')print('Python rules!')
# Here the 'end' parameter's default new line# character argument is replaced# by a space character so no new line is begunprint('EV3', end=' ')print('Python rules!')
sleep(15)  # display the text long enough for it to be seen
Вот результат выполнения приведенного выше скрипта (вы можете сделать  снимок экрана, щелкнув правой кнопкой мыши зеленую точку, указывающую на успешное подключение к EV3, а затем выбрав  «Сделать снимок экрана»):

Вот результат выполнения того же скрипта, но с использованием шрифта  Lat15-TerminusBold32x16 (большая часть текста прокручивается за пределы экрана):

Печать в окно вывода VS Code
Скрипт, работающий на EV3, но запущенный из VS Code, может печатать на панели вывода VS Code. Есть много причин, по которым вы можете захотеть печатать на панели «Вывод», а  не на экране EV3 (или вместе с ним): текст на  панели «Вывод» будет легко читаем, тогда как текст на экране EV по умолчанию крошечный и его трудно прочитать на  экране без подсветки.текст на панели вывода можно легко скопировать и вставить при необходимостивы можете получать показания вашего робота в режиме реального времени на своем ПК, даже если робот находится на расстоянии нескольких метров и подключен к ПК по беспроводной связи.нет ограничений на объем текста, который вы можете напечатать на панели «Вывод» (при необходимости вы можете прокручивать вверх), тогда как при печати на экране EV3 текст теряется, как только он прокручивается за пределы экрана.Любой текст, напечатанный на экране EV3, теряется, как только программа завершается, тогда как текст на экране вывода остается.даже при использовании крошечного шрифта по умолчанию текст на экране EV3 будет переноситься после 45 символов, тогда как на панели вывода кода VS текст может быть намного длиннее до переноса.Обратите внимание, что такая печать на панели «Вывод» не имеет аналога для EV3-G, поэтому это пример того, чего можно достичь с помощью EV3 Python, чего нельзя достичь с помощью EV3-G.
В приведенном ниже сценарии показано, как печатать как на ЖК-экране EV3, так и на панели вывода. Он печатает два раза в секунду интенсивность окружающего света, определяемую датчиком цвета. Конечно, вы можете печатать на панели вывода VS Code только в том случае, если вы запускаете скрипт из VS Code — если вы запускаете скрипт из Brickman, то на панель вывода ничего не печатается. На самом деле вывод будет помещен в файл my_program_name.py.err.log в той же папке. 
#!/usr/bin/env python3from ev3dev2.sensor.lego import ColorSensorиз системного импорта stderrfrom time import sleep
cl = ColorSensor()
'''To be able to print to the VS Code Output panel, thisscript must be launched from VS Code, not from Brickman'''while True:    # print to EV3 LCD screen    print(cl.ambient_light_intensity)     # print to VS Code output panel    print(cl.ambient_light_intensity, file=stderr    sleep(0.5)
Приведенный выше скрипт печатает только одно чтение в строке, поэтому распечатка вскоре начнет прокручиваться. Сценарий ниже делает то же самое, что и выше, но печатает 10 показаний в строке. Аргумент ключевого слова ‘ end ‘ объясняется далее на этой странице.

#!/usr/bin/env python3from ev3dev2.sensor.lego import ColorSensorfrom sys import stderrfrom time import sleep
cl = ColorSensor()
while True:    for i in range(10):        # print to EV3 LCD screen        # print a space instead of starting a new line        print(cl.ambient_light_intensity, end=' ')        # print to VS Code output panel        print(cl.ambient_light_intensity, end=' ', file=stderr)        sleep(0.5)    print('') # start new line on EV3 screen    print('', file=stderr) # start new line in VS Code
Отображение текста с помощью  text_pixels() или text_grid()Отображение текста с помощью этих функций  сложнее, чем с помощью  print()  , но дает вам больше контроля, так как вы можете указать, где должен быть размещен текст  . Вы также можете одновременно отображать разные шрифты, чего нельзя сделать с помощью  print() . Текст, отображаемый с помощью  text_pixels() или text_grid() , не будет обтекать правый край экрана и не будет прокручиваться. Кроме того, вам необходимо обновить() экран после использования этих функций, иначе на экране ничего не будет отображаться.
text_pixels (text, clear_screen=True, x=0, y=0, text_color=’black’, font=None)
отображает текст таким образом, что верхний левый угол текста находится в пикселях, заданных x,y. Напомним, что экран EV3 имеет разрешение 178 x 128 пикселей и что верхний левый пиксель имеет координаты (0,0). 
text_grid (text, clear_screen=True, x=0, y=0, text_color=’black’, font=None)
отображает «текст», начиная с сетки (x, y), где сетка состоит из ячеек шириной 8 пикселей и 10 пикселей в высоту, так что дисплей EV3 имеет 22 столбца в ширину и 12 строк в высоту. Размер ячеек сетки не зависит от размера выбранного шрифта. Не существует доступного шрифта с фиксированной шириной, размер которого соответствует размеру ячейки сетки, и поэтому я рекомендую вам избегать использования этой функции и вместо этого использовать text_pixels() . Даже если бы был доступен шрифт, соответствующий размерам ячейки сетки, это был бы очень маленький шрифт (размер 10, что означает высоту 10 пикселей), и его было бы очень трудно читать.
Обе эти функции имеют параметр clear_screen , который по умолчанию имеет значение True, что означает, что если ваш скрипт записывает строку текста, за которой следует вторая строка, то, если вы забудете установить для clear_screen значение False для второй строки, первая строка не будет напечатана.
Вы должны обновить () экран, чтобы ожидающие изменения были записаны на экран. Если вы забудете обновить экран, то вообще ничего не будет печатать!
Есть много шрифтов, доступных для использования с  text_pixels()  и text_grid() , и вы можете найти полный список ЗДЕСЬ  . Все шрифты доступны в следующих размерах (высота в пикселях): 8, 10, 12, 14, 18, 24.
Для максимальной удобочитаемости и привлекательности я рекомендую выбирать шрифт переменной ширины из набора ‘ helvB ‘ (это ‘B’ для ‘жирного’). Шрифты фиксированной ширины менее привлекательны, но с ними легче работать. Для шрифтов фиксированной ширины  я рекомендую ‘ courB ‘ и ‘ lutBS‘. Вы можете увидеть, как выглядят эти шрифты, внизу страницы. Я рекомендую оставлять как минимум один пиксель вертикального пространства между одной строкой текста и следующей. Например, если вы решите использовать шрифт размером 24 (высота 24 пикселя), я рекомендую оставлять 25 пикселей для каждой строки. На самом деле размер текста 24 позволяет аккуратно разместить 5 строк текста на экране EV3, если вы печатаете с такими координатами y: 0, 25, 50, 75, 100.
Шрифты с фиксированной шириной courB24 и lutBS24  имеют ширину символов 15 пикселей и 14 пикселей соответственно, что означает, что 12 символов достаточно хорошо помещаются по горизонтали на экране EV3, как вы можете видеть на снимках экрана ниже.
Обратите внимание, что вы можете включить символ новой строки ‘ \n ‘ в строки, которые вы просите эти функции напечатать, но я не рекомендую этого делать, потому что это дает межстрочный интервал, который я считаю слишком большим.

Вот сценарий, который сначала печатает выбранный набор шрифтов размером 10, 14, 18 и 24, а затем, через 6 секунд, печатает текст на весь экран размером 24. Используйте разные значения для «стиля», чтобы попробовать разные наборы шрифтов. Под скриптом находится результат запуска скрипта со стилем helvB , courB и lutBS соответственно.

#!/usr/bin/env python3from ev3dev2.display import Displayfrom ev3dev2.sound import Soundfrom time import sleep
lcd = Display()sound = Sound()
def show_for(seconds):    ЖК.update()    sound.beep()    sleep(seconds)    ЖК.clear()
# Try each of these different sets:style = 'helvB'#style = 'courB'#style = 'lutBS'
y_value = 0str1 = ' The quick brown fox jumped'str2 = '123456789012345678901234567890'for height in [10, 14, 18, 24]:    text = style+str(height)+str1    lcd.text_pixels(text, False, 0, y_value, font=style+str(height))    y_value += height+1   # short for  y_value = y_value+height+1    lcd.text_pixels(str2, False, 0, y_value, font=style+str(height))    y_value += height+1show_for(6)
strings = [] # create an empty list# Screen width can accommodate 12 fixed# width characters with widths 14 or 15#               123456789012strings.append(style+'24 The')strings.append('quick brown ')strings.append('fox jumps   ')strings.append('over the dog')strings.append('123456789012')
for i in range(len(strings)):    lcd.text_pixels(strings[i], False, 0, 25*i, font=style+'24')show_for(6)

                
                
Примечания к приведенному выше сценарию:
Я обычно включаю имена параметров (ключевые слова), чтобы сделать код более понятным, но в некоторых строках выше я пропустил некоторые имена, потому что в противном случае строки были бы слишком длинными. Например:lcd.text_pixels(text, False, 0, y_value, font=style+str(height))
Аргументы, выделенные жирным шрифтом, являются позиционными аргументами, значение которых известно функции в соответствии с их позициями в списке аргументов, поэтому включение имен параметров необязательно. Однако мне пришлось включить имя «шрифт» — его нельзя было обработать как позиционный аргумент, потому что оно находится «не в том месте». В определении функции мы виделиtext_pixels (текст, clear_screen = True, x = 0, y = 0, text_color = «черный», шрифт = нет)поэтому, чтобы быть действительным в качестве позиционного аргумента, аргумент шрифта должен быть шестым аргументом, но в моем коде это пятый аргумент, поскольку я не указал значение text_color (я счастлив использовать значение по умолчанию, «черный») . Поскольку аргумент не является допустимым позиционным аргументом при размещении на пятом месте, должно быть указано имя, превращающее его в аргумент ключевого слова или «kwarg».
Сценарий демонстрирует один из способов построения списка (называемого «массивом» в EV3-G). 
Отцентрируйте текстГоризонтально центрировать строку текста в шрифте фиксированной ширины довольно просто : для каждого символа в строке вычтите половину ширины символа из 89 (горизонтальная средняя точка экрана EV3). Например, если вы хотите центрировать строку «Hello», написанную шрифтом  lutBS24  , который имеет ширину символа 14, вычтите 5×7 = 35 пикселей из 89, чтобы получить 89-35 = 54, поэтому напечатайте координату x 54.
Чтобы центрировать одну строку текста по вертикали , процедура аналогична:  вычтите половину высоты шрифта из 63 (вертикальная середина экрана EV3). Например, если вы хотите центрировать по вертикали строку «Hello», написанную шрифтом lutBS24 высотой 24 пикселя, вычтите 12 пикселей из 63, чтобы получить 51, поэтому напечатайте координату y 51.
Следующий скрипт способен вычислять координаты y для печати нескольких строк, расположенных одна над другой. Это немного сложнее — я дам вам понять это самостоятельно. Сценарий оставляет одну пустую горизонтальную строку пикселей между каждой строкой текста.
Сценарий использует стандартную функцию Python  wrap(text, width), которая  оборачивает один абзац в текст (строку), поэтому каждая строка имеет длину не более ширины символов. Он возвращает список выходных строк, т.е. список строк. Напримерwrap('The quick brown fox jumps over the lazy dog', width=12)возвращает  [‘Быстрая’, ‘бурая лиса’, ‘перепрыгивает’, ‘ленивая собака’].Чтобы иметь возможность использовать функцию wrap() , вы должны сначала импортировать ее с помощьюиз переноса импорта textwrap
Вот скрипт, который центрирует по горизонтали и вертикали некоторый текст, напечатанный несколькими разными шрифтами фиксированной ширины. Я знаю, что это довольно сложный сценарий, поэтому я не объяснял его подробно — возможно, стоит потратить несколько минут на его изучение. Центрирование текста может быть очень полезным в будущих сценариях, поэтому оно было преобразовано в определяемую пользователем функцию, которую мы можем использовать в других местах. Результат ниже.
#!/usr/bin/env python3из ev3dev2.display импортировать дисплейиз переноса импорта textwrapиз времени импортировать сон
ЖК = Дисплей ()
def show_text (строка, font_name = ‘courB24’, font_width = 15, font_height = 24):    ЖК.очистить()    строки = перенос (строка, ширина = int (180/font_width))    для i в диапазоне (len (строки)):        x_val = 89-font_width/2*len(строки[i])        y_val = 63-(font_height+1)*(len(strings)/2-i)        lcd.text_pixels(strings[i], False, x_val, y_val, font=font_name)    lcd.update()
my_text = ‘Быстрая коричневая лиса перепрыгивает через ленивую собаку’
show_text(мой_текст, ‘courB14’, 9, 14)спать(5)
show_text(мой_текст, ‘lutBS14’, 9, 14)спать(5)
show_text(my_text, ‘courB18’, 11, 18)спать(5)
show_text(мой_текст, ‘lutBS18’, 11, 18)спать(5)
show_text(мой_текст, ‘courB24’, 15, 24)# или просто show_text(my_text), так как значения по умолчанию# были установлены для courB24спать(5)
show_text(мой_текст, ‘lutBS24’, 14, 24)спать(5)
Значения по умолчанию были включены в определение функции, поэтому, если вы хотите использовать шрифт courB24, все, что вам нужно сделать, это:show_text(‘Это мой текст’)
        
        
ГрафикаВ EV3 Python есть несколько простых в использовании команд для рисования простых фигур:

line(clear_screen=True, x1=10, y1=10, x2=50, y2=50, line_color='black', width=1)Проведите линию от (x1, y1) до (x2, y2)
circle(clear_screen=True, x=50, y=50, radius=40, fill_color='black', outline_color='black')Нарисуйте круг «радиуса» с центром в (x, y)
rectangle(clear_screen=True, x1=10, y1=10, x2=80, y2=40, fill_color='black', outline_color='black')Нарисуйте прямоугольник, левый верхний угол которого находится в точке (x1, y1), а правый нижний угол — в точке (x2, y2). 
point(clear_screen=True, x=10, y=10, point_color='black')Нарисуйте один пиксель в (x, y)
Следующий сценарий должен быть простым для понимания. Результат ниже. Что касается цветов, имейте в виду, что ЖК-экран EV3 может отображать только четыре оттенка серого , которые соответствуют этим названиям цветов: черный, серый, светло-серый, белый . Придерживайтесь этих названий цветов, потому что в противном случае у вас будет несоответствие между ЖК-дисплеем (4 оттенка серого) и снимками экрана (намного больше оттенков серого).
#!/usr/bin/env python3из ev3dev2.display импортировать дисплейиз времени импортировать сон
ЖК = Дисплей ()
# Нарисуйте круг радиуса с центром в (x, y)lcd.circle (clear_screen=False, x=89, y=64, radius=61, fill_color=’светло-серый’)lcd.circle(False, x=65, y=45, radius=10, fill_color=’черный’)lcd.circle(False, x=113, y=45, radius=10, fill_color=’черный’)
# Нарисуйте линию от (x1, y1) до (x2, y2)lcd.line (ложь, x1=89, y1=50, x2=89, y2=80, line_color=’серый’, ширина=4)
# Нарисуйте прямоугольник, где верхний левый угол находится в точке (x1, y1)# и нижний правый угол находится в (x2, y2). lcd.rectangle (False, x1=69, y1=90, x2=109, y2=105, fill_color=’grey’)
# Рисуем один пиксель в точке (x, y)lcd.point (ложь, x=65, y=45, point_color=’white’)lcd.point(False, x=113, y=45, point_color=’white’)
lcd.update()спать(10)
P IL (НИЗКИЙ) функцииДругие фигуры можно рисовать, используя  мощную графическую библиотеку  Pillow  , которая является  частью стандартного Python, а не чем-то уникальным для EV3 Python. Обратите внимание, что  Pillow возникла из  библиотеки изображений Python  ( PIL ). Вы можете найти подробную документацию в официальной документации Pillow  ЗДЕСЬ  особенно  документацию по модулю ImageDraw . Модуль ImageDraw автоматически импортируется при импорте класса Display, поэтому вам не нужно его явно импортировать . Однако, когда вы хотите отобразить файл изображения, вы  делаете необходимо импортировать класс  Image , как будет объяснено позже. Модуль ImageDraw предоставляет следующие методы:дуга (xy, начало, конец, заполнение = нет)растровое изображение (xy, растровое изображение, заполнение = нет)аккорд (ху, начало, конец, заполнение = нет, контур = нет)эллипс (xy, заливка = нет, контур = нет)линия (ху, заливка = нет, ширина = 0)pieslice (xy, начало, конец, заполнение = нет, контур = нет)точка (ху, заполнение = нет)многоугольник (xy, заливка = нет, контур = нет)прямоугольник (ху, заливка = нет, контур = нет)текст (xy, текст, заливка = нет, шрифт = нет, якорь = нет, интервал = 0, выравнивание = «слева»)multiline_text(xy, text, fill=None, font=None, anchor=None, spacing=0, align=»left»)размер текста (текст, шрифт = нет, интервал = 0)multiline_textsize (текст, шрифт = нет, интервал = 0)Вы можете найти  это руководство  хорошим отправным пунктом. 
Я вычеркнул последние четыре строки, потому что рекомендую вам использовать функции EV3 Python text_pixels() и text_grid() для вывода текста на экран, а не более сложные (но немного более мощные) текстовые функции PIL. Функция  draw.text() очень похожа на  text_pixels()  , за исключением того, что она добавляет возможность установки цвета заливки (фона) для текста. Если вы абсолютно хотите узнать о текстовых функциях PIL, см. ЭТУ СТРАНИЦУ  и официальную документацию . 
Смайлик / сварливыйЭтот скрипт использует функцию draw.ellipse() для рисования двух кругов (круг на самом деле является разновидностью эллипса) для глаз, а затем метод draw.arc() для рисования дуги (в данном случае половина эллипса), которая то открывается вверх (улыбка ) и открывающийся вниз (ворчливый). Остановите скрипт долгим нажатием на любую кнопку или кнопкой «Стоп», если вы запускали его из VS Code.
#!/usr/bin/env python3из ev3dev2.display импортировать дисплейиз ev3dev2.button Кнопка импортаиз времени импортировать сон
ЖК = Дисплей ()кнопка = кнопка ()
улыбка = правда
while not btn.any(): # выйти из цикла долгим нажатием на любую кнопку    lcd.clear()
    lcd.draw.ellipse(( 20, 20,  60, 60))    lcd.draw.ellipse((118, 20, 158, 60))
    if smile:        lcd.draw.arc((20, 80, 158, 100), 0, 180)    else:        lcd.draw.arc((20, 80, 158, 100), 180, 360)
    smile = not smile  # toggle between True and False
    # Update lcd display    lcd.update() # Applies pending changes to the screen.    # Nothing will be drawn on the lcd screen    # until this function is called.
    sleep(1)
Запуск сценария заставляет экран чередоваться один раз в секунду между двумя изображениями ниже:
              
Обратите внимание, что команда  draw.ellipse()  имеет параметры, которые представляют собой верхний левый угол и нижний правый угол ограничительной рамки (воображаемой рамки, которая будет содержать эллипс). Команде draw.arc  ()  нужна та же пара координат, а также начальный и конечный углы, оба в градусах. Углы измеряются от 3 часов, увеличиваясь по часовой стрелке.
Показать файл изображенияПрежде чем вы сможете отобразить файл изображения, вы должны иметь файл изображения для отображения! Большинство популярных форматов изображений должны работать (jpg, bmp, gif, png и т. д.), но они будут отображаться только в четырех оттенках серого (черный, светло-серый, темно-серый, черный). Анимированные файлы gif не будут «воспроизводиться». Я предлагаю вам начать с того, что сделал я: скопировать все стандартные файлы изображений Lego EV3 BMP, которые включены в бесплатное программное обеспечение Lego EV3, в каталог с именем «pics» в вашем каталоге «robot». Вы можете увидеть файлы BMP, перечисленные на этой странице, а внизу этой страницы есть ссылка на zip-файл ( 328 КБ)  , содержащий 107 монохромных файлов BMP, каждый из которых идеально подходит для экрана EV3 (178 * 128 пикселей). Распакуйте zip-файл в папку на вашем ПК.
При желании вы можете найти файлы на ПК с Windows в следующем расположении:  C:\Program Files (x86)\LEGO Software\LEGO MINDSTORMS EV3 Home Edition\Resources\BrickResources\Retail\Images\files . Папка «Program Files (x86)» также может называться просто « Program Files». Если вы получаете файлы со своего ПК, я предлагаю вам скопировать все файлы BMP (не файлы RGF) в одну папку.
Когда у вас есть все файлы изображений в папке «pics» на вашем ПК, вы захотите загрузить копию этой папки в папку «robot» на EV3. Если вы используете VS Code с расширением EV3, как я рекомендую  , лучше всего открыть папку «pics» в VS Code и щелкнуть значок «Отправить проект на устройство» в заголовке браузера устройств EV3 в левом нижнем углу. окна VS Code. Это загрузит папку и ее содержимое в папку «робот» на EV3 . После того, как вы все это сделали, вы должны быть готовы запустить следующий сценарий, заменив «Bomb.bmp» именем файла изображения по вашему выбору. Если вы прошьете новый образ Stretch на свою SD-карту, папки «pics» и «sounds» (и все ваши сценарии) будут удалены, поэтому вам нужно будет снова загрузить их на EV3.
#!/usr/bin/env python3from ev3dev2.display import Displayfrom time import sleepfrom PIL import Image
lcd = Display()
logo = Image.open('/home/robot/pics/Bomb.bmp')lcd.image.paste(logo, (0,0))lcd.update()sleep(5)
Вот результат:
Как сделать скриншот экрана EV3Если вы используете VS Code с расширением EV3, сделать снимок экрана так же просто, как щелкнуть правой кнопкой мыши зеленую точку «подключено» в браузере устройств EV3 и выбрать «Сделать снимок экрана». Сохраните изображение с помощью «Сохранить как», чтобы вы могли выбрать удобное место для этого изображения, поскольку расположение по умолчанию неудобно. Обязательно сохраните файл изображения с расширением .png.

Скриншотам намеренно придан желтый оттенок, поэтому, если вы просматриваете их на белом фоне, таком как эта страница, вы все равно можете видеть, где находятся края изображения.
Что касается цветов, имейте в виду, что  ЖК-экран EV3 может отображать только четыре оттенка серого  , которые соответствуют этим названиям цветов:  черный, серый, светло-серый, белый . Придерживайтесь этих названий цветов, потому что в противном случае у вас будет несоответствие между ЖК-дисплеем (4 оттенка серого) и снимками экрана (намного больше оттенков серого).
Как  запустить из терминала скрипт, который пишет на ЖК-дисплей EV3Это для тех, кто не использует VS Code с расширением EV3 . Если вы запускаете код, который обращается к экрану из сеанса SSH, не следуя этим инструкциям, вы можете столкнуться с двумя проблемами:дисплей Брикмана может снова появиться до того, как ваш скрипт перестанет работать, даже через секунду или меньшеили у вас может быть противоположная проблема: когда скрипт останавливается, может пройти минута или две, прежде чем экран вернется к интерфейсу Брикмана.Дэвид Л., главный участник проекта ev3dev, дал мне следующий совет:
Простой способ , рекомендуется, если вы не перфекционист. Недостаток:  затем вы  увидите  небольшой мигающий курсор в нижней части небольшого «мертвого квадрата» где-то на экране (вы можете видеть курсор на изображении «Hello World» выше на этой странице). :Запустите sudochvt 6 . Это просто переключает дисплей, чтобы показать вам пустой терминал вместо Брикмана, чтобы Брикман не связывался с вами. Вам нужно будет ввести пароль для робота, который является «производителем».Запустите вашу программу. Вы должны увидеть его на дисплее EV3, как и ожидали. При необходимости вы можете остановить выполнение скрипта с помощью Ctrl+C. Вы можете работать с этого терминала, как обычно, запускать свою программу несколько раз и т. д.Запустите sudo chvt 1 , чтобы вернуть Брикмана .Путь перфекциониста . Недостаток: еще несколько шагов, и вы будете использовать копию крошечного дисплея EV3 .Запустите  sudochvt 6 . Это просто переключает дисплей, чтобы показать вам пустой терминал вместо Брикмана, чтобы Брикман не связывался с вами. Вам нужно будет ввести пароль для робота, который является «производителем».Запустите  sudoconspy . Это заставит ваш сеанс SSH отображать тот же терминал, что и на дисплее EV3. Войдите в подсказку, которую он показывает вам, с логином = robot и паролем = maker.Запустите вашу программу. Вы должны увидеть его на дисплее EV3, как и ожидали. При необходимости вы можете остановить выполнение скрипта с помощью Ctrl+C. Вы можете работать с этого терминала, как обычно, запускать свою программу несколько раз и т. д.Нажмите клавишу ESC на ПК 3 раза, чтобы выйти из терминала дисплея.Запустите  sudo chvt 1  , чтобы вернуть Брикмана .
Основы

Основы
Этот сайт создан для того, чтобы помочь людям, которые уже имеют базовые знания стандартного Python, сделать дополнительный шаг и научиться использовать роботизированные функции, доступные в EV3 Python.

Кроме того, этот сайт написан только для того, чтобы помочь людям, использующим VS Code с расширением EV3 и использующим новую (версия 2, выпущенная летом 2018 г.) библиотеку EV3 Python. Если вы используете VS Code с расширением EV3.

#!/usr/bin/env python3

Включен Shebang в первую строку каждой программы на этом сайте. Поскольку строка начинается с символа решетки, можно предположить, что это просто комментарий, который будет проигнорирован компилятором при запуске программы. Это было бы ложным предположением, потому что на самом деле строки, начинающиеся с #! на самом деле это специальные инструкции, называемые «Shebang», которые ДЕЙСТВИТЕЛЬНО влияют на работу программы, поскольку они сообщают компилятору, какую программу использовать для открытия файла и где найти эту программу. Вы также можете встретить программы, начинающиеся с #!/usr/bin/python, что является инструкцией по использованию Python 2 для открытия программы, но вам следует отдать предпочтение Python 3, поскольку Python 2 уже устарел. Все программы Python на этом сайте написаны на Python 3 и используют Shebang Python 3.

Shebang можно сравнить с ассоциацией файлов в Windows. В Windows вы можете использовать «Открыть с помощью…», чтобы указать, что все файлы с определенным расширением должны открываться в определенной программе. Например, вы можете указать, что программы с расширением .txt должны открываться в MS Word. Shebangs имеет тот же эффект, что и ассоциация файлов, но shebang должен быть включен в каждый файл, который должен быть открыт определенной программой.

Запуск программ Python из VS Code
Чтобы узнать, как писать и запускать скрипты Python в VS Code, посетите страницу «Рабочий процесс VS Code».

Запуск программ Python из меню Brickman EV3.
Чтобы запустить программу из Brickman, просто откройте файловый браузер, используйте стрелки вверх и вниз для перехода к нужному сценарию, а затем нажмите кнопку Enter. Имейте в виду, что этот процесс, конечно же, не приведет к загрузке последней версии скрипта в EV3, поэтому, если вы изменили скрипт и хотите запустить модифицированный скрипт из Brickman, а не из VS Code, вам следует сначала нажать кнопку « Значок «Отправить проект на устройство» в заголовке браузера устройств EV3, а затем запустите скрипт из Brickman.

Остановка программы, запущенной из VS Code
Большинство программ, конечно, останавливаются сами по себе. Если вы запустили программу, которая не останавливается сама по себе, возможно, потому, что вы намеренно включили бесконечный цикл, например, или из-за того, что что-то пошло не так, принудительно остановите программу, нажав кнопку остановки (красный квадрат), которая появляется в VS Code. когда вы запускаете программу на EV3, используя расширение EV3.

Остановка программы, запущенной из Brickman
Большинство программ, конечно, останавливаются сами по себе. Если вы запустили программу, которая не останавливается сама по себе, возможно, потому, что вы намеренно включили бесконечный цикл, например, или из-за того, что что-то пошло не так, принудительно остановите программу, нажав и удерживая кнопку «Назад».

Запустите интерпретатор Python 3 из командной строки.
Поскольку вы используете VS Code с расширением EV3, вы можете легко запустить интерпретатор Python, после чего вы сможете выполнять команды Python одну за другой без необходимости создавать и сохранять скрипт Python. Вы можете либо запустить интерпретатор Python на ПК, и в этом случае вы не будете использовать Python EV3 на EV3, поэтому функции, специфичные для робота, будут недоступны, либо вы можете запустить интерпретатор Python на самом EV3, и в этом случае вы может использовать специальные функции робота.

Чтобы запустить интерпретатор Python на EV3 из VS Code
Щелкните правой кнопкой мыши зеленую точку, которая показывает, что EV3 подключен к вашему ПК, и выберите «Открыть SSH-терминал». Когда терминал откроется, введите Python3 (не Python) в приглашении. Затем вы должны увидеть это приглашение: >>> что означает, что вы можете начать вводить команды Python, которые будут выполняться, как только вы нажмете клавишу Enter. Например, вы можете ввести эти три строки, чтобы левая пара светодиодов EV3 светилась желтым цветом:

from ev3dev2.led import Leds
leds = Leds()
leds.set_color(‘LEFT’, ‘AMBER’)


Чтобы закрыть интерпретатор Python, введите exit() и нажмите клавишу Enter.

Если при использовании SSH-терминала вас когда-либо попросят ввести пароль для пользователя с именем «робот» (вы), это «производитель» (без кавычек).