Índice general Foros Digital, Electricidad e Informática Decodificador DCC para 16 motores lentos

Decodificador DCC para 16 motores lentos

Moderador: 241-2001



Desconectado
Mensajes: 761
Ubicación: Salamanca
Registrado: 12 Ene 2012 14:44
El código que adjunto es el que controla estos dos decodificadores DCC para manejar 16 desvíos lentos cada uno, de los que llevan un motor de corriente continua que, girando a uno y otro lado, mueven la palanca acoplada a la aguja.

DCC_16Lentos_01.jpg


Notas:

    Responde a los desvíos números 1 a 16 de la central LENZ. Para asignarle otros hay que cambiar las definiciones en las líneas iniciales del código antes de volcarlo al Arduino.

    Para Roco Multimaus donde dice ((DIR_01 - 1) / 4) + 129... hay que cambiar el 129 por un 128 (en las 16 líneas donde aparece).

    La señal se lee en el pin2 de un Arduino Nano a través de un optoacoplador.

    Los motores de los desvíos se controlan con los pines 11, 12 y 13 mediante un circuito integrado L293.

    Solo se puede mover un desvío a la vez.

DCC_16Lentos_02.png
DCC_16Lentos_02.png (337.06 KiB) Visto 1779 veces


/*
  Para MACI
  Deco DCC accesorios para 16 motores lentos

  Arduino Nano Pro como
    - Decodificador para accesorios DCC central LENZ LH100
    - L293D para doble puente H
    - 16 canales si/no para relés

  Code by German Trinidad and Norber, November 2020
  Freely distributable for private, non commercial, use.
*/

#define DUR_OP  540000   // Duración de cada maniobra (540000 = 3s)

#define NUM_ACC 16       // Número de motores lentos a controlar

// Bloque "A"
#define DIR_01  1       // Direcciones de cada motor en la central
#define DIR_02  2
#define DIR_03  3
#define DIR_04  4
#define DIR_05  5
#define DIR_06  6
#define DIR_07  7
#define DIR_08  8

// Bloque "B"
#define DIR_09  9
#define DIR_10  10
#define DIR_11  11
#define DIR_12  12
#define DIR_13  13
#define DIR_14  14
#define DIR_15  15
#define DIR_16  16

struct Accesorios {
  byte    direc;
  byte    port;
  byte    pinV;
};

// #58 en ROCO: (58-1)/4=57/4=14.25->14+128=142
// #58 en LENZ: (58-1)/4=57/4=14.25->14+129=143
Accesorios miAcc[] = {
  //Address                , Port              , Pin√
  {((DIR_01 - 1) / 4) + 129, ((DIR_01 - 1) % 4), 10  },
  {((DIR_02 - 1) / 4) + 129, ((DIR_02 - 1) % 4), 9   },
  {((DIR_03 - 1) / 4) + 129, ((DIR_03 - 1) % 4), 8   },
  {((DIR_04 - 1) / 4) + 129, ((DIR_04 - 1) % 4), 7   },
  {((DIR_05 - 1) / 4) + 129, ((DIR_05 - 1) % 4), 6   },
  {((DIR_06 - 1) / 4) + 129, ((DIR_06 - 1) % 4), 5   },
  {((DIR_07 - 1) / 4) + 129, ((DIR_07 - 1) % 4), 4   },
  {((DIR_08 - 1) / 4) + 129, ((DIR_08 - 1) % 4), 3   },

  {((DIR_09 - 1) / 4) + 129, ((DIR_09 - 1) % 4), 1   },
  {((DIR_10 - 1) / 4) + 129, ((DIR_10 - 1) % 4), 0   },
  {((DIR_11 - 1) / 4) + 129, ((DIR_11 - 1) % 4), A5  },
  {((DIR_12 - 1) / 4) + 129, ((DIR_12 - 1) % 4), A4  },
  {((DIR_13 - 1) / 4) + 129, ((DIR_13 - 1) % 4), A3  },
  {((DIR_14 - 1) / 4) + 129, ((DIR_14 - 1) % 4), A2  },
  {((DIR_15 - 1) / 4) + 129, ((DIR_15 - 1) % 4), A1  },
  {((DIR_16 - 1) / 4) + 129, ((DIR_16 - 1) % 4), A0  }
};

byte rele[] = {10, 9, 8, 7, 6, 5, 4, 3, 1, 0, A5, A4, A3, A2, A1, A0};

#include <EEPROM.h>
#define SI        0
#define NO        1
#define TICKS    180           // Prescaler 8 -> pulso de Timer cada 0.5 µs -> 200 ticks son 100 µs

volatile byte buf_dcc[6];      // Buffer del último comando recibido
volatile boolean comandoRecibido = false;

#define ENA     13
#define IN1     12
#define IN2     11

void setup() {
  for (int i = 0; i < 20; i++) {
    if ( i != 2) {
      pinMode(i, OUTPUT);
      digitalWrite(i, HIGH); // Los relés se activan por bajos
    }
    else pinMode(i, INPUT); // pin2 = DCC
  }
  digitalWrite(ENA, LOW);
  pruebaReles();

  attachInterrupt(0, dcc_int, CHANGE);       // pin2 = DCC      externalInterrupt 0
  cli();
  TCCR0A = 0;
  TCCR0B = 0;
  TCCR0B |= (1 << CS01);                     // Set CS01 bit for 8 prescaler (0.5 µs) on Timer0 - DCC
  sei();
}

void pruebaReles() {
  for (byte i = 0; i < 16; i++) {
    digitalWrite(rele[i], LOW);
    delay(100);
    digitalWrite(rele[i], HIGH);
    delay(50);
  }
}

void aDesviado(byte i) {
  if (EEPROM.read(20 + i) == 1) return;      // Ya estaba desviado
  digitalWrite(miAcc[i].pinV, LOW);
  delay(10000);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(ENA, HIGH);
  delay(DUR_OP);
  digitalWrite(ENA, LOW);
  digitalWrite(IN1, LOW);
  delay(10000);
  digitalWrite(miAcc[i].pinV, HIGH);
  delay(10000);
  EEPROM.write(20 + i, 1);
}

void aRecto(byte i) {
  if (EEPROM.read(20 + i) == 0) return;      // Ya estaba recto
  digitalWrite(miAcc[i].pinV, LOW);
  delay(10000);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(ENA, HIGH);
  delay(DUR_OP);
  digitalWrite(ENA, LOW);
  digitalWrite(IN2, LOW);
  delay(10000);
  digitalWrite(miAcc[i].pinV, HIGH);
  delay(10000);
  EEPROM.write(20 + i, 0);
}

void loop() {
  static byte servo, estado;
  if (comandoRecibido == true) {
    byte port = buf_dcc[1];
    byte addr = buf_dcc[0];
    byte port1 = (port & 0x06) >> 1;     // 0x06 = B0000 0110
    for (byte i = 0; i < NUM_ACC; i++) {
      if ((addr == miAcc[i].direc) && (port1 == miAcc[i].port)) {   // Es de los míos
        if (port & 0x01) aDesviado(i);   // √  selected
        else aRecto(i);                  // -- selected
        break;                           // No hace falta seguir buscando coincidencia
      }
    }
    comandoRecibido = false;
  }
}

void dcc_int() {                        // ISR(INT0_vect) External interrupt routine for signal on pin2
  static int tmp_pulso;
  static byte bit_dcc;
  static byte preamb;
  static byte aux_dcc, x_or, idx, num_bits;
  if (PIND & (0x04)) TCNT0 = 0;                                // pin2 acaba de pasar a HIGH
  else  {                                                      // cuando acaba de pasar a LOW
    tmp_pulso = TCNT0;                                         // lee los microsegundos (un byte)
    if (tmp_pulso > TICKS) bit_dcc = 0;                        // duración mayor de XX us => cero
    else bit_dcc = 1;                                          // y menor uno
    if (preamb == SI) {                                        // preámbulo
      if (bit_dcc) {                                           // otro '1'
        if (num_bits) num_bits--;
      }
      else {
        if (!num_bits) {                                       // el '0' de inicio de datos
          preamb = NO;
          num_bits = 9;
          x_or = 0;
          idx = 0;
        }
        else num_bits = 10;                                    // no se cumple la trama, vuelta a inicio
      }
    }
    else {                                                     // recepción de los bytes
      if (--num_bits) aux_dcc = aux_dcc * 2 + bit_dcc;
      else {                                                   // el separador de bytes
        if (!bit_dcc) {                                        // cero, a por el siguiente byte
          buf_dcc [idx++] = aux_dcc;
          x_or ^= aux_dcc;                                     // actualiza la x_or
          num_bits = 9;
        }
        else {                                                 // uno, fin del paquete
          preamb = SI;
          num_bits = 10;                                       // vuelta a empezar
          if (x_or == aux_dcc) comandoRecibido = true;         // paquete correcto
        }
      }
    }
  }
}


La fuente de alimentación del Arduino y los relés es lo del centro. Reduce a 5 V cc la tensión que llega de un transformador de aproximadamente 12 V cc, que es la que se aplica a los motores de los desvíos. Regulando esta tensión se consigue que vayan más o menos lentos, a gusto de cada uno. La fuente se adapta automáticamente para sacar 5 V constantes.

Es un circuito sencillo y muy barato de hacer. Y los componentes son totalmente convencionales.

A ver cuándo lo podemos ver todo en acción!!! :D
Saludos

[Multimaus + GenLi-S88 + +z21f. + RocRail (MacOsX)]
H0 Renfe, sin catenaria


Desconectado
Mensajes: 173
Ubicación: Salamanca
Registrado: 07 Feb 2012 23:50
Montado debajo de la playa de vías
Adjuntos
0A712CBD-33AF-48B7-979A-3591E3B356C3.jpeg
Instagram: supermacias44


Desconectado
Mensajes: 3176
Ubicación: Salamanca
Registrado: 07 Nov 2008 10:51
Ya se menean?


Desconectado
Mensajes: 173
Ubicación: Salamanca
Registrado: 07 Feb 2012 23:50
Si si, ya funciona. El finde que viene pongo vídeos. La Silvi me obligó a desmontar.
Instagram: supermacias44


Desconectado
Mensajes: 173
Ubicación: Salamanca
Registrado: 07 Feb 2012 23:50
Montada la segunda placa en el segundo módulo
Adjuntos
E3A0F3FA-16C8-40EF-8A63-87B7BA8896C9.jpeg
AC8D1072-4072-4E93-A287-784A59E50578.jpeg
Instagram: supermacias44


Desconectado
Mensajes: 53
Registrado: 14 Dic 2015 17:19
Muy buenas
No entiendo el control de los motores
Con un solo l293, se controlan todos?
Porque los relés son para polarizar las agujas, no?
Un saludo


Desconectado
Mensajes: 173
Ubicación: Salamanca
Registrado: 07 Feb 2012 23:50
los relés son para cambiar la polaridad de la corriente que mueve el motor de la aguja y que se mueva hacia un lado o hacia el otro.
Instagram: supermacias44


Desconectado
Mensajes: 235
Ubicación: Valencia
Registrado: 19 Nov 2011 16:51
Hola.

Utilizando el L293D (se trata de dos puentes "en H"), evitarías el empleo de los relés.

Asimismo, mediante señal de PWM hacia el L293D, conseguirías regular por software, la velocidad de giro de los motores, y por tanto, de desplazamiento de los espadines de la aguja.

Un saludo.

Atentamente:

Dvorak.


Desconectado
Mensajes: 761
Ubicación: Salamanca
Registrado: 12 Ene 2012 14:44
El doble puente "H" contenido en el circuito integrado L293 se emplea para invertir la polaridad de los 12 V cc con que se alimenta este achiperre. Los dos puentes trabajan a la vez (hacen lo mismo): cambian la tensión aplicada a los 16 motores posibles a través de la única salida existente. Los relés se encargan luego de que sólo uno de ellos se mueva: hay que cablear esa salida de tensión ±12 V cc que da la plaquita central que hemos construido a través de dichos relés, uno por cada desvío.

El programa identifica qué desvío hay que mover, "enciende" su relé correspondiente, determina la polaridad que aplicará el comentado L293, y finalmente lo "enciende" durante 3 ó 4 s para que el motor correspondiente se mueva a su sitio.

Se pueden hacer otros programas. Por ejemplo, que admitan en una "cola" toda una serie de comandos que la central pueda enviar todos seguidos (como hace cuando manda una ruta completa), y se puede programar un retraso en la ejecución de esa cadena de acciones, o incluso se podrían ejecutar de dos en dos o de tres en tres, según preferencias y consumo / potencia disponibles. Pero en este caso la programación está hecha para que sea el software del usuario el que espacie los comandos encadenados en una ruta, y por eso solo se mueve un desvío de cada vez, y hasta que no termina no se aceptan las órdenes para cambiar los demás. En mando manual, desde la central, hay que esperar también.
Saludos

[Multimaus + GenLi-S88 + +z21f. + RocRail (MacOsX)]
H0 Renfe, sin catenaria


Desconectado
Mensajes: 235
Ubicación: Valencia
Registrado: 19 Nov 2011 16:51
Norber escribió:
El doble puente "H" contenido en el circuito integrado L293 se emplea para invertir la polaridad de los 12 V cc con que se alimenta este achiperre. Los dos puentes trabajan a la vez (hacen lo mismo): cambian la tensión aplicada a los 16 motores posibles a través de la única salida existente. Los relés se encargan luego de que sólo uno de ellos se mueva: hay que cablear esa salida de tensión ±12 V cc que da la plaquita central que hemos construido a través de dichos relés, uno por cada desvío.

El programa identifica qué desvío hay que mover, "enciende" su relé correspondiente, determina la polaridad que aplicará el comentado L293, y finalmente lo "enciende" durante 3 ó 4 s para que el motor correspondiente se mueva a su sitio.

Se pueden hacer otros programas. Por ejemplo, que admitan en una "cola" toda una serie de comandos que la central pueda enviar todos seguidos (como hace cuando manda una ruta completa), y se puede programar un retraso en la ejecución de esa cadena de acciones, o incluso se podrían ejecutar de dos en dos o de tres en tres, según preferencias y consumo / potencia disponibles. Pero en este caso la programación está hecha para que sea el software del usuario el que espacie los comandos encadenados en una ruta, y por eso solo se mueve un desvío de cada vez, y hasta que no termina no se aceptan las órdenes para cambiar los demás. En mando manual, desde la central, hay que esperar también.


Norber, con el L293D se puede mover hasta cuatro motores (girando siempre en el mismo sentido), pero a nuestros efectos, como hay que cambiar la polaridad (para desplazar el espadín en posición recta o desviada) puedes mover dos motores para sendos cambios de aguja. No necesitas los relés. A cada dispositivo de accionamiento lento por aguja, puedes aplicar permanentemente la tensión (positiva o negativa), porque tiene unos finales de carrera y unos diodos que utiliza internamente, para cortar la tensión al motor, cuando ha llegado al final de su recorrido. Así es como yo los utilizo. Lo único que no hago (y debería hacer), es ajustar la tensión que llega al motor, mediante la señal PWM (la tensión la ajusto mediante una fuente de alimentación externa, craso error por mi parte). Lo bueno de estos motores de accionamiento lento de Fulgurex o Lemaco, es que tienes dos contactos auxiliares para el usuario, que yo empleo para polarizar los corazones de las agujas, y para mostrar en un panel, la posición del cambio de agujas (recto o desviado).

Un saludo.

Dvorak.


Desconectado
Mensajes: 235
Ubicación: Valencia
Registrado: 19 Nov 2011 16:51
Hola de nuevo. Adjunto el esquema eléctrico que saqué del motor de accionamiento lento de Fulgurex o Lemaco:
esquema_motor_accionamiento_lent_FULGUREX.jpg


Un saludo.

Dvorak.


Desconectado
Mensajes: 761
Ubicación: Salamanca
Registrado: 12 Ene 2012 14:44
En efecto, mi primera intención fue resolverlo todo con 8 integrados L293, controlando dos motores cada uno (total 16) y de hecho compramos los 8 circuitos L293...

Pero luego pensé que era una solución más robusta usar en su lugar las dos pastillas de 8 relés cada una, porque son fácilmente reemplazables, bastante baratas, y añaden un bonito led rojo que señaliza qué desvío se activa en cada momento. También pesó en mi decisión el que la plaquita del micro controlador me salió muy mona con los dos grupos de 10 conectores, uno a cada lado, mientras que los intentos de diseño con los 8 integrados L293 me resultaban complicados de resolver (ya sabes que solo hago circuitos impresos a una cara). También pesó sobre el diseño final que no recuerdo haber quemado muchos integrados por exceso de consumo salvo, precisamente, los L293... Que desconfiaba de ellos, vamos. Así que preferí usar solo uno en lugar de 8, por si las moscas, y añadir lo de los relés.

Lo que no recuerdo es haber pensado mucho sobre el tema, que es un fallo del que me acuso, sin duda. Vi una solución, vi la alternativa, debí considerar brevemente y opté. Aunque, por si acaso, se compraron los 8 circuitos L293, que permitirían volver a la primera opción si la segunda hubiera salido mal.
Saludos

[Multimaus + GenLi-S88 + +z21f. + RocRail (MacOsX)]
H0 Renfe, sin catenaria


Volver a Digital, Electricidad e Informática

Síguenos en Facebook Síguenos en Youtube Síguenos en Instagram Feed - Nuevos Temas
©2017   -   Información Legal