POV-спидометр для велосипеда
- Платформы: Espruino Pico, Iskra JS
- Языки программирования: JavaScript
- Тэги: велосипед, подсветка, Espruino Pico, персистенция, рисуем светодиодами, обман зрения
Что это?
Хотите выделиться в толпе велосипедистов? Используя знания из прошлых проектов, соберём простой велокомпьютер и покажем скорость прямо на колесе байка.
Что нам понадобится?
- 8 × Светодиоды 5 мм
- 8 × Резисторы 220 Ом
- Синяя изолента
- Пластиковые стяжки
- Монтажный провод
- Аккумулятор
Как собрать?
- Изучите проект POV-бегущей строки. Бегущая строка для велосипеда основана на этом проекте. Вместо акселерометра используйте цифровой датчик линии. Он замеряет скорость велосипеда и служит началом координат для отображения строки на колесе.
- Один пиксель строки состоит из светодиода и резистора, подключенных к Espruino Pico.
- Возьмите макетную плату Breadboard PCB на 400 точек и соберите устройство из восьми таких пикселей. Припаяйте светодиоды к пинам Espruino Pico
A8
,A6
,A7
,B1
,B10
,B13
,B14
иB15
через резисторы 220 Ом. Правильно подобрать сопротивление резисторов поможет статья в конспекте-Arduino. Припаяйте Espruino Pico и провода питания датчика линии. - Разместите плату, датчик линии и аккумулятор на колесе. Закрепите с помощью пластиковых стяжек.
Алгоритм
- Каждый раз при прохождении датчика линии мимо рамы велосипеда запускается обработчик прерывания.
- Функция обработки прерывания вычисляет скорость движения велосипеда. Зная интервал времени между текущим и предыдущим оборотами, скорость можно рассчитать по формуле:
- Угол сектора колеса, внутри которого будет отображаться скорость, определяет время свечения светодиодов. Чем меньше угол сектора, тем меньше время свечения.
- Угловая частота вращения колеса вычисляется по формуле: Чем больше скорость колеса, тем меньше время свечения светодиодов.
Исходный код
- veloPOV.js
// массив символов var image = { '0': [0x7C, 0x8A, 0x92, 0xA2, 0x7C], '1': [0x00, 0x42, 0xFE, 0x02, 0x00], '2': [0x42, 0x86, 0x8A, 0x92, 0x62], '3': [0x44, 0x82, 0x92, 0x92, 0x6C], '4': [0x10, 0x30, 0x50, 0xFE, 0x10], '5': [0xE4, 0xA2, 0xA2, 0xA2, 0x9C], '6': [0x3C, 0x52, 0x92, 0x92, 0x0C], '7': [0x80, 0x86, 0x98, 0xE0, 0x80], '8': [0x6C, 0x92, 0x92, 0x92, 0x6C], '9': [0x60, 0x92, 0x92, 0x94, 0x78], 'k': [0xFE, 0x08, 0x08, 0x14, 0x22], 'm': [0x3E, 0x20, 0x1C, 0x20, 0x1E], '/': [0x02, 0x0C, 0x10, 0x60, 0x80], 'h': [0xFE, 0x10, 0x10, 0x10, 0x0E] }; // массив пинов для подключения светодиодов var led = [A8, A6, A7, B1, B10, B13, B14, B15]; // радиус колеса в метрах var wheelRadius = 0.165; // количество пустых столбцов между буквами var spaceColomns = 1; // текст для отображения var toShow = ''; // угол отображения текста в радианах var tetta = 0.1; // счетчик обновления текста var update = 0; // длина окружности колеса var circle = 2 * 3.14159 * wheelRadius; // ставим триггер на срабатывание датчика линии, подключенного к пину B3 setWatch(function(e) { // период вращения колеса в секундах var dT = e.time - e.lastTime; // линейная скорость велосипеда в метрах в секунду var speed = circle / dT; // обновляем текст для отображения каждые 5 оборотов if (update++ % 5 === 0) { // переводим из метров в секунду в километры в час toShow = Math.round(speed * 3.6) + 'km/h'; } // угловая частота колеса var omega = speed / wheelRadius; // временной период отображения текста var wordPeriod = tetta / omega; // временной период отображения одной колонки символа var colomnPeriod = wordPeriod / (toShow.length * (spaceColomns + 5) - spaceColomns); // выводим текст на POV дисплей show(toShow, colomnPeriod); }, B3, { edge: 'rising', repeat: true }); // функция отображения текста на дисплее function show(word, colomnPeriod) { var w = 0; var i = 0; var pause = 0; // показываем каждый столбец "пикселей" в символах с периодом colomnPeriod var id = setInterval(function () { // если требуется сделать паузу между символами if (pause-- > 0) { // гасим все пиксели colomn(0x00); } else { // иначе показываем столбцы пикселей colomn(image[word[w]][i++]); } // когда показали все столбцы в символе if (i === 5) { i = 0; // задаем паузу после символа pause = spaceColomns; // когда показали все символы в строке, гасим пиксели и отключаем таймер if (++w === word.length) { colomn(0x00); clearInterval(id); } } }, colomnPeriod); // функция включения нужных пикселей в столбце function colomn(col) { for (var j = 0; j < 8; ++j, col >>= 1) { digitalWrite(led[j], !(col & 1)); } } }
Демонстрация работы устройства
Что дальше?
Добавьте в проект Bluetooth-модуль HC-06 и меняйте текст строки со смартфона прямо на ходу.
Не хотите зависеть от внешнего света при работе с инфракрасным датчиком? Замените его на датчик Холла, а на раму велосипеда прикрепите магнит.
Используйте больше светодиодных линеек и создавайте сложные картины на колесе своего железного коня.