А что там вообще случилось-то?

Несколько раз до меня донеслось, что на этой неделе что-то там стряслось с windows, и что кошмар-кошмар и всё пропало.

Судя по выдаче Яндекса — реально что-то произошло. (См. рис. 1.)

Надо будет почитать про всё это. А то мне с Линукса плохо видно детали этого происшествия.

Рис. 1

(не)переполнение millis()

Как, наверное, любой начинающий ардуинщик, когда я узнал о том, как можно реализовать всякое с использованием функции millis(), возвращающей 32-разрядное беззнаковое целое число миллисекунд, прошедших с момента запуска микроконтроллера, я задался вопросом: «а что будет, когда счётчик миллисекунд переполнится?»

Функция millis() для ардуинщика — это альфа и омега всей «многозадачности» ардуино. Если что-то нужно регулярно выполнять через заданный интервал времени, то обычно пишут какой-то такой код:

uint32_t  my_timer;    // где-то объявляем переменную "таймер"
#define MY_PERIOD 1000 // "раз в секунду"

...

my_timer = millis();    // "запускаем" таймер, запоминая в
                        // переменной текущее значение millis()

...

// и где-то в основном рабочем цикле пишем примерно такое:
if ( millis() - my_timer > MY_PERIOD ){
    // Заданное время ожидания прошло
    // делаем здесь, что хотели

    my_timer = millis(); // снова взводим таймер для следующего
                         // срабатывания
}

Так вот, предположим, что в «таймере» мы сохранили число 0xFFFFFFFE. Естественно, 32-разрядный счётчик переполняется через 1 миллисекунду и millis() начинает возвращать 0, 1, 2, и т.д.

И куча новичков-ардуинщиков в интернете пугается, когда понимает, что при таком раскладе «всё пропало», потому что в этом случае при проверке срабатывания таймера из 1 будет вычитаться 0xFFFFFFFE и, вроде бы, так нельзя. Поиск по клчевым словам «переполнение millis()» выдаёт кучу ссылок на страницы, где «знатоки» со знанием делом говорят «не ссыте, всё будет нормально, потому что вычитание беззнаковое», не объясняя при этом ничего.

А я объясню, мне не жалко. 🙂

Для того, чтобы убедиться, что «так можно», нужно всего лишь понимать, как в процессорах общего назначения происходит вычитание целых чисел. А происходит оно через сложение.

В этом месте, может, стоило бы рассказать про комбинационную схему «сумматор» и объяснить, как она работает. Для того, чтобы на низком уровне показать, как же, собственно, компьютер складывает числа. И чтобы стало понятно, что вычитать (подобно тому, как это делает человек) процессор не умеет. Он умеет только складывать. Но про (полный) сумматор читайте в другом месте. А здесь и сейчас достаточно понять, что кто-то очень умный придумал, как можно вычитать одно число из другого, имея в качестве инструмента комбинационную схему, которая умеет только складывать (суммировать).

Он придумал представлять отрицательные числа в т.н. «дополнительных кодах«. То есть, если нам надо вычесть из положительного числа А положительное число Б, нужно преобразовать число Б в дополнительный код (получив тем самым число -Б), и после этого спокойно складывать числа «А» и «-Б». Здесь важно то, что беззнаковые числа тоже преобразуются в дополнительный код при вычитании.

Т.е. если наше А = 3 и Б = 1 (00000011 и 00000001 в двоичном представлении), то при вычитании Б из А будут складываться числа 00000011 и 11111111. В результате такого сложения мы получим 00000010, а точнее (1)00000010, где единица, образующаяся при сложении старших разрядов улетает в переполнение (за пределы нашего 8-разрядного целого). То есть, при сложении числа 3 и представленного в дополнительном коде числа -1 мы получили число 2.

В случае с millis(), нам надо было из беззнакового числа 1 вычесть беззнаковое число 0xFFFFFFFE (т.е. двоичное 1111111111111110). Ну, хорошо, преобразуем вычитаемое в дополнительный код и получаем двоичное 0000000000000010. В результате мы складываем 1 и двоичное 10, получая двоичное 11, т.е 3. Т.е. результатом операции «1 — 0xFFFFFFFE» будет 3. И это именно то, что мы рассчитывали получить, проверяя таймер:

1111111111111110 <-- здесь "засекли" таймер
1111111111111111
0000000000000000
0000000000000001 <-- а здесь "1 - 0xFFFFFFFE = 3"

Т.е. всё, что надо, успешно вычитается, и получается именно то, что надо. Вот такая магия.

P.S. Только что осознал, что двоичное представление 32-разрядных чисел у меня получилось 16-разрядным :). Но не буду исправлять, т.к. будет хуже читаться. А на суть явления размерность чисел не влияет. Можно было хоть на 3-разрядных числах это показывать.

Смонтировал немножко электроники в правый полукорпус

Сегодня я подготовил места крепления платы микроконтроллера и дифференциального датчика давления (см. рис. 1).

Заодно просверлил в деке 2 отверстия ∅4 мм. Одно отверстие для силиконовой трубки, которая будет соединять один из входов датчика давления с внешней средой (т.е. с зоной условно-нулевого давления). А второе отверстие — для жгута проводов, которые пойдут к плате панели управления и к платам датчиков правой клавиатуры.

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

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

Рис. 1

Установил гнёзда

Гнездо MIDI-out (которое DIN-5) в данный момент держится на трении. Отверстия под крепёжные винты я делать не буду, чтобы не дырявить лишний раз герметичный корпус. Думаю, что при финальной сборке это гнездо отлично будет держаться на термоклее, которого придётся наляпать в изобилии, т.к. этот разъём сам по себе не герметичен.

А вот разъём питания вкручен в стенку корпуса на резьбу. Длина резьбовой части разьёма оказалась практически равна толщине стенки. Поэтому я просверлил в стенке отверстие 7.5 мм и нарезал резьбу М8×0.75. Благо нужный метчик у меня нашёлся. При финальной сборке перед закручиванием я намажу резьбу разъёма клеем (не суперклеем, а каким-нибудь ПВА или «Моментом». Сам разъём выглядит герметичным. Надеюсь, не придётся его заливать термоклеем.

Рис. 1

Снаружи это выглядит так:

Рис. 2

Магниты 3 ряда приклеены

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

Следующий шаг — сверление монтажных отверстий в корпусе для разъёмов MIDI-out и питания. И сверление отверстия в правой деке, через которое будет проходить жгут из 12 проводов МГТФ 0.12 к плате 1-го и 2-го рядов и к плате панели управления.

Про панель управления я ещё не решил, как её крепить на время наладки датчиков. В итоговом варианте она будет крепиться на декоративную решётку, примерно в то место, где у многотембровых инструментов находятся переключатели регистров. Но на время наладки, думаю, прилеплю её просто на корпус на 2-сторонний скотч. Главное предусмотреть, чтобы соответствующие жгуты проводов были достаточной длины, чтобы дотянуться до места. Но с этой стороны проблем не ожидаю: 40 метров провода МГТФ должно хватить. 🙂

Рис. 1

Вообще, я уже устал от этой работы. Начинаю понимать, почему Бутусов за установку одной MIDI-системы в один инструмент берёт 200 тыр.

P.S. На рис. 1 — магниты, приклеенные неправильно. 🙂 Надо было клеить с другой стороны рычагов и с противоположным направлением полюсов. Вот что значит «устал». В результате в тот же вечер я эти 18 магнитов отодрал и переклеил по-правильному.

Магниты 1-го и 2-го рядов приклеены

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

Откуда знаю, что крепко? Знаю, потому что несколько магнитов 2-го ряда пришлось отламывать и переклеивать. Они, видите ли, выпирали за габарит рычага и стучали по плате. Переклеил так, чтобы магниты не выпирали. Теперь не стучат. Но всё равно осталась пара мест, где рычаги задевают плату, если нажать клавишу «с размаху». Т.е. всё-таки придётся саму плату слегка поднимать над рычагами. Немного, не больше, чем на миллиметр. Но придётся.

А значит, что следом за платой придётся поднимать и декоративную решетку. Ничего страшного; добавлю прокладку/проставку между решеткой и корпусом.

Рис. 1

На очереди — подгибка датчиков на плате 3-го ряда и приклеивание магнитов на рычаги 3-го ряда.

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

Всё это издержки того, что этот баян всё-таки изначально не был рассчитан на установку в него MIDI системы. Но ничего. Справлюсь.

Клею магниты на 1 и 2 ряды правой клавиатуры

Сегодня я начал клеить магниты на рычаги клапанов 1 и 2 рядов правой клавиатуры. Разметил все места на рычагах 1-го ряда и приклеил первые 4 магнита (см. рис. 1).

Рис. 1

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

  1. сам датчик находился на одном уровне со «своим» рычагом;
  2. датчик был развернут «лицом» к рычагу.

Т.е. сначала выводы датчика сгибаем почти до нужного положения, потом поворачиваем сам датчик на 90 градусов. Результат — на рис. 2:

Рис. 2

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

Вело-маршрут по Борской пойме в 2024

В этом году Можно более-менее нормально использовать только вот этот маршрут, показанный на карте (ниже). Для сухой погоды он хороший.

(Если будет дождь, то больше половины маршрута развезёт; на колёса будет налипать очень много земли. Но самое плохое — это то, что колёса будут соскальзывать в колею, а колея там глубокая, и она будет полна воды. В некоторых местах можно проехать «рядом по траве», но не везде.)

Параметры маршрута — на рис. 1. Условно «скоростных» участков там всего два, но они короткие и погоды не делают. Так что маршрут в целом — «силовой» (как я его для себя называю).

Рис. 1

Ну и закупленный ранее подседельный хомут показывает себя очень хорошо. Очень я люблю запчасти класса «установил один раз — и забыл о проблеме». На моём велосипеде таких деталей, кроме этого хомута, сейчас несколько:

  • Сам подседельный штырь (родной не справлялся с удержанием седла в нужном положении)
  • Седло Brooks B17 (у современных очень быстро гнутся/ломаются рамки)
  • Передний и задний переключатели скоростей (родные глючили и работали неустойчиво)
  • Спицы в заднем колесе (родные под моей 120-килограммовой тушкой лопались)

А, чуть не забыл. Ещё одна запчасть есть класса «поставил и забыл» — титановая рама, сделанная на заказ. В 2020 году мне её сделали, после того, как у третьей по счёту рамы треснула подседельная труба. (Рамы меняли по гарантии, кстати.) Но когда и у третьей рамы труба треснула в том же самом месте, я, как говорится, психанул, и заказал титановую раму. Её уже просто так хер сломаешь.

Изголовье для кровати – 5

Сегодня всё закончено в полном объёме. Доделал длинную настенную панель.

Для её изготовления пришлось купить целый лист фанеры 12 мм. «Обрезок» оказался больше по размеру, чем сама панель. Кстати, если кому нужна фанерка толщиной 12 мм и размерами 2000 * 730 мм — обращайтесь. Продам дешевле, чем в магазине.

Рис. 1