Наилучший метод проектирования схемы с 20 кнопками

Я буду управлять роботом с более чем 10 двигателями, а это значит, что мне понадобится по 2 кнопки для управления движением вперед и назад. Мой контроллер - Arduino mega. Является ли 1 контакт = 1 кнопке лучшим решением здесь? Или следует использовать для этого другую микросхему?

, 👍7

Обсуждение

"лучшее решение" зависит от ваших предпочтений. Поскольку Arduino Mega имеет достаточное количество выводов ввода-вывода, вы можете использовать их без дополнительного оборудования. Если вы не хотите полагаться на используемую плату (например, в будущем переключитесь на другой/более быстрый MCU), вы можете использовать мультиплексоры ввода-вывода, такие как MCP23017, что дает вам 16 дополнительных вводов/ОС через I2C, и вы можете использовать до 8 из них на одной линии I2C. На самом деле мы используем четыре из них для 61 сенсорного переключателя. Существуют также прорывные платы с этими чипами., @ridgy


5 ответов


2

вы можете использовать так называемый регистр сдвига. Одним из очень распространенных является регистр сдвига 74HC165 (https://playground.arduino.cc/Code/ShiftRegSN74HC165N/).

С помощью одной из таких микросхем вы можете подключить 8 кнопок, однако вы можете подключить максимум 4, чтобы получить 4 * 8 = 32 кнопочных входа, используя только 4 цифровых вывода Arduino. В вашем случае вам понадобятся 3 микросхемы, чтобы получить 24 (таким образом, 20) кнопочных входа.

,

Регистр сдвига не является мультиплексором. Регистр сдвига смещает все входы, а мультиплексор выбирает один из N входов для прохождения., @Majenko

@Majenko да, вы правы, я это исправил (спасибо), @Michel Keijzers

Вот в чем проблема у меня с мультиплексором. Мне нужно, чтобы он мог функционировать независимо без необходимости быть "выбранным"., @Julius Noel Banayo

С помощью этой микросхемы вам не нужно" выбирать", или, по крайней мере, вы получаете все входные данные., @Michel Keijzers

@Julius С помощью мультиплексора вы программируете Arduino так, чтобы он выбирал каждую кнопку, а затем по очереди проверял, нажата ли она. Поскольку Arduino намного быстрее человеческого пальца, он по-прежнему видит все нажатия кнопок., @user253751


15

Для 20 кнопок вы можете использовать матрицу клавиатуры (множество примеров в Интернете), в которой вы использовали бы только 9 контактов (5 столбцов по 4 строки-это 5+4 контакта). Это немного сложнее, чем простые кнопки 1:1 для контактов, но, к счастью, есть библиотека Keypad.h, которая избавляет вас от тяжелой работы.

Если вы хотите иметь возможность нажимать несколько кнопок одновременно, вам необходимо включить диоды в матрицу, чтобы предотвратить "появление призраков".

У Ника Гэммона есть отличная статья об этом здесь.

,

Голосовали за. Хорошая альтернатива ... могу ли я предположить, что ваши преимущества заключаются в меньшем количестве микросхем, одновременном вводе, а мои-в меньшем количестве входных контактов?, @Michel Keijzers

Да. 3/4 в отличие от 9., @Majenko

Да, на самом деле это одно из моих решений, которое я имею в виду. Может быть, применить множественную матрицу нет?, @Julius Noel Banayo

Чем больше кнопок у вас в матрице, тем эффективнее она работает с выводами., @Majenko


4

Приведенный ниже пример проекта может управлять 16 переключателями. Если у вас есть мембранная клавиатура размером 5 x 4 или 5 x 5, вы можете выполнить свои требования.

Вскоре я добавлю пример использования регистров сдвига для нескольких входов (основной вариант использования регистров сдвига одинаков).

Ссылка


Ниже приведен пример использования регистров сдвига. Вам нужны три регистра сдвига, как упоминал @Michael в своем ответе. Вот один пример, в котором вы можете управлять максимум 32 переключателями. Вы используете только 3 вывода данных и два вывода питания. Это основное применение регистра сдвига. Вам не нужно делать никакого выбора, всякий раз, когда вы читаете данные последовательного ввода, вы автоматически получаете статус всех 32 переключателей за один раз.

Вот код

// File : Cascade165.ino
//
// Version 1, 5 August 2021, by Koepel
//     Initial version.
// Version 2, 5 August 2021, by Koepel
//     Layout of the wiring made better.
// Version 3, 13 August 2021, by Koepel
//     Changed 'SCK' to 'clockPin'.
//
// Cascade of four 74HC165 shift-in registers.
// Only three pins are used on the Arduino board, to read 32 switches.
//
// Using the 74HC165 is safe, because a pulse to the Latch pin 
// ('PL' on the 74HC165) will make a new start every time. 
// In case of an error or a wrong clock pulse by noise, 
// it synchronizes the data when inputs are read the next time.
//
// Based on:
//   (1)
//     Demo sketch to read from a 74HC165 input shift register
//     by Nick Gammon, https://www.gammon.com.au/forum/?id=11979
//   (2)
//     74HC165 Shift register input example
//     by Uri Shaked, https://wokwi.com/arduino/projects/306031380875182657
//
//

const byte latchPin = 9;        // to latch the inputs into the registers
const byte clockPin = 13;       // I choose the SCK pin
const byte dataPin = 12;        // I choose the MISO pin
uint32_t oldOptionSwitch = 0;   // previous state of all the inputs

const int pulseWidth = 10;      // pulse width in microseconds

void setup ()
{
  Serial.begin( 115200);
  Serial.println( "Turn on and off the switches");
  Serial.println( "Top row is switch 0 (right) to switch 7 (left)");
  Serial.println( "Second row is 8 to 15, and so on");

  pinMode( clockPin, OUTPUT);   // clock signal, idle LOW
  pinMode( latchPin, OUTPUT);   // latch (copy input into registers), idle HIGH
  digitalWrite( latchPin, HIGH);
}

void loop ()
{
  // Give a pulse to the parallel load latch of all 74HC165
  digitalWrite( latchPin, LOW);    
  delayMicroseconds( pulseWidth);
  digitalWrite( latchPin, HIGH);

  // Reading one 74HC165 at a time and combining them into a 32 bit variable
  // The last 74HC165 is at the bottom, but the switches start numbering
  // at the top. So the first byte has to be shifted into the highest place.
  uint32_t optionSwitch = 0;
  for( int i=24; i>=0; i-=8)
  {
    optionSwitch |= ((uint32_t) ReadOne165()) << i;
  }

  for( int i = 0; i<32; i++)
  {
    if( bitRead( optionSwitch, i) != bitRead( oldOptionSwitch,i))
    {
      Serial.print( "Switch ");
      if( i < 10)
        Serial.print( " ");
      Serial.print( i);
      Serial.print( " is now ");
      Serial.println( bitRead( optionSwitch, i) == 0 ? "down ↓" : "up   ↑");
    }
  }
  
  oldOptionSwitch = optionSwitch;
  delay( 25);      // slow down the sketch to avoid switch bounce
}

// The ReadOne165() function reads only 8 bits,
// because of the similar functions shiftIn() and SPI.transfer() 
// which both use 8 bits.
//
// The shiftIn() can not be used here, because the clock is set idle low
// and the shiftIn() makes the clock high to read a bit.
// The 74HC165 require to read the bit first and then give a clock pulse.
//
byte ReadOne165()
{
  byte ret = 0x00;

  // The first one that is read is the highest bit (input D7 of the 74HC165).
  for( int i=7; i>=0; i--)
  {
    if( digitalRead( dataPin) == HIGH)
      bitSet( ret, i);

    digitalWrite( clockPin, HIGH);
    delayMicroseconds( pulseWidth);
    digitalWrite( clockPin, LOW);
  }

  return( ret);
}

Ссылка на проект регистра сдвига: https://wokwi.com/arduino/projects/306024460940476993

,

существует так много версий этого сдвигового регистра. https://www.digikey.com/en/products/base-product/texas-instruments/296/74HC165/16 как вы решаете, какой из них использовать?, @aquagremlin


0

Кнопки Max для минимальных контактов (через электротехнику и ожидание занятости в перерыве)

Подключите каждую кнопку к прерыванию и аналоговому контакту. Вы можете использовать одни и те же прерывания и аналоговые контакты для всех кнопок, если используете резисторы для различения между кнопками.

Используйте вывод прерывания, чтобы получать уведомления при нажатии кнопки. Используйте резисторы, чтобы иметь различное целевое напряжение для каждой кнопки в делителе напряжения. Затем в обработчике прерываний используйте аналоговый вывод для измерения напряжения.
Основная проблема заключается в том, что для стабилизации напряжения потребуется некоторое время после того, как прерывание уже сработало. Я бы проверил по крайней мере 3 последовательных одинаковых показания (задержка~30 мс после стабилизации напряжения).

Убедитесь, что у вас есть некоторый допуск, например, сдвинув по крайней мере два наименее значимых бита (значение = analogRead(PIN) >>> TOLERANCE_BIT_COUNT;). С 10-битным разрешением аналоговых выводов (1024 значения, AFAIR), 2 битами, потерянными для допуска, и дополнительным битом, потерянным для разницы между HI и LO (необходимым для запуска прерывания), осталось не менее 7 бит, которых может хватить для 127 кнопок.

Да, вы можете подключить клавиатуру с 2 контактами, если вы реализуете часть логики в аппаратном обеспечении (127 тщательно разработанных делителей напряжения) и часть в программном обеспечении (обнаружение стабилизированного напряжения). Однако идентификация того, какая кнопка нажата, может быть восприимчива к отклонениям напряжения всего в 4,8 мВ (разница в 1 в значении аналогового напряжения, которая может превышать допустимые значения). Также вы не можете обнаружить одновременное нажатие нескольких кнопок. Однако, если электрическая конструкция была тщательно спроектирована, для нажатия нескольких кнопок может не потребоваться обнаружение сбоя, поскольку прерывание не сработает, в зависимости от того, как будут складываться целевые напряжения.

Проблемы электротехники, которые необходимо решить:

  • Проектирование делителей напряжения остается на усмотрение читателя, потому что вы можете увеличить допуск, если вам нужно меньше кнопок. Это может снизить восприимчивость к небольшим отклонениям напряжения. Мое предложение состояло бы в том, чтобы получить X идентичных резисторов R Ом для X кнопок. Подключите резисторы последовательно и распределите напряжение между резисторами с помощью кнопок. Подключите все вилки после соответствующей кнопки к аналоговому контакту и другому резистору (X раз R Ом) либо к заземлению, либо к Vcc (в зависимости от выбора прерывания HI или LO). При необходимости добавьте подтягивающий/опускающий резистор к концу последовательно расположенных резисторов.
  • Возможно, вам потребуется убедиться, что вы не потеряете слишком много битов слишком рано, потому что в противном случае могут быть последовательные "одинаковые" значения без стабилизации напряжения.
  • Проверьте, должно ли прерывание срабатывать для HI->LO или LO->>HI, так как одно может предлагать более четкие целевые напряжения, чем другое. Я просто предположил, что первый analogRead вернет значение около 512 в любом случае.
  • Я помню, что вы можете переназначить значения analogRead, чтобы восстановить 1 бит, потерянный для HI-LO против Переход ЛО-ХАЙ. Это не рекомендуется, так как это может повлиять на поведение других аналоговых контактов. Однако в крайнем случае это может либо удвоить количество возможных кнопок, либо добавить еще один бит для допуска.
  • Небольшой конденсатор может помочь отфильтровать действие переключения кнопок, чтобы вы не получали несколько прерываний при одном нажатии кнопки. Однако это может увеличить время, необходимое для стабилизации делителя напряжения на целевом напряжении. Так что выбирайте самый маленький конденсатор и резисторы, которые вам сойдут с рук.
,

0

Другой подход

Используйте приложение для создания виртуальных элементов управления на экране вместо использования физических кнопок и отправки событий нажатия по Bluetooth, Wi-Fi или ESPNOW.

Преимущества

  • никаких запчастей не требуется, если у вас уже есть телефон/ноутбук
  • никакой пайки
  • никаких отслаивающихся деталей, изнашивающихся
  • полный контроль над расположением кнопок
  • простота обновления/изменения схемы управления на основе опыта работы в полевых условиях
  • одной деталью меньше, которую нужно нести
  • тривиально иметь дополнительные резервные пульты дистанционного управления
  • открывает двери для макросов (например, автоматической посадки), процедур тестирования и т.д
  • позволяет регистрировать данные робота для отладки
  • ЛЕГКО добавляйте классное оборудование для управления, такое как геймпады, голос или камера
  • гораздо проще кодировать кнопки, например, в HTML+JS, чем в C++
  • отделяет проблемы программирования и позволяет отделить эволюцию
  • позволяет использовать интернет/дистанционное управление
  • может быть разработан на ноутбуке, перенесен в портативный RaspPi или телефон
  • может управлять более чем одним (или новым) роботом с пульта дистанционного управления

Недовольство

  • нужен код на двух языках
  • дополнительная деталь (например, ESP8266), хотя кнопки тоже стоят дорого
  • немного увеличенная задержка (но кнопки все равно должны быть отменены)
  • возможно, это не так приятно, как 80+ часовой ручной контроллер
  • требует немного соображений безопасности (возможно)

В целом, я думаю, что преимущества НАМНОГО перевешивают недостатки. Если вам нужна практика пайки и опыт проектирования аппаратного обеспечения с участием человека, физический пульт дистанционного управления-достойный проект, но вы всегда можете сделать это позже, как только заставите робота работать с абстрактными командами; вам не нужно создавать и отлаживать оба одновременно, что для меня очень важно...

Если вам НУЖЕН физический пульт дистанционного управления

Вы все еще можете получить многие из вышеперечисленных преимуществ на физическом пульте дистанционного управления, если вы поместите MCU/SBC в пульт дистанционного управления. Затем поговорите с роботом с помощью uart/wifi/bt/и т.д. Uart позволяет подключать к пульту всего 4 провода вместо десятков. Существует множество существующих 4+проводных разъемов (USB-B, RJ-45, XLR, DIN и т.д.), Которые вы можете использовать для этого; тонкие, легкие, дешевые, сменные. Такая конфигурация позволяет выполнять последовательную отладку, ведение журнала и т.д. Это освобождает процессор робота от необходимости иметь дело с прерываниями и библиотечными следами.

В целом, это ускорит создание при небольшой стоимости дешевого микроконтроллера, такого как nano/bluepill/esp32...

,