На разработку этой поделки меня подвигла статья
USB регулятор громкости для ПК и не только.
Но просто «volume + mute» меня не устраивала, хотелось бы иметь функциональные кнопки для управления плеером. Так как ранее с AVR дела не имел от слова совсем — решил заказать одну штучку Digispark85 (с microUSB портом). Пока ехала посылка — курил мануалы, рылся в уголке некроманта и прикидывал дизайн корпуса.
В обзоре не будет распаковки, ТТХ, описания Attiny85 — сразу к делу.
Вводная часть
Контроллер использует постоянное соединение с хост устройством по USB, задействуя два порта (P3/ADC3, Р4/ADC2). Еще два порта задействуются для энкодера (о них ниже), один используется при (пере-)программировании контроллера (Р5/ADC0/Reset). Таким образом, для блока функциональных кнопок остается один порт. Проще всего его подключить по классической схеме с резистивным делителем напряжения, а для распознавания нажатий использовать встроенный в контроллер АЦП. Исходя из ограничений (см выше) остается единственный вариант такого подключения – в порт Р2/ADC1.
Энкодер будем подключать на порты Р0 и Р1 (вместо Р0 и Р2 как в
базовом варианте), а встроенную в энкодер кнопку «mute» вынесем на блок кнопок (сорри за тавтологию).
Принципиальная схема контроллера
Обратите внимание: из схемы исключен светодиод подключенный к порту PB1.
Немного математики
Количество дополнительных кнопок зависит от вашей фантазии, но ограничено объемом программного кода, точностью АЦП и выбранной разрядностью. Для моих нужд достаточно 5 кнопок и 8-битного режима АЦП. В качестве опорного напряжения лучше всего использовать Vcc (при питании от USB это примерно +5в +-допуски), при этом результаты отсчетов АЦП не будут зависеть от колебаний этого напряжения. Для четкого распознавания нажатий я подобрал номиналы резисторов таким образом, чтобы разница между отсчетами АЦП для соседних кнопок была не менее 40.
Для упрощения расчетов сделал таблицу (прилагаю) по которой можно подобрать оптимальные параметры делителя и рассчитать пороги для определения нажатой кнопки. Три правые колонки с серым заголовком содержат реальные измерения и расчеты для АЦП после сборки блока, в программном коде используются именно они.
Скорость преобразования АЦП зависит текущей тактовой частоты микроконтроллера и выбранного делителя, т.н. prescaler'а. Устройство работает на 16.5МГц, поэтому для функционирования АЦП необходимо будет установить максимальное значение prescaler =128. Это обеспечит тактирование с частотой примерно 128КГц, время на одно преобразование составит 1/10000 сек.
Программная часть
Представляет модифицированный код из TrinketVolumeKnobPlus, из которого убрано лишнее и добавлено нужное.
При нажатии и удержании любой кнопки подается только одна команда (блокировка от keystroke repeat), но при желании можно модифицировать код таким образом, чтобы при нажатии
<< /
>> контроллер повторял соответствующие команды.
После компиляции прошивка занимает примерно 60% от отведенных 8КБ flash памяти (часть занимает специальный загрузчик).
Листинг под спойлером
#include "TrinketHidCombo.h"
#define PIN_ENCODER_A 0
#define PIN_ENCODER_B 1 //changeв from P2 port
#define TRINKET_PINx PINB
static uint8_t enc_prev_pos = 0;
static uint8_t enc_flags = 0;
static char sw_was_pressed = 0; //keystroke flag
static uint8_t adc_val = 255; //ADC value
void setup()
{
pinMode(PIN_ENCODER_A, INPUT);
pinMode(PIN_ENCODER_B, INPUT);
digitalWrite(PIN_ENCODER_A, HIGH);
digitalWrite(PIN_ENCODER_B, HIGH);
// init ADC1 at 8bit 16MHz 128 prescaler
ADMUX =
(1 << ADLAR) | // left shift result
(0 << REFS1) | // Sets ref. voltage to VCC, bit 1
(0 << REFS0) | // Sets ref. voltage to VCC, bit 0
(0 << MUX3) | // use ADC1 for input (PB2), MUX bit 3
(0 << MUX2) | // use ADC1 for input (PB2), MUX bit 2
(0 << MUX1) | // use ADC1 for input (PB2), MUX bit 1
(1 << MUX0); // use ADC1 for input (PB2), MUX bit 0
ADCSRA =
(1 << ADEN) | // Enable ADC
(1 << ADPS2) | // set prescaler to 128, bit 2
(1 << ADPS1) | // set prescaler to 128, bit 1
(1 << ADPS0); // set prescaler to 128, bit 0
TrinketHidCombo.begin();
if (digitalRead(PIN_ENCODER_A) == LOW) {
enc_prev_pos |= (1 << 0);
}
if (digitalRead(PIN_ENCODER_B) == LOW) {
enc_prev_pos |= (1 << 1);
}
}
void loop()
{
int8_t enc_action = 0;
uint8_t enc_cur_pos = 0;
if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_A)) {
enc_cur_pos |= (1 << 0);
}
if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_B)) {
enc_cur_pos |= (1 << 1);
}
if (enc_cur_pos != enc_prev_pos) {
if (enc_prev_pos == 0x00) {
if (enc_cur_pos == 0x01) {
enc_flags |= (1 << 0);
}
else if (enc_cur_pos == 0x02) {
enc_flags |= (1 << 1);
}
}
if (enc_cur_pos == 0x03) {
enc_flags |= (1 << 4);
}
else if (enc_cur_pos == 0x00) {
if (enc_prev_pos == 0x02) {
enc_flags |= (1 << 2);
}
else if (enc_prev_pos == 0x01) {
enc_flags |= (1 << 3);
}
if (bit_is_set(enc_flags, 0) && (bit_is_set(enc_flags, 2) || bit_is_set(enc_flags, 4))) {
enc_action = 1;
}
else if (bit_is_set(enc_flags, 2) && (bit_is_set(enc_flags, 0) || bit_is_set(enc_flags, 4))) {
enc_action = 1;
}
else if (bit_is_set(enc_flags, 1) && (bit_is_set(enc_flags, 3) || bit_is_set(enc_flags, 4))) {
enc_action = -1;
}
else if (bit_is_set(enc_flags, 3) && (bit_is_set(enc_flags, 1) || bit_is_set(enc_flags, 4))) {
enc_action = -1;
}
enc_flags = 0; // reset for next time
}
}
enc_prev_pos = enc_cur_pos;
if (enc_action > 0) {
TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP);
}
else if (enc_action < 0) {
TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN);
}
// Buttons decoder block
ADCSRA |= (1 << ADSC); // start ADC measurement
while (ADCSRA & (1 << ADSC)); // waiting for completion
adc_val = ADCH; // read ADC register
if (adc_val < 210) { //some button pressed
if (sw_was_pressed == 0) { // check for hold down button
if (adc_val < 150) {
if (adc_val < 95) {
if (adc_val < 55) {
if (adc_val < 35) { //sw1 is pressed
TrinketHidCombo.pressMultimediaKey(MMKEY_MUTE);
}
else
{ //sw2 is pressed
TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_PREV_TRACK);
}
}
else
{ //sw3 is pressed
TrinketHidCombo.pressMultimediaKey(MMKEY_STOP);
}
}
else
{ //sw4 is pressed
TrinketHidCombo.pressMultimediaKey(MMKEY_PLAYPAUSE);
}
}
else
{ //sw5 is pressed
TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_NEXT_TRACK);
}
delay(5);
sw_was_pressed = 1; // set keystroke flag
}
}
else
{
sw_was_pressed = 0; // clear keystroke flag
}
TrinketHidCombo.poll();
}
Печатная плата и корпус
Печатная плата — это сам Digispark. Подключение к внешним устройствам — через штатный microUSB порт.
Для блока кнопок я использовал платку управления от старого сгоревшего монитора LG, поменяв в соответствии с таблицей SMD резисторы. Саму платку и поддерживающую рамку с толкателями немного укоротил, подклеил для жесткости бортики убрал гнездо для шлейфа. Соединение с Digispark85 — пайкой.
А вот корпус пока существует в предварительном чертеже и дубовом полене :)
И есть инет-радио из старенького телефона, на котором тоже можно задействовать этот девайс.
Решил, что должно установиться в отсек для 2.5 диска.
Акцент в обзоре — на программную реализацию.
Звук как? C 13 Pins или внешняя звуковуха? У меня просто на базе OPiZero плеер с внешней USBшной звуковухой, софт MPD и ympd для управления.
Если аппарат рутован проще всего подправить файл /system/usr/keylayout/Generic.kl, его структура проста: код кнопки — функция.
Либо считать с клавиатуры PID/VID и создать свой файл именно под эту клаву, назвать его Vendor_ХХХХ_Product_YYYY.kl и положить в указанную папку. Тогда при подключении именно этой клавиатуры кнопки будут работать как настроено.
в стандарте хид дескрипторов есть даже такие для управления медиаустройствами
я сейчас посмотрел малость эту библиотеку, но дескрипторы не смотрел, может там обычные функции мультимедиа кнопок, просто валкодер автор тут привязал к нажатию кнопок громкости
у меня была клавиатура и там был валкодер для громкости
гораздо интересней сделать кастомный хид для своего устройства и написать софт, но драйвер будет использоваться системный
я сейчас этим занимаюсь
Вообще, лучше забей на кубохал хоть на первом этапе, в докубовых либах как то проще разобраться.
если куб сделали, значит не просто так же
мне он нравится, особенно карта тактирования, да и включение периферии
а ковырять эти огромные простыни нет никакого желания
программирование должно быть легким, а оно с каждым днем все сложнее и сложнее
Статья про софтовое развитие проекта.
Кста по идее на кнопку энкодера можно повесить еще 3 действия. 1 — долгий тап (плей-пауза), 2 — крутить влево с нажатым энкодером (мотать назад, если крутнули один раз и отпустили, то трек назад), 3 — крутить вправо с нажатым энкодером (мотать вперед, если крутнули один раз и отпустили, то трек вперед).
И не надо кнопок городить )
Напишу ка я статью ))) (шЮтка)
Реализуй и напиши :)
1) у кнопки состояния — нажали, отпустили. Считаем время между нажали и отпустили и если оно больше заданного, то плейпауза, иначе муть.
Сразу видно что как программист вы нуб.
Еще раз повторю — это мой первый проект.
А про код — на словах ты Лев Толстой, а конкретный пример?
К длительному нажатию надо просто завести 2 переменных (long integer) и первой присваивать при нажатии текущий тик, второй при отпускании. И надо переписать немного код (просто передвинуть выполнение мути из «кнопка сейчас нажата» в «кнопка сейчас отпущена»).
Инет очень плох и через RDP с шифрованием через VPN… короче строгать код одно мучение. курсор не успевает за ходом мысли. А дома по определению сейчас ни чего не держу.
Антидребезг будем добавлять, или так сойдёт?
Да, чуть не забыл — в стандартной HID клавиатуре нет перемотки там только переключение треков в плейлисте вперёд и назад. И как поведет себя энкодер в режиме переключения треков когда ламели будут на границах секторов — хз.
2. Грубо говоря именно что пара строк, что пара десятков. В программировании не сложно написать эти строки. Главное понять что написать и как. Это называется алгоритм. И он самое сложное. А строки… 2 или 10… это уже особенности языка.
Хочешь пример? А чего спрашиваю )))
if(A>B)
{A=1;}
else
{A=2;}
Огромный текст? Смотри как можно:
(A>B?A=1:A=2)
И уже одна строка )
3. Но мы же можем передавать не одну кнопку, а комбинацию. Це хоткеи )
И как нет?
pccar.ru/showthread.php?t=27389
Там у чувака
Мультимедийные кнопки — PLAYPAUSE, STOP, NEXT, PREVIOUS, FASTFORWARD, REWIND (мультимедиа HID)
Так что все есть. Просто тут не до конца реализовано. Выдрать коды и вставить их.
circuitpython.readthedocs.io/projects/hid/en/latest/api.html
circuitpython.readthedocs.io/projects/hid/en/latest/api.html#adafruit_hid.consumer_control_code.ConsumerControlCode.FAST_FORWARD
Так что ни каких проблем. Читайте маны. Я же говорю, в программировании ты слишком слаб. К примеру вот была задача… 6 дней сидел корпел, ни как не мог осилить, а потом в пятницу подбухнул и за 3 полторашки пива и 2 часа наваял почти 1000 строк. Клиентсерверное приложение, мне надо было описать поведение клиентской части.
4. А что ему будет? Лично у себя проверял, все нормально. Громкость регулируется все так же нормально без сбоев.
2. Комбинаторика.
3. Ресурсы посмотрю.
Если честно мне плевать что ты думаешь о моем уровне программирования. Главное что у меня есть желание изучать и пробовать, и учиться (даже в моем возрасте).
И печально что люди завышенным ЧСВ на непрофессиональном форуме начинают гнобить новичков.
Разбираешься — укажи на ошибки, знаешь как сделать лучше — напиши.
Это только плюс.
Все просто. Ты сам еще не в зуб ногой, а уже учишь остальных. Хотя сам и половина кода не понимаешь. И о каком завышенном ЧСВ? Я больше чем уверен что ты в чем-то другом реально сильнее волокешь чем я. Я это прекрасно понимаю.
И я не гнобил тебя еще раз. Я искренне рад что тебе понравилась ардуинотыканье. Пусть оно заводит сильно не в ту сторону юные умы юных программистов, но это уже ого-го.
Именно в этом и есть практика (хотя многие программеры сейчас полезут с вилами, но все же рискну), когда ты вместо того чтобы что-то выдумывать самому — берешь готовый код. Это мир ООП (объектно ориентированное программирование). Там сам язык построен на этом.
Конкретно в твоем случае я и не смотрел код, ибо… там и не должно быть ошибок, это же пример из библиотеки )
Если будут вопросы, пиши, поможем чем сможем )
А я вот тут вообще самокат изобрел… Гордился… Пока меня математики не опустили… По самое не могу… О как…
правда она на прерываниях и не понятно как AVR USB драйвер к этому отнесется
Каждый раз при старте уволить в ноль вообще не вариант.
На ноутах у меня штатная софтина реализует OSD.
Софтина ключевое слово.
Тут же не надо писать драйвер. Объясняю. в win 8 уже нельзя не включив режим тестирования запустить драйвер не подписанный. Подписать драйвер у майкрософта стоит просто страшных денег. От сюда и подобный костыль. Клиент серверное приложение тоже не есть хорошо. От этого уходят.
Зачем это?
HID устройство командами изменения громкости меняет ее уровень (в 7ке и убунте в системном микшере бегает ползунок).
LMS (крутится на armbian) как-то сам видит изменения громкости и перемещает слайдер (он выводится справа на панели управления плеером).
Там тоже устройство HID, но кроме изменения, оно еще и наглядно показывает уровень громкости.
Вот видишь. Ты не знаешь как, а все туда же. Видит он клиентской (или серверной, хз как там верно будет) частью которая ставится на твою бубнту или семерку.
Еще раз — HID устройство, а дигиспарк в данном примере им и становится обратно уровень громкости не получает!
Ну есть он у кого-то, отлично. А мне не надо.
Контроллеры (аппаратный HID, программный из аппы и тд) меняют уровень master volume в системном микшере сервера, все изменения отображаются на дисплее реальном времени. Точно так же отображается текущая позиция в треке. И мне (и 99.999% людей) пофиг какая технология при этом используется.
Я и заметил. Либо хнык, либо пофиг…
Тут с обработкой бывают фантомы (до бесконечности ждать «успокоения» кнопки нельзя, поэтому при неудачном варианте ни один обработчик не спасёт), а без — это очень, очень плохая идея
Во вторых — читаем даташит: ADC считывает напряжение на входе в течение первых двух тактов ADC_clock после команды на чтение, в данном случае это 0,00000775 сек. После чего все происходящее на входе игнорируется и ещё 11 тактов идёт собственно конвертация а далее — декодирование. Это временные задержки образуют ещё один 'антидребезговый фильтр'.
тут кнопки аналоговые и у них такая штука как дребезг отсутствует
а вот уход сопротивления это как раз есть, поэтому там резисторы сотни ом надо ставить, да и неплохо бы в коде диапазон значений ацп под каждую кнопку сделать
тогда уход можно избежать
И при увеличении количества кнопок точность упадёт и объем кода ещё увеличится.
Дребезг может быть на любых сухих контактах, неважно в каком они виде выполнены.
Например кнопка срабатывающая на звук, или вот — на свет, или на радиосигнал…
И, вот же ещё они —
ЗЫ: кроме того, устройства, срабатывающие на все вышеперечисленное — как раз аналоговые :)
Смотрите фото выше.
Они — ЦИФРОВЫЕ!
И вообще — фиг его знает, что там за рамкой: микрик, КД, геркон, оптопара — или вообще изврат из штока с зубчатой передачей на «оптопарный энкодер» :-)
скорость ацп может быть меньше времени фиксации + конденсатор по питанию
поэтому на аналоговых кнопках дребезг не надо обрабатывать
я по крайней мере не видел ничего такого по этой теме
mySKU.me/blog/aliexpress/68887.html#comment2927498
Если АЦП защелкнет вход в начале переходного процесса, особенно при нажатии 'дальней' кнопки, там где суммарное сопротивление уже велико, то измеренное напряжение будет больше установившегося.
И все они подключены по 1-2х проводной схеме с АЦП. И mcu обрабатывает все это без всяких там фильтров усреднения и тп. Потому что все и так работает.
Даже если кому-то вздумается нажать одновременно 1-2-5 кнопок — mcu отработает по меньшему сопротивлению и ничего ужасного не случится.
За это я и слова не сказал. Это вроде бы как закон физики, он незыблем.
Практика показала что даже триггерного обработчика с подциклом while не всегда хватает, а delay 5 лучше как минимум удвоить.
Сами кнопки как я написал — от старой 15«ки которой черт знает сколько лет. Окислы наверняка есть (не вскрывал).
дребезг кнопки это не только нестабильный контакт на протяжении несколькольких микросекунд в момент включения, это еще и окисленные контактв (мембранна кнопки), которая провоцирует нестабильный контакт в течении значимого интервала времени, в особо «удачных» случаях во время длительности всего нажатия.
В таком случае ты поймайшь «нажатие» кнопки в своей программе раз 100 в секунду (5 милисекунд делай компенсирует + столько же отведем время на цикл скетча, с большим запасом) ибо осциллограмма нажатой кнопки будет весьма красивым «ёжиком», и почти в каждом цикле программа увидит «очередное» нажатие
Самое забавное что никто не возбудился насчёт дребезга на гитхабе или готовом изделии у Vitgo.
Наверняка десятки тысяч людей уже повторяли этот проект, а там дребезг, ой-ой!
А если серьёзно — схема допускает изменения кода в любой момент, можно вставить фильтр, изменить функции кнопок и тд и тп.
Все ахали и охали над корпусом, а мне за код и дребезг — ведро наплевали :))))
Если работает- пусть работает, в зоопарке зайцу не нужны быстрые ноги.
вся суть современного кодинга и вообще подхода в целом
И всё-таки я выбираю иной путь.
Дискуссию, правда, не вижу смысла продолжать. Мой подход явно в меньшинстве.
Лично я вижу только одну причину переделать опрос кнопок- оупенсорсность проекта, это может оказаться полезным если этот проект попадется на глаза потенциального работодателя с высокими требованиями к коду.
Могу на пальцах.
Играетесь вы в думчик, ночью, тихо… но вот пару процентов бы добавить к громкости. Улац на кнопку, а оно вместо 1 срабатывания — пачку из 50 «словило» за пол секунды. В итоге и вы, и ваши соседи рискуют поймать коричневую ноту часа в 3 ночи.
Это только первый пришедший на ум пример.
Прежде всего необходимо оценить время, которое потребуется на написание и отладку правильного алгоритма, и сравнить это со временем, которое теоретически может понадобиться на чистку или замену кнопок, которые так окислятся, что для игнорирования ложного срабатывания уже недостаточно будет простой задержки, которая уже реализована и отлажена.
И в итоге выйдет что на дребезг он угрохает дня три, а заменить окисленные кнопки работы на пол часа, раз в пол года. Вот и считай через сколько десятилетий его труд перестанет быть напрасным, при условии что он не откажется от эксплуатации этого устройства.
По времени на код — тем более бред.
Школьник-ардуинщик напишет это быстрее, чем вы писали свой камент.
Опытный программер напишет это в 1 строчку, еще быстрее школьника и в 10 раз красивее.
Во-вторых автор черным по белому написал
и на нормальный алгоритм селективной обработки нажатия кнопок через АЦП он потратит много времени, по этому не мешай ему работать, его цель как можно быстрее сделать рабочее устройство, увидеть результат своего труда.
Окисел в этих кнопках бывает только после попадания в них жидкостей либо паров, а это уже нарушение условий эксплуатации.
только я этих мембранных кнопок десятками меняю в тачпадах ноутов.
кроме того периодически приходится менять в своих приборах — блоках питания, паяльнйо станции итп, по разу на круг уж точно поменял. А юзаю — ежедневно по нескольку раз. Кстати чаще дохнут те, которые чаще юзаешь.
От рук уже рассыпалось резиновое покрытие вокруг тачпада, кнопку еще не менял, даже намека на проблемы нет.
Что я делаю не так? Может я не заливаю тачпад кофем?
На старых кнопках аж темное все от патины.
Хотя, главное — чтобы с твоими кнопками в реале всё работало четко и стабильно. Все остальное — побоку. Ты ведь делаешь разработку для себя и под себя, а не универсальное легко повторяемое устройство для любого типа кнопок…
Фильтр 'среднего окна' был в одном из вариантов скетча, оказалось он не нужен.
Естественно! Если бы проект был коммерческим — я бы развел печатку, собрал все из рассыпухи, нарисовал лейбл на корпусе и… фиг бы сюда все это выложил. Логично?
Как правило здесь на муське хорошо пилят, строгают, сверлят и печатают.
Мало кто кодит и понятно объясняет что как и почему он делает.
У меня к сожалению нет 3D принтера и фрезера с ЧПУ, я не могу за день изготовить чистовое устройство.
И моделить не пришлось, кто-то уже за меня все придумал. А уж для своих девайсов… Я помню как раньше пользовался корпуса от CD приводов… задняя стенка боль… передняя немного проще, но все же… склеил, вырезал отверстия нужные, потом заливаешь цианакрилатом и засыпаешь содой, потом шрукинг, грунтинг и красинг. А сейчас 5-10-15 минут в каде, и в печать. через час ни чего не деланья очень красивая морда, собирай и пользуйся.
Но никакой пластик не заменит хорошего дерева.
Зы я не настоящий
сварщиксамодельщик.Эта пробка, лучше...:)
Да и зачем мне это? 500 рублей килограмм пластика. Печать для меня давно бесплатная )
Надо немного вникнуть в 3д печать и все станет на свои места.
В девичестве это был тарантул. НО за 2 года он претерпел кардинальные изменения. В скором времени уйдет в разбор скорее всего.
Аня вполне может после небольших доработак так печатать. Да даже не 60мм/с, но на 40мм/с сможет легко.
Для меня.
Заказал себе еще такую шайбу
aliexpress.com/item/PC-USB-Wire-Controller-USB-Volume-Control-Knobs-Audio-Controller-for-Adjusting-Volume-of-Computer-Laptop/32649442146.html
Декоративный диск будет сантиметров 4-5 в диаметре, при наклоне большой риск сломать шток. А выводить упоры под диск это гимор.
Человек описал как сделать с его точки зрения интересную штуку, пусть даже и не до конца оконченную.
Но имеющий руки и желание, если понравится — сделает подобное, а не имеющий — ничего не сделает, даже если бы фотка готового устройства была или что-то еще.
Налетели «экс-перты», все раскритиковали и об#ли, и улетели :)
Особенно двое отличились — одному энтерпрайс надежность подавай, а второму микшерский пульт :D
Это устройство для дома, человек делал его для себя — и самое главное — сделал.
Оно не надежное как танк, но зато быстро и четко исполняет функции, автору нужные.
Вы чего все такие нетерпимые, а?
Чувствую, вряд-ли автор еще сюда писать будет, умники.
Лучше обзоры трусов почитать, ага? :D
Автору зачет. Плюй на всех этих придурков — они дальше болтовни ничего не сделают :)
Можно быть тысячу раз правым и про схемотехнику и про дизайн — но если до дела не дошло — грош цена всему этому.
А ты сделал с нуля — ты уже во сто крат круче них.
Есть такая китайская мудрость:
-На стволе поваленного дерева сидело три лягушки, одна из них решила спрыгнуть — сколько лягушек осталось на стволе?
-Три, потому-что решить спрыгнуть и спрыгнуть — две большие разницы…
P.S.
Дребезг кнопок на АЦП лечится тем, что указывается диапазон возможных значений для каждой кнопки + несколькими чтениями с задержкой. Вообще АЦП не очень для кнопок, т.к. если нажать их несколько то… будет работать не так как хочется :) Но здесь, действительно, особого выхода нет — разве что i2c экстендер ставить — но это +1 корпус, да и особо не нужно, если кнопки разом не давить.
Код для новичка вполне — не обращай внимание на эспертофф — вообще если стабильно работает — ну и нехай.
Апартно дребезг можно устранить RC цепочкой — если очень охота — про это куча информации в инете, но здесь абсолютно не нужно — програмного выше крыши.
Я бы еще сделал чтобы при длительном нажатии на энкодер громкость ставилась 50% — это очень удобно, делается очень просто.
Шутки шутками, но у вас все печально. Советую ознакомится с этим — www.allaboutcircuits.com/technical-articles/switch-bounce-how-to-deal-with-it/
И этим — protological.com/debounce-calaculator/
И да, threshold на АЦП реально решает задачу дебаунса — но это не идеально, однако тут никто за исо9001 не гонится.
В статье тоже весьма не ах написано, кстати — крайне не советую этим пользоваться, в том числе — кодом оттуда, ибо это полный ппц а не код.
Кол-во шагов громкости фиксированно в винде.
Делается «меньше» * количество шагов, потом «больше» " количество шагов / 2
А таких умников-экспердоф в офисе половина этажа, и как везде главное им уцепиться за мелкий вопрос где есть знакомое слово — и начинается пустой срач…
Самое смешное — код не мой, моего там только расчёт делителей, порогов, ну и паяльник с напильником.
Громкость на 50% не требуется: контроллер может переключаться между несколькими устройствами: где-то внешний усилитель, где-то наушники могут подключаться, средний уровень не одинаков.
В законченном устройстве — да удобно.
Красота кода, правильность выбора алгоритмов- все это живет только в связке с классом устройства, его назначением, условиям его эксплуатации.
Требуют стрелять из пушки по воробьям — стреляй, но только если тот, кто это требует, хорошо за это платит.
Ну и, напоследок, анекдотец
Это устройство — не ядерная кнопка, не промышленный автомат, и даже диджеить им не будут — для всего этого есть свои инструменты.
Вцепились в дребезг, а вопрос с одновременным нажатием кнопок — побоку, давайте ещё там защиту напишем :)))
Корпус сделал и розетки
Только возникла одна проблемка… на некоторых компах не обознается устройство при загрузке пока не переподключишь или не сбросишm через Reset, затем и кнопочка сбоку.
Хотелось бы реализовать индикацию включения микрофона, но как задействовать пин P5 не знаю. Подскажите если кто в курсе.
Щас не помню как это там решаюсь, но можно без кнопочки — программно отключить нужное USB и снова включить.
Попробуйте поиграться в коде в части Play/Pause. возможно лучше будет поменять на «Пробел». Конкретно в моей реализации применительно к браузеру Хром в винде, при наличии нескольких вкладок с youtube или другими плеерами эмуляция нажатия Play/Pause применяется сразу ко всем вкладкам.
Или может подскажете как лучше сделать, в машину установил планшет SAmsung G Tab 3 8.0, все замечательно, лучше магнитолы и управлялки к КарПК не сыскать, но хочется камеру заднего вида. Думаю WiFI камеру установить, и чтоб при включении ЗХ активировалось приложение которое будет выводить картинку с камеры.
Если говорить об Android, то далее происходит распознавание принятого кода согласно содержимому файла /system/usr/keylayout/Generic.kl
В этом файле каждому коду кнопки сопоставляется своя команда: mute, play, brightness, home и так далее. Но там нет вызова приложений, кроме Camera, Calendar, Call и ещё нескольких.
Как я понимаю — ты хочешь отловить сигнал ЗХ с коробки передач и вызвать приложение которое покажет картинку задней камеры.
С камеры WiFi картинку как смотреть — в браузере?
Думаю это можно сделать с помощью tasker. Вроде бы оно может по шорткартам вызывать приложения, но с браузерным просмотром хз получится ли…
Но надо подумать как закрывать это приложение при переключении с ЗХ на нейтраль или передние передачи.
Насколько я помню можно делать шорткат на конкретную закладку, так что должно выйти
притом недавно она стоила 64 рублика по акции
аттини слишком кастрирована по пинам
Вешать каждую кнопку на отдельный пин? Так они одновременно все равно не нажимаются.
я про вообще и на будущее
в данный момент разница между ними 2 рубля но разница в возможностях колосальная
досих пор валяются даже не распакованные ибо применить их это надо что бы подвернулся какойнить проект маломальский это мне в одно время требовалось сделать ложную световую автосигнализацию
еслиб они стоили рублей 30 если не меньше согласно возможности на их для переферии я бы и слова не сказал