Благодарим вежливых водителей: LED-табло для автомобиля на Arduino MKR1000
Компоненты и материалы
- Arduino MKR1000 — 1 шт.
- Bluetooth-модуль BlueSMiRF Silver — 1 шт.
- Logic Level Converter 4-канальный (BSS138) — 1 шт.
- Adafruit DotStar Matrix 8×32 (256 RGB LED) — 1 шт.
- JST SM 4-pin кабель — 1 шт.
- DC Jack 2.1 мм — 1 шт.
- Блок питания 5V 4A — 1 шт.
- Pin header 4pin — 1 шт.
- Макетная плата — 1 шт.
- Корпус проекта — 1 шт.
- Фанера берёзовая 6 мм (1/4″) 11×38 см — 1 шт.
- Двусторонний скотч — 1 рулон
Инструменты
- Паяльник
- Клейкий пистолет
- Фрезерные коронки (Forstner bits) для чистых отверстий
- Дрель
- Наждачная бумага (120 grit)
Программное обеспечение
- Arduino IDE (версия 1.6.9 hourly build для MKR1000)
- Virtual Shield for Arduino (Windows)
- Библиотеки: Adafruit DotStar, Adafruit DotStarMatrix, Adafruit GFX, ArduinoJson, VirtualShield
О проекте
Хотел общаться с водителями понятнее, чем мигание фарами или жестами. Вдохновился Джеймсом Бондом: текст на заднем стекле. Устройство крепится на заднее стекло, управляется с телефона по Bluetooth — можно показать «Спасибо», «Пропускаю», «Поворот налево» и т.д.


Особенности MKR1000
Плата 3.3В, не 5В-толерантна. Для DotStar-матрицы и Bluetooth нужен 5В — обязателен логический преобразователь уровня (Logic Level Converter).
Проверка компонентов
- DotStar Matrix — подключаем Data/Clock к SPI (пины 11/12 на MKR1000), пример
matrixtest. - Virtual Shield + Bluetooth — по инструкции GitHub. TX/RX на пинах 14/13.

Разбор кода
Подключение библиотек
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_DotStarMatrix.h>
#include <Adafruit_DotStar.h>
#include <ArduinoJson.h>
#include <VirtualShield.h>
#include <Text.h>
#include <Graphics.h>
#include <Recognition.h>
#include <Colors.h>
Инициализация матрицы и шилда
Adafruit_DotStarMatrix matrix = Adafruit_DotStarMatrix(
32, 8, DATAPIN, CLOCKPIN,
DS_MATRIX_TOP + DS_MATRIX_LEFT + DS_MATRIX_COLUMNS + DS_MATRIX_ZIGZAG,
DOTSTAR_GBR
);
const uint16_t colors[] = {
matrix.Color(255,0,0), matrix.Color(0,255,0), matrix.Color(0,0,255),
matrix.Color(255,0,255), matrix.Color(255,0,106), matrix.Color(255,255,255)
};
VirtualShield shield;
Graphics screen = Graphics(shield);
Recognition speech = Recognition(shield);
Setup
void setup() {
matrix.begin();
matrix.setTextWrap(false);
matrix.setBrightness(40);
matrix.setTextColor(colors[0]);
DisplayText("Initializing...", 4, 10);
shield.setOnRefresh(refresh);
speech.setOnEvent(onSpeech);
screen.setOnEvent(screenEvent);
shield.begin(); // 115200 baud
DisplayText("Initializing...finished", 3, 10);
}
Главный цикл
void loop() {
shield.checkSensors(); // обработка событий Bluetooth
}
Обработка обновления экрана (кнопки)
void refresh(ShieldEvent* shieldEvent) {
screen.clear(ARGB(123,86,204));
thanksId = screen.addButton(10, 50, ". Thank you .");
welcomeId = screen.addButton(10, 100, ". Welcome .");
turnLeftId = screen.addButton(10, 150, ". Left .");
stoppingId = screen.addButton(175, 50, ". Stopping .");
startingId = screen.addButton(175, 100,". Starting .");
turnRightId = screen.addButton(175, 150,". Right .");
backoffId = screen.addButton(10, 225, ". Back Off .");
calling911Id= screen.addButton(10, 290, ". Calling 911 .");
}
Обработка нажатий кнопок
void screenEvent(ShieldEvent* shieldEvent) {
if(screen.isPressed(thanksId)) DisplayText("Thank You", 5, 100);
if(screen.isPressed(welcomeId)) DisplayText("You're welcome", 2, 100);
if(screen.isPressed(backoffId)) DisplayText("Please back off", 4, 100);
if(screen.isPressed(stoppingId)) DisplayText("...stopping...", 0, 100);
if(screen.isPressed(startingId)) DisplayText("...starting...", 1, 100);
if(screen.isPressed(turnLeftId)) DisplayText("Turning LEFT", 3, 100);
if(screen.isPressed(turnRightId)) DisplayText("Turning RIGHT", 3, 100);
if(screen.isPressed(calling911Id))DisplayText("Calling 911", 0, 100);
}
Вывод бегущей строки на матрицу
void DisplayText(String message, int colorIndex, int currDelay) {
int x = matrix.width();
int maxX = -1 * (message.length() * 6); // 5px буква + 1px пробел
matrix.setTextColor(colors[colorIndex]);
while(x > maxX) {
matrix.fillScreen(0);
matrix.setCursor(x, 0);
matrix.print(message);
--x;
matrix.show();
delay(currDelay);
}
}
Сборка корпуса
Корпус из фанеры с вырезами под матрицу и разъёмы. Отверстия сверлятся фрезерными коронками (Forstner) для чистоты. Макетная плата укорочена для доступа к USB. Матрица клеится термоклеем. Питание: 5V 4A на матрицу через auxiliarный разъём, MKR1000 — от отдельного 5V адаптера через DC-DC или прямо от USB.


Монтаж в автомобиле
Планировались вентильные чашки и резинки — требует доработки.
Код
Полный скетч: GitHub
Схемы

Производственный процесс
- UnifiedWater v1: полный набор датчиков качества воды на Arduino MKR GSM
- Переносная система голосования с GSM-связью
- Умные очки для знакомств на Arduino 101 и tinyTILE BLE
- DIY аркадная игра Whac-A-Mole (кнопочная версия) — проект на Arduino
- Модерн-джукебокс: Raspberry Pi + Arduino, LED-визиализация музыки, 3D-корпус
- DIY Arduino Smartwatch: самодельные умные часы в стиле Apple Watch
- DIY полнодиапазонная Arduino-радиоприемник на Si4730 (ДВ, СВ, КВ, УКВ) — бюджетная пошаговая сборка
- Покрытия печатных плат: типы, применение и лучшие практики
- Электроэрозия (ЭЭО): технология, методы и применение
- Подробное руководство по фланцевым подшипникам: Типы, особенности и применение