Пост состоит из 2 частей. Общая система управления для 5D кинотеатра и исполнительная часть smell-o-vision.
Для управления внешними устройствами используется программа MultiFunPlayer. Пока про нее не узнал планировал использовать писк в правом канале аудиодорожки. Для воспроизведения используется MultiFunPlayer версии 1.31.3 и MPC-BE версии 1.7.3. В настройках MPC-BE нужно включить дистанционное управление.
Для аудио/видеофайла должен быть составлен файл funscript. Аудио/видеофайл воспроизводится MPC-BE. MultiFunPlayer синхронизируется с MPC-BE и подхватывает funscript с темже именем файла и лежащий в тойже папке. MultiFunPlayer в нужный момент времени отправляет команды в COM порт.
Пример funscript.
{
"version": "1.0",
"inverted": false,
"range": 90,
"actions": [
{ "at": 0, "pos": 0 },
{ "at": 1000, "pos": 10 },
{ "at": 2000, "pos": 20 },
{ "at": 3000, "pos": 30 },
{ "at": 4000, "pos": 40 },
{ "at": 5000, "pos": 50 },
{ "at": 6000, "pos": 0 },
{ "at": 7000, "pos": 0 },
]
}
После "at": указывается таймкод в миллисекундах. После "pos": указывается значение от 0 до 100 которое будет отправлено внешнему устройству. Первая и последняя строка могут быть не выполнены. Если устройств несколько то для управления каждым используется свой файл funscript и к названию файла дописывается канал (еще не пробовал использовать). По умолчанию используется канал L0. Чтобы MultiFunPlayer не давал лишние команды нужно переключить интерполяцию в Step и отключить Auto-home.
MultiFunPlayer отправляет в COM порт команды на языке T-code. Я использую настройки COM порта типичные для устройств на Arduino: скорость 9600, формат данных 8N1.
Пример строки T-code:
L01000I100
L0 канал (L группа каналов, 0 номер канала в группе), 1000 значение(от 0000 до 9999), I100 время выполнения(не используется).
"pos": 0 соответствует L00000
"pos": 10 соответствует L01000
"pos": 20 соответствует L02000
"pos": 90 соответствует L09000
"pos": 100 соответствует L09999
Для упрощения прошивки Arduino я жду по UART букву L, R, V или A (группа каналов) и читаю следующие за ними 2 цифры (номер канала и 1 разряд значения). Так на каждый канал можно получить 10 дискретных значений.
"pos": 0 соответствует L00
"pos": 10 соответствует L01
"pos": 20 соответствует L02
"pos": 90 соответствует L09
Во время инициализации MultiFunPlayer и Arduino возможны ложные команды поэтому нужно предусмотреть выключатель блокирующий работу исполнительных устройств.
Исполнительная часть smell-o-vision.
Прошивка написана в ArduinoIDE 1.8.19 (последняя версия не требующая интернет для установки и работы). 3D модели делались в OpenSCAD
Состоит из 5 вентиляторов направленных в сторону зрителя. Используются осевые вентиляторы 80X25 12V. Провода + вентиляторов соединены вместе. Перед вентиляторами установлены картриджи.
Держатель картриджа
Код OpenSCAD
$fn=100;
difference()
{
union()
{
translate([-45,-45,0])
cube([90,90,4]);
}
union()
{
union()
{
translate([-71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([-71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
}
cylinder(d=78,h=4);
}
}
difference()
{
cylinder(d=87,h=20);
cylinder(d=83,h=20);
}
Средний соединитель вентиляторов
Код OpenSCAD
$fn=100;
difference()
{
union()
{
translate([-45,-75,0])
cube([110,150,4]);
}
union()
{
union()
{
translate([-71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([-71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
cylinder(d=78,h=4);
}
translate([0,-100,0])
union()
{
translate([-71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([-71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
cylinder(d=78,h=4);
}
translate([0,100,0])
union()
{
translate([-71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([-71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
cylinder(d=78,h=4);
}
translate([55,-57,0])
cylinder(d=4.5,h=4);
translate([55,57,0])
cylinder(d=4.5,h=4);
}
}
Крайние соединители вентиляторов
Код OpenSCAD
$fn=100;
difference()
{
union()
{
translate([-45,-25,0])
cube([90,50,4]);
}
union()
{
translate([0,-50,0])
union()
{
translate([-71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([-71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
cylinder(d=78,h=4);
}
translate([0,50,0])
union()
{
translate([-71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,-71.5/2,0])
cylinder(d=5.5,h=4);
translate([-71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
translate([71.5/2,71.5/2,0])
cylinder(d=5.5,h=4);
cylinder(d=78,h=4);
}
}
}
Картриджи сделаны из фильтров респиратора Исток. От фильтра оставлен только корпус и пластмассовые решетки. Внутри лежит ватный диск пропитанный ароматизатором. Картриджи нужно хранить в герметичных контейнерах. Экспериментально выяснено что в корпусе должно быть много свободного места и свободный проход воздуха.
Прошивка Arduino. Для управления вентиляторами использован релейный модуль с инверсными входами. HIGH выключение вентилятора, LOW включение вентилятора.
void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT); //fan1
pinMode(12, OUTPUT); //fan2
pinMode(11, OUTPUT); //fan3
pinMode(10, OUTPUT); //fan4
pinMode(9, OUTPUT); //fan5
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, HIGH);
}
byte key=0;
byte group=0;
byte channel=4;
void loop()
{
if (Serial.available())
{
byte in = Serial.read();
if(in=='L')
{
key=1;
group=1;
}
if(key==1)
{
if(in=='0')
{
key=2;
channel=0;
}
}
else if(key==2)
{
key=3;
if(group==1&channel==0)
{
//smell-o-vision code
if(in=='0')
{
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, HIGH);
}
if(in=='1')
{
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, HIGH);
digitalWrite(13, LOW);
}
if(in=='2')
{
digitalWrite(13, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, HIGH);
digitalWrite(12, LOW);
}
if(in=='3')
{
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, HIGH);
digitalWrite(11, LOW);
}
if(in=='4')
{
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
}
if(in=='5')
{
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, LOW);
}
//smell-o-vision code end
}
}
}
}
Соответствие команд и вентиляторов
"pos": 0 выключает все вентиляторы
"pos": 10 включает вентилятор 1
"pos": 20 включает вентилятор 2 "pos": 30 включает вентилятор 3 "pos": 40 включает вентилятор 4 "pos": 50 включает вентилятор 5
Между включение вентилятора и тем как воздух дойдет до лица есть задержка. Решить эту проблему можно включая вентилятор заранее или расположив более компактный вариант исполнительного устройства ближе к лицу (работа над этим уже идет). Планирую сделать и другие устройства работающие синхронно с видео (имитатор климата, трясущееся кресло ...)
Если захотели повторить и код из поста не работает попробуйте его не скопировать а перепечатать.
Этот редуктор можно собрать с передаточным числом 1/3 , 1/4 , 1/9 , 1/12 , 1/16.
Изменение формы корпуса позволило немного уменьшить габариты и освободить место для крепежных отверстий.Крепежные винты стягивают части корпуса.
Для выходного вала использован подшипник 6700.Он намного меньше чем 608.При этом диаметр выходного вала 10 mm вместо 8.Все остальные подшипники 604.
Изначально планировалась возможность сборки 3 ступенчатого редуктора.Но когда получилось сделать передачу 1/4 (15/60) в одну ступень остановился на 2 ступенчатом варианте.
Это упростило конструкцию.Все детали печатаются без поддержек.мосты стали короче.
base1 мотор находится соосно с выходным валом.расстояние между осями выходного вала и промежуточной шестеренки 40 mm.
base2 мотор сдвинут к промежуточной шестеренке на 2.5 mm.расстояние между осями выходного вала и промежуточной шестеренки 40мм.
base3 мотор находится соосно с выходным валом.расстояние между осями выходного вала и промежуточной шестеренки 37.5 mm.
мотор прикручивается к основанию(base) двумя винтами m3x6 с потайной головкой.на вал мотора напрессовывается шестеренка(motorgear).
В одноступенчатом варианте на основание ставится выходная шестеренка(outgear) и закрывается крышка(cover).с нижней стороны выходной и промежуточной шестеренки углубление для подшипника 604.
В двухступенчатом варианте на основание ставится промежуточная шестеренка(intgear) и закрывается корпусом первой ступени(intcover).на корпус первой ступени ставится выходная шестеренка и закрывается крышкой.в крышке находится верхний подшипник промежуточной шестеренки(604) и подшипник выходного вала(6700).
Необходимые детали для сборки редукторов с разными передаточными числами
Распечатал планетарный редуктор для мотора R540 33110.
Передаточное число 4 , количество сателлитов 4 , количество зубьев солнца и сателлитов 20 , количество зубьев короны 60 , модуль 1.
Материал PETG MAKO , слой 0.2mm , линия 0.4mm (на первом слое 0.6mm) , скорость первого слоя и внешних периметров 20mm/s , скорость в остальных местах 50mm/s.
Сателлиты на подшипника 604RS зафиксированных стопорным кольцом.
Водило собрано из верхней и нижней половинки.
в центре подшипник 604RS.
Мотор закреплен на 2 потайных винта M3x6 под шестигранник.