Светодиод - RGB - Arduino / ArduBlock
Самая маленькая контролька на Arduino с дисплеем ФИНАЛ
Привет друзья, сегодня мы соберём самую маленькую контрольку на ATTINY85, я знаю, что никто из Вас не ждал продолжения этого проекта, но крупные проекты требуют много времени, а видео на канале не могут выходить раз в три месяца. Поэтому сегодня, мы завершим этот проект.
Несмотря на свои размеры, контролька обладает довольно большим функционалом по сравнению со своими китайскими собратьями с AliExpress.
Первое, контролька имеет функцию прозвонки, если прозваниваемый провод цел, на экране появляется надпись MASSA, SMD зумера под такие размеры платы я не нашёл, поэтому вместо него на выход PB0 (он же AREF) поставил конденсатор, для стабильности измерений (более подробно об этом мы поговорим при разборке скетча).
Второе, контролька может измерять напряжение в диапазоне от 0 до 50 вольт.
Третье, контролька имеет защиту от переплюсовки.
И при всех своих преимуществах, печатная плата нашего измерительного прибора меньше спичечного коробка.
Схема контрольки (в картинках)
Конденсаторы C1 и C2 это фильтры по питанию. Резисторы R1-R3 и R4-R2 это делители напряжения, конденсаторы C4 и C3 – фильтры. Про конденсатор C5 мы поговорим отдельно. Дисплей к ATTINY85 подключается напрямую.
Плата в Sprint-Layout
Так же я снял для Вас подробную инструкцию и подготовил печатную плату в Sprint-Layout и PDF все ссылки в описании под видео на ютубе.
Цифровои потенциометр - X9C103S - Arduino / ArduBlock
Датчик тока - ACS712 - Arduino / ArduBlock
Расширитель портов - Servo PCA9685 I2C - Arduino / ArduBlock
Светодиодные матрицы для "чайников" (часть 2)
Ну что, дружище, надеюсь ты освоил первую часть моего лонгрида и уже запилил свою лампу Гайвера с блэкджеком и всем остальным? Тогда вперед, через тернии к звездам, гексагонам, кругам, гирляндам.
Во многих подобных конструкциях раскладка светодиодов не имеет строк и столбцов, а порой она и вовсе хаотичная. Да и и соединены диоды не рядами, а как было удобно для разводки платы.
Возьмем, к примеру, мою новогоднюю звезду . Диоды там уложены концентрическими звездами, да еще и змейкой.
Но отчаиваться не будем, попробуем мыслить логически. У каждого диода на звезде есть реальные координаты центра в миллиметрах, или координаты на картинке в пикселях.
Мы можем создать таблицу соответствия порядкового номера диода и его координат. Изменим наш цикл обхода диодов по координатам на обход по номерам.Перепишем функцию мэппинга так, чтобы она искала координаты по индексу диода в таблице и дело в шляпе.
uint16_t mapTable[][2] = {
{ 206, 340 },
{ 181, 354 },
{ 156, 369 },
{ 132, 383 },
{ 107, 398 },
{ 89, 404 },
{ 89, 385 },
{ 95, 357 },
{ 101, 329 },
{ 107, 301 },
{ 114, 273 },
... // и так далее, для всех 180 диодов
};
struct ledCoords {
uint16_t x;
uint16_t y;
};
ledCoords mapIdxToXY( byte index ) {
return { mapTable[index][0], mapTable[index][1] };
}
void loop() {
for ( byte i = 0; i < NUM_LEDS; i++ ) {
ledCoords lc = mapIdxToXY(i);
leds[i] = effectColorByCoords(lc.x, lc.y);
}
FastLED.show();
}
На практике это оказывается не очень удачным решением. Координаты - штука относительная. У кого-то линейка в дюймах, а у кого-то 4К картинка с четырехзначными координатами. Замучаешься подгонять масштаб анимации под каждое устройство. Чтобы избежать этого выполняют нормализацию координат.
Звучит страшно, но на практике это просто пересчет в некую фиксированную систему координат. Например, давай примем за правило, что минимальная координата по X среди всех диодов это 0 в нашей "нормализованной" системе, а максимальная - 1. И все остальные координаты пересчитаем пропорционально Xn = ( x - Xmin )/(Xmax - Xmin). Аналогично поступим с координатами Y.
Теперь у нас все координаты на любом устройстве лежат в пространстве 0..1
Такой подход используется в программируемых контроллерах Pixelblaze.
Казалось бы, можно закончить занудствовать на этом, но позволь еще немного помучать тебя.
Во-первых все эти дробные координаты для контроллера являются числами с плавающей точкой (float) и он тебе не скажет спасибо за их использование. В отместку контроллер будет тратить кучу времени на расчеты даже простой арифметики, не говоря уж о корнях, степенях и тригонометрии.
Во-вторых, некоторые алгоритмы эффектов требуют расчета по всей площади, а не только в точках расположения диодов. Например операция размытия (blur) требует значения цветов всех соседних точек в пределах радиуса размытия.
Ну и в-третьих, тут уж мое личное мнение, куча дробных чисел в формулах снижает читабельность кода, а отладка такого кода вызывает у меня тихий ужас.
И тут ты подкидываешь наивную идею: "А можно как-то так чтобы координаты остались целыми, но не такими большими и более-менее схожей размерности на разных устройствах?"
Можно!
Потребуется всего лишь привести реальные координаты диодов к прямоугольной матрице низкого разрешения. Представь, что мы взяли листок бумаги в клеточку и положили поверх нашей звезды и пометили клетки в которые попали центры диодов.
Теперь у каждого диода есть простые координаты в координатной системе листочка в клеточку. И эти координаты гораздо более удобоваримые чем реальные. И если мы захотим посчитать наш эффект для каждой клеточки на этом листочке, то даже наш не супер-мощный контроллер это осилит. Попробуем записать результат в таблицу мэппинга.
byte mapTable[][2] = {
{ 12, 18 },
{ 11, 19 },
{ 9, 20 },
{ 7, 21 },
{ 6, 22 },
{ 5, 22 },
{ 5, 21 },
{ 5, 19 },
{ 6, 18 },
{ 6, 16 },
{ 6, 15 },
... // и так далее, для всех 180 диодов
}
Вроде неплохо получается.
А чтобы все алгоритмы были похожи на работу с обычной прямоугольной матрицей,можно развернуть мэппинг. Будем хранить в таблице не координаты, а индексы диодов для каждой ячейки нашей матрицы 27x23
Только как же быть с пустыми клеточками, ведь их нужно как-то пропустить при обработке? Да запиши в них просто какое-то значение индекса которое ты отловишь в цикле и пропустишь обработку. Например любое число большее общего количества диодов. И таблица примет такой вид:
byte mapTableIndex[23][27] = {
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 27,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 26, 255,
28, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 25, 77,
29, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 78, 255,
76, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 24, 255, 255,
255, 30, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 23, 255, 79, 117,
75, 255, 31, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
... // и еще 17 строк
}
Тогда функция мэппинга и рабочий цикл будут выглядеть как-то так:
byte mapXYtoIdx( byte x, byte y ) {
return mapTableIndex[y][x];
}
void loop() {
for ( byte y = 0; y < 23; y++ ) {
for ( byte x = 0; x < 27; x++ ) {
byte ledIndex = mapXYToIdx(x,y);
if ( ledIndex == 255 ) continue;
leds[ledIndex] = effectColorByCoords(x, y);
}
}
FastLED.show();
}
Конечно, хранить такие большие массивы с таблицами мэппинга в оперативной памяти не стоит, обычно их загоняют во flash используя PROGMEM.
Собираем все полученные знания в кучу и зажигаем)
(Продолжение следует, stay tuned)
В Питере шаверма и мосты, в Казани эчпочмаки и казан. А что в других городах?
Мы постарались сделать каждый город, с которого начинается еженедельный заед в нашей новой игре, по-настоящему уникальным. Оценить можно на странице совместной игры Torero и Пикабу.
Реклама АО «Кордиант», ИНН 7601001509