FT4232H
FT4232H переключить в режим MODBUS 485 https://manpages.debian.org/testing/ftdi-eeprom/ftdi_eeprom.1.en.html https://netcup-03.armbian.com/dl/rockpi-s/archive/Armbian_26.2.1_Rockpi-s_trixie_current_6.18.9_minimal.img.xz PID 6011 = FT4232H в режиме Quad UART (4 последовательных порта) PID 6014 = FT4232H в режиме Quad UART/FIFO (с поддержкой дополнительных режимов)
napic arbian
0. Дистрибутив: Armbian_26.2.1_Rockpi-s_trixie_current_6.18.9_minimal 1. Оверлеи: /boot/armbianEnv.txt overlays=otg-host 2. Костюмные оверлеи от напи: команда для добавления: armbian-add-overlay <файл.dts> инструкция: https://napiworld.ru/recipes/armbian-tuning/ где брать файлы: https://gitlab.nnz-ipc.net/pub/napilinux/kernel/-/tree/linux6.6/arch/arm64/boot/dts/rockchip/overlay 3. Необходимый софт установка: apt update apt install libftdi1-2 libftdi-dev ftdi-eeprom gcc libftdi1-dev libftdi1 libudev-dev 4. Проверка usb: lsusb lsusb -v -d 0403:6011 | grep -i "serial\|product" Выгрузка модулей если требуется: rmmod ftdi_sio rmmod usbserial 5. ДОКИ /usr/share/doc/ftdi-eeprom/examples/ zcat /usr/share/doc/ftdi-eeprom/example.conf.gz 6. Пример конфигурационный файл для прошивки FT4232 в режиме MODBUS 485: cat > ft4232h.conf << EOF # Имя файла, содержащий образ EEPROM, который будет создан filename=test.bin # Идентификатор производителя. Для FT4232H значение по умолчанию: 0x0403 vendor_id=0x0403 # Идентификатор продукта. Для FT4232H значение по умолчанию: 0x6011 product_id=0x6011 # Тип EEPROM микросхемы. 0x46 для 93xx46, 0x56 для 93xx56 и 0x66 для 93xx66 #eeprom_type=0x46 eeprom_type=0x56 manufacturer="lablab2" product="Quad RS485" serial="1234" # Разрешить использование серийного номера use_serial=true # Ограничение по потреблению микросхемы: (значение параметра) * 2 мА. Значение параметра # должно быть равно 0, когда self_powered=true #max_power=0 #max_power=500 # Микросхема питается не от USB, а от собственного источника питания #self_powered=true #self_powered=false # Если на линии RI логический 0 и значение параметра равно true, то хост контроллер USB # выйдет из режима ожидания примерно через 20 мс. # remote_wakeup=false #remote_wakeup=true # Задать режим работы порта # # "UART", "FIFO", "OPTO", "CPU", "FT1284" #cha_type=UART #chb_type=FIFO #chc_type=OPTO #chd_type=CPU # Использовать драйвер виртуального com-порта #cha_vcp=true #chb_vcp=true #chc_vcp=true #chd_vcp=true # Разрешить режим RS-485 #cha_rs485=true #chb_rs485=true #chc_rs485=true #chd_rs485=true # Channel A cha_type=UART cha_vcp=true cha_rs485=true #cbush0 = TXDEN # Channel B chb_type=UART chb_vcp=true chb_rs485=true # Channel C #chc_type=UART chc_vcp=true chc_rs485=true #CDBUS7=TXDEN # Channel D #chd_type=UART chd_vcp=true chd_rs485=true #DDBUS7=TXDEN # Управление направлением (TXDEN) # invert_txd = true EOF 7. Работа с прошивкой ft4232 Зашить: ftdi_eeprom --flash-eeprom ft4232h.conf прочитать: ftdi_eeprom --read-eeprom ft4232h.conf
Сборка libftdi
Собирем сам соберется, но тут 0.17 :( cd /opt git clone https://github.com/lipro/libftdi cd libftdi mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX="/usr" ../ make make install
Собираем с сайта libftdi
###https://www.intra2net.com/en/developer/libftdi/download.php ###Requirements and dependencies ###libusb 1.0 - Library for talking to USB devices from user-space. Needed by libftdi. ###libconfuse - Library for parsing configuration files. Needed by ftdi_eeprom. ### wget https://www.intra2net.com/en/developer/libftdi/download/libftdi1-1.5.tar.bz2 mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX="/usr" ../ make make install
Питон скрипт для тестов:
Python env:
0. Установите пакеты: apt update && apt install python3-venv python3-full -y 1. Создайте виртуальное окружение (например, в папке myenv): python3 -m venv myenv 2. Активируйте его: source myenv/bin/activate 3. Установите библиотеку: pip install minimalmodbus 4. Пере использование окружения: cd /root/myenv source /root/myenv/bin/activate Запуск python read_modbus.py
Python скрипты для тестов:
cat > 1.txt << "EOF"
import minimalmodbus
import serial
# Настройка порта
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', slaveaddress=1)
instrument.serial.baudrate = 9600
instrument.serial.bytesize = 8
instrument.serial.parity = serial.PARITY_NONE
instrument.serial.stopbits = 1
instrument.serial.timeout = 1.0
# Самая важная строчка для FTDI под Linux:
# Драйвер очистит входной буфер от эха сразу после отправки запроса
instrument.serial.flushInput()
try:
# Читаем 1 регистр (holding) с адреса 769 (в mbpoll это -r 769 -t 4)
# minimalmodbus использует адресацию от 0, поэтому проверяем 769 или 768 в зависимости от карты регистров устройства
value = instrument.read_register(769, functioncode=3)
print(f"Значение регистра: {value}")
except Exception as e:
print(f"Ошибка чтения: {e}")
EOF
python 1.txt
cat > 2.txt << "EOF"
import serial
import time
# Настройки порта
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate=9600,
bytesize=8,
parity='N',
stopbits=1,
timeout=1.0
)
# Формируем запрос Modbus RTU (тот самый, что слал mbpoll)
# Чтение 1 регистра с адреса 769 (0x0301) для устройства 1
request = b'\x01\x03\x03\x00\x00\x01\x84\x4E'
# Очищаем буферы
ser.reset_input_buffer()
ser.reset_output_buffer()
# Отправляем запрос
ser.write(request)
ser.flush()
# Ждем ответа и вычитываем порцию (запрос занял время, плюс ответ)
time.sleep(0.1)
# Читаем сырые данные
raw_response = ser.read(ser.in_waiting)
print(f"Сырой ответ из порта: {raw_response}")
# Отсекаем эхо, если оно есть (ищем начало нашего ответа с адреса \x01)
# Если устройство вернуло 7 байт, как в ошибке:
if len(raw_response) >= 7:
# Если в начале висит эхо запроса (8 байт), отрезаем его
if raw_response.startswith(request):
response = raw_response[len(request):]
else:
response = raw_response
print(f"Пакет после отсечения эха: {response}")
if len(response) >= 7:
# Извлекаем данные из 4-го и 5-го байта (индексы 3 и 4)
high_byte = response[3]
low_byte = response[4]
value = (high_byte << 8) + low_byte
print(f"🎉 Успешно! Значение регистра: {value}")
else:
print("Не удалось получить полный ответ от устройства.")
ser.close()
EOF
python 2.txt
cat > rs485.py << "EOF"
import os
import fcntl
import struct
import sys
TIOCGRS485 = 0x542E
TIOCSRS485 = 0x542F
SER_RS485_ENABLED = 0x01
SER_RS485_RX_DURING_TX = 0x08
def set_rs485(port, enable=True):
fd = os.open(port, os.O_RDWR | os.O_NOCTTY)
try:
# Читаем текущие настройки
buf = fcntl.ioctl(fd, TIOCGRS485, struct.pack('8I', 0,0,0,0,0,0,0,0))
flags = struct.unpack('8I', buf)[0]
if enable:
flags |= SER_RS485_ENABLED
flags &= ~SER_RS485_RX_DURING_TX
else:
flags &= ~SER_RS485_ENABLED
fcntl.ioctl(fd, TIOCSRS485, struct.pack('8I', flags, 0,0,0,0,0,0,0))
finally:
os.close(fd)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python rs485.py /dev/ttyUSB0")
sys.exit(1)
set_rs485(sys.argv[1], True)
EOF
python3 rs485.py /dev/ttyUSB0
python3 rs485.py /dev/ttyUSB1
python3 rs485.py /dev/ttyUSB2
python3 rs485.py /dev/ttyUSB3
mbpoll и modpoll:
0. датчик:
holding (output) регистры:
768 температура * 10
796 влажность *10
ID, по умолчанию 1. Как изменить пока не ясно.
13 скорость, по умолчанию 3 - 9600
14 чётность, по умолчанию 0 - NONE
1279 коррекция температуры
1280 коррекция влажности
В некоторых сниферах и OPC серверах надо указывать адрес на 1 больше.
1. Пример команд:
mbpoll -m rtu -a 1 -r 769 -c 1 -t 4 -b 9600 -P none -v /dev/ttyUSB0
modpoll -b 9600 -p none -m rtu -a 1 -r 769 -c 1 -t 4 -1 /dev/ttyUSB1
for i in 0 1 2 3 ; do
modpoll -b 9600 -p none -m rtu -a 1 -r 769 -c 1 -t 4 -1 /dev/ttyUSB$i
sleep 2
done
for port in 0 1 2 3 ; do
for reg in 768 796 1279 1280 ; do
modpoll -b 9600 -p none -m rtu -a 1 -r $reg -t 4 -c 1 -1 /dev/ttyUSB$port
sleep 1
done
done
screen /dev/ttyUSB0 9600 cs8 -parenb -cstopb
stty -F /dev/ttyUSB0 9600 raw -echo; cat /dev/ttyUSB0
socat -d -d OPEN:/dev/ttyUSB0,b9600,rawer,echo=0 SYSTEM:'tee /tmp/tty.log | socat - "OPEN:/dev/ttyUSB0,b9600,rawer,echo=0"'
2. Тесты:
while true; do echo "x" > /dev/ttyUSB0; sleep 0.1; done
3. Снять блокировку если нужно
rm -f /var/lock/LCK..ttyUSB0