Skip to content

Commit 7abe9cc

Browse files
committed
добавлен скетч stm32 hid и скрипт на питоне
1 parent 5faf8e1 commit 7abe9cc

File tree

2 files changed

+359
-0
lines changed

2 files changed

+359
-0
lines changed

addons/AS5600-Sensor-HID/SensorHID.py

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
'''
2+
SensorHID.py
3+
4+
Скрипт визуализации принятых данных через USB HID
5+
от датчика AS5600 или AS5600L. Этот скрипт часть
6+
библиотеки AMS-AS5600-Arduino-Library.
7+
Скетч Arduino STM32/SensorUSBHID_STM32.ino
8+
9+
Требуется pywinusb -> pip install pywinusb
10+
Проверялся на Python 3.10.8
11+
12+
Документация к датчику https://ams.com/documents/20143/36005/AS5600_DS000365_5-00.pdf
13+
14+
Контакты
15+
GitHub: https://github.com/S-LABc
16+
Gmail: romansklyar15@gmail.com
17+
18+
Copyright (C) 2022. v1.0 / Скляр Роман S-LAB
19+
'''
20+
21+
from pywinusb import hid # модуль для работы с USB HID под Windows
22+
from time import sleep # модуль для паузы
23+
import math # модуль для константы pi
24+
25+
TX_SIZE = 2 # количество передаваемых байт из скрипта через USB по протоколу HID, передается всегда + 1 байт - Report ID
26+
27+
DEV_VID = 0x1EAF # Vendor ID устройства (связан со скетчем Ардуино)
28+
DEV_PID = 0x0024 # Product ID устройства (связан со скетчем Ардуино)
29+
30+
REPORT_ID = 0x00 # Report ID со значением 0, так требует библиотека USBComposite_stm32f1 https://github.com/arpruss/USBComposite_stm32f1
31+
UNIQ_KEY = 0x15 # уникальный ключ для проверки пакета (связан со скетчем Ардуино)
32+
33+
PAUSE_TIME = 1 # время паузы отправления запросов на получение данных в секундах
34+
35+
send_buffer = [i for i in range(TX_SIZE)] # создаем массив для отправки данных, 0 байт нужен как ключ, 1 байт нужен как Report ID
36+
send_buffer[0] = REPORT_ID # устанавливаем 0 элемент массива равный REPORT_ID
37+
send_buffer[1] = UNIQ_KEY # устанавливаем 1 элемент массива равный UNIQ_KEY
38+
39+
# метод обработки и вывода принятых по USB HID данных в терминал
40+
def receive_handler(data):
41+
print("================================")
42+
print("Состояние датчика: ", end = '')
43+
if data[1] == 0:
44+
print("НЕ ОБНАРУЖЕН!")
45+
if data[1] == 1:
46+
print("ОБНАРУЖЕН!")
47+
else:
48+
print("ОШИБКА")
49+
50+
start_pos = data[2] << 8 | data[3]
51+
print("Начальное положение: ", start_pos)
52+
53+
end_pos = data[4] << 8 | data[5]
54+
print("Конечное положение: ", end_pos)
55+
56+
max_ang = data[6] << 8 | data[7]
57+
print("Максимальный угол: ", max_ang)
58+
59+
print("Режим питания: ", end = '')
60+
if data[8] == 0:
61+
print("Нормальный")
62+
elif data[8] == 1:
63+
print("Энергосбережение 1")
64+
elif data[8] == 2:
65+
print("Энергосбережение 2")
66+
elif data[8] == 3:
67+
print("Энергосбережение 3")
68+
else:
69+
print("ОШИБКА")
70+
71+
print("Гистерезис: ", end = '')
72+
if data[9] == 0:
73+
print("Выключен")
74+
elif data[9] == 1:
75+
print("1 LSB")
76+
elif data[9] == 2:
77+
print("2 LSB")
78+
elif data[9] == 3:
79+
print("3 LSB")
80+
else:
81+
print("ОШИБКА")
82+
83+
print("Режим контакта OUT: ", end = '')
84+
if data[10] == 0:
85+
print("Аналоговый (0 - 100%)")
86+
elif data[10] == 1:
87+
print("Аналоговый (10 - 90%)")
88+
elif data[10] == 2:
89+
print("Цифровой ШИМ")
90+
else:
91+
print("ОШИБКА")
92+
93+
print("Несущая частота ШИМ: ", end = '')
94+
if data[11] == 0:
95+
print("115 Гц")
96+
elif data[11] == 1:
97+
print("230 Гц")
98+
elif data[11] == 2:
99+
print("460 Гц")
100+
elif data[11] == 3:
101+
print("920 Гц")
102+
else:
103+
print("ОШИБКА")
104+
105+
print("Коэф. медленной фильтрации: ", end = '')
106+
if data[12] == 0:
107+
print("16х")
108+
elif data[12] == 1:
109+
print("8х")
110+
elif data[12] == 2:
111+
print("4х")
112+
elif data[12] == 3:
113+
print("2х")
114+
else:
115+
print("ОШИБКА")
116+
117+
print("Порог быстрой фильтрации: ", end = '')
118+
if data[13] == 0:
119+
print("Включена медленная фильтрация")
120+
elif data[13] == 1:
121+
print("6 LSB")
122+
elif data[13] == 2:
123+
print("7 LSB")
124+
elif data[13] == 3:
125+
print("9 LSB")
126+
elif data[13] == 4:
127+
print("18 LSB")
128+
elif data[13] == 5:
129+
print("21 LSB")
130+
elif data[13] == 6:
131+
print("24 LSB")
132+
elif data[13] == 7:
133+
print("10 LSB")
134+
else:
135+
print("ОШИБКА")
136+
137+
print("Сторожевой таймер: ", end = '')
138+
if data[14] == 0:
139+
print("Выключен")
140+
elif data[14] == 1:
141+
print("Включен")
142+
else:
143+
print("ОШИБКА")
144+
145+
raw_ang = data[15] << 8 | data[16]
146+
print("Угол в сыром виде: ", raw_ang)
147+
148+
deg_ang = raw_ang * 360 / 4096
149+
print("Угол в градусах: ", deg_ang)
150+
151+
rad_ang = deg_ang * math.pi / 180
152+
print("Угол в радианах: ", rad_ang)
153+
154+
scl_ang = data[17] << 8 | data[18]
155+
print("Масштабированный угол: ", scl_ang)
156+
157+
print("Состояние магнита: ", end = '')
158+
if data[19] == 0:
159+
print("Не обнаружен")
160+
elif data[19] == 2:
161+
print("Не обнаружен и слишком слабый")
162+
elif data[19] == 4:
163+
print("Обнаружен и нормальный")
164+
elif data[19] == 5:
165+
print("Обнаружен и слишком сильный")
166+
elif data[19] == 6:
167+
print("Обнаружен и слишком слабый")
168+
else:
169+
print("ОШИБКА")
170+
171+
print("Автоусиление: ", data[20])
172+
173+
mag = data[21] << 8 | data[22]
174+
print("Магнитуда: ", mag)
175+
176+
print("Счетчик ZMCO: ", data[23])
177+
178+
print("================================")
179+
print()
180+
181+
return None
182+
183+
hid_list = hid.HidDeviceFilter(vendor_id = DEV_VID, product_id = DEV_PID) # создаем фильтр устройств HID в ОС
184+
devices_list = hid_list.get_devices() # получаем устройства с нужными VID и PID
185+
device = devices_list[0] # выбираем самое первое из доступных
186+
device.set_raw_data_handler(receive_handler) # устанавливаем обработчик на прием данных (что выполнять когда пришли данные от устройства по USB HID)
187+
device.open() # открываем канал связи по USB HID с устройством
188+
189+
while True:
190+
for out_report in device.find_output_reports():
191+
out_report.set_raw_data(send_buffer) # указываем массив с данными для отправки в устройство
192+
out_report.send() # отправляем данные в устройство
193+
sleep(PAUSE_TIME) # пауза для удобства чтения данных в терминале
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*
2+
* SensorUSBHID_STM32
3+
*
4+
* Демонстрация вывода данных от датчика AS5600 на компьютер
5+
* для отображения в скрипте Python "SensorHID.py"
6+
*
7+
* Подключение:
8+
* AS5600 Board
9+
* VCC -> +3V3
10+
* GND -> GND
11+
* DIR -> GND
12+
* SDA -> SDA
13+
* SCL -> SCL
14+
*
15+
* Примечения:
16+
* 1. Если используется плата с логическими уровнями 5В, то
17+
* необходимо удалить резистор R1 (0 Ом) с платы датчика,
18+
* а вывод VCC подкючить к 5В питанию!
19+
* 2. Скетч использует ядро Arduino_STM32 и библиотеку USBComposite_stm32f1
20+
* 3. Скетч настраивает микрокотроллер USB HID устройство без классификации
21+
* 4. Запущенное устройство не требует никаких драйверов
22+
*
23+
* Проверка:
24+
* 1. Подключить датчик согласно распиновке
25+
* 2. Загрузить скетч в плату
26+
* 3. Запустить скрипт Python [библиотеки]\AMS-AS5600-Arduino-Library\addons\AS5600-Sensor-HID\SensorHID.py
27+
* 4. Смотреть расшифровку принятых данных в терминале Python
28+
*
29+
* Зависимости:
30+
* https://github.com/rogerclarkmelbourne/Arduino_STM32
31+
* https://github.com/arpruss/USBComposite_stm32f1
32+
*
33+
* Документация к датчику:
34+
* AS5600 https://ams.com/documents/20143/36005/AS5600_DS000365_5-00.pdf
35+
* AS5600L https://ams.com/documents/20143/36005/AS5600L_DS000545_3-00.pdf
36+
*
37+
* Больше информации в WiKi:
38+
* https://github.com/S-LABc/AMS-AS5600-Arduino-Library/wiki
39+
*
40+
* Контакты:
41+
** GitHub - https://github.com/S-LABc
42+
** Gmail - romansklyar15@gmail.com
43+
*
44+
* Copyright (C) 2022. v1.0 / Скляр Роман S-LAB
45+
*/
46+
47+
// Подключаем библиотеки
48+
#include <AMS_AS5600.h>
49+
//#include <AMS_AS5600L.h> // Для другой версии датчика
50+
#include <USBComposite.h>
51+
52+
// Раскомментировать, если используется второй аппаратный блок I2C у платы
53+
//TwoWire Wire2 (2, I2C_FAST_MODE);
54+
//#define Wire Wire2
55+
56+
#define TX_SIZE 23 // Количество передаваемых байт данных по USB
57+
#define RX_SIZE 1 // Количество принимаемых байт данных по USB за вычетом 1 байта Report ID, так требует библиотека USBComposite
58+
59+
// Общая информация об устройстве
60+
#define DEV_VID 0x1EAF // Значение по умолчанию (связано со скриптом Python)
61+
#define DEV_PID 0x0024 // Значение по умолчанию (связано со скриптом Python)
62+
#define DEV_MUNUF "S-LAB"
63+
#define DEV_PROD "SENSOR-HID-RAW"
64+
#define DEV_SER "v001"
65+
66+
#define UNIQ_KEY 0x15 // Уникальный ключ (связан со скриптом Python)
67+
68+
// Инициализация массивов буферизации для принимаемых и передаваемых данных
69+
uint8_t rx_buf[RX_SIZE];
70+
uint8_t tx_buf[TX_SIZE];
71+
72+
// Создаем объект Sensor с указанием ссылки на объект Wire
73+
AS5600 Sensor(&Wire);
74+
75+
// Создание объекта HID плагина
76+
USBHID HID;
77+
// Создание объекта чистого HID
78+
HIDRaw<TX_SIZE, RX_SIZE> rawHID(HID);
79+
// Дескриптор отчета для чистого HID
80+
const uint8_t reportDescription[] = {
81+
HID_RAW_REPORT_DESCRIPTOR(TX_SIZE, RX_SIZE)
82+
};
83+
84+
void setup(){
85+
// Настройка информации об устройстве
86+
USBComposite.setVendorId(DEV_VID);
87+
USBComposite.setProductId(DEV_PID);
88+
USBComposite.setManufacturerString(DEV_MUNUF);
89+
USBComposite.setProductString(DEV_PROD);
90+
USBComposite.setSerialString(DEV_SER);
91+
92+
// Зпуск плагина HID
93+
HID.begin(reportDescription, sizeof(reportDescription));
94+
// Запускаем соединение с датчиком
95+
Sensor.begin();
96+
// Настраиваем шину I2C на 400кГц
97+
Sensor.setClock();
98+
//Можно на друие частоты, но работает не на всех микроконтроллерах
99+
//Sensor.setClock(AS5600_I2C_CLOCK_100KHZ); // 100кГц
100+
//Sensor.setClock(AS5600_I2C_CLOCK_1MHZ); // 1МГц
101+
//Sensor.setClock(725000); // Пользовательское значение 725кГц
102+
103+
// Ожидание установки связи по USB
104+
while (!USBComposite);
105+
// Запуск чистого HID
106+
rawHID.begin();
107+
}
108+
109+
void loop() {
110+
if (rawHID.getOutput(rx_buf)) { // Если пришли данные от хоста
111+
if (rx_buf[0] == UNIQ_KEY) { // Если в данных есть правильный уникальный ключ
112+
// Собираем данные в буфер для передачи
113+
prepareData();
114+
// Отправляем собранные данные хосту
115+
rawHID.send(tx_buf, sizeof(tx_buf));
116+
}
117+
}
118+
}
119+
120+
void prepareData() {
121+
tx_buf[0] = Sensor.isConnected();
122+
123+
word zero_pos = Sensor.getZeroPosition();
124+
tx_buf[1] = zero_pos >> 8;
125+
tx_buf[2] = zero_pos & 0x00FF;
126+
127+
word max_pos = Sensor.getMaxPosition();
128+
tx_buf[3] = max_pos >> 8;
129+
tx_buf[4] = max_pos & 0x00FF;
130+
131+
word max_ang = Sensor.getMaxAngle();
132+
tx_buf[5] = max_ang >> 8;
133+
tx_buf[6] = max_ang & 0x00FF;
134+
135+
tx_buf[7] = Sensor.getPowerMode();
136+
137+
tx_buf[8] = Sensor.getHysteresis();
138+
139+
tx_buf[9] = Sensor.getOutputStage();
140+
141+
tx_buf[10] = Sensor.getPWMFrequency();
142+
143+
tx_buf[11] = Sensor.getSlowFilter();
144+
145+
tx_buf[12] = Sensor.getFastFilterThreshold();
146+
147+
tx_buf[13] = Sensor.isWatchdog();
148+
149+
word raw_ang = Sensor.getRawAngle();
150+
tx_buf[14] = raw_ang >> 8;
151+
tx_buf[15] = raw_ang & 0x00FF;
152+
153+
word scl_ang = Sensor.getScaledAngle();
154+
tx_buf[16] = scl_ang >> 8;
155+
tx_buf[17] = scl_ang & 0x00FF;
156+
157+
tx_buf[18] = Sensor.getStatus();
158+
159+
tx_buf[19] = Sensor.getAutomaticGainControl();
160+
161+
word magn = Sensor.getMagnitude();
162+
tx_buf[20] = magn >> 8;
163+
tx_buf[21] = magn & 0x00FF;
164+
165+
tx_buf[22] = Sensor.getBurnPositionsCount();
166+
}

0 commit comments

Comments
 (0)