Совместное использование последовательного вывода с одного на несколько Arduino (плюс компьютер) через USB-концентратор

Я пытаюсь отправить выходной сигнал поворотного энкодера с UNO на семь Trinket M0 и компьютер через USB-концентратор (с питанием).

В настоящее время бит UNO → Laptop отлично работает, последовательный мониторинг работает через концентратор для всех, и я могу установить соединение ведущий/ведомый между UNO и Trinket через библиотеку Arduino Wire. Но Wire использует контакты, и мне не удалось найти аналогичное решение для USB. На данный момент лучшие результаты связаны с использованием чего-то вроде stty в скрипте bash для прослушивания того, что делает каждый порт но я так далеко зашел в тупик, что это может быть просто принятием желаемого за действительное.

Я не ищу здесь решения, а просто предлагаю несколько советов, куда двигаться дальше. В частности:

  1. Полезна ли библиотека Wire для связи по USB? Есть ли что-то подобное (главное/подчиненное), что было бы полезно?
  2. Предполагая, что последовательное подключение/прослушивание работает, есть ли хорошие способы перенаправить данные на другие порты? В настоящее время я думаю, что-то вроде $ echo $encoderVal > /dev/cu.usbmodem????? каждому отдельно... но это может быть совершенно нубской идеей.)
  3. i2c продолжает фигурировать в результатах поиска, но выглядит излишним. Это направление к голове?
  4. Это все полная ерунда?

В любом случае, заранее всем спасибо.

Обновить

Хорошо! Благодаря совету @Gerben и @chrisl я закончил маршрутизировать все вокруг с помощью PySerial и (для чрезвычайно ограниченных целей этого маленький проект) работает хорошо! Вот что сейчас работает:

import serial
from time import sleep
import os

# Connect to each Arduino individually
serialUno = serial.Serial("/dev/cu.usbmodem141101", 9600, timeout=0)
serialTrinket1 = serial.Serial("/dev/cu.usbmodem1414401", 9600, timeout=0)
# (+ 6 more. serialTrinket2, serialTrinket3, etc)

# Open a text file to save the encoder value in
f = open("encoderVal.txt", "w")

while True:
  # Read encoderVal from the UNO
  data = serialUno.read(9999)
  if len(data) > 0:

    # Send data to each trinket
    serialTrinket1.write(data)

    # Save val to text file to Unity
    with open('encoderVal.txt', 'r+') as f:

      # Wipe the file so it's only the most recent value
      f.truncate()
      dataStripped = data.strip()

      # Return the last int in the data stream
      dataSplit = dataStripped.split('\n')
      f.write(dataSplit[-1])

  sleep(0.05)

# Close serial connections & file on interrupt
serialUno.close()
serialTrinket1.close()
f.close()

Что касается ноутбука, я отказался от последовательной библиотеки, которую использовал, в пользу это инструмент Unity-to-Python, который отлично работает.

Единственная проблема на данный момент заключается в том, что PySerial время от времени теряет несколько байтов здесь и там, что приводит к шаткому числу, равному 30 или около того. Это будет завтрашний проект. Спасибо всем за помощь!

, 👍0

Обсуждение

Почему бы не использовать для этого Serial (UART)? Вы можете подключить одну плату передатчика (в данном случае Uno) к нескольким платам приемника (Trinkets)., @chrisl

Я бы использовал что-то вроде Python на ПК для подключения ко всем последовательным портам UNO и Trinkets. Пусть код Python анализирует входящие данные (например, положение поворотного энкодера) и отправляет их на те платы, которым нужны эти данные. Или даже проще. Прочитайте входящие последовательные данные и отправьте их на все доступные последовательные порты (вроде повторителя). Единственное, чего я не понимаю, так это почему у вас вообще есть ПК в вашей установке. Какова его польза? Использование чего-то другого, кроме USB, означает, что вы можете запускать всю систему без подключенного ПК., @Gerben

@chrisl Хорошо, но не будет ли это дополнительной сложностью? (Первый поиск привел к [Эмуляция UART через USB](https://stackoverflow.com/questions/12678698/emulatory-uart-over-usb), что приводит нас к виртуальным COM-портам и ... больше., @laffan

@Gerben Это кажется солидным планом. Я начну исследовать сериал и питон. Re: ваш вопрос, ПК должен быть там, потому что последовательный вход от поворотного энкодера запускает игру Unity (вся сторона HDMI не показана на диаграмме)., @laffan


2 ответа


Лучший ответ:

0

Полезна ли библиотека Wire для связи по USB? Есть ли что-то похожее (ведущее/подчиненное), что было бы полезно?

Библиотека Wire обеспечивает связь I2C, которая не имеет абсолютно никакого отношения к USB. На самом деле USB-соединение на Uno не родное. Atmega328P на Uno имеет только последовательный (UART) интерфейс, который на борту подключен к другому чипу (Atmega82U или другому), имеющему встроенную поддержку USB. Этот чип будет осуществлять связь через USB. Затем драйвер на ПК будет эмулировать последовательный COM-порт, так что это будет что-то вроде соединения «Последовательный COM-порт через USB». USB сложный и с ним напрямую возиться не стоит, если только вы не очень продвинуты в этом направлении. И я не думаю, что это поможет вам здесь.

Предполагая, что последовательное соединение/прослушивание работает, есть ли хорошие способы перенаправить данные на другие порты? В настоящее время я думаю, что-то вроде $ echo $encoderVal > /dev/cu.usbmodem????? каждому индивидуально... но это может быть совершенно нубская идея.)

Поскольку у вас есть полноценная игра на Unity, вам нужно что-то запрограммировать в этом направлении. Использование bash кажется здесь не очень хорошим. Я не знаю, можете ли вы общаться с последовательными COM-портами из Unity (поскольку я еще не работал с ним), но в Python это работает как шарм. Существует множество руководств, в которых показано, как это сделать.

i2c продолжает появляться в результатах поиска, но это выглядит как излишество. Это направление движения?

Если это излишество, зависит от ваших конкретных требований к системе. Конечно, у протокола I2C есть некоторые накладные расходы, но, возможно, вам нужна функциональность.

Это все полная ерунда?

В настоящее время это выглядит примерно так. Я думаю, это из-за того, что у вас нет хорошей структуры проекта. Чтобы помочь вам в этом, ниже я объясню некоторые возможности.


Как я понял, у вас следующие настройки: У Uno есть поворотный энкодер, который управляет игрой на ПК. Все платы (Uno и Trinkets) имеют одну светодиодную ленту, которая должна загораться в зависимости от того, что происходит в игре.

Теперь у вас есть 2 основные структуры для общения:

  1. Все делается через собственное USB-подключение. Это то, что вы нарисовали выше. Каждая плата имеет свой собственный последовательный COM-порт (который на самом деле эмулируется драйвером через USB) на ПК, и ваша игра/программа на нем должна подключаться ко всем этим портам и отправлять соответствующие данные. Конечно, это возможный дизайн, но у него есть недостатки: в настоящее время не кажется, что вы уже внедрили коммуникационную программу. Это важно в этом дизайне, но это не совсем про Arduino и зависит от того, как вы программируете игру в Unity (раньше этого не делали и не знаете, как подключить к нему последовательное устройство. Может быть, через скрипт Python ). Вторая проблема заключается в том, что вам придется выбирать последовательный порт для каждой платы при запуске игры. Номера/имена портов не всегда совпадают; это зависит от операционной системы, чтобы установить их. Это не очень удобно.

  2. Вы можете напрямую использовать другие интерфейсы связи между платами. В этом случае только Uno будет подключен через USB к ПК, и все данные будут проходить через Uno. Какой интерфейс вы должны использовать, зависит от ваших конкретных требований. Поскольку вы не указали их подробно, я объясню несколько примеров:

    • Каждый Trinket получает одни и те же данные, и из них ничего не нужно читать: В этом случае вы можете использовать последовательный (UART) интерфейс. Он использует контакты, помеченные RX (приемный контакт) и TX (передающий контакт). Обычно это соединение только между двумя платами, но можно просто подключить несколько приемников (с их контактом RX) ровно к 1 передатчику (с его контактом TX).

      У Uno есть один аппаратный последовательный интерфейс, который также используется для связи с ПК. Если это нормально, что ПК также получает данные, предназначенные для Trinket (а Trinkets получают данные, предназначенные для ПК), вы можете использовать этот интерфейс и подключить TX Uno ко всем контактам Trinket RX. . Вы можете погуглить, как читать данные из интерфейса с библиотекой Serial, которая напрямую доступна с Arduino. Если вы не хотите, чтобы ПК получал те же данные, вы можете настроить интерфейс SoftwareSerial (с библиотекой с таким именем). Это обеспечивает тот же интерфейс, но обрабатывается программно, поскольку у Uno нет другого аппаратного последовательного интерфейса (UART).

      В обоих случаях вы должны передавать данные с ПК (данные из игры) через последовательный порт USB на Uno, который затем, в свою очередь, отправляет их на все платы Trinket. Они читают данные и действуют соответственно. Каждый раз, когда Uno определяет новое положение поворотного энкодера, он отправляет данные на ПК.

      Для подключения Uno к Trinket в этой конструкции требуется всего 2 провода (1 для Uno TX к Trinket RX и 1 провод заземления). Конечно, вам также придется обеспечить питание безделушек. Пожалуйста, смотрите ниже по этому вопросу.

    • Каждый Trinket может быть адресован индивидуально, и данные также могут быть считаны из них: В этом случае I2C может быть подходящим способом. Для связи вам потребуется как минимум 3 провода (SDA, SCL и земля). Каждый Trinket подключается к шине I2C с настроенным адресом. Uno выступает в роли ведущего в автобусе. Он может вызвать Брелок по его адресу и отправить или запросить данные. Протокол I2C более структурирован , чем последовательный (UART), поскольку он разделен на передачи. Это прекрасно работает, если все тринкеты могут получать разные данные, и если вы также хотите считывать данные с них. Обязательно дайте самой Брелке уникальный адрес в автобусе. Программную часть смотрите в библиотеке Wire.

    • Очень быстрая отправка и получение отдельных данных: если вам нужна индивидуальная передача и чтение данных из I2C, но вам также нужна очень быстрая связь, вы можете использовать SPI . Шина SPI использует не адреса, а контакты Slave Select. Вам нужен 1 контакт на ведущем (Uno) для каждого ведомого устройства. Если вы хотите связаться с одним Trinket, вы потяните его штифт выбора ведомого устройства в положение LOW. Для этой шины требуется 5 проводов (MISO, MOSI, SCK, Slave Select и земля), но связь может быть очень быстрой; намного быстрее, чем I2C. Загляните в библиотеку SPI для программирования этого.


Подача питания: В зависимости от вашего дизайна, количества и типа светодиодов, вы должны изучить, как вы обеспечиваете необходимое питание для плат. В дизайне, который вы нарисовали выше (каждая плата напрямую к USB), сами платы должны иметь достаточную мощность, но светодиодные ленты могут быть очень энергоемкими, достигая тока более 1 А. Распиновка Adafruits Trinket M0 показывает максимальный ток 500 мА от контакта Vusb. Контакт 5V Uno может выдерживать около 200 мА (насколько я помню, в настоящее время не уверен. Вы можете найти это в Google).

Если вы выберете дизайн, в котором к USB подключен только Uno, вам может понадобиться дополнительный блок питания, чтобы вы могли обеспечить питание для всех безделушек и их светодиодов. Пожалуйста, соблюдайте текущие ограничения компонентов, иначе вы можете сжечь свои платы.

Надеюсь, что помогу. Получайте удовольствие

,

Спасибо, что потратили все время на этот ответ. Как вы увидите, я пришел к гораздо более хакерскому решению, чем вы, вероятно, посоветовали бы, но эй, оно вроде как работает!, @laffan


1

Во-первых, прочтите немного об USB, это целый протокол, а не просто аппаратно-контактный интерфейс. Это на самом деле весьма вовлечено. Тогда вам будет понятнее, почему USB (от Nano) решение будет... сложным.

Насколько я понимаю, я бы воспользовался вашей идеей №2 и тем, что было предложено, и сделал следующее...

  1. Настройте Uno как ведомое устройство USB, а не как ведущее.
  2. Используя ПК, подключитесь к Uno и Trinkets.
  3. Когда ПК получает данные от Uno, пусть ПК "повторяет" их на Брелки.

Я думаю, что это будет самое простое и быстрое решение.

,