decoder para desvíos fleischmann con arduino
#14
Aquí os dejo el Sketch que tendréis que meter al Arduino Nano para que funcione la tarjeta como decoder de desvíos tipo Fleischmann de bobina/solenoide.
Supongo que este programa no será perfecto y muy mejorable, pero es lo que conseguí elaborar para mis propósitos tras pegarme con él largas horas y sin conocer este lenguje de programación.

Tal y como está, si no se programase una nueva dirección, sería de la 33 a la 40 y los impulso de tensión a las bobinas, para accionar el desvío, de 450 ms.


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Arduino DCC Solenoid Switch Decoder.
// Author: Ruud Boer - January 2015
// Modificado por Pecetero - Julio 2018
// This sketch turns an Arduino into a DCC decoder to drive max 8 dual coil solenoid switches.
// The DCC signal is optically separated and fed to pin 2 (=Interrupt 0). Schematics: www.mynabay.com
// Many thanks to www.mynabay.com for publishing their DCC monitor and -decoder code.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <DCC_Decoder.h>
#include <EEPROM.h>

#define kDCC_INTERRUPT 0
#define EEPROM_ADDRESS 2  // dode se guardara la direccion dcc
#define pulsador 3
#define aviso_tiempo 20

unsigned long Tprog_Milli;  // Tiempo de espera para programar
int direccion=33;
int bucle ;
int reset = 0;
const byte impulso=250;  // Se sumará 200 al valor definido

////////////////////////////////////////////////////////
//El numero de desvios que se van a controlar
const byte maxaccessories=8; 
///////////////////////////////////////////////////////

typedef struct
{
  int               address;         // Address to respond to
  byte              output;          // State of accessory: 1=on, 0=off (for internal use only)
  int               outputPin;       // Arduino output pin
  int               outputPin2;      // Arduino output pin2, used for solenoid junctions
  byte              highlow;         // State of outputpin: 1=HIGH, 0=LOW
  byte              highlow2;        // State of outputpin2: 1=HIGH, 0=LOW
  boolean           finished;        // Memory location that says the oneshot is finished
  boolean           finished2;       // Memory location that says the second oneshot (for solenoid) is finished
  int               durationMilli;   // ms flash time
  unsigned long     onMilli;         // for internal use
  unsigned long     offMilli;        // for internal use
  


DCCAccessoryAddress;
DCCAccessoryAddress accessory[maxaccessories];

void ConfigureDecoderFunctions() 
{
  accessory[0].address = direccion;
  accessory[0].durationMilli = impulso + 200;
  accessory[0].outputPin = 4;
  accessory[0].outputPin2 = 5;
  accessory[0].highlow = 0; // Do not change this value
  accessory[0].highlow2 = 0; // Do not change this value
  accessory[0].finished = false; // Do not change this value
  accessory[0].finished2 = true; // Do not change this value
  accessory[0].output = 0; // Do not change this value

  accessory[1].address = direccion + 1;
  accessory[1].durationMilli = impulso + 200;
  accessory[1].outputPin = 6;
  accessory[1].outputPin2 = 7;
  accessory[1].highlow = 0; // Do not change this value
  accessory[1].highlow2 = 0; // Do not change this value
  accessory[1].finished = false; // Do not change this value
  accessory[1].finished2 = true; // Do not change this value
  accessory[1].output = 0; // Do not change this value

  accessory[2].address = direccion + 2;
  accessory[2].durationMilli = impulso + 200;
  accessory[2].outputPin = 8;
  accessory[2].outputPin2 = 9;
  accessory[2].highlow = 0; // Do not change this value
  accessory[2].highlow2 = 0; // Do not change this value
  accessory[2].finished = false; // Do not change this value
  accessory[2].finished2 = true; // Do not change this value
  accessory[2].output = 0; // Do not change this value

  accessory[3].address = direccion + 3;
  accessory[3].durationMilli = impulso + 200;
  accessory[3].outputPin = 10;
  accessory[3].outputPin2 = 11;
  accessory[3].highlow = 0; // Do not change this value
  accessory[3].highlow2 = 0; // Do not change this value
  accessory[3].finished = false; // Do not change this value
  accessory[3].finished2 = true; // Do not change this value
  accessory[3].output = 0; // Do not change this value

  accessory[4].address = direccion + 4;
  accessory[4].durationMilli = impulso + 200;
  accessory[4].outputPin = 12;
  accessory[4].outputPin2 = 13;
  accessory[4].highlow = 0; // Do not change this value
  accessory[4].highlow2 = 0; // Do not change this value
  accessory[4].finished = false; // Do not change this value
  accessory[4].finished2 = true; // Do not change this value
  accessory[4].output = 0; // Do not change this value

  accessory[5].address = direccion + 5;
  accessory[5].durationMilli = impulso + 200;
  accessory[5].outputPin = 14;
  accessory[5].outputPin2 = 15;
  accessory[5].highlow = 0; // Do not change this value
  accessory[5].highlow2 = 0; // Do not change this value
  accessory[5].finished = false; // Do not change this value
  accessory[5].finished2 = true; // Do not change this value
  accessory[5].output = 0; // Do not change this value

  accessory[6].address = direccion + 6;
  accessory[6].durationMilli = impulso + 200;
  accessory[6].outputPin = 16;
  accessory[6].outputPin2 = 17;
  accessory[6].highlow = 0; // Do not change this value
  accessory[6].highlow2 = 0; // Do not change this value
  accessory[6].finished = false; // Do not change this value
  accessory[6].finished2 = true; // Do not change this value
  accessory[6].output = 0; // Do not change this value

  accessory[7].address = direccion + 7;
  accessory[7].durationMilli = impulso + 200;
  accessory[7].outputPin = 18;
  accessory[7].outputPin2 = 19;
  accessory[7].highlow = 0; // Do not change this value
  accessory[7].highlow2 = 0; // Do not change this value
  accessory[7].finished = false; // Do not change this value
  accessory[7].finished2 = true; // Do not change this value
  accessory[7].output = 0; // Do not change this value

  // Setup output pins
  for(int i=0; i<maxaccessories; i++)
  {
    if( accessory[i].outputPin )
{
      pinMode( accessory[i].outputPin, OUTPUT );
      digitalWrite( accessory[i].outputPin, LOW);
    }
    if( accessory[i].outputPin2 )
{
      pinMode( accessory[i].outputPin2, OUTPUT );
      digitalWrite( accessory[i].outputPin2, LOW);
    }
  }
  pinMode(aviso_tiempo,OUTPUT);
  
} // END ConfigureDecoderFunctions

//////////////////// DCC packet handler //////////////////////////////////////
void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
{

  // Convert NMRA packet address format to human address
  address -= 1;
  address *= 4;
  address += 1;
  address += (data & 0x06) >> 1;

  boolean enable = (data & 0x01) ? 1 : 0;

/////////////////////////////////////////////////////////////////////////////
//========== lectura de direccion para guardar =============================//
  //Si estamos en modo programacion, se guarda la direccion                //
 
   if (bucle==1)   {
     while (millis()- (Tprog_Milli) < 5000) { 
        //digitalWrite(13, HIGH); //provisional
        digitalWrite(aviso_tiempo, HIGH);  
        EEPROM.update(EEPROM_ADDRESS,address%256);                
        EEPROM.update(EEPROM_ADDRESS+1,address/256);
        reset = 1;
     }
     bucle = 0;                              
   }
     if (reset==1) { 
       reset = 0;
       //digitalWrite(13, LOW); //provisional
       digitalWrite(aviso_tiempo, LOW);
       //declara función de reset @ address 0 
       void(* resetFunc) (void) = 0;
       resetFunc(); //Reset  
     }

//=========================================================================//  
/////////////////////////////////////////////////////////////////////////////

  for(int i=0; i<maxaccessories; i++)
{
    if( address == accessory[i].address )
{
      if( enable ) accessory[i].output = 1;
      else accessory[i].output = 0;
    }
  }
} // END BasicAccDecoderPacket_Handler

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Setup (run once)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() 


  DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);
  ConfigureDecoderFunctions();
  DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT );
  pinMode(2,INPUT_PULLUP); //Interrupt 0 with internal pull up resistor (can get rid of external 10k)
    
} //END setup

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main loop (ejecucion continua)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{

if (digitalRead(pulsador)==HIGH) {  //pulsador de programación
    //digitalWrite(13, HIGH);  //provisional
    digitalWrite(aviso_tiempo, HIGH);
    Tprog_Milli = millis();
    bucle = 1;
  }
if(millis()- (Tprog_Milli) > 5000)   {
   //digitalWrite(13, LOW);  //provisional
   digitalWrite(aviso_tiempo, LOW); 
}
  static int addr = 0;

   DCC.loop(); // Loop DCC library
 
  if( ++addr >= maxaccessories ) addr = 0; // Bump to next address to test

  if (accessory[addr].output == 1)
{
if (!accessory[addr].highlow && !accessory[addr].finished)
{
accessory[addr].highlow = 1;
      accessory[addr].offMilli = millis() + accessory[addr].durationMilli;
}
if (accessory[addr].highlow && millis() > accessory[addr].offMilli)
{
accessory[addr].highlow = 0;
accessory[addr].finished = true;
}
accessory[addr].finished2 = false;
  }

  else // output==0
  {
accessory[addr].highlow = 0;
//accessory[addr].finished = false;
if (!accessory[addr].highlow2 && !accessory[addr].finished2)
{
accessory[addr].highlow2 = 1;
accessory[addr].offMilli = millis() + accessory[addr].durationMilli;
}
if (accessory[addr].highlow2 && millis() > accessory[addr].offMilli)
{
accessory[addr].highlow2 = 0;
accessory[addr].finished2 = true;
}
    accessory[addr].finished = false;
  }

  if (accessory[addr].highlow) digitalWrite( accessory[addr].outputPin, HIGH);
  else digitalWrite( accessory[addr].outputPin, LOW);
       
  if (accessory[addr].highlow2) digitalWrite( accessory[addr].outputPin2, HIGH);
  else digitalWrite( accessory[addr].outputPin2, LOW);

 } //END loop

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Responder


Mensajes en este tema
RE: decoder para desvíos fleischmann con arduino - por Pecetero - 30-11-2018, 14:56

Posibles temas similares...
Tema Autor Respuestas Vistas Último mensaje
  Pido ayuda para mapear un Zimo Next 18 tigrin 13 469 08-04-2024, 14:12
Último mensaje: tigrin
  Proyecto de pupitre para control simple DCC Kris Kelvin 28 1,873 13-03-2024, 13:18
Último mensaje: Kris Kelvin
Bombilla Encendido lento luces decoder DH18A Pedro MT 3 422 23-01-2024, 00:02
Último mensaje: Pedro MT
  Decoder Zimo Next 18 tigrin 12 1,877 15-01-2024, 22:42
Último mensaje: tigrin
  Ayuda/consejo para decoders desvíos Speedy González 3 1,068 03-01-2024, 22:12
Último mensaje: Speedy González
  Desvíos y Semáforos Adolfo Ant. 23 4,788 02-01-2024, 17:53
Último mensaje: Adolfo Ant.
  Decoder TER (Mabar) Albatros768 6 1,563 21-12-2023, 13:04
Último mensaje: Sanbernardo
  Ayuda para identificar componente en placa. Caribue 30 2,833 14-12-2023, 09:26
Último mensaje: leptrain
  decoder bloqueado tigrin 10 1,619 03-11-2023, 18:56
Último mensaje: Alco
  Programar un DH18A para una 277 Arnold tigrin 6 2,384 08-10-2023, 17:50
Último mensaje: mario1969

Salto de foro:


Usuarios navegando en este tema: 2 invitado(s)