Страница 1 из 1

Сканер с Dmx-512 по теме "Прибор поворотная голова".

Добавлено: 22 апр 2020, 22:11
Лев
Привет Народ!
Я расскажу про свой первый световой прибор под управлением DMX-512.
История началась с того, что мой знакомый Dj отдал мне со школы сканер(stardance).
У него, к моему сожалению вылетели мозги, были они сделаны на микроконтроллере pic.
Я долго думал что с ним сделать, читал форумы и наткнулся на тему Антона Н - Прибор "Поворотная голова" , на этом форуме.
Идея Антона меня заинтересовала. Мой проект собран полностью на его основе, за исключением еще одного канала для вращения чашки с зеркалами.
Сканер работает с тремя шаговыми двигателями: 1)Двигатель панорамы (1 канал dmx); 2)Двигатель тилта (2 канал dmx); 3) Двигатель чашки с зеркалами, именно он вращает "лунный цветок" (3 канал dmx).
Я использовал для двигателей драйвер a4988, мне показались они довольно шумными, лучше поискать что то подороже.
Каждый мотор останавливается по датчику(на фото будут видны) и ходит в своем диапазоне.
Этот диапазон, прошу прощение за тавтологию, настраивается в прошивке, в подпункте двигатель(1,2,3)>Слежение>Получение заданного положения>(NUM_STEPS_MOTOR - 1) / 127) ;
А еще в скетче я настраивал делитель частоты, для настройки моторов (myMotor1.setDivider(5); // делитель частоты) и число шагов (#define NUM_STEPS_MOTOR 806 // число шагов двигателя на оборот).
В качестве мозгов использовал Arduino Pro Mini на Atmega 168. Все паял на макетной платке.
Намотал торик с тремя обмотками для раздельного питания. Для лампы использовал электронный трансформатор, после тестов добавил фильтр от компьютерного блока
питания, чтобы убрать помехи по сети.
Пока что все, если возникнут вопросы - спрашивайте.
Я добавлю свои фото, и с темы "Прибор поворотная голова", если так можно.
От себя скажу, что не стоит заниматься данным делом. Я потратил много времени, но желаемого результата не добился, зато опыт получил.
Если тянет к свету, лучше поискать сканеры/головы на вторичке, с клубов, можно найти реально хорошие приборы, подделать и работать на них.
Вот скетч:
=====================================================================================

Код: Выделить всё

#include <TimerOne.h>
#include <StepDirDriver.h>
#include <DMXSerial.h>
#include <Button.h>

#define NUM_STEPS_MOTOR 806  // число шагов двигателя на оборот
#define DMX_CHANEL_MOTO_1 1   // канал DMX для двигателя 1
#define DMX_CHANEL_MOTO_2 2   // канал DMX для двигателя 2
#define DMX_CHANEL_MOTO_3 3   // канал DMX для двигателя 2

unsigned int currentStep1=0;  // текущее положение двигателя
unsigned int setStep1=0;  // заданное положение двигателя
int stepsToDo1;  // сколько шагов надо сделать
byte mode1=0;  // режим: 0 - пауза, 1 - синхронизация датчик закрыт, 2 - синхронизация датчик открыт, 3 - слежение
unsigned int currentStep2=0;  // текущее положение двигателя
unsigned int setStep2=0;  // заданное положение двигателя
int stepsToDo2;  // сколько шагов надо сделать
byte mode2=0;  // режим: 0 - пауза, 1 - синхронизация датчик закрыт, 2 - синхронизация датчик открыт, 3 - слежение
unsigned int currentStep3=0;  // текущее положение двигателя
unsigned int setStep3=0;  // заданное положение двигателя
int stepsToDo3;  // сколько шагов надо сделать
byte mode3=0;  // режим: 0 - пауза, 1 - синхронизация датчик закрыт, 2 - синхронизация датчик открыт, 3 - слежение
byte timer=0; // таймер

StepDirDriver myMotor1(11, 10, 5);  // создаем объект типа StepDirDriver, задаем выводы для сигналов STEP, DIR, ENABLE
StepDirDriver myMotor2(13, 12, 6);  // создаем объект типа StepDirDriver, задаем выводы для сигналов STEP, DIR, ENABLE
StepDirDriver myMotor3(2, 3, 9);  // создаем объект типа StepDirDriver, задаем выводы для сигналов STEP, DIR, ENABLE
Button sens1 (7, 11);  // создание объекта для датчика 1
Button sens2 (8, 13);  // создание объекта для датчика 2
Button sens3 (4, 2);  // создание объекта для датчика 3

void setup() {
  DMXSerial.init(DMXReceiver);
  Timer1.initialize(250);  // инициализация таймера 1, период 250 мкс
  Timer1.attachInterrupt(timerInterrupt, 250);  // обработчик прерываний
  myMotor1.setMode(0, false);  // шаговый режим, без фиксации при остановке
  myMotor1.setDivider(5);     // делитель частоты 30
  myMotor2.setMode(0, false);  // шаговый режим, без фиксации при остановке
  myMotor2.setDivider(2);     // делитель частоты 30
  myMotor3.setMode(0, false);  // шаговый режим, без фиксации при остановке
  myMotor3.setDivider(8);     // делитель частоты 30
}

void loop() {

//--------------------------------- двигатель 1 ---------------------------
  if( mode1 == 0 ) {
    // ожидание фильтрации датчиков
    if( timer > 40 ) {
      if( sens1.flagPress == true ) mode1=2;   
      else mode1=1;     
    }   
  }

  else if( mode1 == 1 ) {
    // синхронизация датчик закрыт
    myMotor1.step(-10); // по часовой
    if( sens1.flagPress == true ) {
      myMotor1.step(0);
      mode1=3;
    }
  }

  else if( mode1 == 2 ) {
    // синхронизация датчик открыт
    myMotor1.step(10); // против часовой
    if( sens1.flagPress == false ) {
      myMotor1.step(0);
      mode1=3;
    }
  }
 
  else if( mode1 == 3 ) {
    // слежение

  // ------------------------------------ СЛЕЖЕНИЕ
   
  // проверка остановки двигателя
  if( myMotor1.readSteps() == 0) {
    // двигатель остановился

    // получение заданного положения
    setStep1 = (unsigned int)((unsigned long)DMXSerial.read(DMX_CHANEL_MOTO_1) * (NUM_STEPS_MOTOR - 1) / 255) ;
   
    // определение сколько шагов надо сделать
    stepsToDo1 = currentStep1 - setStep1; // ошибка рассогласования

//    if( abs(stepsToDo1) >= (NUM_STEPS_MOTOR / 2) ) {

//      if((stepsToDo1) > 0) stepsToDo1 -= NUM_STEPS_MOTOR;
//      else                stepsToDo1 += NUM_STEPS_MOTOR;     
//    }
 
    myMotor1.step(stepsToDo1);  // запуск двигателя
    currentStep1 = setStep1;  // перегрузка текущего положения   
  }

  }
  else mode1=0;


//--------------------------------- двигатель 2 ---------------------------
  if( mode2 == 0 ) {
    // ожидание фильтрации датчиков
    if( timer > 40 ) {
      if( sens2.flagPress == true ) mode2=2;   
      else mode2=1;     
    }   
  }

  else if( mode2 == 1 ) {
    // синхронизация датчик закрыт
    myMotor2.step(-10); // по часовой
    if( sens2.flagPress == true ) {
      myMotor2.step(0);
      mode2=3;
    }
  }

  else if( mode2 == 2 ) {
    // синхронизация датчик открыт
    myMotor2.step(10); // против часовой
    if( sens2.flagPress == false ) {
      myMotor2.step(0);
      mode2=3;
    }
  }
 
  else if( mode2 == 3 ) {
    // слежение

  // ------------------------------------ СЛЕЖЕНИЕ
   
  // проверка остановки двигателя
  if( myMotor2.readSteps() == 0) {
    // двигатель остановился

    // получение заданного положения
    setStep2 = (unsigned int)((unsigned long)DMXSerial.read(DMX_CHANEL_MOTO_2) * (NUM_STEPS_MOTOR - 1) / 800) ;
   
    // определение сколько шагов надо сделать
    stepsToDo2 = currentStep2 - setStep2; // ошибка рассогласования

//    if( abs(stepsToDo2) >= (NUM_STEPS_MOTOR / 2) ) {

//      if((stepsToDo2) > 0) stepsToDo2 -= NUM_STEPS_MOTOR;
//      else                stepsToDo2 += NUM_STEPS_MOTOR;     
//    }
 
    myMotor2.step(stepsToDo2);  // запуск двигателя
    currentStep2 = setStep2;  // перегрузка текущего положения   
  }

  }
  else mode2=0;

  //--------------------------------- двигатель 3 ---------------------------
  if( mode3 == 0 ) {
    // ожидание фильтрации датчиков
    if( timer > 40 ) {
      if( sens3.flagPress == true ) mode3=2;   
      else mode3=1;     
    }   
  }

  else if( mode3 == 1 ) {
    // синхронизация датчик закрыт
    myMotor3.step(-10); // по часовой
    if( sens3.flagPress == true ) {
      myMotor3.step(0);
      mode3=3;
    }
  }

  else if( mode3 == 2 ) {
    // синхронизация датчик открыт
    myMotor3.step(10); // против часовой
    if( sens3.flagPress == false ) {
      myMotor3.step(0);
      mode3=3;
    }
  }
 
  else if( mode3 == 3 ) {
    // слежение

  // ------------------------------------ СЛЕЖЕНИЕ
   
  // проверка остановки двигателя
  if( myMotor3.readSteps() == 0) {
    // двигатель остановился

    // получение заданного положения
    setStep3 = (unsigned int)((unsigned long)DMXSerial.read(DMX_CHANEL_MOTO_3) * (NUM_STEPS_MOTOR - 1) / 255) ;
   
    // определение сколько шагов надо сделать
    stepsToDo3 = currentStep3 - setStep3; // ошибка рассогласования

//    if( abs(stepsToDo3) >= (NUM_STEPS_MOTOR / 2) ) {

//      if((stepsToDo3) > 0) stepsToDo3 -= NUM_STEPS_MOTOR;
//      else                stepsToDo3 += NUM_STEPS_MOTOR;     
//    }
 
    myMotor3.step(stepsToDo3);  // запуск двигателя
    currentStep3 = setStep3;  // перегрузка текущего положения   
  }

  }
  else mode3=0;
 
}

//-------------------------------------- обработчик прерывания 250 мкс
void  timerInterrupt() {
  timer++;
  myMotor1.control(); // управвление двигателем
  myMotor2.control(); // управвление двигателем
  myMotor3.control(); // управвление двигателем
  sens1.filterAvarage();  // вызов метода фильтрации по среднему для датчика 1
  sens2.filterAvarage();  // вызов метода фильтрации по среднему для датчика 2
  sens3.filterAvarage();  // вызов метода фильтрации по среднему для датчика 3
}
==============================================================================
// программа следящего электропривода без обратной связи
 
#include <TimerOne.h>
#include <StepDirDriver.h>
#include <DMXSerial.h>
#include <Button.h>

#define NUM_STEPS_MOTOR 400  // число шагов двигателя на оборот
#define DMX_CHANEL_MOTO_1 1   // канал DMX для двигателя 1
#define DMX_CHANEL_MOTO_2 2   // канал DMX для двигателя 2
#define DMX_CHANEL_MOTO_3 3   // канал DMX для двигателя 2

unsigned int currentStep1=0;  // текущее положение двигателя
unsigned int setStep1=0;  // заданное положение двигателя
int stepsToDo1;  // сколько шагов надо сделать
byte mode1=0;  // режим: 0 - пауза, 1 - синхронизация датчик закрыт, 2 - синхронизация датчик открыт, 3 - слежение
unsigned int currentStep2=0;  // текущее положение двигателя
unsigned int setStep2=0;  // заданное положение двигателя
int stepsToDo2;  // сколько шагов надо сделать
byte mode2=0;  // режим: 0 - пауза, 1 - синхронизация датчик закрыт, 2 - синхронизация датчик открыт, 3 - слежение
unsigned int currentStep3=0;  // текущее положение двигателя
unsigned int setStep3=0;  // заданное положение двигателя
int stepsToDo3;  // сколько шагов надо сделать
byte mode3=0;  // режим: 0 - пауза, 1 - синхронизация датчик закрыт, 2 - синхронизация датчик открыт, 3 - слежение
byte timer=0; // таймер

StepDirDriver myMotor1(11, 10, 5);  // создаем объект типа StepDirDriver, задаем выводы для сигналов STEP, DIR, ENABLE
StepDirDriver myMotor2(13, 12, 6);  // создаем объект типа StepDirDriver, задаем выводы для сигналов STEP, DIR, ENABLE
StepDirDriver myMotor3(2, 3, 9);  // создаем объект типа StepDirDriver, задаем выводы для сигналов STEP, DIR, ENABLE
Button sens1 (7, 11);  // создание объекта для датчика 1
Button sens2 (8, 13);  // создание объекта для датчика 2
Button sens3 (4, 2);  // создание объекта для датчика 3

void setup() {
  DMXSerial.init(DMXReceiver);
  Timer1.initialize(250);  // инициализация таймера 1, период 250 мкс
  Timer1.attachInterrupt(timerInterrupt, 250);  // обработчик прерываний
  myMotor1.setMode(1, false);  // шаговый режим, без фиксации при остановке
  myMotor1.setDivider(3);     // делитель частоты 30
  myMotor2.setMode(1, false);  // шаговый режим, без фиксации при остановке
  myMotor2.setDivider(6);     // делитель частоты 30
  myMotor3.setMode(1, false);  // шаговый режим, без фиксации при остановке
  myMotor3.setDivider(4);     // делитель частоты 30
}

void loop() {

//--------------------------------- двигатель 1 ---------------------------
  if( mode1 == 0 ) {
    // ожидание фильтрации датчиков
    if( timer > 40 ) {
      if( sens1.flagPress == true ) mode1=2;   
      else mode1=1;     
    }   
  }

  else if( mode1 == 1 ) {
    // синхронизация датчик закрыт
    myMotor1.step(-10); // по часовой
    if( sens1.flagPress == true ) {
      myMotor1.step(0);
      mode1=3;
    }
  }

  else if( mode1 == 2 ) {
    // синхронизация датчик открыт
    myMotor1.step(10); // против часовой
    if( sens1.flagPress == false ) {
      myMotor1.step(0);
      mode1=3;
    }
  }
 
  else if( mode1 == 3 ) {
    // слежение

  // ------------------------------------ СЛЕЖЕНИЕ
   
  // проверка остановки двигателя
  if( myMotor1.readSteps() == 0) {
    // двигатель остановился

    // получение заданного положения
    setStep1 = (unsigned int)((unsigned long)DMXSerial.read(DMX_CHANEL_MOTO_1) * (NUM_STEPS_MOTOR - 1) / 127) ;
   
    // определение сколько шагов надо сделать
    stepsToDo1 = currentStep1 - setStep1; // ошибка рассогласования

//    if( abs(stepsToDo1) >= (NUM_STEPS_MOTOR / 2) ) {

//      if((stepsToDo1) > 0) stepsToDo1 -= NUM_STEPS_MOTOR;
//      else                stepsToDo1 += NUM_STEPS_MOTOR;     
//    }
 
    myMotor1.step(stepsToDo1);  // запуск двигателя
    currentStep1 = setStep1;  // перегрузка текущего положения   
  }

  }
  else mode1=0;


//--------------------------------- двигатель 2 ---------------------------
  if( mode2 == 0 ) {
    // ожидание фильтрации датчиков
    if( timer > 40 ) {
      if( sens2.flagPress == true ) mode2=2;   
      else mode2=1;     
    }   
  }

  else if( mode2 == 1 ) {
    // синхронизация датчик закрыт
    myMotor2.step(-10); // по часовой
    if( sens2.flagPress == true ) {
      myMotor2.step(0);
      mode2=3;
    }
  }

  else if( mode2 == 2 ) {
    // синхронизация датчик открыт
    myMotor2.step(10); // против часовой
    if( sens2.flagPress == false ) {
      myMotor2.step(0);
      mode2=3;
    }
  }
 
  else if( mode2 == 3 ) {
    // слежение

  // ------------------------------------ СЛЕЖЕНИЕ
   
  // проверка остановки двигателя
  if( myMotor2.readSteps() == 0) {
    // двигатель остановился

    // получение заданного положения
    setStep2 = (unsigned int)((unsigned long)DMXSerial.read(DMX_CHANEL_MOTO_2) * (NUM_STEPS_MOTOR - 1) / 425) ;
   
    // определение сколько шагов надо сделать
    stepsToDo2 = currentStep2 - setStep2; // ошибка рассогласования

//    if( abs(stepsToDo2) >= (NUM_STEPS_MOTOR / 2) ) {

//      if((stepsToDo2) > 0) stepsToDo2 -= NUM_STEPS_MOTOR;
//      else                stepsToDo2 += NUM_STEPS_MOTOR;     
//    }
 
    myMotor2.step(stepsToDo2);  // запуск двигателя
    currentStep2 = setStep2;  // перегрузка текущего положения   
  }

  }
  else mode2=0;

  //--------------------------------- двигатель 3 ---------------------------
  if( mode3 == 0 ) {
    // ожидание фильтрации датчиков
    if( timer > 40 ) {
      if( sens3.flagPress == true ) mode3=2;   
      else mode3=1;     
    }   
  }

  else if( mode3 == 1 ) {
    // синхронизация датчик закрыт
    myMotor3.step(-10); // по часовой
    if( sens3.flagPress == true ) {
      myMotor3.step(0);
      mode3=3;
    }
  }

  else if( mode3 == 2 ) {
    // синхронизация датчик открыт
    myMotor3.step(10); // против часовой
    if( sens3.flagPress == false ) {
      myMotor3.step(0);
      mode3=3;
    }
  }
 
  else if( mode3 == 3 ) {
    // слежение

  // ------------------------------------ СЛЕЖЕНИЕ
   
  // проверка остановки двигателя
  if( myMotor3.readSteps() == 0) {
    // двигатель остановился

    // получение заданного положения
    setStep3 = (unsigned int)((unsigned long)DMXSerial.read(DMX_CHANEL_MOTO_3) * (NUM_STEPS_MOTOR - 1) / 130) ;
   
    // определение сколько шагов надо сделать
    stepsToDo3 = currentStep3 - setStep3; // ошибка рассогласования

//    if( abs(stepsToDo3) >= (NUM_STEPS_MOTOR / 2) ) {

//      if((stepsToDo3) > 0) stepsToDo3 -= NUM_STEPS_MOTOR;
//      else                stepsToDo3 += NUM_STEPS_MOTOR;     
//    }
 
    myMotor3.step(stepsToDo3);  // запуск двигателя
    currentStep3 = setStep3;  // перегрузка текущего положения   
  }

  }
  else mode3=0;
 
}

//-------------------------------------- обработчик прерывания 250 мкс
void  timerInterrupt() {
  timer++;
  myMotor1.control(); // управвление двигателем
  myMotor2.control(); // управвление двигателем
  myMotor3.control(); // управвление двигателем
  sens1.filterAvarage();  // вызов метода фильтрации по среднему для датчика 1
  sens2.filterAvarage();  // вызов метода фильтрации по среднему для датчика 2
  sens3.filterAvarage();  // вызов метода фильтрации по среднему для датчика 3
}

===================================================================================

Re: Сканер с Dmx-512 по теме "Прибор поворотная голова".

Добавлено: 22 апр 2020, 22:12
Лев
Вот еще фото.

Re: Сканер с Dmx-512 по теме "Прибор поворотная голова".

Добавлено: 22 апр 2020, 22:13
Лев
Фото

Re: Сканер с Dmx-512 по теме "Прибор поворотная голова".

Добавлено: 22 апр 2020, 22:13
Лев
.

Re: Сканер с Dmx-512 по теме "Прибор поворотная голова".

Добавлено: 22 апр 2020, 22:14
Лев
.

Re: Сканер с Dmx-512 по теме "Прибор поворотная голова".

Добавлено: 23 апр 2020, 00:14
АнтонНикиточкин
Привет Лев! Достойный проект! Мне понравилось!
Скажите, Лев, в чем отличие от сканера с оригинальными мозгами? И какие использовали драйвера ШД?

Re: Сканер с Dmx-512 по теме "Прибор поворотная голова".

Добавлено: 23 апр 2020, 08:30
Лев
Привет Антон.
Оригинальные мозги были автономными, то есть работали от микрофона и крутили шаговые двигатели по своему циклу.
Я использовал для двигателей драйвер a4988, мне показались они довольно шумными.

Re: Сканер с Dmx-512 по теме "Прибор поворотная голова".

Добавлено: 25 апр 2020, 13:31
WadimZ
Добрый день!
Подскажи пожалуйста - почему в скетче после вот этой строки:

==============================================================================

идет опять код?
при том почти повторяется, только немного поменялись параметы.
Зачем это нужно?

Спасибо

Re: Сканер с Dmx-512 по теме "Прибор поворотная голова".

Добавлено: 25 апр 2020, 15:53
Лев
Добрый!
Я вот только сейчас это заметил, видимо первый скетч - последняя версия, а тот который за ним - первая. Они различаются только в параметрах настройки двигателей, вам придется подбирать их самому, добиваться лучшей конфигурации.