Грабли замечательной схемы R2R

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Это продолжение материала о замечательной схеме R2R и посвящено оно граблям, которые разбросаны на пути реализации этой идеи на практике.

Как было описано в первой части, я собрал R2R модуль на богомерзких кнопочных переключателях PS-22F11. Написал программу, которая просто выводила в сериал комбинацию нажатых кнопок, при любом изменении в этой самой комбинации и … вдруг заметил интересный глюк. В процессе нажатия кнопки в сериал иногда вылетала совершенно левая комбинация, а затем, приходила и правильная, соответствующая только что нажатой кнопке.

Эффект был нестабильный, но достаточно частый. Стал смотреть, в чём дело. Причина оказалось простой до банальности! Дело в том, что все наши расчёты исходили из того, что кнопка может быть только в одном из двух положений: либо замкнута на питание (включена), либо замкнута на землю (выключена). Но ведь реальная кнопка (в отличие от математической) имеет ещё и третье состояние – не замкнута никуда! На чёртовых PS-22F11 этого состояния официально нет, но если нажимать кнопку медленно, то оно легко ловится! Движок успевает отсоединиться от одного контакта, но ещё не успевает добраться до другого – кнопка повисла в воздухе!

А теперь посмотрим на схему и посчитаем, какое напряжение должно быть при таком «промежуточном» положении кнопки! Это, зависит от того, какая кнопка у нас залипла «ни туда, и ни сюда»! Некоторые кнопки дают совсем неправильные напряжения (которые невозможны при правильно замкнутых кнопках), которые легко отфильтровать, но бывает и так, что отфильтровать ошибку невозможно.

Давайте на примере. Допустим, изначально кнопки у нас замкнуты, как показано на схеме (т.е. вторая слева – на питание, а остальные – на землю). Код комбинации – 4 (дв. 0100).

Теперь начинаем включать самую левую кнопку, и делаем это неторопливо. Ожидаем получить код 12 (дв. 1100), это в итоге и получаем, но по ходу процесса ненадолго наша кнопка теряет контакт и оказывается не замкнутой никуда! Это всё равно, как если бы мы перерезали провод в том месте, где на схеме нарисованы красные ножницы. И что мы при этом имеем? Правильно, наша включённая кнопка (вторая слева) на время разрыва контакта становится самой левой и вместо родных 1/4 напряжения питания начинает выдавать половину (код 8). А это ведь соответствует тому, что якобы нажата самая левая кнопка, которую мы «отрезали»! И никак это не отфильтруешь, код то допустимый!

Вот и получается, что вместо того, чтобы переключиться с кода 4 на код 12, из-за того, что наши кнопки имеют «промежуточное положение» мы между кодами 4 и 12 наблюдаем появление совершенно левого кода 8!

Ну, вот собственно … нормальные такие грабли … получите, распишитесь.

И что делать?

Ну, вариантов, как всегда, 100500.

Лучше всего, наверное, проектировать систему так, чтобы этот эффект ей попросту не мешал. Например, если на этих кнопках только набирается какой-то код, а отправка его делается каким-нибудь «Энтером» (помните, «Наберите пин-код и нажмите зелёную кнопку»), то этот эффект никак не будет проявляться, т.к. к моменту нажатия «Энтера» все кнопки уже будут в своих нормальных состояниях.

Также, можно заметить, что благодаря нашему алгоритму опроса (изложен в предыдущем материале) для того, чтобы зафиксировать новую комбинацию, нужно чтобы она была прочитана дважды с интервалом в 10-16 миллисекунд (как настроим), а потому быстрая (короче этого интервала) потеря контакта нам бы никак не помешала. Поэтому вторым решеним можно предложить использование кнопок, которые переключаются быстрым щелчком, который невозможно замедлить. И той же оперы решение использовать вместо кнопок SPDT реле, а уже те переключать кнопками. Реле не имеют дурацкой привычки зависать в промежуточном положении и переключаются быстро.

Но в моём случае всё это не прокатывало. Я ведь потратил пару дней на разводку и распайку модуля и после этого, как говорил Марк Твен, «мне легче было бы изменить положение Атлантического океана, чем допустить, чтобы все мои труды пошли насмарку». Поэтому, я пошёл по старому, доброму, любимому на нашем форуме пути …

Ортопедия

а именно, присобачил такой костыль: прочитав новый код, я первым делом смотрю, чтобы все неиспользуемые доверительные биты были нулями. Если это не так, я считаю этот результат нелегитимным и отбрасываю его. Через 10 миллисекунд прочитается следующий. Если же с нулями всё в порядке, я сравниваю вновь прочитанную комбинацию с текущей и смотрю сколько битов в них различаются. Если один, то принимаю прочитанную комбинацию, если больше – отбрасываю. Как нелегитимную (случай 4-8-12, рассмотренный выше отфильтруется здесь, т.к. 4 и 8 различаются двумя битами).

Конечно, из-за отбрасываемых нелегитимных комбинаций, я теряю в скорости реакции на нажатие, но меня это не напрягает. Это кнопочный выключатель, а не высокочастотный модуль и сработает он сразу по нажатию, через 10 мс или 20-50 мс – на глаз никто и никогда не заметит (что и показывают мои эксперименты). Также я теряю возможность строго одновременного нажатия двух и более кнопок. Да, теряю, на то он костыль, чтобы что-то терять.

Вот как-то так. решите реализовывать R2R – помните о граблях, коллеги.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Это продолжение разговора о схеме R2R. Начало здесь.

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

ЕвгенийП пишет:

На чёртовых PS-22F11 этого состояния официально нет...

с чего бы этого состояния там не было официально, если это состояние обусловлено конструктивно практически во всех переключателях?

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

подпружиненые кликающие контакты отсутсвуют.

ползунок, Карл. ползунок мееедлееенно ползёёёт.

*хотя, изначально схемотехническое решение проблемы - каличное.

 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Можно ещё чисто аппаратное решение - на каждую кнопку RS триггер, он принципиально не даст возможности ни дребезгу, ни Z состоянию. А вообще первый раз вижу, что кто-то прикручивает к R2R кнопки :)

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

dimax пишет:

Можно ещё чисто аппаратное решение - на каждую кнопку RS триггер, он принципиально не даст возможности ни дребезгу

кстати, dimax, в который раз от тебя слышу, что RS триггером борешься с дребезгом - со всех сторон думал, но не смог понять алгоритм, куда дребезг девается.

ну, да - ты отфильтруешь недо-единицы и недо-нули по напряжению и пила дребезга станет у тебя красивой, но всё же останется.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

dimax пишет:

Можно ещё чисто аппаратное решение - на каждую кнопку RS триггер

Да, можно, конечно, но это если бы я подумал, прежде, чем делать :(

А когда уже платка спаяна, я ж написал "проще океан передвинуть" :) Лень - она ж ... двигатель прогресса в общем :)

dimax пишет:

А вообще первый раз вижу, что кто-то прикручивает к R2R кнопки :)

Я прям аж горжусь! :)))

 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Клапауций 112, я активно пользуюсь этой фишкой.  Там хитрость именно в переключающих контактах, с обычной кнопкой не прокатит. За счёт триггера выход остаётся в устойчивом состоянии пока переключатель движется от одного полюса к другому. Вот тут есть пояснения и примеры.

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

dimax пишет:

Там хитрость именно в переключающих контактах, с обычной кнопкой не прокатит. 

ок. спасибо. я именно про кнопку думал.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

dimax пишет:

Можно ещё чисто аппаратное решение - на каждую кнопку RS триггер, он принципиально не даст возможности ни дребезгу, ни Z состоянию.

Ох, смутили Вы меня, аж в одном месте свербит попробовать.

Скажите, пожалуйста, я правильно понимаю, что CD4043BE как раз и "спасёт отца русской демократии" - один корпус на все четыре кнопки?

SLKH
Онлайн
Зарегистрирован: 17.08.2015

ЕвгенийП пишет:

dimax пишет:

Можно ещё чисто аппаратное решение - на каждую кнопку RS триггер, он принципиально не даст возможности ни дребезгу, ни Z состоянию.

Ох, смутили Вы меня, аж в одном месте свербит попробовать.

Скажите, пожалуйста, я правильно понимаю, что CD4043BE как раз и "спасёт отца русской демократии" - один корпус на все четыре кнопки?

1 корпус и 8 резисторов. другой вариант - 1 корпус (повторители,  4503 или 4030) и 4 резистора.

Дребезга не будет, но возможны грабли №2: достаточно заметное выходное сопротивление, что опорочит красоту схемы. Для кнопок и матрицы R/2R польза сомнительна, ибо, как сказано выше, всё программно фильтруется.

Для других надобностей при наличии "перекидных" кнопок - вполне удобно, дребезг полностью исключен.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

ЕвгенийП, по идее да. Но я то делал на ЛА7, так что может какие нюансы и выпозут, например выяснится что нужна была логика  CD4044. Но эксперимент в любой случае не долгий, можно на макетке сначала проверить.

SLKH
Онлайн
Зарегистрирован: 17.08.2015

dimax пишет:

ЕвгенийП, по идее да. Но я то делал на ЛА7, так что может какие нюансы и выпозут, например выяснится что нужна была логика  CD4044. Но эксперимент в любой случае не долгий, можно на макетке сначала проверить.

Ну какие там нюансы? "Триггер - он при всех властях триггер!"

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Одна большая "грабля", которую забыл упомянуть ЕвгенийП в том R2R из интегральной схемотехники (схемотехнике на кристалле), а использует ее в дикретной (дискретными деталями). Радует что у нас не языковый форум. А то будет вешать туфту про склонения глаголов в русском языке по правилам английского.  И да эта проблема решается сейчас программно, но раньше можно решить с помощью параллельного регистра сдвига и генератора импульса в 100 Гц на сдвиг.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну сами микросхемы появились достаточно давно. Так что задолго я сомниваюсь. Разве что на реле ее применять. Опять же плюсом ее может быть только компактность при достаточно нестабильных компонентах. Вам что нужна схема из компонетнов с размером с маковое зернышко. Севодня я такие видел собственными глазами.

SLKH
Онлайн
Зарегистрирован: 17.08.2015

ЕвгенийП пишет:

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

А раньше было в этом: https://ru.wikipedia.org/wiki/Covox

 

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Я бы добавил к ранее сказаному. Вначале я бы сказал, что кто-то забыл "переобутся" , когда начал проектировать схему и плату снаружи микросхем. Но все было прозаичнее. Платы на SMD уже давно паяют роботы. И им пофигу сколько элементов на плату поставить. А вот чем меньше количество номиналов, тем меньшим количеством лент надо зарядить. И тем дешевле станок и дешевле получаемая плата.

ПС:https://www.youtube.com/watch?v=JUdmrmyxCn0

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

"Одна большая "грабля", которую забыл упомянуть ЕвгенийП в том R2R из интегральной схемотехники"

Странная у Вас "грабля" .. нормальная схема, сам пользовал ещё в бытность студентом .. и точно также и кнопки вешали на неё. Нормальная и крайне простая схемка, надежная и рабочая. Выбираешь резюки из одной партии - вот тебе и 1%, а можно и лучше.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

По поводу подбора резюков:

1. Берешь 1% штук 30 из одной партии (это на 7-8 разрядов).

2. Измеряешь у них номиналы с точностью 0.1% или лучше (главное - относительная точность, абсолютная не так важна).

3. Треть в середине распределения - это резисторы "R". Те, что ближе всего к середине - для старших разрядов. С бОльшим отклонением - для младших.

4. Из двух крайних групп попарно составляются "2R" так, чтобы в сумме были как можно ближе к 2*R.

5. Несколько штук должно остаться - из тех, что по краям, и к ним не удалось подобрать пару.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Был опыт поголовного тестирования заведомо одной партии (завод) МЛТ-0.25 5% 10кОм в количестве 100шт на хорошем измерительном мосту (метрология) из одной партии. Так вот больше 3/4 партии имели и вовсе ОДИН номинал. правда не 10кОм :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

SLKH пишет:

№2: достаточно заметное выходное сопротивление

Ну, типа "как минимум не меньше резистора, что притягивает S и R ноги с земле (или питанию)"? Даташит рекомендут 1МОм - нексисло - 1/100 сопртивления входа. Ладно, дождусь деталей посмотрю как это будет влиять на измерение. Оно, конечно, повторитель напряжения решит эту проблему, но rail-to-rail ОУ у меня нет, а для 358-го ещё и повышалка нужна. "Платка с четырьмя кнопочками" грозит немного подрасти в размерах и сложности :)))

SLKH
Онлайн
Зарегистрирован: 17.08.2015

ЕвгенийП пишет:

SLKH пишет:

№2: достаточно заметное выходное сопротивление

Ну, типа "как минимум не меньше резистора, что притягивает S и R ноги с земле (или питанию)"? Даташит рекомендут 1МОм - нексисло - 1/100 сопртивления входа. Ладно, дождусь деталей посмотрю как это будет влиять на измерение. Оно, конечно, повторитель напряжения решит эту проблему, но rail-to-rail ОУ у меня нет, а для 358-го ещё и повышалка нужна. "Платка с четырьмя кнопочками" грозит немного подрасти в размерах и сложности :)))

Хмм... я писал не о том.

Речь про ненулевое (притом ненормированное и нестабильное) сопротивление МОП-транзисторов на выходах микросхемы общего применения - она, в отличие от кнопки, не может прямо подключить входы матрицы (которые 20к) к VCC или GND. Так что вместо отобранных 0,1% резисторов 2R в реале у нас будет 2R+x, причем этот х - разный для разных выходов.  В результате напряжение на выходе цапа будет отличаться от расчетного. Впрочем, для четырехбитного цапа эта погрешность не будет слишком значительной; всё равно Вы будете округлять замеры и подбирать пороги программно.

 

ОУ на выходе цапа не нужен, входы ардуины высокоомные.

И повтор: ну совершенно не нужна в этой схеме с кнопками ещё и аппаратная защита от дребезга и разрывов при переключении, решение этих проблем написано в разделе "Ортопедия".

Оставьте начальную схему - 4 кнопки и 8 резисторов. 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Arhat109-2 пишет:

"Одна большая "грабля", которую забыл упомянуть ЕвгенийП в том R2R из интегральной схемотехники"

Странная у Вас "грабля" .. нормальная схема, сам пользовал ещё в бытность студентом ..

Я не говорю что это "грабля" не "граблит". А то что ведет себя как новичек, у которого скетч не загружается, а если не загружается, то не работает, а если работает, то не так как надо. Интегральная схемотехника это не только R2R,а много чего еще. Вот ЕвгенийП не хочет вешать операционник, так решение из интегральной схемотехники- токовое зеркало на всего лишь двух интегральных транзисторах, транзисторах размещеных на одном кристалле. Мало ли транзисторных сборок. В краймем случае возьмите два транзистора из одной партии с одним бета и все.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

SLKH пишет:
ну совершенно не нужна в этой схеме с кнопками ещё и аппаратная защита от дребезга и разрывов при переключении, решение этих проблем написано в разделе "Ортопедия".

Не, ну, понятно, что проблему я решил, о чём и написал в том самом разделе, и всё работает прилично. Просто программные решения мне неинтересны - там нет ничего, что было бы для меня вызовом и что мне было бы трудно сделать. А вот аппаратные - я совсем начинающий "электронщик" и мне это просто интересно попробоваь, пощупать ... 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

ЕвгенийП, я бы поступил так-же :)  Понимание того, что ты решил задачу технически совершенно, а не приделал программный костыль -приносит удовлетворение от проделанной работы!

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Там в разделе "Ортопедия" есть пассаж "смотрю на сколько битов различаются теущее сочетание и прочитанное". Можно узнать как это красиво сделать?

SLKH
Онлайн
Зарегистрирован: 17.08.2015

dimax пишет:

ЕвгенийП, я бы поступил так-же :)  Понимание того, что ты решил задачу технически совершенно, а не приделал программный костыль -приносит удовлетворение от проделанной работы!

несколько строк простой программной защиты от дребезга - что в этом неприличного?

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

 

мне это решение представляется не технически совершенным, а технически неграмотным.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

а не надежней ли I2C экспандер повесить?

К слову, надысь замечательное решение нашел: http://we.easyelectronics.ru/lcd_gfx/znakosinteziruyuschiy-zhki-1602-i-klaviatura-ekonomim-vyvody-mikrokontrollera.html

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Tomasina пишет:

а не надежней ли I2C экспандер повесить?

Не решает поставленной задачи. В задаче было явно прописано - один пин.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ворота пишет:

Там в разделе "Ортопедия" есть пассаж "смотрю на сколько битов различаются теущее сочетание и прочитанное". Можно узнать как это красиво сделать?

Эта величина называется "растояние Хэмминга". Гуглите как оно считается. Например, в книге Уоррена этому целая глава посвящена.

Я считал до безобразия просто (насчёт красивости помолчу - это очень субъективно)

//
//	Если растояние Хэмминга между параметром a 
//	и buttonsState меньше двух, то возвращается a
//	в противном случае - INVALID_STATE 
//
uint8_t hammingDistance(const uint8_t a) const {
	register uint8_t sum = a ^ buttonsState;
	// Поскольку количество битов ограничено 7-ю,
	// расстояние будет меньше 2 только при sum in { 0, 1, 2, 4, 8 }
	return (sum < 3 || sum == 4 || sum == 8) ? a : INVALID_STATE;
}

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ЕвгенийП пишет:

Эта величина называется "растояние Хэмминга"

Погуглил, спасибо.

Вот, что меня всегда поражает в таких как ты и wdracula - это как вы умудряетесь видеть вот в этом

вот это

и делать из одного другое.

Для меня первое - гнусный матан, а второе просто спаянная плата :(

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Парни, dimax, SLKH, огромное спасибо за советы и желание помочь.

Попробовал сделать на CD4043. Подключил точно по даташиту. На плате остался свободный угол, так что я всунул-таки туда усилитель (справа вверху восьминогий корпус). Пусть будет, тем более повышалки не надо, у меня в основном модуле есть 12В. А так, выход теперь низкоомный, по многим причинам это приятнее.

Работает прекрасно. Никаких программных фильтров и ухищрения. Программа чтения и нормализации результата ADC - две строчки (она приведена в оригинальном сообщении). Фильтровать ничего не надо (с запасом-то в шесть бит!).

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

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

ЕвгенийП, рад что у вас всё получилось! Замечу, что SLKH вас отговаривал от этого "технически безграмотного" решения. Хорошо, что вы всё таки не прислушались к его мнению. И опер на выходе -тоже отличная мысль,  с учётом того факта, что сигнал пошёл на АЦП. Где в прямо даташитах прописана необходимость в низкоимпендансном источнике сигнала для корректной работы.

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

как-то не в ту сторону всё ушло в аппаратном плане - в сторону триггеров... и, нафига, если всего-то, что нужно - суммировать четыре напряжения.

есть же аналоговые ключи - 1561КТ3, например: четыре управляемых аналоговых канала.

соединяем выходы в один, на входы ставим резисторные делители напряжения - каждый генерит, рассчитанное по хитрой формуле напряжение.

управляем всей этой балалайкой кнопками или тумберами с двумя контактами - не нужно городить огород с триггерами и уродскими переключателями.

Картинки по запросу кр1561кт3

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

а, если полностью абстрагироваться от аппаратной части, то можно взять эту хитрую формулу 

и генерить ШИМом на аналоговый вход напряжение в зависимости от комбинаций нажатых кнопок.

и, всё это в пределах одного корпуса контроллера... думаю, самый оптимальный вариант.

О_О

Logik
Offline
Зарегистрирован: 05.08.2014

Дак в том и дело, что вариантов решений по условию использовать один пин довольно много. И все можна довести до более-менее рабочего состояния. Навскид добавлю такой - делаем RC генератор, например на ОУ или 555, где резюками и/или кондерами номиналами кратными 2^n задаем длительности 0 и/или 1 на выходе. Соответственно частота и/или ШИМ принимать. Разумеется все подходы имеют те или иные + и -. С текущими ценами на МК оправдано ставить отдельный контролер на работу с кнопками и связывать цифровым интерфейсом с основнім, например UART симплексный или OneWare или на крайняк богомерзкий ШИМ. В чем преимущество такого подхода? А как потребуется кнопок добавить или расстояние увеличить поймете. А с R2R я бы радоватся не спешил, на столе работает, а при длинном проводе ИМХО начнет ловить помеху.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

dimax пишет:

Замечу, что SLKH вас отговаривал от этого "технически безграмотного" решения. 

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

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

Logik пишет:

Дак в том и дело, что вариантов решений по условию использовать один пин довольно много. 

да, но если вариант решения с ипользованием аналоговой схемы R2R на цифровом контроллере, так или иначе, разворачивается в цифровую передачу данных, то стоит задуматься - а, для чего, вообще, R2R нужна и где она безальтернативно применима.

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

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

[

Эта величина называется "растояние Хэмминга". Гуглите как оно считается. Например, в книге Уоррена этому целая глава посвящена.

Я считал до безобразия просто (насчёт красивости помолчу - это очень субъективно)

//
//	Если растояние Хэмминга между параметром a 
//	и buttonsState меньше двух, то возвращается a
//	в противном случае - INVALID_STATE 
//
uint8_t hammingDistance(const uint8_t a) const {
	register uint8_t sum = a ^ buttonsState;
	// Поскольку количество битов ограничено 7-ю,
	// расстояние будет меньше 2 только при sum in { 0, 1, 2, 4, 8 }
	return (sum < 3 || sum == 4 || sum == 8) ? a : INVALID_STATE;
}

 

Разность старого и нового значения должна быть степенью двойки (расстояние Хэмминга как-то очень сильно звучит для столь простого условия).  Классически "красивый" способ убедится. что x есть степень двух (для любого числа бит)

return ((x != 0) && !(x & (x - 1)));
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707 пишет:

Классически "красивый" способ убедится. что x есть степень двух (для любого числа бит)

Мне нравится. Хотя, конечно, "красивый" - понятие субъективное.

Но в данной задаче 0 - тоже положительный результат, потому всё ещё сильнее упрощается. Остаётся только

!(x & (x - 1))

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

b707 пишет:

return ((x != 0) && !(x & (x - 1)));

MISRAстов на тебя нет!

ЕвгенийП пишет:

Мне нравится. 

И на тебя тоже!

И куда GarryC запропастился?

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

Но в данной задаче 0 - тоже положительный результат, потому всё ещё сильнее упрощается. Остаётся только

!(x & (x - 1))

Так делать нельзя, так как без первой скобки во второй получится отрицательное число при x==0. Чтобы включить значение x=0, тогда так:

return ((x == 0) || !(x & (x - 1)));

 

b707
Offline
Зарегистрирован: 26.05.2017

b707 пишет:

ЕвгенийП пишет:

Но в данной задаче 0 - тоже положительный результат, потому всё ещё сильнее упрощается. Остаётся только

!(x & (x - 1))

Так делать нельзя, так как без первой скобки во второй получится отрицательное число при x==0. Чтобы включить значение x=0, тогда так:

return ((x == 0) || !(x & (x - 1)));

 

хотя нет, ступил...

будет работать !(x & (x - 1))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Можно.

Плевать на его отрицательность - в нужных битах всё равно будет то, что нужно. Просто запустите и проверьте. Я вот прямо сейчас не поленился - запустил (не на ардуине, правда).

typedef unsigned char uint8_t;

void main(void) {
	for (uint8_t x = 0; x < 255; x++) {
		if (!(x & (x - 1))) printf("x = %d\n", x);
	}
}

Результат

x = 0
x = 1
x = 2
x = 4
x = 8
x = 16
x = 32
x = 64
x = 128

Как видите, всё в порядке. И ноль нормально отрабатывает.

UPD: одновременно написали :))))

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

Хотя, конечно, "красивый" - понятие субъективное.

!(x & (x - 1))

красота - она в простоте :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Эх.. когда-то сборник таких красот для начинающих назывался просто: "Кнут".. :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А что, он перестал так называться? И как же он называется теперь? Как-то это мимо меня прошло.

SLKH
Онлайн
Зарегистрирован: 17.08.2015

b707 пишет:

ЕвгенийП пишет:

Хотя, конечно, "красивый" - понятие субъективное.

!(x & (x - 1))

красота - она в простоте :)

А не в обвешивании кнопок лишними микросхемами   ;-)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

ЕвгенийП пишет:

А что, он перестал так называться? И как же он называется теперь? Как-то это мимо меня прошло.

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

- "Пушной зверек, а пушной зверек! Тебя как зовут?"

-"никак не зовут, сам прихожу"

SLKH, да, тоже верно. Если уж делать "просто", то такой обвес банальных кнопок никак "не просто".. (нафига коту баян?)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

на столе работает

Это у кого как. У кого-то на столе, а у кого-то в изделии стоит себе и уж три недели работает безо всяких нареканий.