Начало в заметке "Быт - Модель железной дороги (часть 5)".
На предыдущем этапе постройки макета были уложены рельсы для разворотной петли, а сама петля прикреплена снизу основного макета. Чтобы петля работала правильно и не вызывала короткого замыкания в электрической схеме макета, необходимо изолировать петлю от магистрали и спроектировать электронную схему управления подачи питания на рельсы петли.
Логику работы схемы будет обеспечивать микроконтроллер ATMega328, в качестве датчиков прохождения состава будут использоваться герконы, а срабатывание герконов будет осуществлять неодимовый магнит на днище локомотива, состав должен проходить петлю меньше, чем за 30 секунд. Схема подходит как для цифрового, так и для аналогово управления поездами. Дополнительную информацию по организации разворотной петли можно прочитать на форуме ScaleTrainsClub. Ниже подробно описаны электрическая схема, логика и программа, а так же показаны фотография сборки и видео работы устройства.
Электроника разворотной петли
Компоненты:
- Контроллер Arduino UNO R3 (или Arduino Mini со стабилизатором LM2596).
- Блок из 2 реле.
- Блок из 4 реле.
- Привод стрелки PIKO 55271.
- Изоляторы рельс PIKO 55291.
- Герконы 2.
- Резисторы 10 кОм.
- Соединительные провода.
- Клеммная колодка.
- Корпус или подложка для крепления электроники.

Алгоритм работы разворотной петли

Схема 0 – выключено
- На магистраль подан сигнал DCC;
- На контроллер Arduino питание не подано;
- На разворотную петлю сигнал DCC не подан;
- Реле RL1: K1 и K2 разомкнуты – питание на привод стрелки не подано, стрелка в неизвестном состоянии;
- Реле RL2: K1 и K2 разомкнуты – питание на разворотную петлю не подано;
- Реле RL2: К3 и К4 в положении, подготовленном для прямого питания петли;
- От датчиков D1 и D2 нет никакого сигнала.
Схема 1 – подготовка к работе
- На магистраль подан сигнал DCC (далее этот пункт не указывается, подразумевается, что на магистрали напряжение есть всегда);
- На контроллер Arduino подано питание;
- Контроллер дает команду на перевод стрелки S1 в правое положение (если смотреть от входящего поезда);
- Контроллер дает команду на замыкание RL2.1 и RL2.2
- На разворотную петлю подан прямой сигнал DCC;
- Биты памяти M1 и М2 пустые;
- Разворотная петля готова к приему поезда

Схема 2 – прием поезда справа
- Поезд входит в разворотную петлю и пересекает датчик D1;
- Датчик D1 посылает сигнал в контроллер, что на участке есть состав (геркон замыкается магнитом на днище локомотива);
- Контроллер устанавливает в памяти бит M1 в 1;
Схема 3 – подготовка к переключению полярности
- Поезд находится в разворотной петле и пересекает датчик D2;
- Датчик D2 посылает сигнал в контроллер, что на участке есть состав;
- Контроллер проверяет в памяти бит M1, если M1 = 1, то это означает, что поезд выходит из петли слева – необходимо перевести стрелку влево;
Схема 4 – переключение полярности, фаза 1 - обесточивание петли
- Контроллер посылает сигнал на размыкание RL2.1 и RL2.2;
- Разворотная петля обесточивается – поезд останавливается;
- Контроллер посылает сигнал на размыкание RL2.3 и RL2.4;
Схема 5 – переключение полярности, фаза 2 - подключение к магистрали с обратной полярностью
- Контроллер посылает сигнал на перевод стрелки S1 в левое положение;
- Контроллер посылает сигнал на замыкание RL2.1 и RL2.2;
- На разворотную петлю посылается обратный DCC сигнал;
- Поезд может выходить из разворотной петли;
Схема 6 – выход поезда
- Датчики D1 и D2 не фиксируют нахождение поезда в течении 30 секунд;
- Контроллер очищает биты присутствия поезда M1 и M2;
- Разворотная петля готова к приему поезда слева.

Схема 7 – прием поезда слева
- Поезд входит в разворотную петлю и пересекает датчик D2;
- Датчик D2 посылает сигнал в Arduino, что на участке есть состав;
- Arduino устанавливает бит M2 в 1;
Схема 8 – подготовка к переключению
- Поезд находится в разворотной петле и пересекает датчик D1;
- Датчик D1 посылает сигнал в Arduino, что на участке есть состав;
- Arduino проверяет бит M2, если M2 = 1, то поезд выходит из петли справа – необходимо перевести стрелку вправо;
Схема 9 – переключение фаза 1
- Arduino посылает сигнал на размыкание RL2.1 и RL2.2;
- Разворотная петля обесточивается – поезд останавливается;
- Arduino посылает сигнал на замыкание RL2.3 и RL2.4;
Если отключится питание, то контакты всех реле вернутся в изначальное положение, то есть в состояние на Схеме 0. При появлении питания петля перейдет в состояние на Схеме 1. Если в момент отключения в петле находился состав, он начнет движение, и может произойти короткое замыкание при прохождении составом стрелки. Поэтому я рекомендую запитывать схему управления петлей от отдельного источника питания или аккумуляторов, чтобы иметь возможность отключать питание макета при авариях на магистрали.
Листинг программы для контроллера Arduino
//#include <Bounce2.h>
#define SERIAL_SPEED 9600 // скорость порта ввода-вывода
#define SENSOR_DELAY 30000 // время на прохождение петли 30 секунд
#define RELAY_DELAY 100 // время задержки переключения реле
#define SWITCH_TIME 500 // время переключения стрелки
// Установка номеров контактов
const byte Sensor1_Pin = 2;
const byte Sensor2_Pin = 4;
const byte Led_Pin = 13;
const byte SwitchRight_Pin = 8;
const byte SwitchLeft_Pin = 9;
const byte Power1_Pin = 10;
const byte Power2_Pin = 11;
// Инверстная логика реле
const byte RelayON = LOW;
const byte RelayOFF = HIGH;
// флаги прохода датчиков
byte Sensor1_Passed = 0;
byte Sensor2_Passed = 0;
// таймеры датчиков
long Sensor1_Timer = 0;
long Sensor2_Timer = 0;
// флаг положения стрелки: 0 - вправо, 1 - влево
byte TurnOutPosition = 1;
void setup() {
Serial.begin(SERIAL_SPEED);
Serial.println("--- Initialization started ---");
// Инициализация выходов
pinMode(Led_Pin, OUTPUT);
pinMode(SwitchRight_Pin, OUTPUT);
pinMode(SwitchLeft_Pin, OUTPUT);
pinMode(Power1_Pin, OUTPUT);
pinMode(Power2_Pin, OUTPUT);
// Отключение всех реле
digitalWrite(SwitchRight_Pin, RelayOFF);
digitalWrite(SwitchLeft_Pin, RelayOFF);
digitalWrite(Power1_Pin, RelayOFF);
digitalWrite(Power2_Pin, RelayOFF);
// Инициализация входов
pinMode(Sensor1_Pin, INPUT);
// pinMode(Button1bPin, INPUT);
pinMode(Sensor2_Pin, INPUT);
// pinMode(Button2bPin, INPUT);
delay(500);
// Перевод стрелки в начальное положение
MoveSwitchRight();
Serial.println("--- Initialization finished ---");
Serial.println();
}
void loop() {
// прохождение состава справа
// Прохождение локомотивом датчика 1
if (digitalRead(Sensor1_Pin) == HIGH && Sensor1_Passed == 0 && Sensor2_Passed == 0) {
Serial.println("Sensor 1 is ON");
// Запуск таймера датчика 1
Sensor1_Timer = millis();
// Установка флага прохождения датчика 1
Sensor1_Passed = 1;
Serial.println("Waiting for Sensor 2");
}
// Прохождение локомотивом датчика 2 и проверка, что датчик 1 был пройден
if ((digitalRead(Sensor2_Pin) == HIGH) && Sensor1_Passed == 1 && Sensor2_Passed == 0) {
Serial.println("Sensor 2 is ON+");
// Проверка, что датчики сработали через разрешенное время
if ((millis() - Sensor1_Timer) < SENSOR_DELAY) {
Serial.println("Ready for switching");
// Перевод стрелки влево
MoveSwitchLeft();
}
}
// прохождение состава слева
// Прохождение локомотивом датчика 2
if (digitalRead(Sensor2_Pin) == HIGH && Sensor2_Passed == 0 && Sensor1_Passed == 0) {
Serial.println("Sensor 2 is ON");
// Запуск таймера датчика 2
Sensor2_Timer = millis();
// Установка флага прохождения датчика 2
Sensor2_Passed = 1;
Serial.println("Waiting for Sensor 1");
}
// Прохождение локомотива датчика 1 и проверка, что датчик 2 был пройден
if ((digitalRead(Sensor1_Pin) == HIGH) && Sensor2_Passed == 1 && Sensor1_Passed == 0) {
Serial.println("Sensor 1 is ON+");
// Проверка, что датчики сработали через разрешенное время
if ((millis() - Sensor2_Timer) < SENSOR_DELAY) {
Serial.println("Ready for switching");
// Перевод стрелки вправо
MoveSwitchRight();
}
}
// Сброс флагов прохождения и таймеров датчиков
if ((millis() - Sensor1_Timer) > SENSOR_DELAY && Sensor1_Passed == 1) {
Serial.println("Sensor 1 is ready for next cycle");
Sensor1_Passed = 0;
}
if ((millis() - Sensor2_Timer) > SENSOR_DELAY && Sensor2_Passed == 1) {
Serial.println("Sensor 2 is ready for next cycle");
Sensor2_Passed = 0;
//Sensor2_Timer = millis();
}
}
/* Функция перевода стрелки вправо */
void MoveSwitchRight () {
// Проверка, что стрелка еще не переведена вправо
if (TurnOutPosition == 1) {
Serial.println("Moving switch to Right");
// Отключение питания петли
digitalWrite(Power1_Pin, RelayOFF);
Serial.println(" Loop power is OFF");
delay(RELAY_DELAY);
// Прямая коммутация петли и перевод стрелки
digitalWrite(Power2_Pin, RelayOFF);
Serial.println(" Loop power is DIRECT");
digitalWrite(SwitchRight_Pin, RelayON);
delay(SWITCH_TIME);
digitalWrite(SwitchRight_Pin, RelayOFF);
Serial.println(" Turnout is moved to Right");
// Включение питания петли
delay(RELAY_DELAY);
digitalWrite(Power1_Pin, RelayON);
Serial.println(" Loop power is ON");
TurnOutPosition = 0;
}
}
/* Функция перевода стрелки влево */
void MoveSwitchLeft () {
// Проверка, что стрелка еще не переведена влево
if (TurnOutPosition == 0) {
Serial.println("Moving switch to Left");
// Отключение питания петли
digitalWrite(Power1_Pin, RelayOFF);
Serial.println(" Loop power is OFF");
delay(RELAY_DELAY);
// Обратная коммутация петли и перевод стрелки
digitalWrite(Power2_Pin, RelayON);
Serial.println(" Loop power is REVERSED");
digitalWrite(SwitchLeft_Pin, RelayON);
delay(SWITCH_TIME);
digitalWrite(SwitchLeft_Pin, RelayOFF);
Serial.println(" Turnout is moved to Left");
// Включение питания петли
delay(RELAY_DELAY);
digitalWrite(Power1_Pin, RelayON);
Serial.println(" Loop power is ON");
TurnOutPosition = 1;
}
}
От теории к практике

