Voilà une solution pour moteur classique avec décodeur DCC sur base de but Loconet
à noter que l'interface est toujours la même entre la carte Arduino et le bus Loconet
Cf.
https://www.modelrailway-online.com/ard ... loconet-3/
Une photographie de la platine de commande:
Le câblage de la platine:
- 2024-02-23_105406.jpg (45.78 Kio) Vu 142 fois
Le code :
// Name
#define NAME "DCC-TT-Motor"
#define NAME2 "LocoNet protocol (Digitrax) uses to manage a TurnTable by a DCC Decoder without stepper motor"
#define NAME3 "Sounds by a DFPlayer board"
// Version & Copyright
#define VERSION "1.0 (Arduino Uno)"
#define COPYRIGHT "Fabrice Fayolle, November 2019"
// Digitrax LocoNet -> LocoNet
// DCC Throttle -> Throttle
// Sound system -> DFPlayer
// Arduino Uno
// Pin -> Use for -> Connect to
// 0
// ...
// 4 -> Signal -> SPDT ON-ON
// 5 -> Light -> SPDT ON-ON
// 6 -> Default -> Red LED (with a 220 ohms resistor)
// 7 -> LocoNet Transmit pin -> Locoshield PCB Tx pin
// 8 -> LocoNet Receive pin -> Locoshield PCB Rx pin
// 9 -> Emergency Stop -> Push button
// 10 -> Serial Rx pin -> DFPlayer PCB Tx pin
// 11 -> Serial Tx pin -> DFPlayer PCB Rx pin
// 12
// 13
// 14
// 15 -> Turntable direction -> SPDT ON-ON
// 16 -> Turntable stop -> Push button
// 17 -> Turntable brake -> Push button
// 18 -> Turntable low speed -> Push button
// 19 -> Turntable mid speed -> Push button
// INPUT
// Push button
// 1 -> Arduino Pin
// 2 -> GND
// SPDT ON-ON
// 1 -> 5V -> Normal position
// Common point -> Arduino Pin
// 2 -> GND -> Reverse position
// OUTPUT
// Digitrax LocoNet message
// Global constants and variables
const boolean Activated = LOW;
// Visual management for interlocking system
// Default lever position
const int DefaultPin = 6;
// Throttle
// Define used slots table
int used_SLOT[120];
// Define the address of the turntable DCC decoder
const int ADR_Turntable = 101;
// Define constants and variables for the turntable
boolean TT_dir = false;
const int TT_dir_PIN = 15;
const int TT_stop_PIN = 16;
const int TT_brake_PIN = 17;
#define TT_brake -0x01
const int TT_lowspeed_PIN = 18;
#define TT_lowspeed 0x03
const int TT_midspeed_PIN = 19;
#define TT_midspeed 0x40
// DFPlayer
//
https://github.com/PowerBroker2/DFPlayerMini_Fast
#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>
// LocoNet
//
https://github.com/mrrwa
#include <LocoNet.h>
// Define LocoNet Transmit Pin
#define LN_TX_PIN 7
// Emergency Stop
const int Emergency_PIN = 9;
// Pointer to a received LocoNet packet
lnMsg *LnPacket;
void slot_Init()
// Initiliaze all slots
{
for (int slot = 0; slot < 120; slot++)
{
sendOPC_xxx(OPC_RQ_SL_DATA, slot, 0);
}
}
void sendOPC_x(int OPC_Type)
// OPC_GPOFF - OPC_GPON - OPC_IDLE LocoNet Message
{
lnMsg SendPacket;
SendPacket.data[0] = OPC_Type;
LocoNet.send( &SendPacket );
switch (OPC_Type)
{
case OPC_GPOFF:
// OPC_GPOFF -> Power OFF
Serial.print("OPC_GPOFF");
break;
case OPC_GPON:
// OPC_GPON -> Power ON
Serial.print("OPC_GPON");
break;
case OPC_IDLE:
// OPC_IDLE -> Emergency Stop
Serial.print("OPC_IDLE");
break;
}
Serial.println(" LocoNet message sent");
delay(250);
return;
}
void sendOPC_xxx(int OPC_Type, int Arg1, int Arg2)
// OPC_LOCO_SPD - OPC_LOCO_DIRF - OPC_LOCO_SND - OPC_SW_REQ - OPC_MOVE_SLOTS - OPC_RQ_SL_DATA - OPC_LOCO_ADR LocoNet Message
{
lnMsg SendPacket;
SendPacket.data[0] = OPC_Type;
SendPacket.data[1] = Arg1;
SendPacket.data[2] = Arg2;
LocoNet.send( &SendPacket );
switch (OPC_Type)
{
case OPC_LOCO_SPD:
// OPC_LOCO_SPD
Serial.print ("SLOT ");
Serial.print(Arg1);
Serial.print(" : OPC_LOCO_SPD");
break;
case OPC_LOCO_DIRF:
// OPC_LOCO_DIRF
Serial.print ("SLOT ");
Serial.print(Arg1);
Serial.print(" : OPC_LOCO_DIRF");
break;
case OPC_LOCO_SND:
// OPC_LOCO_SND
Serial.print ("SLOT ");
Serial.print(Arg1);
Serial.print(" : OPC_LOCO_SND");
break;
case OPC_SW_REQ:
// OPC_SW_REQ
Serial.print ("Turnout Adr ");
Serial.print(Arg1 + 1);
Serial.print(" : OPC_SW_REQ");
break;
case OPC_MOVE_SLOTS:
// OPC_MOVE_SLOTS
Serial.print ("SLOT ");
Serial.print(Arg1);
Serial.print(" : OPC_MOVE_SLOTS");
break;
case OPC_RQ_SL_DATA:
// OPC_RQ_SL_DATA
Serial.print ("SLOT ");
Serial.print(Arg1);
Serial.print(" : OPC_RQ_SL_DATA");
break;
case OPC_LOCO_ADR:
// OPC_LOCO_ADR
Serial.print ("DCC Adr ");
Serial.print(Arg2);
Serial.print(" : OPC_LOCO_ADR");
break;
}
Serial.println(" LocoNet message sent");
delay(250);
return;
}
void LocoNet_Message_For_Lever(int SLever_dcc, int SLever_type, boolean SLever_state)
{
int sw1 = 0x00;
int sw2 = 0x00;
switch (SLever_type)
{
case 0 :
// 0 -> Not use
break;
case 1 :
// 1 -> Point
SLever_dcc = SLever_dcc - 1;
if (SLever_state)
{
sw1 |= B00100000;
sw2 |= B00100000;
}
sw1 |= B00010000;
sw1 |= (SLever_dcc >> 7) & 0x0F;
sw2 |= (SLever_dcc >> 7) & 0x0F;
sendOPC_xxx(OPC_SW_REQ, SLever_dcc & 0x7F, sw1);
sendOPC_xxx(OPC_SW_REQ, SLever_dcc & 0x7F, sw2);
break;
case 2:
// 2 -> FPL
break;
case 3:
// 3 -> Signal
break;
case 4:
// 4 -> Block signal
break;
}
return;
}
// DFPlayer
// Define DFPlayer Serial Receive and Transmit Pin
#define DFPl_RX_PIN 10
#define DFPl_TX_PIN 11
SoftwareSerial mySerial(DFPl_RX_PIN, DFPl_TX_PIN);
DFPlayerMini_Fast myMP3;
// Object "Throttle"
class Throttle
{
private:
int SLOT;
int ADR;
int SPD;
int DIRF;
int SND;
public:
void Setup(int SADR);
void Change_SPD(int SSPD);
void Change_DIRF(int SDIRF);
void Change_SND(int SSND);
}
;
void Throttle::Setup(int SADR)
{
sendOPC_xxx(OPC_LOCO_ADR, 0, SADR);
LnPacket = LocoNet.receive() ;
//while ((LnPacket->data[0] != 0xE7) | (LnPacket->data[4] != SADR))
//{
//sendOPC_xxx(OPC_LOCO_ADR, 0, SADR);
//LnPacket = LocoNet.receive();
//}
Serial.print(LnPacket->data[0], HEX);
Serial.print(" LocoNet Message Received -> DCC Adr ");
Serial.print(LnPacket->data[4]);
Serial.print(" was found in SLOT ");
Serial.println(LnPacket->data[2]);
SLOT = LnPacket->data[2];
ADR = LnPacket->data[4];
SPD = 0x00;
DIRF = 0x00;
SND = 0x00;
sendOPC_xxx(OPC_MOVE_SLOTS, SLOT, SLOT);
sendOPC_xxx(OPC_LOCO_DIRF, SLOT, DIRF);
sendOPC_xxx(OPC_LOCO_SPD, SLOT, SPD);
sendOPC_xxx(OPC_LOCO_SND, SLOT, SND);
Serial.println("Communication initialized");
int i = 0;
while (used_SLOT
!= 0)
{
i = i + 1;
}
used_SLOT = SLOT;
return;
}
void Throttle::Change_SPD(int SSPD)
{
if (SSPD < 0)
{
if (SPD > 0) SPD = SPD + SSPD;
}
else
{
SPD = SSPD;
}
Serial.print("SPD at ");
Serial.print((SPD * 100) / 128);
Serial.println("%");
sendOPC_xxx(OPC_LOCO_SPD, SLOT, SPD);
}
void Throttle::Change_DIRF(int SDIRF)
{
DIRF = DIRF + SDIRF;
Serial.print("DIRF:");
Serial.print(DIRF);
Serial.print("\t\tDirection: ");
Serial.print(((DIRF & 0x20) == 0) ? "<-" : "->");
Serial.print("\tFunction(s): ");
Serial.print(((DIRF & 0x10) == 0) ? "" : "F0 ");
Serial.print(((DIRF & 0x01) == 0) ? "" : "F1 ");
Serial.print(((DIRF & 0x02) == 0) ? "" : "F2 ");
Serial.println(((DIRF & 0x04) == 0) ? "" : "F3");
sendOPC_xxx(OPC_LOCO_DIRF, SLOT, DIRF);
}
void Throttle::Change_SND(int SSND)
{
SND = SND + SSND;
Serial.print("SND:");
Serial.println(SND);
sendOPC_xxx(OPC_LOCO_DIRF, SLOT, SND);
}
Throttle TT_Throttle;
void setup()
{
// Initialize Serial Port USB at 9600 baud
Serial.begin(9600);
Serial.println(NAME);
Serial.println(NAME2);
Serial.println(NAME3);
Serial.println("---------------------------------------------------------------------------");
Serial.print("Version "); Serial.print(VERSION); Serial.print(", "); Serial.println(COPYRIGHT);
Serial.println("---------------------------------------------------------------------------");
// Visual management
pinMode(DefaultPin, OUTPUT);
digitalWrite(DefaultPin, LOW);
// LocoNet
LocoNet.init(LN_TX_PIN);
pinMode(Emergency_PIN, INPUT_PULLUP);
DCC_On();
// Throttle
// Initialize used_SLOT
for (int i = 0; i < 120; i++)
{
used_SLOT = 0;
}
// Initialize Turntable INPUT
pinMode(TT_dir_PIN, INPUT_PULLUP);
pinMode(TT_stop_PIN, INPUT_PULLUP);
pinMode(TT_brake_PIN, INPUT_PULLUP);
pinMode(TT_lowspeed_PIN, INPUT_PULLUP);
pinMode(TT_midspeed_PIN, INPUT_PULLUP);
// Initialize Turntable Throttle
TT_Throttle.Setup(ADR_Turntable);
// DFPlayer
// Initialize Serial Communication at 9600 baud
//mySerial.begin(9600);
//myMP3.begin(mySerial);
//myMP3.volume(30);
//
Serial.println("Ready to use");
}
void loop()
{
// Loconet
Emergency();
// Throttle (Turntable)
Turntable_Order();
// DFPlayer
//myMP3.play(1);
}
void DCC_On()
// DCC Power ON
{
sendOPC_x(OPC_GPOFF);
delay(100);
sendOPC_x(OPC_GPON);
return;
}
void Emergency()
// Emergency Stop required
{
int i = 0;
if (digitalRead(Emergency_PIN) == Activated)
{
delay(100);
if (digitalRead(Emergency_PIN) == Activated)
{
while (digitalRead(Emergency_PIN) == Activated)
{
digitalWrite(DefaultPin, HIGH);
delay(100);
digitalWrite(DefaultPin, LOW);
delay(100);
}
Serial.println("Emergency STOP!!!");
//sendOPC_x(OPC_IDLE);
while (used_SLOT != 0)
{
sendOPC_xxx(OPC_LOCO_SPD, used_SLOT, 0x00);
i = i + 1;
}
}
}
return;
}
void Turntable_Order()
// Control Turntable Direction by a SPDT ON-ON (Input: TT_dir_PIN)
// and Turntable Speed by some Push buttons (Input: TT_stop_PIN, TT_brake_PIN, TT_lowspeed_PIN and TT_midspeed_PIN)
{
if ((digitalRead(TT_dir_PIN) == HIGH) && TT_dir)
{
TT_dir = false;
TT_Throttle.Change_DIRF(-0x20);
}
if ((digitalRead(TT_dir_PIN) == LOW) && !TT_dir)
{
TT_dir = true;
TT_Throttle.Change_DIRF(0x20);
}
if (digitalRead(TT_stop_PIN) == Activated)
{
delay(100);
if (digitalRead(TT_stop_PIN) == Activated)
{
while (digitalRead(TT_stop_PIN) == Activated)
{
digitalWrite(DefaultPin, HIGH);
delay(100);
digitalWrite(DefaultPin, LOW);
delay(100);
}
Serial.print("Stop -> Turntable ");
TT_Throttle.Change_SPD(0x00);
}
}
if (digitalRead(TT_brake_PIN) == Activated)
{
delay(100);
if (digitalRead(TT_brake_PIN) == Activated)
{
while (digitalRead(TT_brake_PIN) == Activated)
{
digitalWrite(DefaultPin, HIGH);
delay(100);
digitalWrite(DefaultPin, LOW);
delay(100);
}
Serial.print("Brake -> Turntable ");
TT_Throttle.Change_SPD(TT_brake);
}
}
if (digitalRead(TT_lowspeed_PIN) == Activated)
{
delay(100);
if (digitalRead(TT_lowspeed_PIN) == Activated)
{
while (digitalRead(TT_lowspeed_PIN) == Activated)
{
digitalWrite(DefaultPin, HIGH);
delay(100);
digitalWrite(DefaultPin, LOW);
delay(100);
}
Serial.print("Low speed -> Turntable ");
TT_Throttle.Change_SPD(TT_lowspeed);
}
}
if (digitalRead(TT_midspeed_PIN) == Activated)
{
delay(100);
if (digitalRead(TT_midspeed_PIN) == Activated)
{
while (digitalRead(TT_midspeed_PIN) == Activated)
{
digitalWrite(DefaultPin, HIGH);
delay(100);
digitalWrite(DefaultPin, LOW);
delay(100);
}
Serial.print("Mid speed -> Turntable ");
TT_Throttle.Change_SPD(TT_midspeed);
}
}
return;
}