Я потратил на изготовление этой футболки два вечера, а потом еще неделю игрался, выдумывая различные фигуры для её оживления. Из чего это сделано:
1. Arduino Nano – она маленькая и её очень удобно вшивать в подобные конструкции. Только ножки отпаяйте!
2. 64 светодиода SK6812. Для матрицы 8 х 8. Это RGBW светодиоды с пиксельной адресацией. RGBW – это значит, что в них три кристалла RGB и одна “яичница” белого свечения. Очень яркая!
3. Кнопка для смены эффектов.
4. Аккумулятор 1800 мА.час.
5. Провод МГТФ.
6. Припой, флюс, и 8 часов свободного времени.
Что должно получится:
Носимую матрицу 8 х 8 делаем так – берем лоскут ткани 20 на 20 см. и приклеиваем к ней «Моментом» все 64 светодиода на расстоянии 2,5 см. Обратите внимание – первая строчка из восьми светодиодов яичницей вверх, втора вниз, затем вверх, вниз и.т.д. Если перепутаете замучаетесь соединять… Держаться они очень крепко отодрать можно только с тканью. Дальше соединяем их по схеме:
Здесь тоже строго. В скетче описана матрица из светодиодов сигнальные линии, которых соединяются как на схеме. Сверху вниз и поочередно слева направо, затем справа налево.
Питание светодиодов в любом направлении. Питание я делал тоже “змейкой”. Вход первого светодиода подключаем к 12 входу ардуины. Сама ардуина пришита на этот же лоскут. Маленькая Nano, без ножек её под футболкой почти не видно.
Между первыми и последними столбиками пришита лента-липучка для одежды, ответная часть которой пришита к футболке с внутренней стороны. Ну и теперь матрица-лоскут приклеивается изнутри к футболке.
В конструкции ещё есть кнопка для смены эффектов и аккумулятор. Они пока в заднем кармане.
Теперь о скетче. Писать, рисовать очень просто. В ролике на футболке у моей помощнице Екатерины сначала поочередно зажигаются буквы – KATRINDETKA. Ниже проиллюстрировано как написать букву K. Первая строчка буквы – 11100011. 1 – светодиоды светятся, 0 – нет.
Виндусовым калькулятором в режиме программиста переводим бинарный код в HEX получаем 0xE3.
В скетче (файл LEDS_64_panel.h) смотрим на строчку:
const uint8_t DIG_0[] PROGMEM =
{
0xE3, 0xE7, 0xEE, 0xFC, 0xFC, 0xEE, 0xE7, 0xE3,
}; //k
Это буква К, все восемь строчек. Первая строчка как раз 0xE3. Мне кажется дальше всё понятно.
Это отображение картинки в байтах. Но можно и бинарном коде без перевода в HEX. Ищите ниже массив:
const uint8_t SQUARE_1[PIXEL_NUM] PROGMEM =
{
1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1,
};
Это квадрат на футболке. На видео после нажатия кнопки. Он описывается просто в двоичном коде. Можно изменить цвет и яркость фона или рисунка.
BACK_COLOUR
MAIN_COLOUR
Можно изменить частоту кадров
SHOW_DELAY
TETRIS_DELAY
Схема очень простая, скетч тоже. Работа очень кропотливая! Зато результат невероятно красивая техно одежда. Видео не передает и десятую долю вау эффекта.
Как работают светодиоды с пиксельной адресацией, рассказывать не буду. Просто сделайте красивую вещь!
Хороших вам выходных!
#define LED_PIN 12
#define KEY_PIN 7
#define PIXEL_IN_STICK 8
#define STICK_NUM 8
#define PIXEL_NUM (PIXEL_IN_STICK * STICK_NUM)
#define MAIN_COLOUR ((uint32_t) 0xff000000)
#define BACK_COLOUR ((uint32_t) 0x00000010)
#define SHOW_DELAY 600
#define TETRIS_DELAY 200
#define CharGroups 3
const uint8_t DIG_0[] PROGMEM =
{
0xE3, 0xE7, 0xEE, 0xFC, 0xFC, 0xEE, 0xE7, 0xE3,
}; //k
const uint8_t DIG_1[] PROGMEM =
{
0x7E, 0xFF, 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0xE7,
};//a
const uint8_t DIG_2[] PROGMEM =
{
0x7F, 0x7F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
};//t
const uint8_t DIG_3[] PROGMEM =
{
0xFE, 0xFF, 0xE3, 0xFF, 0xFE, 0xE7, 0xE7, 0xE7,
};//r
const uint8_t DIG_4[] PROGMEM =
{
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
};//i
const uint8_t DIG_5[PIXEL_NUM] PROGMEM =
{
0xE7, 0xF7, 0xF7, 0xFF, 0xFF, 0xFF, 0xEF, 0xE7,
};//n
const uint8_t DIG_6[] PROGMEM =
{
0xFE, 0xFF, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xFE,
};//d
const uint8_t DIG_7[] PROGMEM =
{
0xFF, 0xFF, 0xE0, 0xFC, 0xFC, 0xE0, 0xFF, 0xFF,
};//e
const uint8_t DIG_8[] PROGMEM =
{
0x7F, 0x7F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
};//t
const uint8_t DIG_9[] PROGMEM =
{
0xE3, 0xE7, 0xEE, 0xFC, 0xFC, 0xEE, 0xE7, 0xE3,
};//k
const uint8_t DIG_10[] PROGMEM =
{
0x7E, 0xFF, 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0xE7,
};//a
const uint8_t DIG_11[] PROGMEM =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const uint8_t SQUARE_1[PIXEL_NUM] PROGMEM =
{
1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1,
};
const uint8_t SQUARE_2[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t SQUARE_3[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t SQUARE_4[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t X_Pixel_1[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t X_Pixel_2[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t X_Pixel_3[PIXEL_NUM] PROGMEM =
{
1, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 1,
};
const uint8_t X_Ray_1[PIXEL_NUM] PROGMEM =
{
1, 0, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 1, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 0, 1,
};
const uint8_t X_Ray_2[PIXEL_NUM] PROGMEM =
{
0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 1, 0,
0, 0, 0, 1, 1, 1, 0, 0,
0, 0, 1, 1, 1, 0, 0, 0,
0, 1, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0,
};
const uint8_t X_Ray_3[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
};
const uint8_t Tetris_1[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t Tetris_2[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t Tetris_3[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t Tetris_4[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t Tetris_5[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_6[PIXEL_NUM] PROGMEM =
{
0, 0, 1, 1, 0, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_7[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_8[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_9[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_10[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_11[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_12[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_13[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_14[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_15[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_16[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_17[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_18[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0,
1, 1, 0, 1, 0, 0, 0, 0,
1, 1, 0, 0, 1, 1, 1, 1,
};
const uint8_t Tetris_19[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_20[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_21[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_22[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0,
0, 0, 0, 0, 0, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_23[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_24[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_25[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_26[PIXEL_NUM] PROGMEM =
{
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_27[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_28[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_29[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 1, 1, 1, 0, 0, 0,
1, 0, 0, 1, 0, 0, 0, 0,
1, 0, 0, 1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_30[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_31[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_32[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_33[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_34[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t Tetris_35[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
};
const uint8_t Tetris_36[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
};
const uint8_t Tetris_37[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 1, 1,
};
const uint8_t EMPTY[PIXEL_NUM] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
p.s. Очень удобно для рисования использовать редактор шрифтов, коих в интернете немерено. Мне понравился этот. Он же на последней картинке за калькулятором. Генерит строчки в С.
И ещё — будут нужны библиотеки: Adafruit_NeoPixel и PinChangeInt. Найдёте у Ады ладно?
Добавлено 09.06.2017
Скетч для цветной матрицы. Скачать.
и ролик с демонстрацией
Комментарии (77)
Hellsy22
05.06.2017 03:39+1Для этого давно придумали Arduino Lilypad и аналогичный обвес. А если гнаться чисто за размером, то ESP8266-09 гораздо меньше — 10mmx10mm.
Рекомендую задуматься, что будет, если у вас за счет сминания одежды или пота закоротит Vcc и Gnd.tolegs
05.06.2017 09:46Lilypad можно, но у него нет USB, а хочется часто менять картинки, немного не удобно с переходником.
ESP сразу нет, скетч после компиляции занимает много памяти. Картинки же. Особенно если фреймы нарисованы в bin.
Atmega328 — самое оно!
Gdalex
05.06.2017 11:06Тогда придется мудрить с питанием: у ESP8266-09 3,3В, а диоды на 5В. Плата меньше, но будет в довесок драйвер на 3.3В.
tolegs
05.06.2017 11:08Светодиоды от 3,5В. На 3,3 работают норм. Памяти нет у ESP — вот проблема!
GennPen
05.06.2017 12:20Без шунтирующих конденсаторов, длинная лента, на пониженном напряжении? Странно что она работает.
tolegs
05.06.2017 12:35Работает. Похоже 160 см. и 64 пикселя — не длинная для них.
GennPen
05.06.2017 12:38+1Ну, в следующий раз советую обратить на это внимание. SMD конденсаторы маленькие, их можно прямо на выводы питания элементов напаивать в подобном навесном монтаже, а хуже от них точно не будет.
tolegs
05.06.2017 13:53Ладно, я ещё разведу платку-пуговицу для подобных носимых проектов. На ней и поставлю кондёр
Gdalex
14.06.2017 09:56У ESP как раз-таки памяти в разы больше, чем у Ардуины (4М против 32К), что называется "почувствуйте разницу"!
sav13
05.06.2017 06:16+2Здравствуйте
Можно крупно показать как светодиоды вшиты в футболку.
Мне кажется, несмотря на МГТФ, провода будут очень быстро отваливаться в месте пайки диодов.GennPen
05.06.2017 08:15Для таких случаев лучше подойдет литцендрат, но с ним мороки гораздо больше чтобы облуживать концы.
LadyN
05.06.2017 13:59Существуют стальные нити и специальные светодиоды, которые этими нитями можно пришивать как пуговицы. В результате контакты не повреждаются при постоянной деформации. Единственная проблема- на стальных нитях нет изоляции, поэтому шить их надо на небольшом расстоянии друг от друга.
tolegs
05.06.2017 14:17Да, да. Я даже сделал такие, но у меня их что-то мало осталось когда пришло вдохновение
lzb_j77
05.06.2017 06:58+1Светодиоды будут нагреваться и обжигать кожу. Как отводится тепло?
nafikovr
05.06.2017 08:35холодным летом этот баг становится фичей
Serge78rus
05.06.2017 10:00+2Однако в начале статьи говорится
шокировать прохожих теплым летним вечером
Oliksolik
05.06.2017 09:46-7Картинка на превью ютуба намекает что такие майки хороши для девушек с низкой социальной ответственностью
цену можно писать)IamMaster65
05.06.2017 11:05+1выражение «ночные бабочки» заиграет новыми красками
prostofilya
06.06.2017 06:53+1Пока клиентов нет, там можно будет и рекламу бегущей строкой пустить, чего время терять.
nafikovr
06.06.2017 09:01+1добавить сервис геолокации и цену динамически формировать с учетом спроса и предложения в конкретной локации. можно еще добавить камеру и выключать показ при обнаружении определенных форм.
Akon32
05.06.2017 12:06А почему все растры, кроме цифр, кодируются байтами, а не битами?
Заголовок спойлераconst uint8_t DIG_10[PIXEL_NUM] PROGMEM = { 0x7E, 0xFF, 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0xE7, };//a const uint8_t DIG_11[PIXEL_NUM] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
но дальше
const uint8_t SQUARE_1[PIXEL_NUM] PROGMEM = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
tolegs
05.06.2017 13:14+1Спасибо за внимательность. Поздно вчера было. Уже поправил.
DIG_** — байтами
SQUARE_* — битами
tolegs
05.06.2017 12:56+1Скетч из статьи выводит на матрицу (футболку) изображение и фон только одного цвета, любого но одного.
Вот вам ещё один скетч позволяющий выводить на футболку цветное изображение.
Ниже массив из скетча. В каждом пикселе первый байт — информация о яркости белого цвета и три последующих информация о цвете. Можно рисовать цветные мультики!
const uint32_t Picture_1[PIXEL_NUM] PROGMEM =
{
0x00FF0000, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x03000000, 0x00030000, 0x00000300, 0x00000003,
0x05000000, 0x00050000, 0x00000500, 0x00000005, 0x07000000, 0x00070000, 0x00000700, 0x00000007,
0x09000000, 0x00090000, 0x00000900, 0x00000009, 0x0B000000, 0x000B0000, 0x00000B00, 0x0000000B,
0x010A0000, 0x00010A00, 0x0000010A, 0x0A000001, 0x030A0000, 0x00030A00, 0x0000030A, 0x0A000003,
0x01000000, 0x00010000, 0x00000100, 0x00000001, 0x03000000, 0x00030000, 0x00000300, 0x00000003,
0x05000000, 0x00050000, 0x00000500, 0x00000005, 0x07000000, 0x00070000, 0x00000700, 0x00000007,
0x09000000, 0x00090000, 0x00000900, 0x00000009, 0x0B000000, 0x000B0000, 0x00000B00, 0x0000000B,
0x010A0000, 0x00010A00, 0x0000010A, 0x0A000001, 0x030A0000, 0x00030A00, 0x0000030A, 0x0000FF00,
};
green_worm
05.06.2017 13:13Не совсем понял схему подключения. Заказывал плату бегущего поворотника на ардуинке. Дак пришлось для последовательного включения 9ти диодов соответственно 10 проводов тянуть. Что в принципе понятно — при последовательном подключении загораться будут все. А тут как управление реализовано?
tolegs
05.06.2017 13:30По-простому очень похоже на работу регистра – у каждого светодиода есть вход и выход они соединяются последовательно друг за другом. В нашем случае 64 штуки -> 8 линеек по 8 светодиодов. (в скетче есть определение, кстати можно поменять). Контроллер заталкивает через всю эту последовательность из 64 светодиодов информацию о яркости и цвете для каждого. Как только в посылке образуется пауза длиннее чем 50 мкс. светодиоды воспринимают её как конец посылки, защелкиваются и каждый выставляет свою информацию о яркости/цвете т.е. зажигаются.
green_worm
07.06.2017 09:49То есть, диод сам вытаскивает из пакета данные о своей светимости? о_О На них какие-то контроллеры стоят что ли на каждом?
Получается, зря я тянул 10 жил проводов на один поворотник? =( Или такая схема не будет работать только при периодически включаемом питании?tolegs
07.06.2017 10:07Да, в каждом светодиоде контроллер и драйвер.
green_worm
07.06.2017 14:37Очень любопытно.
Осенью буду покупать набор новичка с ардуино. Надо будет попробовть эту тему.
Спасибо.tolegs
07.06.2017 17:36Обязательно пробуйте. Очень красиво и эффектно. И самое главное просто
green_worm
07.06.2017 17:53Ну насчет просто — смотря для кого. ;)
У меня крайний опыт в программировании был еще в школе лет 10 назад на турбопаскале да HTML. %)Hellsy22
07.06.2017 22:47На уровне библиотек все действительно элементарно. Вам не нужно думать об интервалах и прочем — просто дайте функции на вход массив из RGB и укажите пин для вывода данных, а она сделает все остальное. Есть и более навороченные библиотеки, которые сами умеют анимировать цвета, создавая плавные переходы, которым можно сообщить как именно сконфигурирована цепочка (типа 10x8) и они уже позволяют с ней обращаться как с экраном имеющим X и Y.
Автор использует серию SK6812, у них есть свои плюсы, но они не так популярны как ws2811/12/12b.green_worm
08.06.2017 11:24Примерно понял, что такое библиотеки. Буду учитывать, когда буду разбираться с языком ардуиновским. Спасибо. =)
GennPen
07.06.2017 15:38Получается, на них проще куб сделать. Гораздо меньше проводов(по три провода на всю плоскость), да еще и с цветом, относительно дешевые(на Али 5р/шт)
tolegs
07.06.2017 17:34Куб! Эти скетчи без изменения подойдут для куба. Да хоть для параллелепипеда )
nafikovr
08.06.2017 09:42где то находил светодиоды в классической форме и с чипом. они для куба подойдут лучше чем сабжевые.
loco777
05.06.2017 13:17Интересно, у кого какие мысли насчёт применения данного устройства для обозначения манёвров на велосипеде. Если его закрепить на спине. Ну и с применением esp или nrf24l01 для избавления от проводов, между человеком и велосипедом.
GennPen
05.06.2017 13:45Нужно тогда думать какие делать понятные знаки для водителей.
Например мигающая стрелка влево:
— Это велосипедист собирается поворачивать влево?
— Или сигнал транспорту сзади чтобы быстрей проезжал слева от велосипедиста?loco777
05.06.2017 14:02+1Мне кажется что у мигающий стрелки влево будет только одно значение. поворот влево. Также как и на машине мигающий левый поворотники, его ведь никогда не воспринимают по правилам как знак для обгона, а наоборот. Если у впереди едущего ТС работает поворотник то обгон запрещен.
GennPen
05.06.2017 14:09Но у машины он не в виде стрелки и не находится посередине. Не воспринимают его как знак для обгона потому что в правилах четко описано в каких случаях он сигнализирует.
Вот если у велосипедиста в районе нижней части спины сделать прямоугольные индикаторы по бокам оранжевого цвета — вот тогда почти сразу будет понятно, что это поворотные сигналы, потому как мысленно будет проводиться аналогия с задними поворотными сигналами на автомобиле.
Заголовок спойлераloco777
05.06.2017 14:24Вы подали хорошую идею, как изменить устройство, сделать в виде прямоугольника. Например как вы написали по бокам оранжевые квадраты для обозначения поворотов и полностью красный прямоугольник как стоп сигнал.
apple01
05.06.2017 21:27Вот готовые реализации, в т.ч. на светодиодной матрице 8x8:
http://www.ebay.com/itm/Rechargeable-Bike-64led-Rear-Tail-Light-Turn-Signal-LaserWireless-Remote-Control/401224203378?_trksid=p2047675.c100005.m1851&_trkparms=aid%3D555018%26algo%3DPL.SIM%26ao%3D2%26asc%3D41376%26meid%3D9d4a5130c73e4a1fa85a7637a729ebb8%26pid%3D100005%26rk%3D1%26rkt%3D6%26mehot%3Dpp%26sd%3D262956571402
http://www.ebay.com/itm/ET-7-LED-Bicycle-Bike-Turn-Signal-Directional-Brake-Light-Lamp-8-sound-Horn/221852005539?_trksid=p2047675.c100005.m1851&_trkparms=aid%3D222007%26algo%3DSIC.MBE%26ao%3D2%26asc%3D41376%26meid%3D9d4a5130c73e4a1fa85a7637a729ebb8%26pid%3D100005%26rk%3D6%26rkt%3D6%26sd%3D262956571402
seri0shka
09.06.2017 14:02Для изучения ардуины и адресных светодиодов подойдёт. Но конкретно для этого проекта было бы выгодней использовать соединение простых светодиодов в матрицу (монохромный вариант). Меньше проводов, дешевле, проще, а главное — время работы больше раз в три-пять от той же батареи. Arduino Nano позволяет без танцев с бубном подсоединить матрицу до 10х10.
матрицаtolegs
09.06.2017 14:09Так тоже хорошо.
Но с SK6812 и этим скетчем можно построить практически не ограниченную по размерам матрицу. Экранище!
А по потреблению они не отличаются от обычных светодиодов той же мощности
Alexey2005
10.06.2017 15:39+1Будь матрица одноцветной, было бы выгодней. Но я не очень представляю, как без танцев с бубном присоединять матрицу трёхцветных RGB-светодиодов (а SK6812 именно RGB). Не говоря уж о том, что по цене примерно то же и выйдет — обычные RGB-светодиоды стоят не сильно дешевле SK6812, а ещё понадобятся дополнительные компоненты, как минимум несколько сдвиговых регистров, которые тоже сколько-то стоят.
seri0shka
10.06.2017 18:23Я писал про монохромный вариант. Кстати, никто не встречал сдвиговых регистров с управлением по одному проводу как у адресных светодиодов?
GennPen
10.06.2017 15:49+1а главное — время работы больше раз в три-пять от той же батареи
В отличии от SK6812 в один момент времени на такой матрице показывается только один столб/строка светодиодов, получается светодиоды работают типа PWM(широта импульса зависит от кол-ва столбцов/строк), без доработок на полную мощность такая матрица никогда не светит. Поэтому и получается якобы экономия энергии. С тем же успехом в матрице на SK6812 можно уменьшить яркость светодиодов.
sstasenco
Здорово! А постирать в машинке можно или лучше сразу новую паять?
betatank
В статье написано, что светодиоды приклеиваются к лоскуту ткани, а он, в свою очередь, крепится к футболке с помощью ленты-липучки. Так что можно просто отлепить и постирать футболку отдельно.
tolegs
Точно, отстегивай и стирай.