Índice general Foros Digital, Electricidad e Informática Decoder para servos y reles para polarizar el corazon de des

Decoder para servos y reles para polarizar el corazon de des

Moderador: 241-2001



Desconectado
Mensajes: 258
Ubicación: Lleida/Madrid
Registrado: 30 Abr 2009 22:42
Hola:

Desde mi ignorancia en la programación de Arduino he logrado modificar un sketch de un decóder, que encontré y no se quién lo realizó, para mover servos y, simultáneamente y con la misma dirección, actuar sobre las bobinas de un relé polarizado tipo TQ2-L2, para polarizar el corazón de los desvíos Peco. Hasta aquí todo funciona pero necesito temporizar la salida al relé para que se desconecte sobre los 500 milisegundos, y no lo logro. Ayuda por favor.

Este es el sketchs que me funciona.

//DECODER_SERVOS_Y_ACCESORIOS_PARA_POLARIZAR_CORAZON_DESVIO_CON_RELES_POLARIZADOS

// IR A configuración () PARA CONFIGURAR DIRECCIONES DCC, NÚMEROS PIN, ÁNGULOS DE SERVO
#define NUMSERVOS 1// Ingrese el número de servos aquí
#define SERVOSPEED 60 // [ms] entre actualizaciones de servo, menor es más rápido

#include <DCC_Decoder.h>
#include <Servo.h>

unsigned long timetomove;

typedef struct DCCAccessoryData {
int address; // Dirección DCC configurable por el usuario
byte outputpin; // Pin Arduino configurable por el usuario
byte outputpin2; // Pin Arduino configurable por el usuario
byte highlow; // estado outputpin: 1=HIGH, 0=LOW
byte highlow2; // estado outputpin2: 1=HIGH, 0=LOW
byte angle; // Ángulo actual de uso interno del punto de consigna del servo
byte setpoint; // Ángulo actual de uso interno del punto de consigna del servo
byte offangle; // Servo ángulo configurable por el usuario para el estado DCC = 0
byte onangle; // Servo ángulo configurable por el usuario para el estado DCC = 1
Servo servo;
};
DCCAccessoryData servo [NUMSERVOS];

void BasicAccDecoderPacket_Handler (int address, boolean activate, byte data) {
address -= 1;
address *= 4;
address += 1;
address += (data & 0x06) >> 1;
// address = address - 4 // descomenta esta línea para Roco Maus o Z21
boolean enable = (data & 0x01)? 1: 0;
for (int i = 0; i <NUMSERVOS; i ++) {
if (address == servo [i] .address) {
if (enable) servo [i] .highlow = 1;
else servo [i] .highlow = 0;
if (enable) servo [i] .highlow2 = 0;
else servo [i] .highlow2 =1;
}
}
}

void setup () {
// CONFIGURACIÓN DE SERVOS
// Copia y pega tantas veces como tengas servos
// La cantidad debe ser igual a NUMSERVOS
// No olvides incrementar el índice de la matriz
servo [0] .address = 1; // DCC direccion
servo [0] .outputpin = 13; // Pin accesorio Arduino
servo [0] .outputpin2 = 12; // Pin accesorio Arduino
servo [0] .highlow = 0; // No cambiar este valor
servo [0] .highlow2 = 0; // No cambiar este valor
servo [0] .servo.attach (4); // Arduino servo pin
servo [0] .offangle = 50; // Ángulo de servo para el estado DCC = 0
servo [0] .onangle = 100; // ángulo servo para el estado DCC = 1


DCC.SetBasicAccessoryDecoderPacketHandler (BasicAccDecoderPacket_Handler, true);
DCC.SetupDecoder (0x00, 0x00, 0);
}


void loop () {
DCC.loop (); // Llamada a la función de biblioteca que lee los datos DCC

for (byte i = 0; i <NUMSERVOS; i ++) {
if (servo [i].highlow == 1) {
digitalWrite (servo [i].outputpin, HIGH);
digitalWrite (servo [i].outputpin2, LOW);
servo [i]. highlow =1;
servo [i].setpoint = servo [i] .onangle;
}
else {
digitalWrite (servo [i].outputpin, LOW);
digitalWrite (servo [i].outputpin2, HIGH);
servo [i].setpoint = servo [i] .offangle;
}
}

// Mueve los servos cuando es timetomove
if (millis ()> timetomove) {
timetomove = millis () + (unsigned long) SERVOSPEED;
for (byte i = 0; i <NUMSERVOS; i ++) {
if (servo [i].angle <servo [i].setpoint) servo [i] .angle ++;
if (servo [i].angle> servo [i].setpoint) servo [i] .angle--;
servo [i].servo.write (servo [i].angle);
}
}
}

Saludos y gracias


Desconectado
Mensajes: 1419
Registrado: 21 Mar 2014 12:52
Veo que el sketch utiliza dos pines por aguja (13 y 12), aparte del de el servo (4) propiamente dicho, que obviamente debe ser un pin PWM.
Estos dos pines se activan/desactivan de forma cruzada, esto es, cuando uno está HIGH el otro está LOW y viceversa, supongo que utilizas uno de los pines para cada una de las bobinas del relé

Por cierto, es conveniente poner un diodo en cada una de las bobinas de forma que la marca apunte al borne de la bobina que se conecta al pin del Arduino, por si no lo tienes. Así evitarás quemar el Arduino pues cuando desconectas la bobina de un relé, se genera una corriente inversa que tiene que para el Arduino. Con este Diodo, esta corriente se desvanece sin quemar nada.

Las líneas que he añadido están marcadas con <===== El Matao

básicamente es que cuando se recibe un comando para la aguja (procedimiento BasicAccDecoderPacket_Handler) marcamos ese momento (millis() ) y le sumamos el tiempo T_RELE (he puesto 500 milisegundos)
Posteriormente en el procedimiento loop, si aún no hemos llegado a ese tiempo, permito poner ese pin en HIGH, pero si lo hemos pasado lo ponemos en LOW.

No puedo compilarlo, no tengo las librerías, pero creo que debería funcionar, quizás con pequeños arreglos sintácticos, que eso siempre me da la lata.

//DECODER_SERVOS_Y_ACCESORIOS_PARA_POLARIZAR_CORAZON_DESVIO_CON_RELES_POLARIZADOS

// IR A configuración () PARA CONFIGURAR DIRECCIONES DCC, NÚMEROS PIN, ÁNGULOS DE SERVO
#define NUMSERVOS 1// Ingrese el número de servos aquí
#define SERVOSPEED 60 // [ms] entre actualizaciones de servo, menor es más rápido

#include <DCC_Decoder.h>
#include <Servo.h>

unsigned long timetomove;

typedef struct DCCAccessoryData {
   int address;      // Dirección DCC configurable por el usuario
   byte outputpin;   // Pin Arduino configurable por el usuario
   byte outputpin2;  // Pin Arduino configurable por el usuario
   byte highlow;     // estado outputpin: 1=HIGH, 0=LOW
   byte highlow2;    // estado outputpin2: 1=HIGH, 0=LOW
   byte angle;       // Ángulo actual de uso interno del punto de consigna del servo
   byte setpoint;    // Ángulo actual de uso interno del punto de consigna del servo
   byte offangle;    // Servo ángulo configurable por el usuario para el estado DCC = 0
   byte onangle;     // Servo ángulo configurable por el usuario para el estado DCC = 1
   Servo servo;
   };
DCCAccessoryData servo [NUMSERVOS];

unsigned long tiempo [NUMSERVOS];                                               // <===== El Matao
unsigned long T_RELE = 500;          // (milisegundos de activación del relé)   // <===== El Matao

void BasicAccDecoderPacket_Handler (int address, boolean activate, byte data) {
   address -= 1;
   address *= 4;
   address += 1;
   address += (data & 0x06) >> 1;
   // address = address - 4 // descomenta esta línea para Roco Maus o Z21
   boolean enable = (data & 0x01)? 1: 0;
   for (int i = 0; i <NUMSERVOS; i ++) {
      if (address == servo [i] .address) {
        tiempo[i] = millis() + T_RELE;                                         // <===== El Matao
         if (enable) servo [i] .highlow = 1;
         else servo [i] .highlow = 0;
         if (enable) servo [i] .highlow2 = 0;
         else servo [i] .highlow2 =1;
      }
   }
}

void setup () {
// CONFIGURACIÓN DE SERVOS
// Copia y pega tantas veces como tengas servos
// La cantidad debe ser igual a NUMSERVOS
// No olvides incrementar el índice de la matriz
   servo [0] .address = 1; // DCC direccion
   servo [0] .outputpin = 13; // Pin accesorio Arduino
   servo [0] .outputpin2 = 12; // Pin accesorio Arduino
   servo [0] .highlow = 0; // No cambiar este valor
   servo [0] .highlow2 = 0; // No cambiar este valor
   servo [0] .servo.attach (4); // Arduino servo pin
   servo [0] .offangle = 50; // Ángulo de servo para el estado DCC = 0
   servo [0] .onangle = 100; // ángulo servo para el estado DCC = 1
   tiempo [0] = 0;                                                              // <===== El Matao

   DCC.SetBasicAccessoryDecoderPacketHandler (BasicAccDecoderPacket_Handler, true);
   DCC.SetupDecoder (0x00, 0x00, 0);
}


void loop () {
   DCC.loop (); // Llamada a la función de biblioteca que lee los datos DCC

   for (byte i = 0; i <NUMSERVOS; i ++) {
      if (servo [i].highlow == 1) {
         if millis()<tiempo[i] {                                                // <=== El Matao
            digitalWrite (servo [i].outputpin, HIGH);
         }                                                                   // <=== El Matao
       else {                                                                 // <=== El Matao
            digitalWrite (servo [i].outputpin, LOW);                            // <=== El Matao
       }                                                                      // <=== El Matao
         digitalWrite (servo [i].outputpin2, LOW);
         servo [i]. highlow =1;
         servo [i].setpoint = servo [i] .onangle;
         }
      else {
         digitalWrite (servo [i].outputpin, LOW);
         if millis()<tiempo[i] {                                                // <=== El Matao
            digitalWrite (servo [i].outputpin2, HIGH);
         }                                                                       // <=== El Matao
         else {                                                                  // <=== El Matao
            digitalWrite (servo [i].outputpin2, LOW);                           // <=== El Matao
         };                                                                     // <=== El Matao
         servo [i].setpoint = servo [i] .offangle;
      }
   }

// Mueve los servos cuando es timetomove
   if (millis ()> timetomove) {
      timetomove = millis () + (unsigned long) SERVOSPEED;
      for (byte i = 0; i <NUMSERVOS; i ++) {
         if (servo [i].angle <servo [i].setpoint) servo [i] .angle++;           
         if (servo [i].angle> servo [i].setpoint) servo [i] .angle--;               
         servo [i].servo.write (servo [i].angle);
      }
   }
}


Un saludo


Desconectado
Mensajes: 258
Ubicación: Lleida/Madrid
Registrado: 30 Abr 2009 22:42
Hola.

El Matao, gracias por tu modificación, este fin de semana probaré si me compila, ya te diré.

Saludos


Desconectado
Mensajes: 258
Ubicación: Lleida/Madrid
Registrado: 30 Abr 2009 22:42
Hola:

Bueno, después de corregir algunos fallos de sintaxis he logrado que funcion, gracias El Matao.

Adjunto el sketch por si alguien lo quiere aprovechar. Puede que alguna cosa de la sintaxis no sea muy ortodoxa pero funciona.

Actúa el servo y las salidas de accesorios correctamente. Solo hay un problema al dar tensión al conjunto arduino y servo, el servo pega un bote a un extremo de su carrera y luego va a la posición correcta.

//DECODER_SERVOS_Y_ACCESORIOS_PARA_POLARIZAR_CORAZON_DESVIO_CON_RELES_POLARIZADOS

// IR A configuración () PARA CONFIGURAR DIRECCIONES DCC, NÚMEROS PIN, ÁNGULOS DE SERVO
#define NUMSERVOS 1// Ingrese el número de servos aquí
#define SERVOSPEED 60 // [ms] entre actualizaciones de servo, menor es más rápido

#include <DCC_Decoder.h>
#include <Servo.h>

unsigned long timetomove;

typedef struct DCCAccessoryData {
int address; // Dirección DCC configurable por el usuario
byte outputpin; // Pin Arduino configurable por el usuario
byte outputpin2; // Pin Arduino configurable por el usuario
byte highlow; // estado outputpin: 1=HIGH, 0=LOW
byte highlow2; // estado outputpin2: 1=HIGH, 0=LOW
byte angle; // Ángulo actual de uso interno del punto de consigna del servo
byte setpoint; // Ángulo actual de uso interno del punto de consigna del servo
byte offangle; // Servo ángulo configurable por el usuario para el estado DCC = 0
byte onangle; // Servo ángulo configurable por el usuario para el estado DCC = 1
Servo servo;
};
DCCAccessoryData servo [NUMSERVOS];

unsigned long tiempo [NUMSERVOS];
unsigned long T_RELE = 500; // (milisegundos de activación del relé)

void BasicAccDecoderPacket_Handler (int address, boolean activate, byte data) {
address -= 1;
address *= 4;
address += 1;
address += (data & 0x06) >> 1;
// address = address - 4 // descomenta esta línea para Roco Maus o Z21
boolean enable = (data & 0x01)? 1: 0;
for (int i = 0; i <NUMSERVOS; i ++) {
if (address == servo [i] .address) {
tiempo[i] = millis() + T_RELE;
if (enable) servo [i] .highlow = 1;
else servo [i] .highlow = 0;
if (enable) servo [i] .highlow2 = 0;
else servo [i] .highlow2 =1;
}
}
}

void setup () {
// CONFIGURACIÓN DE SERVOS
// Copia y pega tantas veces como tengas servos
// La cantidad debe ser igual a NUMSERVOS
// No olvides incrementar el índice de la matriz
servo [0] .address = 1; // DCC direccion
servo [0] .outputpin = 13; // Pin accesorio Arduino
servo [0] .outputpin2 = 12; // Pin accesorio Arduino
servo [0] .highlow = 0; // No cambiar este valor
servo [0] .highlow2 = 0; // No cambiar este valor
servo [0] .servo.attach (4); // Arduino servo pin
servo [0] .offangle = 50; // Ángulo de servo para el estado DCC = 0
servo [0] .onangle = 100; // ángulo servo para el estado DCC = 1
tiempo [0] = 0;

DCC.SetBasicAccessoryDecoderPacketHandler (BasicAccDecoderPacket_Handler, true);
DCC.SetupDecoder (0x00, 0x00, 0);
}


void loop () {
DCC.loop (); // Llamada a la función de biblioteca que lee los datos DCC

for (byte i = 0; i <NUMSERVOS; i ++) {
if (servo [i].highlow == 1) {
if (millis()<tiempo[i]) {
digitalWrite (servo [i].outputpin, HIGH);

} else {
digitalWrite (servo [i].outputpin, LOW);

digitalWrite (servo [i].outputpin2, LOW);
servo [i]. highlow =1;
servo [i].setpoint = servo [i] .onangle;
}
}else {
digitalWrite (servo [i].outputpin, LOW);
if (millis()<tiempo[i]) {
digitalWrite (servo [i].outputpin2, HIGH);
}

else {
digitalWrite (servo [i].outputpin2, LOW);

(servo [i].setpoint = servo [i] .offangle);
}
}


// Mueve los servos cuando es timetomove
if (millis ()> timetomove) {
timetomove = millis () + (unsigned long) SERVOSPEED;
for (byte i = 0; i <NUMSERVOS; i ++) {
if (servo [i].angle <servo [i].setpoint) servo [i] .angle++;
if (servo [i].angle> servo [i].setpoint) servo [i] .angle--;
servo [i].servo.write (servo [i].angle);
}
}
}
}

Saludos


Desconectado
Mensajes: 1419
Registrado: 21 Mar 2014 12:52
cesarnog escribió:
Hola:

Bueno, después de corregir algunos fallos de sintaxis he logrado que funcion, gracias El Matao.

Me alegro, espero que no hayan sido muchos los fallos, ni graves
cesarnog escribió:
.... Solo hay un problema al dar tensión al conjunto arduino y servo, el servo pega un bote a un extremo de su carrera y luego va a la posición correcta.

¿este comportamiento ya lo tenía antes?
Lo digo por que en principio no he tocado nada del control del servo
Pienso que si cambias el procedimiento setup() añadiendo esta línea, el servo irá directamente a la posición DCC 0 (¿recto?) si quieres que inicialmente vaya a la otra posición, cambia el offangle de esa línea por onangle
void setup () {
// CONFIGURACIÓN DE SERVOS
// Copia y pega tantas veces como tengas servos
// La cantidad debe ser igual a NUMSERVOS
// No olvides incrementar el índice de la matriz
   servo [0] .address = 1;                // DCC direccion
   servo [0] .outputpin = 13;             // Pin accesorio Arduino
   servo [0] .outputpin2 = 12;            // Pin accesorio Arduino
   servo [0] .highlow = 0;                // No cambiar este valor
   servo [0] .highlow2 = 0;               // No cambiar este valor
   servo [0] .servo.attach (4);           // Arduino servo pin
   servo [0] .offangle = 50;              // Ángulo de servo para el estado DCC = 0
   servo [0] .onangle = 100;              // ángulo servo para el estado DCC = 1
   servo [0] .angle = servo[0].offangle;  // posición inicial del servo                                   //<=========== El Matao
   tiempo [0] = 0;                                                             

   DCC.SetBasicAccessoryDecoderPacketHandler (BasicAccDecoderPacket_Handler, true);
   DCC.SetupDecoder (0x00, 0x00, 0);
}


Ya nos dirás

Un saludo


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