Начало в заметке "Быт - Модель железной дороги (часть 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; } }
От теории к практике