Часы из часов на дисплее из дисплеев

Arduino & Pi

1.4K поста20.6K подписчиков

Добавить пост

Правила сообщества

В нашем сообществе запрещается:

• Добавлять посты не относящиеся к тематике сообщества, либо не несущие какой-либо полезной нагрузки (флуд)

• Задавать очевидные вопросы в виде постов, не воспользовавшись перед этим поиском

• Выкладывать код прямо в посте - используйте для этого сервисы ideone.com, gist.github.com или схожие ресурсы (pastebin запрещен)

• Рассуждать на темы политики

• Нарушать установленные правила Пикабу

Вы смотрите срез комментариев. Показать все
14
Автор поста оценил этот комментарий

я был больше всего удивлен что ардуинка не вытягивает вычисления в динамике

раскрыть ветку (16)
25
Автор поста оценил этот комментарий

дело в том, что размер блока виртуальных пикселей был сделан 4х6, а операции деления и остатка от деления с числами не из степеней двойки (2 4 8 16 32) выполняются в 20 раз медленнее, потому что у ардуинки нет аппаратного деления. Все остальные вычисления оптимизированы до степеней двойки, поэтому только лишь вот эта шестёрка добавляет около 150 миллисекунд!!!! к расчётам позиций пикселей при отрисовке часов

раскрыть ветку (14)
32
Автор поста оценил этот комментарий

Возможно вам стоило бы подкинуть в программу функцию ускоренного деления на 6 через умножение на заранее посчитанную целочисленную константу.
Ну и вызывать свою функцию вместо оператора деления.

Вот тут немного тема раскрыта:
https://habr.com/ru/post/147096/

раскрыть ветку (13)
19
Автор поста оценил этот комментарий

о, супер, спасибо! Я как раз сейчас сидел гуглил про быстрое деление на 6, но ничего вменяемого не нашёл)

раскрыть ветку (12)
11
Автор поста оценил этот комментарий

Для ардуино с 16-битными регистрами деление на 6 будет примерно так (я не проверял, только прикинул):


final int cpuRegisterSize = 16;

final int b = 3;

final int L = 2; // 2**L >= b

final int N = (cpuRegisterSize – L) / 2; // ==7

final int B = ((1 << (N + L)) / b) + 1;

final int shiftSize = N + L + 1; // additional '+1' to move from div3 to div6


private static int divideBy6(int a) {

    return (a * B) >> shiftSize;

}

private static int modBy6(int a) {

    return a - divideBy6(a) * 6;

}

раскрыть ветку (11)
14
Автор поста оценил этот комментарий

я не очень вник в статью, загуглил - нашёл более короткое объяснение. В моём случае до чисел 150 деление на 6 можно записать так:

x = (i * 342) >> 11;

выполняется в ячейке 2 байта. Точно там же можно найти остаток

val - x * 6

код ускорен в два раза, спасибо за наводку)

11
Автор поста оценил этот комментарий

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

Иллюстрация к комментарию
раскрыть ветку (9)
3
Автор поста оценил этот комментарий

А если quot * 6 заменить на quot << 2 + quot << 1

раскрыть ветку (4)
6
Автор поста оценил этот комментарий

Экономия на крохах буквально ;) возможно компилятор уже оптимизирует это сам, я проверю

раскрыть ветку (2)
раскрыть ветку (1)
2
Автор поста оценил этот комментарий

Хотя при таком разрешении можно разориться на массив готовых значений в памяти - будет вообще реактивно

https://hackaday.com/2016/04/22/embed-with-elliot-keeping-it...

Автор поста оценил этот комментарий

не, это уже получается медленнее ~ на 30%, потому что вместо одной аппаратной операции умножения у нас три операции - два сдвига и одно сложение

Автор поста оценил этот комментарий

Отличное решение! Вероятно, для дальнейшего ускорения деления вам подойдёт таблица заранее посчитанных частных и остатков от деления на 6.

Автор поста оценил этот комментарий

А остаток прямо всегда нужен?
Можно при желании сделать его вычисляемым опционально.
способы разные есть красиво оформить

раскрыть ветку (2)
5
Автор поста оценил этот комментарий

Прямо всегда, для расчетов установки одного пикселя нужно и деление и остаток

раскрыть ветку (1)
Автор поста оценил этот комментарий

тогда отлично вообще

10
Автор поста оценил этот комментарий

Ну ардуина на самом деле довольно примитивный МК. А такие вещи на самом деле довольно ресурсоёмкие. Казалось бы сами по себе вычисления не сложные. Но всё усложняется тем, что они привязаны ко времени. То есть чтобы получить плавную картинку тебе нужно всё обсчитать и и передать по SPI (передача тоже кстати занимает какое то время, что сокращает доступное для расчётов время, ибо DMA в ардуину не завезли) за очень короткое время, через нцать милисекунд тебе нужно повторить операцию снова.


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

Вы смотрите срез комментариев. Чтобы написать комментарий, перейдите к общему списку