Класс для чтения резисторной клавиатуры

Для мотора - тоже не будет.

Странно, если старый работал, то и этот должен.

Ладно, я разберусь, а потом на вопросы отвечу, на Ваши и других ребят.

Отличная новость, может аналогичный разбор и по аппаратной части устроить, а то многие понятия не имеют, почему нельзя устанавливать электролитические конденсаторы с сильно большим напряжением, чем рабочее )))

PS направление мысли есть в этом ролике

В этом случае локальная переменная будет храниться в регистрах. (Наверное можно написать код который займет столько регистров, что заставит выделять под переменную память в стеке, но для архитектуры AVR (attiny atmega) и для millis это надо специально стараться.

Я, например.

Объясните, почему?

Посмотрел.

Последняя работающая версия: 616/43.

Первая нерабочая версия - 588/35. Там мелкая оплошность, добавил явное преобразование типа арифметической операции в строку №43 и всё заработало. Кстати, размер кода уменьшился и теперь она уже не 588/35, а 584/35.

В версии 538/31 исправил такую же оплошность в строке №76. Всё работает. Программа опять уменьшилась и стала на самом деле 518/31.

Все остальные версии (с учётом правок выше) других правок не потребовали. Все работают и у всех размер программы 518.

Правки внесены в мой исходный пост. Берите программы оттуда.

Посмотрел ролик, предполагаю у @ua6em есть некая ̶д̶з̶е̶н̶б̶у̶д̶д̶и̶с̶т̶с̶к̶а̶я̶ теория, связанная с деградацией оксидной пленки анода.

Склонен списать сей факт на побочный эффект лечения приснопамятной катушкой.

1 лайк

Типа того.

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

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

Если при вычисления не нужно ничего, чего не “знает” компилятор, то святое дело поручить вычисления ему - пусть считает, а в код только константу тянет.

в ролике на 2-й минуте 50 секунд ориентировочно, если не выкинул, поищу новые конденсаторы, рубиконовские, пролежавшие порядка 1 года, выложу фото, если коротко - химия разрушает оксидный слой

Ну, не знаю, задержка loop на четверть секунды … тот, кто так пишет, обязательно налажает где-то ещё, так что это место не станет для него определяющим :slight_smile: Ограничение-то всё равно есть, ну будет не четверть секунды, а 65 секунд, и что? Того, кто умудряется делать четвертьсекундный loop без понимания, как это отразится на остальном коде, это не спасёт. Его ничто не спасёт. Он найдёт в какую кучу вступить.

Я же всё объяснил ТС подробно. Она понимает, что там и как, какие могут быть грабли, и может сама принять решение. Жизнь-то в любом случае - лавирование между граблями. А я показал ход рассуждений по привязке общего решения к конкретному проекту.

Нет. Стек используется только если не хватает регистров. Ничего мы тут не увеличиваем - всё в регистрах. Мы просто исключаем “вечное” хранение значения, которое нам не нужно и экономим память.

Нет, см. выше.

@ЕвгенийП , раз тут о классах речь зашла, то придайте, пожалуйста, направление, если оно есть, по след.реализации: имеются две библиотеки, которые изменять желания нет: Wire и SoftwareWire, методы у них, в целом совпадают, разница в конструкторе. Есть желание получить волшебный враппер UniWire, который бы в зависимости от конструктора создавал внутри себя экземпляр
SoftwareWire или брал указатель на Wire, а затем магическим способом дергал, к примеру, Wire->write(…) или SoftwareWire->write(…), когда пользователь использует, например, UniWire.write(…)
Перенаколачивания вызовов всех методов, содержащихся в библиотеках, хотелось бы избежать.

я то тут при чём, все претензии к технологам, тут диаграмму сплава железо-углерод уже не помню…перлит ледебурит мартенсит… прыгать надо, прыгать а за окном ковали железом по железу )))

Пока не до конца понял задачу, но, не подойдёт ли класс, пронаследованный от обоих тех классов? “Множественное наследование” не поможет?

    constexpr Resistive_keyboard(const uint16_t min, const uint16_t max, const uint8_t count) 
        : _min(min / 4), _max(max / 4), _tmr(0), _counts(0), _count(count) {}

Через двоеточие делается присваивание переменным значение?

То есть все расчёты будут на стадии компиляции, это тоже самое что я бы просто записала
: _min(20), _max(25), то есть подставила готовые значения.

Далее

const uint16_t _sensor = analogRead(BUTTONS_PIN) / 4;

Если мы делим на 4, значит и переменной нам хватит uint8_t ?
Или как меня научили uint16_t _sensor = analogRead(BUTTONS_PIN) >> 2;

const uint8_t nowMillis = millis();

Почему uint8_t , ведь millis считает до 4,294,967,295, uint32_t

if (static_cast<uint8_t>(nowMillis - _tmr) >= 50) {

Как работает static_cast<uint8_t>?

Ну, тогда бы Вы не смогли записать три вызова конструктора с разными наборами параметров, как сейчас у Вас. А так - да.

Тут два момента.

Во-первых uint16_t - избыточно. Максимум, что может выдать АЦП - 1023. При делении на 4 это даёт 255. Большего значения там быть не может. Значит, uint8_t - вполне достаточно.

Во-вторых, сдвиг вправо на 2, как Вы написали действительно эквивалентен делению на 4, а операция сдвига быстрее деления. Но! Современные компиляторы это знают не хуже нас с Вами и они сами заменят деление на сдвиг. А поскольку по логике задачи здесь именно деление, то его и надо писать из соображений читабельности - на сдвиг компилятор сам заменит, не сомневайтесь.

Потому, что мы отмеряем интервалы в 50мс и нам не нужен целый миллис - достаточно остатка от деления millis на 256 (что мы и получаем). Зачем нам всё остальное?

Говорит компилятору, чтобы считал, что аргумент (то, что в скобках) всегда имеет тип uint8_t, даже если компилятору кажется, что “возможны варианты” :slight_smile:

Как там с работоспособностью - у Вас тоже всё заработало?

Да. Всё работает. Огромное спасибо.
Изучаю дальше, пока что всё понятно.

ОНИ ПЛОДЯТСЯ!
https://dzen.ru/a/ZMwiWilvySANYCpe

ссылку цитировать не стал, дабы не повышать
Такими дятлами Роскомпозор должен заниматься, а не тем чем вот это все.

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

Это для МК разницы нет, а для человека - есть и принципиальная.
Секунду в качестве единицы измерения времени выбрали не просто так, и для человека “намного меньше секунды” и “намного больше секунды” - это небо и земля. Это то, что отличает “приемлемо” от “категорически неприемлемо”.

Неубедительно.
Нередко как раз после нажатия на кнопку происходит перерисовка экрана. И четверть секунды на сие действо для цветного экрана разрешением, скажем, 320х480 - совсем не признак безумно низкой квалификации программиста.
И перерисовка экрана - далеко не единственное действие, которое может занимать время. Например, у меня в одном проекте реакция на переключение - пересчет массива с плавающей точкой. И сделать это менее чем за 0.6-0.7 секунды у меня не получается. Я считаю такую задержку допустимой. Правда, индицирую ее переключением светодиода с зеленого на красный (при красном светодиоде органы управления неактивны, что отражено в документации). Но факт остается фактом: именно в loop и именно более полсекунды.
Другое дело, что, опираясь на вышеизложенное “намного больше/меньше секунды”, можно разделить значение millis, скажем, на 16: четыре секунды вряд кто будет жать на кнопку по собственной воле.

Да, 32 регистра AVR - это не 4 регистра intel86+. Но чем больше регистров мы используем в функции, тем больше нам сохранять в стеке при вызове вложенной функции. Как-то для меня не очевидно, что регистров должно хватить для хранения локальных переменных одновременно для ВСЕХ вызываемых друг из друга функций. Тем более, что регистры всего 8-разрядные. А для работы даже с однобайтовыми переменными промежуточные результаты не менее двух байт. Да и millis отдает 4 байта даже если мы используем всего один.

Не верю!