Получить больше выводов с поддержкой PCINT на Mega 2560
Я делаю что-то вроде "игры в мяч" в общей сложности 6 игроков на основе следующих характеристик для каждого игрока:
- 1 шаговый двигатель с 4 контактами
- 2 конечных упора (старт и финиш) на двигатель
- 1 индикатор финиша
- 3 лунки, которые нужно забить, что приводит к медленному, среднему или быстрому движению.
Кроме того, существует "общий сброс" чтобы вернуть все двигатели в исходное положение.
Из-за моего первоначального предположения, что 54 контактов будет достаточно, я не понимал, что на самом деле требуется 60 контактов (24 для двигателей, 12 для концевых упоров, 6 для светодиодов, 18 для отверстий). Я также не являюсь экспертом в области микроэлектроники или языка программирования C, но мое понимание штифты Mega заключаются в том, что мне нужно 12 + 18 штифтов с поддержкой PCINT (концевые упоры + отверстия), в то время как доступно только 16 штифтов.
Пока единственная информация, которую я смог найти, предлагает купить Arduino Shield, чтобы решить эту проблему, предоставив дополнительные 16 контактов PCINT. Но при подключении через I2C я подозреваю задержки, приводящие к неравному отношению к очкам игроков.
Как получить по крайней мере 30 выводов с поддержкой PCINT, одинаково обрабатываемых Arduino? Если нет необходимости в требовании PCINT, какие выводы можно использовать в качестве альтернативы?
@Yoda, 👍0
Обсуждение1 ответ
Лучший ответ:
Atmega2560 имеет в общей сложности 24 контакта, связанных с прерыванием PinChange. Вы не можете изменить это. Это внутреннее свойство микроконтроллера.
Как вы уже убедились, вам нужно использовать дополнительные микросхемы, чтобы расширить доступные контакты ввода-вывода. Можно рассмотреть различные варианты:
- Расширители портов ввода-вывода (доступны для I2C или SPI) (например, PCF8574 .Не знаю, может это и лучший, просто расширитель портов, которым я тоже пользовался)
- Регистры Shift-In (для входных данных) или Shift-Out (для выходных данных) (часто используются 74HC595 (регистр Shift-Out) и 75HC165 (регистр Shift-In). Я часто использовал это руководство в качестве справки)
Поскольку вы не хотите постоянно опрашивать эти микросхемы, я предлагаю вам использовать одну, которая обеспечивает дополнительный вывод прерывания. Этот вывод изменит свое значение при изменении одного из входов. Затем вы можете подключить этот вывод к одному из выводов прерывания Atmega2560. Когда срабатывает прерывание, вы можете прочитать состояние входных контактов.
Но при подключении через I2C я подозреваю задержки, приводящие к неравному отношению к очкам игроков.
Действительно, это было бы нехорошо. Таким образом, вы должны разделить кегли по их назначению, а не по их связи с игроком. Например, все входы концевых упоров или все выходы для шаговых двигателей. Затем вам нужно получить доступ к тому, какие временные требования есть у каждой группы. Затем вы можете взять группу с наименьшими требованиями и проверить, сможет ли и какой чип достаточно быстро обрабатывать данные. Например, «финишный светодиод». Вы не указали, что именно он делает, но я предполагаю, что это не очень критично по времени. Таким образом, вы можете управлять всеми индикаторами завершения с помощью одного регистра сдвига.
Или возьмите входные данные для отверстий: я думаю, здесь у вас есть какой-то датчик, который срабатывает, когда мяч проходит мимо него. Проверьте, как долго срабатывает датчик. Скорее всего (в зависимости от типа датчика) это зависит от скорости мяча. Возьмите скорость, которую вы хотите считать максимальной (например, скорость подачи хорошего бейсболиста, так как она действительно высока), и посчитайте, какой длины будет результирующий пульс. Чип, который вы выберете, может быть достаточно быстрым для этого. Таким образом, вы можете обрабатывать все входные данные через дополнительные микросхемы (имеются в виду микросхемы, предоставляющие дополнительные входные микросхемы, такие как регистр Shift-In или расширитель портов).
В случае, если требование PCINT не требуется, какие выводы можно использовать в качестве альтернативы?
Каждый вывод поддерживает цифровой ввод-вывод. Это почти каждый контакт на Arduino Mega. Хотя это означает, что вы не можете использовать прерывания для них, и вы должны постоянно опрашивать их. Это может быть нормально для вас. Это действительно зависит от ваших точных требований к времени.
Я думал, что опросы - это область, которую "избегайте, где это возможно"?!
Да и нет. Сначала вы спросили о возможности использования других контактов, поэтому я упомянул об этом выше. Хотя это означает отсутствие прерывания PinChange. Вообще опрос плохой, когда
- вы тратите на это слишком много времени, не оставляя времени на другие функции кода, или
- если события, которые вы опрашиваете, слишком короткие для вашего кода опроса.
Это может произойти в случаях, когда
- вы используете блокирующий код для опроса (например, ожидание в цикле
while
для нажатия кнопки), который блокирует выполнение всех других функций. - вашему коду требуется достаточно длинное событие, чтобы зарегистрировать его (например, сигнал от ваших датчиков отверстия может быть очень коротким. Если ваш интервал опроса больше, вы потеряете некоторые события)
Если вы остаетесь внутри ограничений и используете неблокирующий код, в опросе нет ничего плохого.
Возьмем часто используемую библиотеку Bounce2 для Arduino. Это помогает вам читать кнопки и обрабатывает устранение дребезга для вас. Он не использует никаких прерываний. Ожидается, что вы будете вызывать Bounce.update()
достаточно часто, чтобы перехватывать все нажатия кнопок, что обычно занимает максимум несколько мс. Но поскольку Arduino Mega работает на частоте 16 МГц, она способна работать на гораздо более высоких скоростях, чем несколько мс. Вызов Bounce.update()
достаточно часто прост, когда вы не пишете код, выполнение которого занимает много времени. Так что никаких задержек, разве что очень коротких. Вместо этого вы можете использовать стиль кодирования из примера BlinkWithoutDelay
, который входит в состав Arduino IDE. Он использует функцию millis()
в качестве временной базы для многократной проверки, не пора ли что-то сделать, и делает это только в том случае, если действительно пришло время для этого. Это похоже на то, как вы печете пиццу, ставя ее в духовку, а затем регулярно смотрите на часы, не пора ли доставать пиццу из духовки. Вы не хотите сидеть перед духовкой в ожидании пиццы. Аналогом этого является написание блокирующего кода с помощью delay()
.
Итак, в целом об опросе и прерываниях: это зависит от ваших требований. Быстрое время отклика или короткие события часто требуют прерываний, хотя вам нужно справляться с ограниченным числом используемых контактов и различными прерываниями (которые немного сложнее кодировать). Опрос, если все сделано правильно, может дать вам большую свободу и довольно простую обработку, сохраняя при этом источники прерываний для более важных функций. Хотя это накладывает большие ограничения на время отклика и продолжительность событий. Также это строго зависит от остальной части вашего кода.
Обратите внимание, что в приведенном выше описании такие термины, как "критическое время", "быстрое время отклика" и такие больше предназначены для области небольшого числа микросекунд. Тайминги в диапазоне миллисекунд можно легко выполнить с помощью упомянутого стиля неблокирующего кодирования (либо с помощью millis()
, либо для большего разрешения и точности с небольшим числом миллисекунд micros()< /код>). Принцип всегда один и тот же, в Интернете есть множество руководств по нему и даже много вопросов и ответов на этом сайте. Так что вы можете поискать в Google более подробное руководство.
Извините, мои обязательства помешали более быстрому ответу. Поскольку у меня нет знаний об I2C/SPI, кроме их базовой работы, не могли бы вы порекомендовать такой расширитель ввода-вывода и / или регистр сдвига в / из с таким дополнительным прерыванием штырь? Что касается «финишного светодиода», то светодиод победителя загорается после того, как его аватар пересекает финишную черту (и все 6 светодиодов вместе при нажатии кнопки сброса) — так что да, это совсем не критично по времени. :) Да, входы в отверстия работают через сенсорные триггеры. Но я не понимаю, что вы подразумеваете под «дополнительными фишками» :( И что касается опроса: я думал, что опрос был областью «избегайте, где это возможно»?!, @Yoda
@Yoda Я добавил в свой ответ больше информации, включая примеры возможных частей (расширитель ввода-вывода, входной регистр сдвига, регистр сдвига-выхода) и раздел об опросе и прерываниях. Под «дополнительными чипами» я имел в виду чипы, подобные приведенным выше, чтобы получить больше контактов ввода-вывода., @chrisl
спасибо за вашу помощь, время и особенно ваши полезные объяснения! Тогда я пойду на опрос, сначала попробую millis()
и micros()
и вернусь к 75HC165/74HC595 или PCF8574, если это не сработает. Еще раз большое спасибо за вашу ценную помощь!, @Yoda
- Неиспользуемые контакты в Arduino L293D motor shield?
- Использование оранжевого/белого контакта экрана двигателя Arduino
- Альтернатива пайке для соединения плат
- Регистр ATmega 32A и 2560 R3 для сопоставления контактов
- Arduino + Solar Charger Shield V2.2: выбор батареи и солнечных панелей
- Как отключить питание устройства, с которого надо прочитать данные?
- NodeMCU - Vin контакт как выход 5V?
- Использовать все контакты как цифровые входы/выходы
Если вы пишете хороший код, вам не потребуется прерывание ни для чего из этого. Как вы думаете, этот переключатель может замыкаться и срабатывать менее чем за миллисекунду? Для сравнения, моргание глазами занимает около 200 мс. Не используйте задержку для синхронизации, и для этого вам не понадобятся прерывания., @Delta_G
Если вы хотите больше PCINT, вы можете сделать это самостоятельно вне чипа. Просто И или ИЛИ (в зависимости от того, хотите ли вы активировать НИЗКИЙ или ВЫСОКИЙ) несколько сигналов вместе и подайте результат на один контакт прерывания * в дополнение к каждому сигналу на свой собственный цифровой контакт *, затем, когда происходит одно прерывание, опрашивайте другой цифрового выврда, чтобы увидеть, что изменилось., @Majenko
@Delta_G Как? Текущий код в
loop()
Arduino фактически использует задержку между настройками, например, степперов, чтобы обеспечить своего рода «охлаждение». Дело не в том, что я хочу время отклика в 1 мс, это больше с точки зрения «равных шансов» между всеми игроками., @Yoda@Majenko Итак, вы предлагаете мне, например, объединить все 6 входов PCINT в 1 и после прерывания опросить все 6, чтобы найти правильный? Как насчет того, чтобы игрок № 2 попал в ту же лунку (на своем столе, а не на столе игрока № 1)? Не будет ли это проглочено зря?, @Yoda
Я бы не знал. Я понятия не имею, о каких дырах вы говорите, и как игрок «бьет» их., @Majenko
@Majenko Это своего рода настольная игра, в которой игроку нужно забросить мяч в 1 из 3 лунок, а затем позволить своему аватару двигаться вперед, пока какой-либо игрок не достигнет финиша., @Yoda
А также...? Вы до сих пор не объяснили свою озабоченность таким образом, чтобы он был осмысленным для тех, кто понятия не имеет, как должна работать ваша игра., @Majenko
@Majenko Я думаю об этом: P1 бросает мяч в лунку A, PCINT для лунки A всех 6 игроков (без каламбура) или в случае, если все 3 типа лунок, то есть A, B и C, связаны вместе на 1 PCINT, их срабатывание предотвращает обнаружение попадания любого другого игрока в лунку A, B или C на его дорожке., @Yoda
Я думаю, вы пропустили тот момент, когда я упомянул «в дополнение к каждому сигналу на свой собственный цифровой вывод» (у меня он даже был выделен курсивом...). Срабатывает одно прерывание. Это прерывание затем смотрит на другие выводы, чтобы увидеть, что активно. Конечно, входящие сигналы должны длиться достаточно долго, чтобы опрос мог их увидеть. Если они очень-очень короткие, вы можете зафиксировать их, возможно, с помощью защелки SR, которая затем сбрасывается MCU после считывания., @Majenko
Я _прочитал_ это, просто вы создали точное настроение «почему ты не видишь, это так просто», которое помешало мне даже написать OP в первую очередь. Я разработчик .NET на своей основной работе, поэтому работа с низкоуровневыми вещами (судя по моему мнению и _не__ в любом случае грубыми) не так доступна, как я надеялся, чтобы помочь моему другу (для которому я пишу/писал код, так как он не говорит по-английски и не умеет писать код). Я просто хочу, чтобы эта плата распознавала входы, но я почти не знаю, что такое (расширение) плата/чип/и т. д. Мне нужно купить и поставить где, получить его библиотеку откуда и скомпилировать., @Yoda
Если вы новичок, то почему вы возитесь с такими сложными понятиями, как прерывания? Сначала получите некоторый опыт с основами. Как я уже говорил, ничто из этого не должно требовать прерываний. Просто не используйте задержку для определения времени. Если вы хотите, чтобы код ничего не делал, позвольте функции цикла работать, ничего не делая. Но вам не нужно никакого прерывания., @Delta_G
Потому что я понимаю концепцию прерываний, поэтому они не являются для меня продвинутой концепцией. Включение/выключение светодиода было таким же простым, как перемещение шаговых двигателей, но есть пробел, за который я виню отсутствие официальных документов, поскольку они скорее придумали новое название «щиты», чем дали полезные примеры. Если оставить это в стороне, я не понимаю, как вы читаете мои слова как «функция цикла ничего не делает между ними». Опять же, пожалуйста, объясните, как я должен получать уведомления об изменении ввода без а) PCINT или б) время от времени опрашивая все такие входы. Может быть, вы можете показать (абстрактный) пример кода?, @Yoda