Índice general Foros Digital, Electricidad e Informática Arduino desvio triple

Arduino desvio triple

Moderador: 241-2001


Nota 11 Abr 2021 17:50

Desconectado
Mensajes: 46
Registrado: 14 Dic 2015 17:19
Muy buenas
Estoy peleado con un decoder con arduino para un desvío triple peco.
La idea es que funcione tanto en analógico como en digital
De momento malfunciona en analógico
La parte eléctrica está formada por un arduino mini, dos servos, dos relés y un pulsador para cambiar de posición (en analógico)
Utilizo la librería VarSpeedServo.h para mover los servos controlando la velocidad y una librería BotonSimple para contar el tiempo que el boton permanece pulsado.
La idea es que el desvío vaya pasando de una posición inicial izq a las otras dos, según la serie izq-centro-dch-centro.
El problema que tengo es que al conectar el arduino o al hacer un reset, el servo que corresponda, según la serie anterior se mueve.
El reset se está comportando como el botón pulsador, o casi.
Casi, porque en el setup tengo
activaSalida (0);
Serial.println(triple_desvio);
Siendo activaSalida la función para mover servos, relés, etc y triple_desvio la variable que marca la posición del desvío.
Al hacer reset se activa el servo y relé que toque, pero no aparece en el monitor serie el valor de triple_desvio.
No sé si será una falta de () o qué, pero de momento no lo encuentro.





//se cambia la libreria botonSimple para que el boton esté configurado como pull down
#include <BotonSimple.h>
#include <EEPROM.h>
#include <VarSpeedServo.h>
#include <NmraDcc.h>
NmraDcc Dcc;
const byte DCC_PIN = 2;
const byte LED_PIN = 13;
byte triple_desvio = 0; //1-> izquierda 2->centro 3->derecha  se guarda en la posicion 0 de la memoria

const byte velocidad = 15; //velocidad a la que se mueven los servos

//////////////////////////////
#define INTERVALO_TIEMPO1 100//tiempo para evitar rebotes en el pulsador
#define INTERVALO_TIEMPO2 3000//si boton pulsado 3s posiciona los servos en 1->izq
unsigned long tiempo_1 = 0;
unsigned long tiempo_2 = 0;

///////////////////////////////
VarSpeedServo myservo1;
VarSpeedServo myservo2;
int direccion_DCC = 7; // Direccion DCC del decoder triple
byte output; //   Estado del accesorio DCC: 1=on, 0=off

//definicion reles
byte rele1 = 11; // Pin de salida para rele1 para polarizar desvio
byte rele2 = 12; // Pin de salida para polarizar desvio

//definicion boton
BotonSimple boton(4);//boton en pin 4
unsigned long inicio, fin, tiempo_boton ;

//definicion servos
const  int servoPin1 = 3; //pin de conexion para el servo 1
const  int servoPin2 = 5; //pin de conexion para el servo 2
byte angulo;
byte setpoint;
byte anguloOff = 50; // Angulo para DCC=off
byte anguloOn = 150; // Angulo para DCC=on
boolean estado;
//definicion led para TCO
const byte led_izq = 8;
const byte led_centro = 9;
const byte led_dch = 10;




/*###################################################################################################
  pines para servos y accesorios
  servo 1 en pin 3 rele en pin 11
  servo 2 en pin 5 rele en pin 12
  led iquierdo en pin 8
  Led centro en pin 9
  Led derecho en pin 10
  ###################################################################################################
  ###################################################################################################*/

void activaSalida (int posicion) {
  //el bucle es izquierda(1) centro_0(2) derecha(3) centro_1(4) izquierda(1)

  switch (posicion) {
    //1-> el desvio está en la posicion izq y pasa a la posicion centro_0, se mueve el servo1 a la izquierda
    //el desvio queda en posicion 2->centro_0
    case 1:
      myservo1. attach (servoPin1);
      myservo1.write(anguloOff , velocidad, true);

      //digitalWrite (rele1, LOW);//normalmente abierto on
      //digitalWrite (rele2, LOW);// normalmente abierto on
      EEPROM.update(0, 2);
      myservo1. detach ();
      digitalWrite (led_izq, LOW);
      digitalWrite (led_centro, HIGH);
      digitalWrite (led_dch, LOW);
      digitalWrite (rele1, HIGH);//rele off
      digitalWrite (rele2, LOW);//rele on
      Serial.println("centro");
      break;

    //2-> el desvio esta en posición centro y pasa a la posicion derecha, se mueve el servo2 a la izquierda
    //el desvio queda en posicion 3->derecha
    case 2:
      myservo2. attach (servoPin2);
      EEPROM.update(0, 3);
      myservo2.write(anguloOff , velocidad, true);
      myservo2. detach ();
      digitalWrite (led_izq, LOW);
      digitalWrite (led_centro, LOW);
      digitalWrite (led_dch, HIGH);
      digitalWrite (rele1, HIGH);//rele off
      digitalWrite (rele2, HIGH);//rele off
      Serial.println("dch");
      break;

    case 3:
      //3-> el desvio está en posicion derecha y pasa a posicion centro_1, se mueve el servo2 a la derecha
      //el desvio queda en posicion 4->centro_1
      myservo2. attach (servoPin2);
      EEPROM.update(0, 4);
      myservo2.write(anguloOn , velocidad, true);
      myservo2. detach ();
      digitalWrite (led_izq, LOW);
      digitalWrite (led_centro, HIGH);
      digitalWrite (led_dch, LOW);
      digitalWrite (rele1, HIGH);//rele off
      digitalWrite (rele2, LOW);//rele on
      Serial.println("centro_1");
      break;

    case 4:
      //4-> el desvio está en posición centro_1 despues de haber efectuado una vuelta y pasa a posicion 1->izquierda
      //se mueve el servo1 a la derecha
      //el desvio queda en posicion 1->izuierda
      myservo1. attach (servoPin1);
      myservo1.write(anguloOn , velocidad, true);
      EEPROM.update(0, 1);
      myservo1. detach ();
      digitalWrite (led_izq, HIGH);
      digitalWrite (led_centro, LOW);
      digitalWrite (led_centro, LOW);
      digitalWrite (rele1, LOW);//rele on
      digitalWrite (rele2, HIGH);//rele off
      Serial.println("izq");
      break;

    default:
      // if nothing else matches, do the default
      // default is optional
      break;
  }
}
/*###################################################################################################
  ###################################################################################################*/
//////////////////////////////////////////////////////
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {//dirección del decoder Addr Direccion 0-dch 1zq OutputPower 1 orden activar decoder

  if ((OutputPower == 1) && (Addr == direccion_DCC))  {                        // si llega comando de activar desvio
    triple_desvio = EEPROM.read(0);
  //  activaSalida (triple_desvio);                // activa salida segun tipo
  }
}


//if (( Addr == DCC_ADDRESS) && OutputPower) {

//  if (Direction == 0)
// digitalWrite(LED_PIN, LOW);
// else
//   digitalWrite(LED_PIN, HIGH);
//}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  delay (1000);
  Serial.begin(9600);

  pinMode(rele1,  OUTPUT) ;
  pinMode(rele2,  OUTPUT) ;
  digitalWrite(rele1, HIGH);
  digitalWrite(rele2, HIGH);
  pinMode (LED_PIN, OUTPUT);
  digitalWrite (LED_PIN, LOW);
  //pinMode( pinboton , INPUT) ;
  Dcc.pin (digitalPinToInterrupt (DCC_PIN), DCC_PIN, 1);
  Dcc.initAccessoryDecoder( MAN_ID_DIY, 1, FLAGS_OUTPUT_ADDRESS_MODE, 0);

  pinMode (led_izq, OUTPUT);
  digitalWrite (led_izq, LOW);
  pinMode (led_centro, OUTPUT);
  digitalWrite (led_centro, LOW);
  pinMode (led_dch, OUTPUT);
  digitalWrite (led_dch, LOW);

  delay (1000);
  myservo1. detach () ; //servos parados al inicio
  myservo2. detach () ;

  //el desvio triple comienza en la posicion izquierda,
  //por lo que antes de conectar el decoder los servos deben estar situados
  //para conseguir dicha posicion
  //el bucle es izquierda(1) centro_0(2) derecha(3) centro_1(4) izquierda(1)

  //triple_desvio = EEPROM.read(0); //lectura posicion del desvio
  //if (triple_desvio == 0xFF) {//es la primera vez que se conecta
  //  triple_desvio = 1;
  //  EEPROM.update(0, triple_desvio);
  //  digitalWrite (led_izq, HIGH);

  //}

  activaSalida (0);
  Serial.println(triple_desvio);
}



void loop() {
  Dcc.process();


  boton.actualizar();
  // Si estamos apretandolo guardamos el valor al inicio de millis.
  if ( boton.leer() == APRETANDOLO )
    inicio = millis();

  // Si estamos soltandolo tomamos el valor del final. El tiempo transcurrido entre el final
  // y el inicio nos dará el tiempo que está el botón pulsado. Ese valor lo mostramos por el puerto serie.
  if ( boton.leer() == SOLTANDOLO ) {
    fin = millis();
    tiempo_boton = fin - inicio;
    if ((tiempo_boton > 200) & (tiempo_boton < 3000)) {
      triple_desvio = EEPROM.read(0);
      Serial.println("boton on");
      activaSalida (triple_desvio);
    }

    if (tiempo_boton > 3000) {
      EEPROM.update(0, 1);
      triple_desvio = 1;
      myservo1. attach (servoPin1);
      myservo2. attach (servoPin2);
      myservo2.write(anguloOn , velocidad, true);
      myservo1.write(anguloOn , velocidad, true);
      myservo1. detach ();
      myservo2. detach ();
      digitalWrite (led_izq, HIGH);
      digitalWrite (led_centro, LOW);
      digitalWrite (led_dch, LOW);
      digitalWrite (rele1, LOW);
      digitalWrite (rele2, HIGH);

      //Serial.println(triple_desvio);
    }


  }

}



Adjuntos
BotonSimple.rar
(984 Bytes) 47 veces

Nota 12 Abr 2021 12:10

Desconectado
Mensajes: 132
Registrado: 26 Feb 2016 20:17
Buenos días, te comento mi experiencia por si te puede ser de interés.

Yo tenía todos los desvíos de la maqueta accionados con bobinas PECO y los estoy sustituyendo paulatinamente con Microservos 9G y motores lentos con contactores de final de carrera tipo Fulgurex, Tortoise, etc. La idea es relegar los desvíos con bobina a las zonas ocultas o bien aquellos en los que el reemplazo sea complicado por razones de acceso.

Los enclavamientos y la gestión de rutas la hago con un Arduino Nano con expansores de pines vía I2C, que reciben la información de los interruptores selectores y sensores de ocupación. El Arduino evalúa la ruta propuesta y envía órdenes a cada desvío a través de expansores de pines (si la ruta es viable) - 1 bit por desvío.

En cada desvío, tengo una placa específicamente diseñada (para Microservo, bobina o motor lento) que transforma el bit en una orden de movimiento del desvío. En cada placa, el circuito que recibe la señal desde el Arduino está eléctricamente separado con Optoacoplador. Las placas también se pueden gestionar en digital con un decoder de accesorios (p.ej. para señales), sólo necesitan un bit de entrada y éste se puede recibir desde Arduino o desde dicho decoder.

Ventajas:

- el programa en el Arduino es mucho más fácil de desarrollar ya que la gestión del movimiento de los aparatos de vía (desvíos, señalización mecánica, señalización luminosa, ...) es independiente del tipo de accionamiento del desvío,
- cada placa gestiona el movimiento de forma independiente, liberando recursos de la placa Arduino,
- cada placa se localiza físicamente junto al desvío correspondiente, así se elimina el riesgo de interferencias en la señal de control de los servos si el Arduino está físicamente lejos del desvío.

En el caso de los desvíos triples de PECO, tengo una placa específica que recibe la orden de movimiento (2 bits) desde el Arduino y efectúa el movimiento de los 2 servos según una secuencia determinada en función de la posición de destino y la posición previa. Para los cruces dobles, tengo una placa parecida.

Saludos cordiales.

Nota 25 Abr 2021 12:05

Desconectado
Mensajes: 46
Registrado: 14 Dic 2015 17:19
Buenos días
Dejo una actualización para el desvío triple.
Permite el funcionamiento en digital o analógico.
Para facilitar la posición inicial de los servos he configurado un pulsador con dos funciones. Si se pulsa normalmente los servos irán moviéndose pasando desde la posición inicial izquierda a centro-> derecha-> centro-> izquierda y vuelta a empezar.
Si se mantiene pulsado más de tres segundos, los servos pasarán a posición izquierda (inicial)
La central que tengo es Lenz.
Hay salidas leds para indicar la posición del desvío en un TCO y salidas para dos relés para polarizar el desvío.
En el programa aparace en qué parte del desvío hay que conectar los relés y la numeración de los servos. Otra configuración no va a funcionar bien.
En principio cuando se apaga y enciende el sistema se mantiene la posición de los servos. No he comprobado los relés ni los leds. Tengo pendiente conectar el desvío a dcc y al TCO .
El programa está comentado, supongo que se pueda seguir bien, además es sencillo.
He utilizado la librería <VarSpeedServo.h> que permite el control de la posición y velocidad de los servos. Esta posición es independiente para cada uno
Está funcionando en un arduino nano ATmega168, en mi caso el desvío está en la dirección 7
Un saludo

/*
 *     I      I      I   TT
 *      I     I     I
 * XX    I    I    I    RELE 1 CONECTADO A IZQUIERDA del DESVIO XX
 *        I   I   I     RELE 2 CONECTADO A DERECHA del DESVIO   TT 
 *         I  I  I
 *          I I I
 *            I
 *            I  SERVO 1
 *            I   
 *            I
 *            I  SERVO 2
 *
 *
 *
 *
 */



#include <EEPROM.h>
#include <VarSpeedServo.h>
#include <NmraDcc.h>
NmraDcc Dcc;
const byte DCC_PIN = 2;
const byte LED_PIN = 13;
byte triple_desvio = 0; //1-> izquierda 2->centro 3->derecha  se guarda en la posicion 0 de la memoria
const byte velocidad = 12; //velocidad a la que se mueven los servos

//////////////////////////////

VarSpeedServo myservo1;
VarSpeedServo myservo2;
int direccion_DCC = 7; // Direccion DCC del decoder triple
byte output; //   Estado del accesorio DCC: 1=on, 0=off

//definicion reles
byte rele1 = 11; // Pin de salida para rele1 para polarizar desvio
byte rele2 = 12; // Pin de salida para polarizar desvio

//definicion boton

const byte boton = 4;

int estadoboton1; // Esto es una variable entera
//int contador=0; // Variable contador igual a cero en el inicio.
int activado = 0; // Al principio no ha sido activado.
unsigned long tiempo, tiempo2, tiempo3; // Tiempos.


//definicion servos
const  int servoPin1 = 3; //pin de conexion para el servo 1
const  int servoPin2 = 5; //pin de conexion para el servo 2
byte angulo;
byte setpoint;
byte anguloOff = 50; // Angulo para DCC=off servo1
byte anguloOn = 150; // Angulo para DCC=on servo1
byte angulo2Off = 30; // Angulo para DCC=off servo2
byte angulo2On = 180; // Angulo para DCC=on servo2
boolean estado;
//definicion led para TCO
const byte led_izq = 8;
const byte led_centro = 9;
const byte led_dch = 10;




/*###################################################################################################
  pines para servos y accesorios
  servo 1 en pin 3 rele en pin 11
  servo 2 en pin 5 rele en pin 12
  led iquierdo en pin 8
  Led centro en pin 9
  Led derecho en pin 10
  ###################################################################################################
  ###################################################################################################*/

void activaSalida (int posicion) {
  //el bucle es izquierda(1) centro_0(2) derecha(3) centro_1(4) izquierda(1)

  switch (posicion) {
    //1-> el desvio está en la posicion izq y pasa a la posicion centro_0, se mueve el servo1 a la izquierda
    //el desvio queda en posicion 2->centro_0
    case 1:
      myservo1. attach (servoPin1);
      myservo1.write(anguloOff , velocidad, true);
      EEPROM.update(0, 2);
      myservo1. detach ();
      digitalWrite (led_izq, LOW);
      digitalWrite (led_centro, HIGH);
      digitalWrite (led_dch, LOW);
      digitalWrite (rele1, HIGH);//rele off
      digitalWrite (rele2, LOW);//rele on
      //Serial.println("centro");
      break;

    //2-> el desvio esta en posición centro y pasa a la posicion derecha, se mueve el servo2 a la izquierda
    //el desvio queda en posicion 3->derecha
    case 2:
      myservo2. attach (servoPin2);
      EEPROM.update(0, 3);
      myservo2.write(angulo2Off , velocidad, true);
      myservo2. detach ();
      digitalWrite (led_izq, LOW);
      digitalWrite (led_centro, LOW);
      digitalWrite (led_dch, HIGH);
      digitalWrite (rele1, HIGH);//rele off
      digitalWrite (rele2, HIGH);//rele off
      //Serial.println("dch");
      break;

    case 3:
      //3-> el desvio está en posicion derecha y pasa a posicion centro_1, se mueve el servo2 a la derecha
      //el desvio queda en posicion 4->centro_1
      myservo2. attach (servoPin2);
      EEPROM.update(0, 4);
      myservo2.write(angulo2On , velocidad, true);
      myservo2. detach ();
      digitalWrite (led_izq, LOW);
      digitalWrite (led_centro, HIGH);
      digitalWrite (led_dch, LOW);
      digitalWrite (rele1, HIGH);//rele off
      digitalWrite (rele2, LOW);//rele on
     // Serial.println("centro_1");
      break;

    case 4:
      //4-> el desvio está en posición centro_1 despues de haber efectuado una vuelta y pasa a posicion 1->izquierda
      //se mueve el servo1 a la derecha
      //el desvio queda en posicion 1->izuierda
      myservo1. attach (servoPin1);
      myservo1.write(anguloOn , velocidad, true);
      EEPROM.update(0, 1);
      myservo1. detach ();
      digitalWrite (led_izq, HIGH);
      digitalWrite (led_centro, LOW);
      digitalWrite (led_centro, LOW);
      digitalWrite (rele1, LOW);//rele on
      digitalWrite (rele2, HIGH);//rele off
      //Serial.println("izq");
      break;

    default:
      // if nothing else matches, do the default
      // default is optional
      break;
  }
}
/*###################################################################################################
  ###################################################################################################*/
//////////////////////////////////////////////////////
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {//dirección del decoder Addr Direccion 0-dch 1zq OutputPower 1 orden activar decoder

  if ((OutputPower == 1) && (Addr == direccion_DCC))  {                        // si llega comando de activar desvio
    triple_desvio = EEPROM.read(0);
     activaSalida (triple_desvio);                // activa salida segun tipo
  }
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  delay (1000);
  Serial.begin(9600);

  pinMode(rele1,  OUTPUT) ;
  pinMode(rele2,  OUTPUT) ;
  digitalWrite(rele1, HIGH);
  digitalWrite(rele2, HIGH);
  pinMode (LED_PIN, OUTPUT);
  digitalWrite (LED_PIN, LOW);
  //pinMode( pinboton , INPUT) ;
  Dcc.pin (digitalPinToInterrupt (DCC_PIN), DCC_PIN, 1);
  Dcc.initAccessoryDecoder( MAN_ID_DIY, 1, FLAGS_OUTPUT_ADDRESS_MODE, 0);

  pinMode (led_izq, OUTPUT);
  digitalWrite (led_izq, LOW);
  pinMode (led_centro, OUTPUT);
  digitalWrite (led_centro, LOW);
  pinMode (led_dch, OUTPUT);
  digitalWrite (led_dch, LOW);
  pinMode(boton, INPUT);

  delay (1000);
  myservo1. detach () ; //servos parados al inicio
  myservo2. detach () ;

  //el desvio triple comienza en la posicion izquierda,
  //por lo que antes de conectar el decoder los servos deben estar situados
  //para conseguir dicha posicion
  //el bucle es izquierda(1) centro_0(2) derecha(3) centro_1(4) izquierda(1)

  activaSalida (0);
  //Serial.println(triple_desvio);
}



void loop() {
  Dcc.process();

  estadoboton1 = digitalRead(boton);
  if (estadoboton1 == HIGH) {
    tiempo = millis();
    while (estadoboton1 == HIGH) {
      tiempo2 = millis();
      estadoboton1 = digitalRead(boton);
    }

    tiempo3 = tiempo2 - tiempo;
  }





  if (tiempo3 > 3000 ) { // Si fue activado=1 pasaron 3s
    EEPROM.update(0, 1);
    triple_desvio = 1;
    myservo1. attach (servoPin1);
    myservo2. attach (servoPin2);
    myservo2.write(angulo2On , velocidad, true);
    myservo1.write(anguloOn , velocidad, true);
    myservo1. detach ();
    myservo2. detach ();
    digitalWrite (led_izq, HIGH);
    digitalWrite (led_centro, LOW);
    digitalWrite (led_dch, LOW);
    digitalWrite (rele1, LOW);
    digitalWrite (rele2, HIGH);
   // Serial.println("tres s");
    tiempo3=0;


  }

  if ((tiempo3 > 200) && (tiempo3 < 3000)) {
    triple_desvio = EEPROM.read(0);
    activaSalida (triple_desvio);
   // Serial.println("normal");
    tiempo3=0;


  }
  }

 


He utilizado un módulo de este tipo para los relés

[url]

https://www.e-ika.com/modulo-de-reles-2 ... ra-arduino
[/url]


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