Bienvenidos a otra publicación de nuestra serie de controladores DMX.
En esta parte, me gustaría presentar una ampliación de la segunda parte de la serie. En la segunda parte programamos un chaser de DMX para la canción "The Final Countdown" de Europe.
Cualquiera que haya mirado el código del chaser se habrá dado cuenta de que requiere un gran esfuerzo de programación, ya que cada secuencia y cada pausa intermedia tienen que coincidir o adaptarse exactamente a la canción. Esto lleva mucho tiempo y es tedioso hacerlo a mano. Para facilitarle la programación de más persecuciones, programamos una "herramienta de programación". Esto significa que escribimos un programa que a su vez emite el código fuente de Arduino que se relaciona con la interfaz serie DMX, que puede ser compilado de nuevo directamente.
Con la ayuda de nuestro programa de hoy, se puede crear cualquier chaser para cualquier canción (propia) en un tiempo relativamente corto. Pero antes de empezar a programar nuestro propio chaser, vamos a echar un vistazo a la función.
Hardware requerido
Cantidad | Componente | Anotación |
---|---|---|
1 | Arduino Nano | |
3 | Módulo de Llaves KY-004 - Botón |
La estructura
La estructura requerida se puede tomar del siguiente diagrama de cableado:
El software
Cargamos el siguiente código en el Arduino Nano:
#define SEQ_Pin 2 #define STARTSEQ_Pin 3 #define ENDSEQ_Pin 4 largo DMX_Pattern_Number = 1; no firmado largo ElapsedMillis = 0; bool ReadPin = cierto; bool EndReached = falso; vacío ISR_SEQ() { noInterrupts(); demora(200); bool PinState = lectura digital de(SEQ_Pin); Si (!(PinState)) { DMX_Pattern_Number = 1; De serie.println("// Conteo de inicio .."); ElapsedMillis = Millis(); EndReached = falso; } interrupciones(); } vacío ISR_STARTSEQ() { noInterrupts(); bool PinState = lectura digital de(STARTSEQ_Pin); Si (!(PinState)y !(EndReached) ) { De serie.impresión("Demora ("); De serie.impresión (Millis()- ElapsedMillis); De serie.println(");"); De serie.impresión("DmxPattern ("); De serie.impresión(DMX_Pattern_Number); De serie.println(");"); DMX_Pattern_Number++; ElapsedMillis = Millis(); } demora(200); interrupciones(); } vacío cabecera código de impresión () { De serie.println(F("// DMX Cazador de la canción '...'. Por Tobias Kuch 2020 V1.0")); De serie.println(F("#Define Start_Switch_Pin 5")); De serie.println(F("// define DMX Actor Dirección Primaria")); De serie.println(F("#Define DMX_Actor_Address 1")); De serie.println(F(" ")); De serie.println(F("// Definir Funciones del dispositivo DMX de canal")); De serie.println(F("#Define DMX_RED_Ch 0 + DMX_Actor_Address")); De serie.println(F("#Define DMX_GREEN_Ch 1 + DMX_Actor_Address")); De serie.println(F("#Define DMX_BLUE_Ch 2 + DMX_Actor_Address")); De serie.println(F("#Define DMX_MACRO_Ch 3 + DMX_Actor_Address")); De serie.println(F("#Define DMX_STROBE_Ch 4 + DMX_Actor_Address")); De serie.println(F("#Define DMX_MODE_Ch 5 + DMX_Actor_Address")); De serie.println(F("#Define DMX_MASTERDIM_Ch 6 + DMX_Actor_Address")); De serie.println(F(" ")); De serie.println(F("#Include" )); De serie.println(F(" ")); De serie.println(F("Byte DMX_MASTERDIM_VAL = 255;")); De serie.println(F("ReadPin Bool;")); De serie.println(F(" ")); De serie.println(F("Void setup () {")); De serie.println(F("PinMode (Start_Switch_Pin, INPUT_PULLUP);")); De serie.println(F("DmxSimple.usePin (3);")); De serie.println(F("DmxSimple.maxChannel (512);")); De serie.println(F("Hacer")); De serie.println(F(" {")); De serie.println(F("ReadPin = lectura digital (Start_Switch_Pin);")); De serie.println(F("Mientras} ((ReadPin)!);")); De serie.println(F(" } ")); De serie.println(F(" ")); De serie.println(F("DmxPattern Void (DMX_Pattern_Number largo)")); De serie.println(F("{")); De serie.println(F("Dmxsimple.write (dmx_red_ch, dmxval (dmx_red_ch, dmx_pattern_number));")); De serie.imprimir(F("Dmxsimple.write (dmx_green_ch, dmxval (dmx_green_ch, dmx_pattern_number));")); De serie.imprimir(F("Dmxsimple.write (dmx_blue_ch, dmxval (dmx_blue_ch, dmx_pattern_number));")); De serie.imprimir(F("Dmxsimple.write (dmx_macro_ch, dmxval (dmx_macro_ch, dmx_pattern_number));")); De serie.imprimir(F("Dmxsimple.write (dmx_strobe_ch, dmxval (dmx_strobe_ch, dmx_pattern_number));")); De serie.imprimir(F("Dmxsimple.write (dmx_mode_ch, dmxval (dmx_mode_ch, dmx_pattern_number));")); De serie.imprimir(F("Dmxsimple.write (dmx_masterdim_ch, dmxval (dmx_masterdim_ch, dmx_pattern_number));")); De serie.imprimir(F("}")); De serie.imprimir(F(" ")); De serie.imprimir(F("Void Loop () {")); } vacío Codelador impreso (largo Dmx_pt_nbr ) { De serie.imprimir(F("do {} mientras (verdad)";)); De serie.imprimir(F("}")); De serie.imprimir(F(" ")); De serie.imprimir(F("// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Rotado GRN BLAU MAC STR MOD MASTER DIM ^^^^^^^^^^^^ ')); De serie.impresión(F("Byte DMXDATA [")); De serie.impresión (Dmx_pt_nbr); De serie.imprimir(F("][7] = {")); por (largo z = 1; z <= Dmx_pt_nbr;z++) { De serie.impresión(F("{0, 0, 0, 0, 0, 0, DMX_MASTERDIM_VAL}, // PATTEL")); De serie.imprimir(z); } De serie.imprimir(F(" };")); De serie.imprimir(F("// ------------------- Patrones de ejemplo común ---------" ")); De serie.imprimir(F("255, 0, 0, 0, 0, 0, DMX_MASTERDIM_VAL}, // VOLLES DOT")); De serie.imprimir(F("// {0,255, 0, 0, 0, 0, DMX_MASTERDIM_VAL}, // VOLLES Grün")); De serie.imprimir(F("// {0, 0,255, 0, 0, 0, DMX_MASTERDIM_VAL}, // VOLLES BLAU")); De serie.imprimir(F("// {255,255,255, 0, 0, 0, dmx_masterdim_val}, // Volles Weiss")); De serie.imprimir(F("// {255,255,255, 0,255, 0, DMX_MASTERDIM_VAL}, // SCHNELLES STROBOSKOP")); De serie.imprimir(F("// {255,255,255, 0, 0, 70, dmx_masterdim_val}, // weiß aufblendern")); De serie.imprimir(F("// {255,255,255, 0, 0, 60, DMX_MASTERDIM_VAL}, // Weiß AbbBlenden")); De serie.imprimir(F("// {255,255,255, 20, 0, 60, DMX_MASTERDIM_VAL}, // Weiß Langsames Blinken")); De serie.imprimir(F(" ")); De serie.imprimir(F("Byte Dmxval (byte dmx_ch, largo dmx_pattern_number)")); De serie.imprimir(F("{")); De serie.imprimir(F("Byte u = dmxdata [dmx_pattern_number-1] [dmx_ch-1];")); De serie.imprimir(F("Regreso u;")); De serie.imprimir(F("}")); } vacío configuración() { // initalisierung De serie.comenzar(115200); mono(Seq_pin,Input_pullup); mono(Startseq_pin,Input_pullup); mono(Endseq_pin,Input_pullup); nointerrupts(); conecterrupt(0, Isr_seq, CAMBIO); conecterrupt(1, Isr_startseq, CAMBIO); PrintcodeHeader (); interrupciones(); Elapsedmillis = milis(); } vacío círculo() { // Ponga su código principal aquí, para ejecutar repetidamente: Readpin = lectura digital (Endseq_pin); Si (!(Readpin) y !(Finalizado)) { Codelador impreso (Dmx_pattern_number-1); demora(100); // debiuncing Finalizado = cierto; } demora(100); }
Algunos aspectos básicos sobre la función: para un programa funciona se necesita la parte Init, en la que se declaran las variables, la parte Setup, que realiza las primeras inicializaciones, y la parte Loop, que realiza las principales tareas del programa. Por último, se completa la parte del bucle y, si es necesario, siguen algunas funciones auxiliares. Los botones funcionan exactamente en este orden.
Cuando se pulsa el botón del puerto 3, las partes de inicialización y configuración de nuestro chaser se emiten en la interfaz serie. El siguiente bloque de código se emite en la interfaz serie y se inicia un temporizador interno:
// DMX Chaser a la canción '...'. por tobias kuch 2020 v1.0 #define Start_switch_pin 5 // definir la dirección primaria del actor DMX #define Dmx_actor_address 1 // definen las funciones del canal de dispositivos DMX #define Dmx_red_ch 0 + Dmx_actor_address #define Dmx_green_ch 1 + Dmx_actor_address #define Dmx_blue_ch 2 + Dmx_actor_address #define Dmx_macro_ch 3 + Dmx_actor_address #define Dmx_strobe_ch 4 + Dmx_actor_address #define Dmx_mode_ch 5 + Dmx_actor_address #define Dmx_masterdim_ch 6 + Dmx_actor_address #include <Dmxsimple.h> byte Dmx_masterdim_val = 255; boquilla Readpin; vacío configuración() { mono(Start_switch_pin,Input_pullup); Dmxsimple.UsoPin(3); Dmxsimple.maxchannel(512); hacer { Readpin = lectura digital (Start_switch_pin); } mientras (!(Readpin)); } vacío Dmxpattern (largo Dmx_pattern_number) { Dmxsimple.escribir(Dmx_red_ch,dmxval(Dmx_red_ch,Dmx_pattern_number)); Dmxsimple.escribir(Dmx_green_ch,dmxval(Dmx_green_ch,Dmx_pattern_number)); Dmxsimple.escribir(Dmx_blue_ch,dmxval(Dmx_blue_ch,Dmx_pattern_number)); Dmxsimple.escribir(Dmx_macro_ch, dmxval(Dmx_macro_ch,Dmx_pattern_number)); Dmxsimple.escribir(Dmx_strobe_ch,dmxval(Dmx_strobe_ch,Dmx_pattern_number)); Dmxsimple.escribir(Dmx_mode_ch, dmxval(Dmx_mode_ch,Dmx_pattern_number)); Dmxsimple.escribir(Dmx_masterdim_ch, dmxval(Dmx_masterdim_ch,Dmx_pattern_number)); } vacío círculo() {
Ahora hemos establecido las bases para la parte principal del programa.
Al pulsar el botón del puerto 2, se miden los intervalos de tiempo entre cada pulsación del botón y se traducen en la siguiente secuencia de comandos:
demora(Zeit); Dmxpattern(Secuenciar);
El chaser se genera pulsando rítmicamente el botón del puerto 2 al compás del ritmo o del bajo de la música. Cuando el chaser se vaya a completar, pulse el botón en el puerto 4. Esto completa el sketch. La siguiente parte final se adjunta al sketch:
hacer {} mientras (cierto); } // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Rotado GRN BLAU MAC STR MOD MASTER DIM ^^^^^^^^^^^^ byte Dmxdata[3][7] = { { 0, 0, 0, 0, 0, 0,Dmx_masterdim_val}, { 0, 0, 0, 0, 0, 0,Dmx_masterdim_val}, { 0, 0, 0, 0, 0, 0,Dmx_masterdim_val}, }; // --------------------- Patrones de ejemplo común --------- // {255, 0, 0, 0, 0, 0, DMX_MASTERDIM_VAL}, // VOLLES ROT // {0,255, 0, 0, 0, 0, DMX_MASTERDIM_VAL}, // VOLLES Grün // {0, 0,255, 0, 0, 0, DMX_MASTERDIM_VAL}, // VOLRES BLAU // {255,255,255, 0, 0, 0, dmx_masterdim_val}, // Volles Weiss // {255,255,255, 0,255, 0, DMX_MASTERDIM_VAL}, // SCHNELLES STROBOSKOP // {255,255,255, 0, 0, 70, DMX_MASTERDIM_VAL}, // Weiß AufLENDEN // {255,255,255, 0, 0, 60, DMX_MASTERDIM_VAL}, // Weiß AbbBlenden // {255,255,255, 20, 0, 60, DMX_MASTERDIM_VAL}, // Weiß Langsames Blinken byte dmxval(byte Dmx_ch,largo Dmx_pattern_number) { byte usted = Dmxdata[Dmx_pattern_number-1][Dmx_ch-1]; regreso usted; }
En el monitor de serie vemos la siguiente salida:
Para terminar y antes de subir el nuevo sketch a un Arduino, se debe rellenar el Array DmxData con los valores de luz propios. Esto supone las siguientes asignaciones de canales DMX: Canal Rojo, Canal Verde, Canal Azul, Velocidad, Efecto, Estroboscopio, Regulador principal.
Para el cableado y el funcionamiento del programa Chaser, la parte anterior (Parte 2) de esta serie se aplica sin cambios 1:1.
Le deseo que se divierat con la reconstrucción.