Оглавление:
2025 Автор: John Day | [email protected]. Последнее изменение: 2025-01-13 06:58
Прежде чем приступить к объяснению этого проекта, я хотел бы извиниться за низкое качество изображения и видео, но, честно говоря, очень сложно получить резкое и четкое изображение при запуске POV с помощью обычной камеры, такой как моя мобильная камера. Для захвата истинного движения нужен очень светосильный диафрагменный оптический объектив, но я загружу лучшее видео, когда наконец смогу купить камеру CANON.
Что такое точка зрения
POV расшифровывается как Persistence Of Vision Globe, который связан с феноменом человеческого зрения. Световой раздражитель задерживается как последействие на сетчатке примерно на 1/10 секунды. Когда световые стимулы чередуются в быстрой последовательности, они сливаются в одно непрерывное изображение. Фактически это основа для кино- и телеаппаратов. POV создает такую иллюзию (обманывает нас) и создает изображение, вращая массив светодиодных фонарей вокруг одной точки или оси.
Что такое проектная инновация
Конечно, POV - это не новая идея, и множество проектов уже существует в Instructables или на других сайтах, однако в этих проектах в основном используется предустановленный статический храм или изображение, которое в основном считывается из памяти MCU или SD-карты, но в этом проекте мы используем развертывание красивых функций чипа с поддержкой IOT, такого как ESP8266, в этом вопросе.
Благодаря этим функциям IOT мы
- может легко загружать новые изображения в память по беспроводной сети
- создать желаемый сценарий показа изображений с любой последовательностью и любой продолжительностью
- нет необходимости перепрограммировать чип или отключать карту памяти и повторно подключать ее для новой анимации
- удобный веб-хостинг IOT позволяет каждому управлять POV с помощью мобильного телефона или планшета даже удаленно
- очень дешевая аппаратная реализация с возможностью хранения более 30 различных изображений
Как работает POV
На дисплеях POV линейный (одномерный) массив светодиодных фонарей вращается вокруг одной точки, как колесо велосипеда. Измеряя скорость их вращения и контролируя их вспышки с точностью до миллисекунды, мы можем создать иллюзию 2- или 3-мерного изображения, задерживающегося в воздухе. Давайте рассмотрим один кадр любого эффекта (изображение, текст,…), каждый кадр состоит из множества пикселей и, следовательно, многих линий в плоскости или сферической области, POV отображает это изображение с одной строкой изображения, положение которой изменяется вместе с его вращением для заполнения это изображение, поэтому проблема заключается в том, как точно контролировать цвет пикселя светодиода во времени и пространстве, чтобы он мог создавать все изображение. POV классифицируется на основе оси вращения, типа эффекта, который может отображаться, и того, сколько цвета может создать.
По разным осям вращения, может производить плоский, цилиндрический и сферический дисплей POV.
во многих проектах POV используются простые одноцветные светодиоды или высокоскоростные интеллектуальные пиксели, такие как WS2812 или APA104, и в этом проекте мы используем быстрое обновление светодиодных чипов APA102 с частотой обновления практически около 16 МГц. Этот светодиодный чип имеет 2 линии для управления (земля, данные, часы, + 5 В)
Шаг 1. Как построить POV
Сначала мне нужна конструкция для крепления концентратора POV, изготовление металлической или неметаллической конструкции зависит от того, что у вас в руках. Вы можете сделать его из любого доступного материала, чтобы установить его на стену или добавить ножки, чтобы сделать подставку. Мой друг делает простой штатив и монтирует механизм зубчатого ремня, чтобы снизить об / мин двигателя постоянного тока примерно на 500. Малая математика Для получения четкого и согласованного изображения нам нужно обновление кадра со скоростью около 20 кадров в секунду, это означает, что иметь четкое изображение, которое нам нужно, чтобы многократно отображать его примерно 20 раз в секунду, так как мой POV состоит из 1 диагональной светодиодной ленты, следовательно, каждый кадр завершается с половиной или вращением, другими словами, нам нужно идеальное число оборотов ступицы около 600, и с этим числом оборотов каждый оборот занимал около 100 мс. следующее уравнение демонстрирует, что концепция RPM = (fps / Nb) * 60, которая Nb равна Number of Branch, и в этом случае у нас есть RPM = (20/2) * 60 = 600, мой POV вращается около 430 об / мин, поэтому мой fps составляет около 15 fsp что довольно хорошо в этом отношении. Сборка механической части
На следующем этапе я использовал кусок фрезерованного цилиндра из ПВХ, чтобы удерживать светодиодную планку. Для соединения ступицы с валом шкива один болт M10 был прикручен к задней части детали PCV. Два медных кольца, установленных на валу шкива, для передачи 5 В постоянного тока на плату и светодиодную ленту, затем, как показано на следующих рисунках, эта деталь установлена на простом шкиве. система передачи времени, которая подключена к двигателю постоянного тока 12 В, каждая часть имеет собственный источник питания и заключена в белый ящик, прикрепленный к ножкам
Шаг 2: реализация программного обеспечения, часть 1
Чтобы продемонстрировать данное изображение в светодиодной ленте, каждое изображение должно быть пикселизировано, затем загружено в память MCU, а затем построчно отправлено на светодиодную ленту, для этого я сделал программное обеспечение для двух разных платформ, одно из которых основано на обработке времени выполнения Java и другие на C ++ для MCUPпиксельной программы обработки, которую эта программа написала в Processing IDE, и она просто открывает файл изображения, а затем поворачивает его поэтапно, чтобы извлечь пиксельные строки изображения. Я выбираю 200 строк для отображения любого изображения, поэтому я поворачиваю изображение вплотную (360 /200=1,8 градуса) 200 раз, чтобы извлечь 200 строк. Поскольку моя светодиодная лента состоит из 144 светодиодов со встроенным чипом APA102, поэтому все изображение имеет 200 * 144 = 28800 пикселей. Поскольку каждый цвет в чипе APA102 отображается с 4 байтами (W, RGB), следовательно, размер каждого изображения составляет точно 200 * 144 * 4 = 115200 или 112,5 КБ, следующий код обработки демонстрирует последовательность пикселизации изображения, и результатом будет файл расширения bin, который может быть выгруженным в память MCU
PImage img, black_b, image_load; вывод PrintWriter; int SQL; float led_t; byte pov_data; int line_num = 200; Строка _OUTPUT = "";
недействительные настройки ()
{selectInput ("Выбрать изображение", "imageChosen"); noLoop (); ждать(); }
установка void ()
{вывод = createWriter (_OUTPUT); black_b = createImage (SQL, SQL, RGB); black_b.loadPixels (); for (int i = 0; i = line_num) {noLoop (); output.flush (); output.close ();} фон (black_b); pushMatrix (); imageMode (ЦЕНТР); перевести (SQL / 2, SQL / 2); повернуть (радианы (l * 360 / line_num)); изображение (img, 0, 0); popMatrix (); pushMatrix (); for (int i = 0; i <144; i ++) {цвет c = get (int (i * led_t + led_t / 2), int (SQL / 2)); output.print ((char) красный (c) + "" + (char) зеленый (c) + "" + (char) синий (c)); // print ((char) red (c) + "" + (char) green (c) + "" + (char) blue (c) + ";"); заполнить (с); rect (i * led_t, (SQL / 2) - (led_t / 2), led_t, led_t); } // println (); popMatrix (); // задержка (500); l ++; }
недействительный keyPressed ()
{output.flush (); // Записывает оставшиеся данные в файл output.close (); // Завершаем работу с файлом exit (); // Останавливает программу}
void imageChosen (Файл f)
{if (f == null) {println ("Окно было закрыто или пользователь нажал кнопку отмены."); exit (); } else {если (f.exists ()) img = loadImage (f.getAbsolutePath ()); Строка s = f.getAbsolutePath (); Строка список = разделить (s, '\'); int n = list.length; Строка fle = split (список [n-1], '.'); println ("Открыть файл:" + fle [0]); _OUTPUT = fle [0] + ". Bin"; // img = loadImage ("test.jpg"); int w = img.width; int h = img.height; SQL = max (ш, в); размер (SQL, SQL); led_t = SQL / 144.0; println ("h =" + h + "w =" + w + "max =" + SQL + "size led =" + led_t); }} void mousePressed () {loop ();}
void mydata ()
{байт b = loadBytes ("something.dat"); // Распечатать каждое значение от 0 до 255 for (int i = 0; i <b.length; i ++) {// Каждое десятое число, начать новую строку if ((i% 10) == 0) println (); // байты от -128 до 127, это преобразуется в 0 до 255 int a = b & 0xff; печать (+ ""); } println (); // Выводим пустую строку в конце saveBytes ("numbers.dat", b); } void wait () {while (img == null) {задержка (200); } петля(); }
Шаг 3: реализация программного обеспечения, часть 2
Программа отображения MCU
Высокопроизводительный чип ESP8266 был выбран по нескольким причинам, во-первых, он хорошо разработал открытые инструменты SDK для использования преимуществ Wi-Fi вместе с памятью для размещения веб-сервера для пользователя. Благодаря этим возможностям удобный веб-сервер, предназначенный для загрузки пиксельного изображения в память MCU и создания пользовательского сценария для показа. С серией ESP-12E 4 Мб мы можем использовать 1 Мб для программы и 3 Мб для изображений, размер которых составляет 112,5 КБ для пиксельного изображения, мы можем примерно 25 изображений, загруженных на MCU, и можем сделать любую последовательность или любой период отображения для загруженного изображения, которое я использую Реализация базы кода Arduino для создания веб-сервера. код имеет три основные функции в своем цикле, как показано ниже
void loop () {если (! ПОКАЗАТЬ &&! ТЕСТ) server.handleClient (); if (SHOW) {if ((millis () - OpenlastTime)> DURATION [image_index] * 1000) {if (image_index> = IMAGE_NUM) image_index = 0; _memory_pointer = начальный_адрес_файла_образа [image_index]; Serial.printf ("Номер файла =% u имя:% s адрес:% u продолжительность:% u / n", image_index, IMAGES [image_index].c_str (), start_address_of_imagefile [image_index], DURATION [image_index]); Current_imageLine = 0; image_index ++; OpenlastTime = миллис (); } если ((micros () - lastLineShow)> lineInterval) {lastLineShow = micros (); ESP.flashRead (_memory_pointer, (uint32_t *) светодиоды, NUM_LEDS * 3); FastLED.show (); _memory_pointer + = (NUM_LEDS * 3); Current_imageLine ++; задержка (LineIntervalDelay); } если (Current_imageLine> = IMAGES_LINES) {Current_imageLine = 0; _memory_pointer = начальный_адрес_файла_образа [image_index-1]; }} optimistic_yield (1000); }
Обработчик сервера server.handleClient (); отвечает за обработку любого клиентского запроса на веб-хосте, этот веб-сайт может быть спроектирован произвольно для загрузки данных, изменения настроек показа любого отчета о состоянии. Мой веб-хостинг состоит из трех вкладок, таких как следующие изображения на первой вкладке, мы можем проверить текущий сценарий шоу с последовательностью и продолжительностью для каждого изображения, а также с сетевой информацией, а также с показанными оборотами POV.
на вкладке загрузки изображения мы можем загрузить пиксельное изображение в память MCU или удалить конкретное изображение
на вкладке сети мы можем изменить настройки сети, такие как режим Wi-Fi, статический IP-адрес, имя сети и пароль,..
Загрузчик изображений
эта функция-сервер-клиент запрашивает Ajax для загрузки пиксельного изображения в память MCU, а затем записывает файл в память в необработанном формате, чтобы чтение файла происходило как можно быстрее. Сохранение начального и конечного местоположения в памяти в таблице для отображения на светодиодной ленте
Функция отображения
Я использовал библиотеку FastLED для отображения пикселей на светодиодной ленте, эта библиотека является одной из самых успешных и хорошо разработанных для светодиодных шоу на платформе AVR и ESP. Просто нужно отправить функцию FastLED, местоположение сохраненного светодиодного пикселя. мы считываем построчно пиксели из памяти и показываем это на светодиодной ленте и ждем, когда сработает новый флаг вращения. мы повторяли эту последовательность, пока не было прочитано 200 строк каждого изображения
весь код находится в моем репозитории git здесь
Ниже приведено видео POV в действии, которое записано мобильной камерой, и, как я объяснил, качество видео не очень хорошее из-за низкой скорости диафрагмы непрофессиональной камеры.