Добавил:
МТУСИ Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Практическая работа - индивидуальное задание / ПР_Индивидуальное_задание_Мягков_БАП2201

.pdf
Скачиваний:
0
Добавлен:
21.04.2026
Размер:
2.33 Mб
Скачать

МИНИСТЕРСТВО ЦИФРОВОГО РАЗВИТИЯ, СВЯЗИ И МАССОВЫХ КОММУНИКАЦИЙ РОССИЙСКОЙ ФЕДЕРАЦИИ

Ордена Трудового Красного Знамени федеральное государственное бюджетное образовательное учреждение высшего образования

«Московский технический университет связи и информатики» (МТУСИ)

Кафедра «Интеллектуальные системы в управлении и автоматизации» (ИСУиА)

ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ

По дисциплине

Технологии промышленного интернета вещей

Выполнили: Студенты 4-го курса Группы БАП2201 Ли Самен Мягков А.К.

Проверил: к.т.н., доцент Воронов В.И.

Москва 2026

СОДЕРЖАНИЕ

 

КРАТКИЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ........................................................

3

ВЫПОЛНЕНИЕ......................................................................................................

4

ВЫВОДЫ ..............................................................................................................

10

2

КРАТКИЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

Модуль 2-х осевого джойстика KY-023 представлен на рисунке 1. Характеристики:

Рабочее напряжение: 3,3 – 5 В;

Потребляемый ток: до 0,25 мА;

Размер: 34х26х32 мм;

Вес: 11 гр.

Рисунок 1 – Внешний вид и габаритные размеры модуля аналогового двухосевого джойстика с пятью контактами для подключения

Модуль KY-023 состоит из двух потенциометров на 10 кОм (расположенных перпендикулярно), для определения осей X и Y (рисунок 2) необходимо изменить положение джойстика. Средняя нога каждого потенциометра выведена на разъем J1 (контакты VRX и VRY), а вторая и третья нога подключена к питанию и массе. Дополнительно установлена тактовая кнопка, показания снимаются с разъема J1 (контакт SW), так-же предусмотрено посадочное место для подтягивающего резистора (R1).

Рисунок 2 – Устройство модуля двухосевого джойстика с тактовой кнопкой для нажатия и двумя потенциометрами для отслеживания осей X и Y

3

Для считывания данных с выводов VRX (ось X) и VRY (ось Y) необходимо использовать аналоговые порт ESP32. (значение от 0 до 5В или от 0 до 1023, как на рисунке 3), а для считывания данных с вывода RW используем цифровой порт (значение 0 В и 5 В или 0 и 1). Так-как один вывод тактовой кнопки подключен к земле и при нажатии на джойстик вниз, происходит замыкание цепи, но возможно ложные срабатывания (наводки). Для получения стабильных показаний, вывод RW необходимо подтянуть к питанию +5В, через подтягивающий резистор R1 или использовать встроенный подтягивающий резистор.

Рисунок 3 – Cхема распределения значений координат X и Y (от 0 до 1023) при перемещении рычага джойстика в крайние положения

ВЫПОЛНЕНИЕ

В отличие от теоретического 10-битного АЦП (0–1023), плата ESP32 обладает 12-битным аналогово-цифровым преобразователем, что расширяет диапазон считываемых значений до 0 – 4095. Логика работы программы (Листинг 1) включает следующие этапы:

1)Непрерывное чтение для сбора данных последовательного порта (COM7, 115200 бод) и парсинг строки, содержащей шесть значений: координаты X, Y и состояние кнопки для каждого из двух модулей KY-023;

2)При запуске программы автоматически вычисляется положение цент-

4

ра стиков путём усреднения выборки показаний за 2 секунды, что компенсирует механическое смещение потенциометров;

3)Нелинейная нормализация – применение мертвой зоны (DEADZONE

=300) для фильтрации шумов и люфта в центральном положении. Значения за пределами мертвой зоны нормализуются в диапазон от -1,0 до 1,0;

4)Использовали экспоненциальное сглаживание как фильтр (коэффициент α = 0,35) для исключения дребезга показаний и обеспечения плавности движения курсора;

5)Преобразование нормализованных значений в 16-битный формат осей Xbox-контроллера (от -32767 до 32767) с последующей инверсией оси Y. Состояния тактовых кнопок (SW) маппируются на виртуальные кнопки «A»

и «B».

Листинг 1 – Программа управления двумя стиками с помощью ESP32 на языке python

import sys import time import serial

import vgamepad as vg

PORT = "COM7"

# Наш рабочий порт

BAUDRATE = 115200

 

# Последние считанные значения

last_values = [2048, 2048, 1, 2048, 2048, 1]

#Центры стиков, будут откалиброваны при запуске center1_x = 2048

center1_y = 2048 center2_x = 2048 center2_y = 2048

#Настройки

DEADZONE = 300

SMOOTHING = 0.35 # 0..1, чем больше, тем резче реакция

PRINT_DEBUG = True

def clamp(value, low, high):

return max(low, min(high, value))

5

def read_serial_line(ser): global last_values

try:

line = ser.readline().decode("utf-8", errors="ignore").strip()

if not line:

return last_values

parts = line.split(",") if len(parts) != 6:

return last_values

values = [int(p) for p in parts] last_values = values

return values except Exception:

return last_values

def calibrate_center(ser, seconds=2.0): print("Калибровка центра. Не трогай джойстики...") samples = []

start = time.time()

while time.time() - start < seconds: vals = read_serial_line(ser) samples.append(vals) time.sleep(0.01)

if not samples:

return 2048, 2048, 2048, 2048

avg_x1 = sum(v[0] for v in samples) // len(samples) avg_y1 = sum(v[1] for v in samples) // len(samples) avg_x2 = sum(v[3] for v in samples) // len(samples) avg_y2 = sum(v[4] for v in samples) // len(samples)

print(f"Центр 1: X={avg_x1}, Y={avg_y1}") print(f"Центр 2: X={avg_x2}, Y={avg_y2}")

return avg_x1, avg_y1, avg_x2, avg_y2

def normalize_axis(raw, center, deadzone): delta = raw - center

if abs(delta) <= deadzone: return 0.0

if delta > 0:

denom = 4095 - center - deadzone

6

if denom <= 0: return 0.0

value = (delta - deadzone) / denom return min(value, 1.0)

else:

denom = center - deadzone if denom <= 0:

return 0.0

value = (delta + deadzone) / denom return max(value, -1.0)

def to_xbox_axis(norm_value):

return int(clamp(norm_value, -1.0, 1.0) * 32767)

def smooth(prev_value, new_value, alpha):

return prev_value * (1.0 - alpha) + new_value * alpha

def main():

global center1_x, center1_y, center2_x, center2_y

try:

ser = serial.Serial(PORT, BAUDRATE, timeout=0.05) except Exception as e:

print(f"Не удалось открыть порт {PORT}: {e}") sys.exit(1)

gamepad = vg.VX360Gamepad()

time.sleep(2.0) # дать порту стабилизироваться

center1_x, center1_y, center2_x, center2_y = calibrate_center(ser, seconds=2.0)

print("Геймпад запущен.") print("SW первого джойстика -> A") print("SW второго джойстика -> B") print("Ctrl+C для выхода")

filtered_lx = 0.0 filtered_ly = 0.0 filtered_rx = 0.0 filtered_ry = 0.0

last_debug_time = 0

try:

while True:

x1, y1, s1, x2, y2, s2 = read_serial_line(ser)

raw_lx = normalize_axis(x1, center1_x, DEADZONE) raw_ly = normalize_axis(y1, center1_y, DEADZONE)

7

raw_rx = normalize_axis(x2, center2_x, DEADZONE) raw_ry = normalize_axis(y2, center2_y, DEADZONE)

# Сглаживание

filtered_lx = smooth(filtered_lx, raw_lx, SMOOTHING) filtered_ly = smooth(filtered_ly, raw_ly, SMOOTHING) filtered_rx = smooth(filtered_rx, raw_rx, SMOOTHING) filtered_ry = smooth(filtered_ry, raw_ry, SMOOTHING)

# Отправка в виртуальный Xbox-геймпад gamepad.left_joystick(

x_value=to_xbox_axis(filtered_lx), y_value=to_xbox_axis(-filtered_ly) # инверсия

Y

)

gamepad.right_joystick( x_value=to_xbox_axis(filtered_rx), y_value=to_xbox_axis(-filtered_ry) # инверсия

Y

)

# Кнопки

if s1 == 0: gamepad.press_button(button=vg.XUSB_BUT-

TON.XUSB_GAMEPAD_A) else:

gamepad.release_button(button=vg.XUSB_BUTTON.XUSB_GAMEPAD_A)

if s2 == 0: gamepad.press_button(button=vg.XUSB_BUT-

TON.XUSB_GAMEPAD_B) else:

gamepad.release_button(button=vg.XUSB_BUT-

TON.XUSB_GAMEPAD_B)

gamepad.update()

# Отладка раз в 0.2 сек now = time.time()

if PRINT_DEBUG and (now - last_debug_time > 0.2): last_debug_time = now

print(

f"J1 raw=({x1:4d},{y1:4d}) norm=({filtered_lx:+.2f},{filtered_ly:+.2f}) | "

f"J2 raw=({x2:4d},{y2:4d}) norm=({filtered_rx:+.2f},{filtered_ry:+.2f})"

)

time.sleep(0.01)

except KeyboardInterrupt: print("Остановлено.")

8

finally:

ser.close()

if __name__ == "__main__": main()

На рисунке 4 представлено присоединение двух стиков к плате ESP32.

Рисунок 4 – Присоединение триггеров к ESP32

Для верификации работоспособности системы была проведена проверка с использованием веб-сервиса mitinogame.ru/gamepad-tester. В ходе тестирования инициилизируется виртуальное устройство (xbox 360) в операционной системе. Отклонение модулей KY-023 отображалось перемещением соответствующих осей на экране, а нажатие на стики вызывало фиксацию кнопок

«A» и «B».

Рисунок 5 – Фиксация отклонения осей и нажатия виртуальных кнопок эмулируемого геймпада на веб-сервисе онлайн-тестирования

9

ВЫВОДЫ

В ходе выполнения работы была разработана программа на языке Python, преобразующая аналоговые сигналы двух модулей KY-023 в данные виртуального Xbox-геймпада. Для обеспечения стабильного управления в коде реализованы процедуры автоматической калибровки центра, программной фильтрации дребезга и настройки мертвой зоны осей. Функциональность созданного устройства успешно подтверждена путем тестирования на специализированном веб-сервисе с фиксацией отклонения стиков и нажатия кнопок.

10