• O nas
  • Ekipa
  • Makieta
    • H0
      • Stacja Lewin Leski
      • Stacja Okunin
      • Stacja Zielona
      • Stacja Klecza Górna
      • Stacja Wysoka Gorzowska
      • Stacja Żelistrzewo
      • Stacja Alt Warnow
      • Żwirownia Roszków
      • Przystanek Karnin Gorzowski
      • Ładownia szlakowa
      • Tunel Rydułtowy
      • Szlak dwutorowy „Podlesie”
      • Przystanek Teodorowo
      • Szlak z przejściem na plażę
      • Szlak ze złomowym taborem
      • Szlak z wiaduktem drogowym
      • Szlak klubowy z łąką
      • Szlak klubowy z polem
      • Szlak na Mazurach
      • Stacja techniczna Gorzów
      • Stacja techniczna Oblotka
    • H0e
      • Stacja Rusinowo Wąskotorowe
      • Przystanek Bożepole Mazurskie
      • Szlak jednotorowy Kwidzyn – Mareza Makieta „Nad dachami Kwidzyna”
      • Szlak wąskotorowy – Gospodarstwo w Lichnówkach
      • Szlak wąskotorowy – Przy ambonie
      • Szlak wąskotorowy – przez Żuławy
      • Szlak wąskotorowy z pastwiskiem
      • Szlak wąskotorowy z kapliczką
  • Modele
    • Transport wojska (eszelon)
    • Ławka dworcowa
    • Lokomotywownia z Cisnej-Majdanu
    • Berliet GBH
    • Polska furmanka
    • Węglarka „Es”
    • Rumpler RuV 29 i RuV 31
  • Imprezy
    • 2025
      • Intermodellbau 2025 Dortmund
      • Festiwal Kultury Modelarskiej – Olsztyn 5-6 kwietnia 2025
      • Modeltrein Expo On traXS 2025 – Utrecht
      • Kozy 2025 – Prezentacja Modułowej Makiety Kolejowej
      • 12. Mittenwalder Modellbahntage 2025
      • Chemnitzer Modelltage 2025
    • 2024
      • Expo – Trains Luksemburg 2024
      • Pokaz makiety Wysoka Gorzowska w Krzyżu Wielkopolskim
      • Gera 2024 – wystawa makiet
      • Poznań 2024 – Targi Hobby
      • Czyżowice 2024 – Prezentacja Makiety Modułowej
      • Rybnik 2024 – Prezentacja Makiety Modułowej w Kopalni Ignacy
      • Lipsk 2024 – Hobby Messe
      • Francja 2024 – Ramma
      • II Wystawa Realistycznych Makiet Kolejowych w Redzie
      • XIII Festiwal Kultury Modelarskiej w Olsztynie
      • Modeltrein Expo On traXS 2024 – Utrecht
      • Wystawa z okazji 50-lecia Klubu MEC01 – Münchberg 2024
      • 11. Wystawa Makiet Kolejowych w Mittenwalde k./Berlina
      • Kozy 2024 – Prezentacja modułowej makiety kolejowej
    • 2023
      • Kühlungsborn 2023 – wystawa makiet kolejowych
      • Luxembourg 2023 – 40. Expo Trains
      • Poznań 2023 – Salon Hobby
      • Gera 2023 – wystawa makiet
      • Lipsk 2023 – Modell-Hobby-Spiel
      • Mini wystawa makiet kolejowych w Kwidzynie
      • Piotrków Trybunalski 2023- VI Trybunały Modelarstwa Kolejowego
      • Reda 2023 – Wystawa realistycznych makiet kolejowych
      • Stęszew 2023 – spotkanie przy makiecie
      • Modeltrein Expo On traXS 2023 – Utrecht
      • Kozy 2023 – Prezentacja modułowej makiety kolejowej
      • Mittenwalde 2023 – 10. Mittenwalder Modellbahntage
    • 2022
      • Kühlungsborn 2022 – wystawa makiet kolejowych
      • Gangelt 2022 – 25. Wystawa Modelarska
      • Gera 2022 – wystawa makiet
      • Poznań 2022 – Salon Hobby
      • Lipsk 2022 – Modell-Hobby-Spiel
      • Rybnik 2022 – Prezentacja makiety modułowej
      • Hochdorf 2022 – Wystawa w szwajcarskim Modellbahn- Expo
      • „Złote myśli” uczestników spotkania
      • Reda 2022 – spotkanie przy makiecie
      • Kozy 2022 – prezentacja makiety modułowej
      • Modeltrein Expo On traXS! 2022 – Utrecht
      • Mittenwalde 2022 – wystawa makiet
      • Czyżowice 2022 – spotkanie przy makiecie
      • Chemnitz 2022 – wystawa makiet
      • I Festiwal Modeli Kartonowych w Redzie
    • 2021
      • Warszawa 2021 – wystawa makiet w Stacji Muzeum
      • Lipsk 2021 – Modell-Hobby-Spiel
      • Kühlungsborn 2021 – wystawa makiet
      • Reda 2021 – Sylwestrowe warsztaty modelarskie
    • 2020
      • Luxembourg 2020 – Model Train
      • Rijswijk 2020 – Prezentacja makiety
      • Utrecht 2020 – OnTraXS!
      • Reda 2020 – Spotkanie przy makiecie
      • Lahnstein 2020 – 18 International Modellbahntage
      • Mittenwalde 2020 – wystawa makiet
    • 2019
      • Tychy 2019 – spotkanie przy makiecie
      • Zgierz 2019 – Warsztaty modelarskie
      • Poznań 2019 – Salon Hobby
      • Gera 2019 – wystawa makiet
      • Lipsk 2019 – Modell-Hobby-Spiel
      • Noc Muzeów – Olsztyn 2019
      • Bytom 2019 – Prezentacja makiety wąskotorowej na Industriadzie
      • Lipusz 2019 – prezentacja makiety Sopockiego Klubu Modelarzy Kolejowych
      • Modeltrein Expo On traXS! 2019 – Utrecht
      • Münchberg 2019 – Prezentacja makiety
      • Czyżowice 2019 – spotkanie przy makiecie
      • Görlitz 2019 – wystawa makiet kolejowych
    • 2018
      • Tczew 2018 – Kolej na Niepodległą!
      • Salon modelarstwa HOBBY w Poznaniu – XV edycja
      • Lipsk 2018 – Modell-Hobby-Spiel
      • Bytom 2018 – Prezentacja makiety wąskotorowej na Industriadzie
      • Rijswijk 2018 – Prezentacja makiety
      • Reda 2018 – Warsztaty Modelarskie PMM H0
      • Miniaturowa Polska – Gliwice 2018
      • Lahnstein 2018 – 16 International Modellbahntage
      • Czyżowice 2018 – spotkanie przy makiecie
      • Berlin 2018 – 7. Internationale Modellbahn Ausstellung
    • 2017
      • Lipsk 2017 – Modell-Hobby-Spiel
      • Szczecin 2017 – Prezentacja makiety
      • Radom 2017 – Prezentacja makiety
      • Piotrków Trybunalski 2017 – IV Piotrkowskie Trybunały Modelarstwa Kolejowego
      • Luxembourg 2017 – Expo Trains
      • Lahnstein 2017 – 15 International Modellbahntage
      • Gangelt 2017 – prezentacja makiety
      • Francja – Trainsmania 2017
      • Czyżowice 2017 – Spotkanie przy makiecie
      • Czyżowice 2017 – Warsztaty Modelarskie PMM H0
      • Bytom 2017 – Prezentacja makiety
    • 2016
      • Poznań 2016 – Salon Hobby
      • Niemcy 2016 – Wakacje PMMH0
      • Lobau 2016 – Prezentacja makiety
      • Piotrków Trybunalski 2016 – III Piotrkowskie Trybunały Modelarstwa Kolejowego
      • Wolsztyn 2016 – Parada parowozów
      • Gdynia 2016 – Warsztaty Modelarskie TT
      • Modeltrein Expo On traXS! 2016 – Utrecht
      • Lahnstein 2016 – 14 International Modellbahntage
      • Reda 2016 – Warsztaty Modelarskie PMM H0
      • Czyżowice 2016 – Spotkanie przy makiecie
      • Berlin 2016 – 6. Internationale Modellbahn Ausstellung
    • 2015
      • Poznań 2015 – Warsztaty Modelarskie PZMK
      • Lipsk 2015 – Modell-Hobby-Spiel
      • Olsztyn 2015 – Wystawa małych modelarskich makiet
      • Podlasie 2015 – wakacje PMM H0
      • Ostrołęka 2015 – Festyn Dworcowy
      • Piotrków Trybunalski 2015 – II Piotrkowskie Trybunały Modelarstwa Kolejowego
      • Pobiedziska 2015 – Spotkanie przy makiecie
      • Noc Muzeów 2015
      • Sinsheim 2015 – 3 Faszination Modellbahn
      • Lahnstein 2015 – 13 International Modellbahntage
      • Czyżowice 2015 – Spotkanie przy makiecie
    • 2014
      • Tychy 2014 – Sylwester przy makiecie
      • Poznań 2014 – Salon Hobby
      • Istebna 2014 – Spotkanie przy makiecie
      • Gdańsk 2014 – Noc Muzeów
      • Żuławy 2014 – wycieczka PMM H0
      • Münchberg 2014 – Prezentacja makiety
      • Cisna Majdan 2014 – Prezentacja makiety
      • Sinsheim 2014 – 2 Faszination Modellbahn
      • Poznań 2014 – Warsztaty Modelarskie PZMK
      • Czyżowice 2014 – Spotkanie przy makiecie
    • 2013
      • Reda 2013 – Sylwester przy makiecie
      • Poznań 2013 – Salon Hobby
      • Lipsk 2013 – Modell-Hobby-Spiel
      • Gdańsk 2013 – Targi Gra i Zabawa
      • Kłodawa 2013 – Spotkanie przy makiecie
      • Rogalinek 2013 – Spotkanie przy makiecie
      • Luxembourg 2013 – Expo Trains
      • Modeltrein Expo On traXS! 2013 – Utrecht
      • Poznań 2013 – Warsztaty Modelarskie PZMK
      • Lahnstein 2013 – 11 International Modellbahntage
    • 2012
      • Reda 2012 – Sylwester przy makiecie
      • Poznań 2012 – Salon Hobby
      • Lipsk 2012 – Modell-Hobby-Spiel
      • Zabrodzie 2012 – Rodzinne Warsztaty Modelarskie
      • Dortmund 2012 – Intermodellbau
      • Modeltrein Expo On traXS! 2012 – Utrecht
      • Czyżowice 2012 – spotkanie przy makiecie
      • Lahnstein 2012 – 10 International Modellbahntage
      • Poznań 2012 – Warsztaty Modelarskie PZMK
    • 2011
      • Poznań 2011 – Salon Hobby
      • Rybnik 2011 – Prezentacja makiety
      • Sopot 2011 – Spotkanie przy makiecie
      • Radom 2011 – Prezentacja makiety
      • Modeltrein Expo On traXS! 2011 – Utrecht
    • 2010
      • Poznań 2010 – Salon Hobby
      • Lipsk 2010 – Modell-Hobby-Spiel
      • Braniewo 2010 – Prezentacja makiety
      • Zabrodzie 2010 – Rodzinne Warsztaty Modelarskie
      • Czyżowice 2010 – Spotkanie przy makiecie
      • Poznań 2010 – Warsztaty Modelarskie PZMK
    • 2009
      • Poznań 2009 – Salon Hobby
      • Lipsk 2009- Modell-Hobby-Spiel
      • Rogalinek 2009 – Spotkanie przy makiecie
      • Reda 2009 – Spotkanie przy makiecie
      • Poznań 2009 – Warsztaty Modelarskie PZMK
    • 2008
      • Poznań 2008 – Salon Hobby
      • Rzeszów 2008 – Prezentacja makiety
      • Rybnik 2008 – Prezentacja makiety
    • 2007
      • Rybnik 2007 – Prezentacja makiety
      • Lipsk 2007- Modell-Hobby-Spiel
      • Bytom 2007 – Spotkanie przy makiecie
    • 2006
      • Poznań 2006 – Salon Hobby
    • 2005
      • Gdańsk 2005 – Targi Trako
      • Radom 2005 – Prezentacja makiety
  • Warsztat
  • Porady
    • Prowadzenie ruchu pociągów na makiecie
    • Praca manewrowa na stacji Wysoka (przykład)
    • Przyczynek do prowadzenia ruchu kolejowego na makiecie modułowej
    • System zależności w urządzeniach srk makiety małej stacji na linii jednotorowej
    • Zależność: rozjazd – semafor(y)
    • Zależność: rozjazd – wykolejnica
    • Realistyczna makieta na niewielkiej powierzchni – czy jest to możliwe?
    • O co chodzi w epokach modelarskich?
  • Felietony
    • Moich kilka spostrzeżeń o modelarstwie kolejowym – felieton Leszka Lewińskiego cz.1
    • Gdzie są wystawy modelarstwa kolejowego? – felieton Leszka Lewińskiego cz.2
    • „Jestem modelarzem kolejowym…”. Czy aby na pewno? – felieton Leszka Lewińskiego cz.3
    • Publiczność: czyli przez kogo i jak oglądane są modele kolejowe – felieton Leszka Lewińskiego cz. 4
    • Więcej realizmu na makiecie – felieton Leszka Lewińskiego cz. 5
    • Makieta kolejowa – modułowa czy prezentacyjna? – felieton Leszka Lewińskiego cz. 6
    • Dlaczego nie zawsze warto kupować w sklepie modelarskim? -felieton Leszka Lewińskiego cz. 7
    • Modelarstwo kolejowe – zawsze trochę kompromisu – Felieton Franza Rittiga
  • Media o nas
  • Kontakt
  • O nas
  • Ekipa
  • Makieta
    • H0
      • Stacja Lewin Leski
      • Stacja Okunin
      • Stacja Zielona
      • Stacja Klecza Górna
      • Stacja Wysoka Gorzowska
      • Stacja Żelistrzewo
      • Stacja Alt Warnow
      • Żwirownia Roszków
      • Przystanek Karnin Gorzowski
      • Ładownia szlakowa
      • Tunel Rydułtowy
      • Szlak dwutorowy „Podlesie”
      • Przystanek Teodorowo
      • Szlak z przejściem na plażę
      • Szlak ze złomowym taborem
      • Szlak z wiaduktem drogowym
      • Szlak klubowy z łąką
      • Szlak klubowy z polem
      • Szlak na Mazurach
      • Stacja techniczna Gorzów
      • Stacja techniczna Oblotka
    • H0e
      • Stacja Rusinowo Wąskotorowe
      • Przystanek Bożepole Mazurskie
      • Szlak jednotorowy Kwidzyn – Mareza Makieta „Nad dachami Kwidzyna”
      • Szlak wąskotorowy – Gospodarstwo w Lichnówkach
      • Szlak wąskotorowy – Przy ambonie
      • Szlak wąskotorowy – przez Żuławy
      • Szlak wąskotorowy z pastwiskiem
      • Szlak wąskotorowy z kapliczką
  • Modele
    • Transport wojska (eszelon)
    • Ławka dworcowa
    • Lokomotywownia z Cisnej-Majdanu
    • Berliet GBH
    • Polska furmanka
    • Węglarka „Es”
    • Rumpler RuV 29 i RuV 31
  • Imprezy
    • 2025
      • Intermodellbau 2025 Dortmund
      • Festiwal Kultury Modelarskiej – Olsztyn 5-6 kwietnia 2025
      • Modeltrein Expo On traXS 2025 – Utrecht
      • Kozy 2025 – Prezentacja Modułowej Makiety Kolejowej
      • 12. Mittenwalder Modellbahntage 2025
      • Chemnitzer Modelltage 2025
    • 2024
      • Expo – Trains Luksemburg 2024
      • Pokaz makiety Wysoka Gorzowska w Krzyżu Wielkopolskim
      • Gera 2024 – wystawa makiet
      • Poznań 2024 – Targi Hobby
      • Czyżowice 2024 – Prezentacja Makiety Modułowej
      • Rybnik 2024 – Prezentacja Makiety Modułowej w Kopalni Ignacy
      • Lipsk 2024 – Hobby Messe
      • Francja 2024 – Ramma
      • II Wystawa Realistycznych Makiet Kolejowych w Redzie
      • XIII Festiwal Kultury Modelarskiej w Olsztynie
      • Modeltrein Expo On traXS 2024 – Utrecht
      • Wystawa z okazji 50-lecia Klubu MEC01 – Münchberg 2024
      • 11. Wystawa Makiet Kolejowych w Mittenwalde k./Berlina
      • Kozy 2024 – Prezentacja modułowej makiety kolejowej
    • 2023
      • Kühlungsborn 2023 – wystawa makiet kolejowych
      • Luxembourg 2023 – 40. Expo Trains
      • Poznań 2023 – Salon Hobby
      • Gera 2023 – wystawa makiet
      • Lipsk 2023 – Modell-Hobby-Spiel
      • Mini wystawa makiet kolejowych w Kwidzynie
      • Piotrków Trybunalski 2023- VI Trybunały Modelarstwa Kolejowego
      • Reda 2023 – Wystawa realistycznych makiet kolejowych
      • Stęszew 2023 – spotkanie przy makiecie
      • Modeltrein Expo On traXS 2023 – Utrecht
      • Kozy 2023 – Prezentacja modułowej makiety kolejowej
      • Mittenwalde 2023 – 10. Mittenwalder Modellbahntage
    • 2022
      • Kühlungsborn 2022 – wystawa makiet kolejowych
      • Gangelt 2022 – 25. Wystawa Modelarska
      • Gera 2022 – wystawa makiet
      • Poznań 2022 – Salon Hobby
      • Lipsk 2022 – Modell-Hobby-Spiel
      • Rybnik 2022 – Prezentacja makiety modułowej
      • Hochdorf 2022 – Wystawa w szwajcarskim Modellbahn- Expo
      • „Złote myśli” uczestników spotkania
      • Reda 2022 – spotkanie przy makiecie
      • Kozy 2022 – prezentacja makiety modułowej
      • Modeltrein Expo On traXS! 2022 – Utrecht
      • Mittenwalde 2022 – wystawa makiet
      • Czyżowice 2022 – spotkanie przy makiecie
      • Chemnitz 2022 – wystawa makiet
      • I Festiwal Modeli Kartonowych w Redzie
    • 2021
      • Warszawa 2021 – wystawa makiet w Stacji Muzeum
      • Lipsk 2021 – Modell-Hobby-Spiel
      • Kühlungsborn 2021 – wystawa makiet
      • Reda 2021 – Sylwestrowe warsztaty modelarskie
    • 2020
      • Luxembourg 2020 – Model Train
      • Rijswijk 2020 – Prezentacja makiety
      • Utrecht 2020 – OnTraXS!
      • Reda 2020 – Spotkanie przy makiecie
      • Lahnstein 2020 – 18 International Modellbahntage
      • Mittenwalde 2020 – wystawa makiet
    • 2019
      • Tychy 2019 – spotkanie przy makiecie
      • Zgierz 2019 – Warsztaty modelarskie
      • Poznań 2019 – Salon Hobby
      • Gera 2019 – wystawa makiet
      • Lipsk 2019 – Modell-Hobby-Spiel
      • Noc Muzeów – Olsztyn 2019
      • Bytom 2019 – Prezentacja makiety wąskotorowej na Industriadzie
      • Lipusz 2019 – prezentacja makiety Sopockiego Klubu Modelarzy Kolejowych
      • Modeltrein Expo On traXS! 2019 – Utrecht
      • Münchberg 2019 – Prezentacja makiety
      • Czyżowice 2019 – spotkanie przy makiecie
      • Görlitz 2019 – wystawa makiet kolejowych
    • 2018
      • Tczew 2018 – Kolej na Niepodległą!
      • Salon modelarstwa HOBBY w Poznaniu – XV edycja
      • Lipsk 2018 – Modell-Hobby-Spiel
      • Bytom 2018 – Prezentacja makiety wąskotorowej na Industriadzie
      • Rijswijk 2018 – Prezentacja makiety
      • Reda 2018 – Warsztaty Modelarskie PMM H0
      • Miniaturowa Polska – Gliwice 2018
      • Lahnstein 2018 – 16 International Modellbahntage
      • Czyżowice 2018 – spotkanie przy makiecie
      • Berlin 2018 – 7. Internationale Modellbahn Ausstellung
    • 2017
      • Lipsk 2017 – Modell-Hobby-Spiel
      • Szczecin 2017 – Prezentacja makiety
      • Radom 2017 – Prezentacja makiety
      • Piotrków Trybunalski 2017 – IV Piotrkowskie Trybunały Modelarstwa Kolejowego
      • Luxembourg 2017 – Expo Trains
      • Lahnstein 2017 – 15 International Modellbahntage
      • Gangelt 2017 – prezentacja makiety
      • Francja – Trainsmania 2017
      • Czyżowice 2017 – Spotkanie przy makiecie
      • Czyżowice 2017 – Warsztaty Modelarskie PMM H0
      • Bytom 2017 – Prezentacja makiety
    • 2016
      • Poznań 2016 – Salon Hobby
      • Niemcy 2016 – Wakacje PMMH0
      • Lobau 2016 – Prezentacja makiety
      • Piotrków Trybunalski 2016 – III Piotrkowskie Trybunały Modelarstwa Kolejowego
      • Wolsztyn 2016 – Parada parowozów
      • Gdynia 2016 – Warsztaty Modelarskie TT
      • Modeltrein Expo On traXS! 2016 – Utrecht
      • Lahnstein 2016 – 14 International Modellbahntage
      • Reda 2016 – Warsztaty Modelarskie PMM H0
      • Czyżowice 2016 – Spotkanie przy makiecie
      • Berlin 2016 – 6. Internationale Modellbahn Ausstellung
    • 2015
      • Poznań 2015 – Warsztaty Modelarskie PZMK
      • Lipsk 2015 – Modell-Hobby-Spiel
      • Olsztyn 2015 – Wystawa małych modelarskich makiet
      • Podlasie 2015 – wakacje PMM H0
      • Ostrołęka 2015 – Festyn Dworcowy
      • Piotrków Trybunalski 2015 – II Piotrkowskie Trybunały Modelarstwa Kolejowego
      • Pobiedziska 2015 – Spotkanie przy makiecie
      • Noc Muzeów 2015
      • Sinsheim 2015 – 3 Faszination Modellbahn
      • Lahnstein 2015 – 13 International Modellbahntage
      • Czyżowice 2015 – Spotkanie przy makiecie
    • 2014
      • Tychy 2014 – Sylwester przy makiecie
      • Poznań 2014 – Salon Hobby
      • Istebna 2014 – Spotkanie przy makiecie
      • Gdańsk 2014 – Noc Muzeów
      • Żuławy 2014 – wycieczka PMM H0
      • Münchberg 2014 – Prezentacja makiety
      • Cisna Majdan 2014 – Prezentacja makiety
      • Sinsheim 2014 – 2 Faszination Modellbahn
      • Poznań 2014 – Warsztaty Modelarskie PZMK
      • Czyżowice 2014 – Spotkanie przy makiecie
    • 2013
      • Reda 2013 – Sylwester przy makiecie
      • Poznań 2013 – Salon Hobby
      • Lipsk 2013 – Modell-Hobby-Spiel
      • Gdańsk 2013 – Targi Gra i Zabawa
      • Kłodawa 2013 – Spotkanie przy makiecie
      • Rogalinek 2013 – Spotkanie przy makiecie
      • Luxembourg 2013 – Expo Trains
      • Modeltrein Expo On traXS! 2013 – Utrecht
      • Poznań 2013 – Warsztaty Modelarskie PZMK
      • Lahnstein 2013 – 11 International Modellbahntage
    • 2012
      • Reda 2012 – Sylwester przy makiecie
      • Poznań 2012 – Salon Hobby
      • Lipsk 2012 – Modell-Hobby-Spiel
      • Zabrodzie 2012 – Rodzinne Warsztaty Modelarskie
      • Dortmund 2012 – Intermodellbau
      • Modeltrein Expo On traXS! 2012 – Utrecht
      • Czyżowice 2012 – spotkanie przy makiecie
      • Lahnstein 2012 – 10 International Modellbahntage
      • Poznań 2012 – Warsztaty Modelarskie PZMK
    • 2011
      • Poznań 2011 – Salon Hobby
      • Rybnik 2011 – Prezentacja makiety
      • Sopot 2011 – Spotkanie przy makiecie
      • Radom 2011 – Prezentacja makiety
      • Modeltrein Expo On traXS! 2011 – Utrecht
    • 2010
      • Poznań 2010 – Salon Hobby
      • Lipsk 2010 – Modell-Hobby-Spiel
      • Braniewo 2010 – Prezentacja makiety
      • Zabrodzie 2010 – Rodzinne Warsztaty Modelarskie
      • Czyżowice 2010 – Spotkanie przy makiecie
      • Poznań 2010 – Warsztaty Modelarskie PZMK
    • 2009
      • Poznań 2009 – Salon Hobby
      • Lipsk 2009- Modell-Hobby-Spiel
      • Rogalinek 2009 – Spotkanie przy makiecie
      • Reda 2009 – Spotkanie przy makiecie
      • Poznań 2009 – Warsztaty Modelarskie PZMK
    • 2008
      • Poznań 2008 – Salon Hobby
      • Rzeszów 2008 – Prezentacja makiety
      • Rybnik 2008 – Prezentacja makiety
    • 2007
      • Rybnik 2007 – Prezentacja makiety
      • Lipsk 2007- Modell-Hobby-Spiel
      • Bytom 2007 – Spotkanie przy makiecie
    • 2006
      • Poznań 2006 – Salon Hobby
    • 2005
      • Gdańsk 2005 – Targi Trako
      • Radom 2005 – Prezentacja makiety
  • Warsztat
  • Porady
    • Prowadzenie ruchu pociągów na makiecie
    • Praca manewrowa na stacji Wysoka (przykład)
    • Przyczynek do prowadzenia ruchu kolejowego na makiecie modułowej
    • System zależności w urządzeniach srk makiety małej stacji na linii jednotorowej
    • Zależność: rozjazd – semafor(y)
    • Zależność: rozjazd – wykolejnica
    • Realistyczna makieta na niewielkiej powierzchni – czy jest to możliwe?
    • O co chodzi w epokach modelarskich?
  • Felietony
    • Moich kilka spostrzeżeń o modelarstwie kolejowym – felieton Leszka Lewińskiego cz.1
    • Gdzie są wystawy modelarstwa kolejowego? – felieton Leszka Lewińskiego cz.2
    • „Jestem modelarzem kolejowym…”. Czy aby na pewno? – felieton Leszka Lewińskiego cz.3
    • Publiczność: czyli przez kogo i jak oglądane są modele kolejowe – felieton Leszka Lewińskiego cz. 4
    • Więcej realizmu na makiecie – felieton Leszka Lewińskiego cz. 5
    • Makieta kolejowa – modułowa czy prezentacyjna? – felieton Leszka Lewińskiego cz. 6
    • Dlaczego nie zawsze warto kupować w sklepie modelarskim? -felieton Leszka Lewińskiego cz. 7
    • Modelarstwo kolejowe – zawsze trochę kompromisu – Felieton Franza Rittiga
  • Media o nas
  • Kontakt

Elektronika w modelarstwie kolejowym – mała stacja kolejowa – część 5

2023-12-28

Kolejna, piąta już, część cyklu o sterowaniu makietą małej stacji kolejowej to opis programu a zarazem sposobu działania pulpitu, który w tym przypadku jest „zarządcą” całego systemu.

Jako że sporo instrukcji zostało już opisanych w poprzednich artykułach to sprawy oczywiste będę traktował z pewną lekkością, aby się nie powtarzać a zarazem nie tworzyć z tego materiału „opasłej księgi”. Artykuł ten – jednak – i tak jest dosyć długi.

A zatem do rzeczy.

Dla przypomnienia – pulpit wygląda następująco :

Pod pulpitem znajduje się oczywiście płytka Arduino MEGA, która jest podłączona zgodnie

z przedstawionym wcześniejszym schematem (część 2).

Na początek deklaracja wejść/wyjść naszego mikrokontrolera:

// przyciski pulpitu //

#define key_a1      A0

#define key_a2      A1

#define key_b1      A2

#define key_c2      A3

#define key_d1      A4

#define key_e2      A5

#define key_f1      A6

#define key_f2      A7

#define key_rozw_przebiegu_1    A9

#define key_rozw_przebiegu_2    A8

#define key_Zw1     2

#define key_Zw2     3

#define key_Zw3_4   4

#define key_Zw5     5

#define key_Wk      6

#define key_SzA     7

#define key_SzB     8

#define key_SzC     9

#define key_SzD     10

#define key_SzE     11

#define key_SzF     12

// diody pulpitu //

#define led_A_czerwone    22

#define led_A_zielone     23

#define led_A_biale       24

#define led_B_czerwone    25

#define led_B_zielone     26

#define led_B_biale       27

#define led_C_czerwone    28

#define led_C_zielone     29

#define led_C_biale       30

#define led_D_czerwone    31

#define led_D_zielone     32

#define led_D_biale       33

#define led_E_czerwone    34

#define led_E_zielone     35

#define led_E_biale       36

#define led_F_czerwone    37

#define led_F_zielone     38

#define led_F_biale       39

#define led_Zw1_plus      40

#define led_Zw1_minus     41

#define led_Zw2_plus      42

#define led_Zw2_minus     43

#define led_Zw3_4_plus    44

#define led_Zw3_4_minus   45

#define led_Zw5_plus      46

#define led_Zw5_minus     47

#define led_a1            48

#define led_a2            49

#define led_b1            50

#define led_c2            51

#define led_d1            52

#define led_e2            53

#define led_f1            14

#define led_f2            15

#define led_Wk_otwarta    16

#define led_Wk_zamknieta  17

#define buzzer            18

Jak zatem widać wszystkie wyjścia i wejścia używane w pulpicie zostały pogrupowane i otrzymały swoje nazwy przypisane do konkretnych wyjść. Pora teraz zadeklarować zmienne, których użyjemy w tym programie. Większość zmiennych deklarujemy jako typ int (integer) – czyli liczby całkowite z określonego przedziału.

Na początek zmienna data która będzie przyjmowała wartość informacji przesyłanych przez makietę do pulpitu:

int data;

Pozostałe zmienne od razu otrzymują wartości początkowe.

Zmienne opisujące stan rozjazdów:

int stan_Zw1 = 1;   // na wprost //

int stan_Zw2 = 1;   // na wprost //

int stan_Zw3_4 = 1; // na wprost //

int stan_Zw5 = 1;   // na wprost //

int stan_Wk = 1;    // zamknięta  //

Zmienne opisujące stan semaforów:

int stan_A = 1;     // S1 czerwone //

int stan_B = 1;     // S1 czerwone //

int stan_C = 1;     // S1 czerwone //

int stan_D = 1;     // S1 czerwone //

int stan_E = 1;     // S1 czerwone //

int stan_F = 1;     // S1 czerwone //

Zmienne opisujące czy dany rozjazd jest utwierdzony jakimś przebiegiem:

int utwierdzenie_Zw1 = 0;

int utwierdzenie_Zw2 = 0;

int utwierdzenie_Zw3_4 = 0;

int utwierdzenie_Zw5 = 0;

int utwierdzenie_Wk = 0;

Zmienne opisujące stan przebiegów pociągowych:

int stan_a1 = 0;

int stan_a2 = 0;

int stan_b1 = 0;

int stan_c2 = 0;

int stan_d1 = 0;

int stan_e2 = 0;

int stan_f1 = 0;

int stan_f2 = 0;

Zmienne związane z sygnałami zastępczymi:

int stan_SzA = 0;

int stan_SzB = 0;

int stan_SzC = 0;

int stan_SzD = 0;

int stan_SzE = 0;

int stan_SzF = 0;

Zmienne przyjmujące wartości czasu są natomiast typu unsigned long.

Licznik czasu jest wywołany funkcją millis(). Startuje on w momencie uruchomienia programu od wartości 0 i co każdą milisekundę zwiększa swą wartość o 1, dlatego jedna sekunda pracy systemu to wartość aż 1000 i trzeba się przygotować na spore liczby. Do tego właśnie nadaje się ten typ danych posiadający przedział „pracy” od zera do  4 294 967 295, co daje 1193 godziny pracy licznika czasu (potem się wyzeruje i zacznie się odliczanie od nowa) i powinno wystarczyć. Jednorazowe uruchomienie makiety trwa maksymalnie kilka godzin, a do dyspozycji mamy prawie 50 dni do ponownego wyzerowania licznika. Gdyby jednak ktoś potrzebował nieprzerwanej pracy na dłużej, to powinien dokonać pewnych modyfikacji.

Zatem nasze zmienne oparte o licznik czasu to:

unsigned long czas;

unsigned long czas_SzA = 0;

unsigned long czas_SzB = 0;

unsigned long czas_SzC = 0;

unsigned long czas_SzD = 0;

unsigned long czas_SzE = 0;

unsigned long czas_SzF = 0;

Pora teraz na konfigurację początkową naszego „komputera”

// —————————————————————————-   S E T U P   ——————

void setup()

{

Zaczynamy od uruchomienia komunikacji:

  Serial.begin(9600);

Następnie czas na skonfigurowanie wszystkich przycisków pulpitu jako wejścia PULL_UP

  // przyciski pulpitu //

  pinMode(key_a1, INPUT_PULLUP);

  pinMode(key_a2, INPUT_PULLUP);

  pinMode(key_b1, INPUT_PULLUP);

  pinMode(key_c2, INPUT_PULLUP);

  pinMode(key_d1, INPUT_PULLUP);

  pinMode(key_e2, INPUT_PULLUP);

  pinMode(key_f1, INPUT_PULLUP);

  pinMode(key_f2, INPUT_PULLUP);

  pinMode(key_rozw_przebiegu_1, INPUT_PULLUP);

  pinMode(key_rozw_przebiegu_2, INPUT_PULLUP);

  pinMode(key_Zw1, INPUT_PULLUP);

  pinMode(key_Zw2, INPUT_PULLUP);

  pinMode(key_Zw3_4, INPUT_PULLUP);

  pinMode(key_Zw5, INPUT_PULLUP);

  pinMode(key_Wk, INPUT_PULLUP);

  pinMode(key_SzA, INPUT_PULLUP);

  pinMode(key_SzB, INPUT_PULLUP);

  pinMode(key_SzC, INPUT_PULLUP);

  pinMode(key_SzD, INPUT_PULLUP);

  pinMode(key_SzE, INPUT_PULLUP);

  pinMode(key_SzF, INPUT_PULLUP);

Teraz pora na skonfigurowanie wyjść i przypisanie im stanów początkowych:

  // diody pulpitu //

  pinMode(led_A_czerwone, OUTPUT);

  pinMode(led_A_zielone, OUTPUT);

  pinMode(led_A_biale, OUTPUT);

  digitalWrite(led_A_czerwone, HIGH);

  digitalWrite(led_A_zielone, LOW);

  digitalWrite(led_A_biale, LOW);

  pinMode(led_B_czerwone, OUTPUT);

  pinMode(led_B_zielone, OUTPUT);

  pinMode(led_B_biale, OUTPUT);

  digitalWrite(led_B_czerwone, HIGH);

  digitalWrite(led_B_zielone, LOW);

  digitalWrite(led_B_biale, LOW);

  pinMode(led_C_czerwone, OUTPUT);

  pinMode(led_C_zielone, OUTPUT);

  pinMode(led_C_biale, OUTPUT);

  digitalWrite(led_C_czerwone, HIGH);

  digitalWrite(led_C_zielone, LOW);

  digitalWrite(led_C_biale, LOW);

  pinMode(led_D_czerwone, OUTPUT);

  pinMode(led_D_zielone, OUTPUT);

  pinMode(led_D_biale, OUTPUT);

  digitalWrite(led_D_czerwone, HIGH);

  digitalWrite(led_D_zielone, LOW);

  digitalWrite(led_D_biale, LOW);

  pinMode(led_E_czerwone, OUTPUT);

  pinMode(led_E_zielone, OUTPUT);

  pinMode(led_E_biale, OUTPUT);

  digitalWrite(led_F_czerwone, HIGH);

  digitalWrite(led_F_zielone, LOW);

  digitalWrite(led_F_biale, LOW);

  pinMode(led_Zw1_plus, OUTPUT);

  pinMode(led_Zw1_minus, OUTPUT);

  pinMode(led_Zw2_plus, OUTPUT);

  pinMode(led_Zw2_minus, OUTPUT);

  pinMode(led_Zw3_4_plus, OUTPUT);

  pinMode(led_Zw3_4_minus, OUTPUT);

  pinMode(led_Zw5_plus, OUTPUT);

  pinMode(led_Zw5_minus, OUTPUT);

  digitalWrite(led_Zw1_plus, HIGH);

  digitalWrite(led_Zw1_minus, LOW);

  digitalWrite(led_Zw2_plus, HIGH);

  digitalWrite(led_Zw2_minus, LOW);

  digitalWrite(led_Zw3_4_plus, HIGH);

  digitalWrite(led_Zw3_4_minus, LOW);

  digitalWrite(led_Zw5_plus, HIGH);

  digitalWrite(led_Zw5_minus, LOW);

  pinMode(led_a1, OUTPUT);

  pinMode(led_a2, OUTPUT);

  pinMode(led_b1, OUTPUT);

  pinMode(led_c2, OUTPUT);

  pinMode(led_d1, OUTPUT);

  pinMode(led_e2, OUTPUT);

  pinMode(led_f1, OUTPUT);

  pinMode(led_f2, OUTPUT);

  digitalWrite(led_a1, LOW);

  digitalWrite(led_a2, LOW);

  digitalWrite(led_b1, LOW);

  digitalWrite(led_c2, LOW);

  digitalWrite(led_d1, LOW);

  digitalWrite(led_e2, LOW);

  digitalWrite(led_f1, LOW);

  digitalWrite(led_f1, LOW);

  pinMode(led_Wk_otwarta, OUTPUT);

  pinMode(led_Wk_zamknieta, OUTPUT);

  digitalWrite(led_Wk_otwarta, LOW);

  digitalWrite(led_Wk_zamknieta, HIGH);

Na koniec funkcji SETUP opisujemy wyjście nazwane jako „buzzer” i przypisujemy mu w krótkich przerwach stan wysoki i niski, co spowoduje dwukrotne „piknięcie” generatora dźwiękowego (buzzera) po uruchomieniu się systemu. 

  pinMode(buzzer, OUTPUT);

  digitalWrite(buzzer, HIGH);

  delay(100);

  digitalWrite(buzzer, LOW);

  delay(100);

  digitalWrite(buzzer, HIGH);

  delay(100);

  digitalWrite(buzzer, LOW);

Oczywiście stan początkowy wszystkich wyjść jest opisany i jasno zadeklarowany, ale aby od początku mieć pewność że wszystkie zmienne mają poprawne wartości i wszystko się zgadza wywołujemy funkcję:

  wyswietl_stan_urzadzen();

} // koniec bloku setup //

Teraz – coś czego wcześniej nie było – czyli króciutka funkcja powodująca, że po jej wywołaniu nastąpi „piknięcie” generatora dźwiękowego. W tym projekcie użyłem standardowego buzzera z generatorem (oczywiście na napięcie 5V), podłączonego do wyjścia nr 18 naszego Arduino. (UWAGA! nie ma go na schemacie w części 2 artykułu!)

Używanie sygnalizacji dźwiękowej do np. potwierdzenia wciśnięcia przycisków pulpitu to oczywiście kwestia gustu i można z niej zrezygnować, warto jednak przynajmniej na początkowym etapie tworzenia jakiegoś projektu mieć potwierdzenie że system faktycznie wykrył wciśnięcie przycisku, bo nie zawsze jest to takie oczywiste. Dodatkową zaletą tej funkcji jest pewna zwłoka czasowa po wciśnięciu przycisku (dokładnie 0,5 sekundy) powodująca że wciśnięcie przycisku zostaje odczytane jako pojedyncze wywołanie a nie np. 64 razy – co mogło by mieć miejsce gdyby owej zwłoki nie było. Z całą pewnością powodowałoby to nieprzewidziane skutki w działaniu programu.

// —————————————————————————–   B E E P   ——————-

void beep()

{

  digitalWrite(buzzer, HIGH);

  delay(250);

  digitalWrite(buzzer, LOW);

  delay(250);

}

Pora teraz na funkcję odczyt_seriala czyli „rozmówki makieta – pulpit”.

Każdą informację jaką może wysłać którykolwiek z segmentów makiety trzeba przypisać do naszych zadeklarowanych zmiennych.

Na przykład kiedy nasz pulpit odczyta kod 4022 to przypisze zmiennej stan_Zw2 wartość 2

itd. zgodnie z poniższym schematem :

// —————————————————————-   O D C Z Y T    S E R I A L A   ——

void odczyt_seriala()

{

  data = Serial.parseInt();

  // rozjazdy //

  if (data == 4011)stan_Zw1 = 1;    // na wprost (plus) //

  if (data == 4012)stan_Zw1 = 2;    // na bok (minus) //

  if (data == 4021)stan_Zw2 = 1;

  if (data == 4022)stan_Zw2 = 2;

  if (data == 5011)stan_Zw3_4 = 1;

  if (data == 5012)stan_Zw3_4 = 2;

  if (data == 6011)stan_Zw5 = 1;

  if (data == 6012)stan_Zw5 = 2;

  // wykolejnica //

  if (data == 4031)stan_Wk = 1;     // zamknięta //

  if (data == 4032)stan_Wk = 2;     // otwarta //

  // semafory //

  if (data == 4041)stan_A = 1;      // S1 czerwone //

  if (data == 4042)stan_A = 2;      // S2 zielone //

  if (data == 4043)stan_A = 3;      // Sz biale //

  if (data == 4044)stan_A = 4;      // S5 pomaranczowe //

  if (data == 4045)stan_A = 5;      // S13 2*pomaranczowe //

  if (data == 4046)stan_A = 6;      // S12 2*pom / miganie //

  if (data == 4047)stan_A = 7;      // S10 zielone + pomaranczowe //

  if (data == 4051)stan_B = 1;      // S1 //

  if (data == 4052)stan_B = 2;      // S2 //

  if (data == 4053)stan_B = 3;      // Sz //

  if (data == 4061)stan_C = 1;      // S1 //

  if (data == 4062)stan_C = 2;      // S2 //

  if (data == 4063)stan_C = 3;      // Sz //

  if (data == 4064)stan_C = 4;      // S10 //

  if (data == 6021)stan_D = 1;      // S1 //

  if (data == 6022)stan_D = 2;      // S2 //

  if (data == 6023)stan_D = 3;      // Sz //

  if (data == 6031)stan_E = 1;      // S1 //

  if (data == 6032)stan_E = 2;      // S2 //

  if (data == 6033)stan_E = 3;      // Sz //

  if (data == 6034)stan_E = 4;      // S10 //

  if (data == 6041)stan_F = 1;      // S1 czerwone //

  if (data == 6042)stan_F = 2;      // S2 zielone //

  if (data == 6043)stan_F = 3;      // Sz biale //

  if (data == 6044)stan_F = 4;      // S5 pomaranczowe //

  if (data == 6045)stan_F = 5;      // S13 2*pomaranczowe //

  if (data == 6046)stan_F = 6;      // S12 2*pom / miganie //

  if (data == 6047)stan_F = 7;      // S10 zielone + pomaranczowe //

Na koniec funkcji odczyt_seriala wywołujemy „odświeżenie” stanu pulpitu, aby pokazał on zmiany, które nastąpiły po odczytaniu danych z makiety:

  wyswietl_stan_urzadzen();

}

Nadeszła kolej na następną funkcję, o której już tu kilkakrotnie wspominałem. Jest to funkcja wyświetlająca na pulpicie wszystkie informacje:

// ——————————————————-   WYSWIETL STAN URZADZEN  

void wyswietl_stan_urzadzen()

{

  if (stan_Zw1 == 1) {

    digitalWrite(led_Zw1_plus, HIGH);

    digitalWrite(led_Zw1_minus, LOW);

  }

  if (stan_Zw1 == 2) {

    digitalWrite(led_Zw1_plus, LOW);

    digitalWrite(led_Zw1_minus, HIGH);

  }

Przykładowo – widać zatem, że w zależności od wartości jaką będzie przyjmowała zmienna stan_Zw1 (1 lub 2) na pulpicie nastąpi zaświecenie odpowiedniej diody i jednocześnie gasnąć będzie druga – nieadekwatna do danego stanu – dioda zwrotnicy rozjazdu Zw1.

  if (stan_Zw2 == 1) {

    digitalWrite(led_Zw2_plus, HIGH);

    digitalWrite(led_Zw2_minus, LOW);

  }

  if (stan_Zw2 == 2) {

    digitalWrite(led_Zw2_plus, LOW);

    digitalWrite(led_Zw2_minus, HIGH);

  }

  if (stan_Zw3_4 == 1) {

    digitalWrite(led_Zw3_4_plus, HIGH);

    digitalWrite(led_Zw3_4_minus, LOW);

  }

  if (stan_Zw3_4 == 2) {

    digitalWrite(led_Zw3_4_plus, LOW);

    digitalWrite(led_Zw3_4_minus, HIGH);

  }

  if (stan_Zw5 == 1) {

    digitalWrite(led_Zw5_plus, HIGH);

    digitalWrite(led_Zw5_minus, LOW);

  }

  if (stan_Zw5 == 2) {

    digitalWrite(led_Zw5_plus, LOW);

    digitalWrite(led_Zw5_minus, HIGH);

  }

  if (stan_Wk == 1) {

    digitalWrite(led_Wk_zamknięta, HIGH);

    digitalWrite(led_Wk_otwarta, LOW);

  }

  if (stan_Wk == 2) {

    digitalWrite(led_Wk_zamknięta, LOW);

    digitalWrite(led_Wk_otwarta, HIGH);

  }

  if (stan_A == 1) {

    digitalWrite(led_A_czerwone, HIGH);

    digitalWrite(led_A_zielone, LOW);

    digitalWrite(led_A_biale, LOW);

  }

  if (stan_A == 2 || stan_A == 4 || stan_A == 5 || stan_A == 6 || stan_A == 7) {

    digitalWrite(led_A_czerwone, LOW);

    digitalWrite(led_A_zielone, HIGH);

    digitalWrite(led_A_biale, LOW);

  }

  if (stan_A == 3) {

    digitalWrite(led_A_czerwone, LOW);

    digitalWrite(led_A_zielone, LOW);

    digitalWrite(led_A_biale, HIGH);

  }

  if (stan_B == 1) {

    digitalWrite(led_B_czerwone, HIGH);

    digitalWrite(led_B_zielone, LOW);

    digitalWrite(led_B_biale, LOW);

  }

  if (stan_B == 2) {

    digitalWrite(led_B_czerwone, LOW);

    digitalWrite(led_B_zielone, HIGH);

    digitalWrite(led_B_biale, LOW);

  }

  if (stan_B == 3) {

    digitalWrite(led_B_czerwone, LOW);

    digitalWrite(led_B_zielone, LOW);

    digitalWrite(led_B_biale, HIGH);

  }

  if (stan_C == 1) {

    digitalWrite(led_C_czerwone, HIGH);

    digitalWrite(led_C_zielone, LOW);

    digitalWrite(led_C_biale, LOW);

  }

  if (stan_C == 2 || stan_C == 4) {

    digitalWrite(led_C_czerwone, LOW);

    digitalWrite(led_C_zielone, HIGH);

    digitalWrite(led_C_biale, LOW);

  }

  if (stan_C == 3) {

    digitalWrite(led_C_czerwone, LOW);

    digitalWrite(led_C_zielone, LOW);

    digitalWrite(led_C_biale, HIGH);

  }

  if (stan_D == 1) {

    digitalWrite(led_D_czerwone, HIGH);

    digitalWrite(led_D_zielone, LOW);

    digitalWrite(led_D_biale, LOW);

  }

  if (stan_D == 2) {

    digitalWrite(led_D_czerwone, LOW);

    digitalWrite(led_D_zielone, HIGH);

    digitalWrite(led_D_biale, LOW);

  }

  if (stan_D == 3) {

    digitalWrite(led_D_czerwone, LOW);

    digitalWrite(led_D_zielone, LOW);

    digitalWrite(led_D_biale, HIGH);

  }

  if (stan_E == 1) {

    digitalWrite(led_E_czerwone, HIGH);

    digitalWrite(led_E_zielone, LOW);

    digitalWrite(led_E_biale, LOW);

  }

  if (stan_E == 2 || stan_E == 4) {

    digitalWrite(led_E_czerwone, LOW);

    digitalWrite(led_E_zielone, HIGH);

    digitalWrite(led_E_biale, LOW);

  }

  if (stan_E == 3) {

    digitalWrite(led_E_czerwone, LOW);

    digitalWrite(led_E_zielone, LOW);

    digitalWrite(led_E_biale, HIGH);

  }

  if (stan_F == 1) {

    digitalWrite(led_F_czerwone, HIGH);

    digitalWrite(led_F_zielone, LOW);

    digitalWrite(led_F_biale, LOW);

  }

  if (stan_F == 2 || stan_F == 4 || stan_F == 5 || stan_F == 6 || stan_F == 7) {

    digitalWrite(led_F_czerwone, LOW);

    digitalWrite(led_F_zielone, HIGH);

    digitalWrite(led_F_biale, LOW);

  }

  if (stan_F == 3) {

    digitalWrite(led_F_czerwone, LOW);

    digitalWrite(led_F_zielone, LOW);

    digitalWrite(led_F_biale, HIGH);

  }

} // wyswietl stan urzadzen //

Wszystkie funkcje pomocnicze mamy już opisane, zatem pora na główną pętlę programu:

// —————————————————————————–   L O O P   ——————-

void loop()

{

Na początek uruchamiamy zmienną czas 

  czas = millis();

Kolejny krok to sprawdzenie czy do portu komunikacyjnego przyszły jakieś dane. Jeśli tak – to konieczne jest wywołanie funkcji odczyt_seriala, aby te dane przypisać do odpowiednich zmiennych.

  if (Serial.available() > 0)odczyt_seriala();

Teraz sprawdzamy czy został naciśnięty przycisk key_Zw1. Jeśli tak – to przechodzimy do bloku opisanego w nawiasach klamrowych {}

  if (digitalRead(key_Zw1) == LOW) {

A zatem – na początek sygnał dźwiękowy – jako potwierdzenie odczytania przez system wciśnięcia przycisku.

    beep();

Teraz sprawdzamy czy rozjazd Zw1 nie jest przypadkiem utwierdzony jakimś przebiegiem pociągowym i czy możliwe jest jego przełożenie. Jeśli wartość utwierdzenie_Zw1==0 (czyli nie jest utwierdzony) to program może wysłać informację do makiety o zmianę położenia tegoż rozjazdu – w zależności od jego obecnego położenia.

    if (utwierdzenie_Zw1 == 0) {

      if (stan_Zw1 == 1)Serial.println(1012);

      if (stan_Zw1 == 2)Serial.println(1011);

    }

  }

Jeśli natomiast będzie utwierdzony – to usłyszymy tylko sygnał dźwiękowy potwierdzający wciśnięcie przycisku i nic więcej się nie stanie.

Analogicznie postępujemy z wszystkimi przyciskami rozjazdów i wykolejnicy:

  if (digitalRead(key_Zw2) == LOW) {

    beep();

    if (utwierdzenie_Zw2 == 0) {

      if (stan_Zw2 == 1)Serial.println(1022);

      if (stan_Zw2 == 2)Serial.println(1021);

    }

  }

  if (digitalRead(key_Zw3_4) == LOW) {

    beep();

    if (utwierdzenie_Zw3_4 == 0) {

      if (stan_Zw3_4 == 1)Serial.println(2012);

      if (stan_Zw3_4 == 2)Serial.println(2011);

    }

  }

  if (digitalRead(key_Zw5) == LOW) {

    beep();

    if (utwierdzenie_Zw5 == 0) {

      if (stan_Zw5 == 1)Serial.println(3012);

      if (stan_Zw5 == 2)Serial.println(3011);

    }

  }

  if (digitalRead(key_Wk) == LOW) {

    beep();

    if (utwierdzenie_Wk == 0) {

      if (stan_Wk == 1 && stan_Zw2==1)Serial.println(1032);

      if (stan_Wk == 2 && stan_Zw2==1)Serial.println(1031);

    }

  }

Teraz będzie trochę trudniej.

Postaram się zatem rozbić ten blok „na drobne” i przejrzyście opisać:

  // przebieg a1 //

Sprawdzamy zatem czy przycisk key_a1 został wciśnięty i jeśli tak się stało to przechodzimy do bloku w nawiasach klamrowych {}

  if (digitalRead(key_a1) == LOW) {

Na początek potwierdzenie dźwiękowe:

    beep();

a teraz dosyć skomplikowany warunek, który musi być spełniony, aby system uaktywnił przebieg a1.

Po kolei wygląda to tak:

Jeśli rozjazd Zw1 == 1 (czyli na wprost) i (&&) rozjazd Zw2 == 1 (czyli również na wprost) i wykolejnica zamknięta (czyli stan_Wk==1) i rozjazdy Zw3_4 również są w położeniu na wprost i rozjazd Zw_5==1 (czyli również na wprost) i stan_a1==0 (czyli nie ma obecnie takiego przebiegu) i stan_a2==0 i … stan_f2==0 (czyli nie ma obecnie aktywnego żadnego z tych przebiegów) – to znaczy, że wszystkie te warunki są spełnione równocześnie i będzie mógł być uruchomiony przebieg a1  :

    if (stan_Zw1 == 1 && stan_Zw2 == 1 && stan_Wk == 1

        && stan_Zw3_4 == 1 && stan_Zw5 == 1 && stan_a1 == 0

        && stan_a2 == 0 && stan_b1 == 0 && stan_c2 == 0

        && stan_e2 == 0 && stan_f1 == 0 && stan_f2 == 0)

{

Jeśli warunek jest spełniony to przypisujemy zmiennej a1 wartość 1, co oznacza że przebieg a1 jest obecnie aktywny i utwierdzony.

      stan_a1 = 1;  // utwierdzenie przebiegu a1 //

Zapalamy na pulpicie grupy diód a1 sygnalizujących tenże fakt:

      digitalWrite(led_a1, HIGH);

oraz wysyłamy informację do makiety o podanie odpowiedniego sygnału na semaforze:

      if (stan_D == 1)Serial.println(1044);     // A >> S5 //

      if (stan_D == 2)Serial.println(1042);     // A >> S2 //

Ale jako że mamy tutaj dwie możliwości czyli :

– semafor D wskazuje sygnał STÓJ (D==1) – to na semaforze A chcemy aby wyświetlił się sygnał S5 – więc wysyłamy informację 1044

– semafor D wskazuje sygnał S2 – czyli zezwala na dalszą jazdę (D==2) – to na semaforze A chcemy wyświetlić również sygnał S2 – więc wysyłamy informację 1042

    }

  } // a1 //

Widać zatem, że uaktywnienie jakiegoś przebiegu i zarazem podanie odpowiedniego sygnału na semaforze to dosyć rozbudowany warunek, który musi zostać spełniony.

Właściwie można uogólnić i stwierdzić, że wszystko co robi nasz system srk jest wyłącznie sprawdzaniem czy jakiś warunek jest spełniony czy też nie.

Zatem niezbędna jest znajomość zasad prowadzenia ruchu kolejowego i przepisów kolejowych. Warto więc (zanim zabierzemy się za pisanie oprogramowania) sprawdzić czy posiadamy poprawnie opisane sytuacje ruchowe dla naszej stacji, gdyż wyeliminowanie błędów z tych – jak by nie było – dość skomplikowanych warunków będzie niezwykle trudne, a na pewno czasochłonne.

Dla wszystkich, którzy chcą dokładniej przyjrzeć się tym zasadom polecam zaglądnięcie do artykułów Leszka, dotyczących przebiegów na tejże właśnie stacji i porównanie opisu słownego z zapisem kodu tego programu.\

Kolejne przebiegi to nic innego jak dalsze warunki dla każdego z tych „przypadków”:

  // przebieg a2 //

  if (digitalRead(key_a2) == LOW) {

    beep();

    if (stan_Zw1 == 2 && stan_Zw5 == 2

        && stan_a1 == 0 && stan_a2 == 0 && stan_b1 == 0 && stan_c2 == 0

        && stan_d1 == 0 && stan_f1 == 0 && stan_f2 == 0) {

      stan_a2 = 1;  // utwierdzenie przebiegu a2 //

      digitalWrite(led_a2, HIGH);

      if (stan_E == 1)Serial.println(1045);   // A >> S 13 //

      if (stan_E == 4)Serial.println(1046);   // A >> S 12 //

    }

  } // a2 //

  // przebieg b1 //

  if (digitalRead(key_b1) == LOW) {

    beep();

    if (stan_Zw1 == 1 && stan_Zw2 == 1 && stan_Wk == 1

        && stan_a1 == 0 && stan_a2 == 0 && stan_b1 == 0 && stan_c2 == 0

        && stan_f2 == 0) {

      stan_b1 = 1;    // utwierdzenie przebiegu b1 //

      digitalWrite(led_b1, HIGH);

      Serial.println(1052);   // B >> S2 zielone //

      // jesli przebieg f1 jest juz utwierdzony to zmiana semafora F na zielony

      if (stan_f1 == 1) Serial.println(3042); // F >> S2 zielone //

    }

  } // b1 //

  // przebieg c2 //

  if (digitalRead(key_c2) == LOW) {

    beep();

    if (stan_Zw1 == 2

        && stan_a1 == 0 && stan_a2 == 0 && stan_b1 == 0 && stan_f1 == 0 && stan_c2 == 0) {

      stan_c2 = 1;    // utwierdzenie przebiegu c2 //

      digitalWrite(led_c2, HIGH);

      Serial.println(1064);   // C >> S 10 zielone+pomaranczowe //

      // jesli przebieg f2 jest juz utwierdzony to zmiana semafora F na zielony

      if (stan_f2 == 1) Serial.println(3046);     // F >> S12 //

    }

  } // c2 //

  // przebieg d1 //

  if (digitalRead(key_d1) == LOW) {

    beep();

    if (stan_Zw3_4 == 1 && stan_Zw5 == 1

        && stan_a2 == 0 && stan_e2 == 0 && stan_f1 == 0 && stan_f2 == 0 && stan_d1 == 0) {

      stan_d1 = 1;                  // utwierdzenie przebiegu d1 //

      digitalWrite(led_d1, HIGH);

      Serial.println(3022);         // D >> S2 zielone //

      // jesli przebieg a1 jest juz utwierdzony to zmiana semafora A na zielony

      if (stan_a1 == 1) Serial.println(1042);     // A >> S2 zielone

    }

  } // d1 //

  // przebieg e2 //

  if (digitalRead(key_e2) == LOW) {

    beep();

    if (stan_Zw5 == 2

        && stan_a2 == 0 && stan_d1 == 0 && stan_f1 == 0 && stan_f2 == 0 && stan_e2 == 0) {

      stan_e2 = 1;                  // utwierdzenie przebiegu e2 //

      digitalWrite(led_e2, HIGH);

      Serial.println(3034);         // E >> S10 //

      // jesli przebieg a2 jest juz utwierdzony to zmiana semafora A na zielony

      if (stan_a2 == 1) Serial.println(1046);   // A >> S 12 //

    }

  } // e2 //

  // przebieg f1 //

  if (digitalRead(key_f1) == LOW) {

    beep();

    if (stan_Zw5 == 1 && stan_Zw3_4 == 1 && stan_Zw2 == 1 && stan_Zw1 == 1 && stan_Wk == 1

        && stan_a1 == 0 && stan_a2 == 0 && stan_c2 == 0 && stan_d1 == 0 && stan_e2 == 0 && stan_f2 == 0 && stan_f1 == 0) {

      stan_f1 = 1;                          // utwierdzenie przebiegu f1 //

      digitalWrite(led_f1, HIGH);

      if (stan_B == 1)Serial.println(3044); // F >> S5 pomaranczowe //

      if (stan_B == 2)Serial.println(3042); // F >> S2 zielone //

    }

  } // f1 //

  // przebieg f2 //

  if (digitalRead(key_f2) == LOW) {

    beep();

    if (stan_Zw5 == 2 && stan_Zw1 == 2

        && stan_a1 == 0 && stan_a2 == 0 && stan_b1 == 0 && stan_d1 == 0 && stan_e2 == 0  && stan_f1 == 0 && stan_f2 == 0) {

      stan_f2 = 1;                            // utwierdzenie przebiegu f2 //

      digitalWrite(led_f2, HIGH);

      if (stan_C == 1)Serial.println(3045);     // F >> S13 2*pomaranczowe //

      if (stan_C == 4)Serial.println(3046);     // F >> S12 //

    }

  } // f2 //

Oczywiście każdy przebieg – po stwierdzeniu „na gruncie”, że nasz modelowy pociąg zwolnił określone rozjazdy – musimy rozwiązać. Do tego służą przyciski rozwiązywania przebiegów.

Zatem sprawdźmy co zrobi nasz program po wciśnięciu przycisku rozwiązania_przebiegu_1:

  // rozwiazywanie przebiegow //

  if (digitalRead(key_rozw_przebiegu_1) == LOW) {

Najpierw oczywiście sygnał dźwiękowy:

    beep();

Dalej zerujemy przebiegi dla tej głowicy i podane sygnały zastępcze (jeśli takowe wystąpią):

    stan_a1 = 0;

    stan_a2 = 0;

    stan_b1 = 0;

    stan_c2 = 0;

    stan_SzA = 0;

    stan_SzB = 0;

    stan_SzC = 0;

Następnie „gasimy” diody wskazujące utwierdzony przebieg na pulpicie:

    digitalWrite(led_a1, LOW);

    digitalWrite(led_a2, LOW);

    digitalWrite(led_b1, LOW);

    digitalWrite(led_c2, LOW);

oraz wysyłamy sygnał stój na semafory A,B,C:

    Serial.println(1041);

    Serial.println(1051);

    Serial.println(1061);

Następnie zmieniamy sygnał dla przebiegu powiązanego z tą głowicą – czyli f1 lub f2 – jeśli oczywiście jest aktywny:

    // zmiana semafora F jesli podany jest wjazd

    if (stan_f1 == 1)Serial.println(3044);  // F >> S5 pomaranczowe //

    if (stan_f2 == 1)Serial.println(3045);  // F >> S13 2*pomaranczowe //

  }

Nie musimy natomiast zmieniać sygnałów wyświetlanych na powtarzaczach semaforów pulpitu, gdyż po wysłaniu do makiety „żądania” zapalenia sygnałów STÓJ na semaforach A, B i C system odeśle do pulpitu potwierdzenie tejże operacji, a to zaowocuje automatycznym odwzorowaniem tej sytuacji na pulpicie (patrz funkcja wyswietl_stan_urzadzen()).

Jak widać przycisk kasowania przebiegu jest „uniwersalny” dla całej jednej głowicy stacji, ale pamiętajmy, że na jednej głowicy tej stacji nie może być utwierdzonych kilku przebiegów, zatem proces kasowania może się odbywać na zasadzie kasowania całej głowicy, co zdecydowanie upraszcza nasz program.

Analogicznie postępujemy z drugą głowicą rozjazdową naszej stacji:

  if (digitalRead(key_rozw_przebiegu_2) == LOW) {

    beep();

    stan_d1 = 0;

    stan_e2 = 0;

    stan_f1 = 0;

    stan_f2 = 0;

    stan_SzD = 0;

    stan_SzE = 0;

    stan_SzF = 0;

    digitalWrite(led_d1, LOW);

    digitalWrite(led_e2, LOW);

    digitalWrite(led_f1, LOW);

    digitalWrite(led_f2, LOW);

    Serial.println(3021);

    Serial.println(3031);

    Serial.println(3041);

    // zmiana semafora A jesli podany jest wjazd

    if (stan_a1 == 1)Serial.println(1044);     // A >> S5 //

    if (stan_a2 == 1)Serial.println(1045);   // A >> S 13 //

  }

Następny fragment dotyczy sygnałów zastępczych.

  // Sygnaly zastepcze //

Sprawdzamy zatem czy został wciśnięty przycisk przebiegu zastępczego SzA:

  if (digitalRead(key_SzA) == LOW) {

Jeśli tak, to oczywiście – sygnał dźwiękowy, a dalej sprawdzamy czy SzA nie jest już czasem podany i jeśli nie jest – to wysyłamy kod 1043:

    beep();

    if (stan_SzA == 0)Serial.println(1043);

Teraz zapisujemy, że SzA=1 czyli jest aktywny:

    stan_SzA = 1;

oraz zapisujemy czas przez jaki ma być wyświetlany ten sygnał, czyli czas obecny + 90 sekund:

    czas_SzA = czas + 90000;

  }

Dla pozostałych sygnałów zastępczych postępujemy dokładnie tak samo:

  if (digitalRead(key_SzB) == LOW) {

    beep();

    if (stan_SzB == 0)Serial.println(1053);

    stan_SzB = 1;

    czas_SzB = czas + 90000;

  }

  if (digitalRead(key_SzC) == LOW) {

    beep();

    if (stan_SzC == 0)Serial.println(1063);

    stan_SzC = 1;

    czas_SzC = czas + 90000;

  }

  if (digitalRead(key_SzD) == LOW) {

    beep();

    if (stan_SzD == 0)Serial.println(3023);

    stan_SzD = 1;

    czas_SzD = czas + 90000;

  }

  if (digitalRead(key_SzE) == LOW) {

    beep();

    if (stan_SzE == 0)Serial.println(3033);

    stan_SzE = 1;

    czas_SzE = czas + 90000;

  }

  if (digitalRead(key_SzF) == LOW) {

    beep();

    if (stan_SzF == 0)Serial.println(3043);

    stan_SzF = 1;

    czas_SzF = czas + 90000;

  }

Teraz pora na automatyczne gaszenie sygnałów zastępczych.

Sprawdzamy zatem, czy nasz licznik czasu jest większy od czasu, który został zapamiętany przy wciśnięciu przycisku SzA i czy jest aktywny SzA.

Przykładowo:

Pamiętamy że zmienna czas ciągle zwiększa swoją wartość (+1) – dokładnie co 1 milisekundę, zatem jeśli np. w dokładnie 60 – tej sekundzie od startu systemu (czas = 60000) wciśniemy przycisk SzA to zmienna czas_SzA=60000+90000 czyli 150000.

Zatem jeśli licznik czasu przekroczy tę wartość czas>150000 to spełnimy pierwszą część poniższego warunku:

  if (czas > czas_SzA && stan_SzA > 0) {

Jeśli tak jest to zerujemy zmienną SzA i wysyłamy kod 1041, który wyświetli sygnał STÓJ na semaforze:

    stan_SzA = 0;

    Serial.println(1041);

  }

Analogicznie postępujemy dla pozostałych sygnałów zastępczych:

  if (czas > czas_SzB && stan_SzB > 0) {

    stan_SzB = 0;

    Serial.println(1051);

  }

  if (czas > czas_SzC && stan_SzC > 0) {

    stan_SzC = 0;

    Serial.println(1061);

  }

  if (czas > czas_SzD && stan_SzD > 0) {

    stan_SzD = 0;

    Serial.println(3021);

  }

  if (czas > czas_SzE && stan_SzE > 0) {

    stan_SzE = 0;

    Serial.println(3031);

  }

  if (czas > czas_SzF && stan_SzF > 0) {

    stan_SzF = 0;

    Serial.println(3041);

  }

Aby nieco ułatwić sobie programowanie wprowadziłem zmienną utwierdzenie, która dotyczy konkretnego rozjazdu np. utwierdzenie_Zw5.  Jest ona zależna od wielu innych zmiennych, a konkretnie od utwierdzonych przebiegów. Aby nie było konieczności wpisywania tych wszystkich warunków podczas np. zmiany położenia rozjazdów, wyprowadziłem te warunki „na zewnątrz”, czyli właśnie poniżej. Do samego przekładania zwrotnic sprawdzamy tylko zmienną utwierdzenie_Zw… która przyjmuje wartość 0 jeśli rozjazd nie jest utwierdzony, lub wartość 1 jeśli jest utwierdzony i nie można go ruszyć:

  // utwierdzenia rozjazdow i wykolejnicy //

  if (stan_a1 == 1 || stan_a2 == 1 || stan_b1 == 1 || stan_c2 == 1 || stan_f1 == 1 || stan_f2 == 1) utwierdzenie_Zw1 = 1;

else utwierdzenie_Zw1 = 0;

Tutaj dla odmiany wystarczy, aby choć jeden z warunków był spełniony. Wówczas wartość zmiennej Zw1 przyjmie wartość 1 lub – jeśli tak się nie stanie (czyli wszystkie będą równe 0) – to zmienna Zw1 przyjmie wartość 0.

Podobnie w pozostałych przypadkach:

  if (stan_a1 == 1 || stan_b1 == 1 || stan_f1 == 1 || stan_Wk == 1) utwierdzenie_Zw2 = 1;

else utwierdzenie_Zw2 = 0;

  if (stan_a1 == 1 || stan_d1 == 1 || stan_f1 == 1 ) utwierdzenie_Zw3_4 = 1;

else utwierdzenie_Zw3_4 = 0;

  if (stan_a1 == 1 || stan_a2 == 1 || stan_d1 == 1 || stan_e2 == 1 || stan_f1 == 1 || stan_f2 == 1) utwierdzenie_Zw5 = 1;

else utwierdzenie_Zw5 = 0;

  if (stan_a1 == 1 || stan_b1 == 1 || stan_f1 == 1) utwierdzenie_Wk == 1;

else utwierdzenie_Wk = 0;

Nie trzeba oczywiście tworzyć takich dodatkowych zmiennych, ale w niektórych sytuacjach jest o wiele czytelniej i prościej, gdy pewne zależności „zgrupuje się” w jednym miejscu,

a następnie w programie skorzysta z gotowych wyników tych warunków, czyli w tym przypadku utwierdzenie_Zw… jest właśnie takim wynikiem kilku zmiennych.

Dobrnęliśmy zatem do końca pętli głównej programu:

} // loop //

Zdaję sobie sprawę z dużej ilości informacji zawartych w tej części artykułu, ale wbrew pozorom jest to tylko kilka prostych funkcji użytych wielokrotnie.

Istotą działania tego systemu są warunki, które muszą być spełnione celem osiągnięcia jakichś konkretnych celów – zupełnie jak na prawdziwej kolei.

Ważne zatem, aby najpierw zrozumieć owe warunki, które determinują tak naprawdę wszystko co się dzieje w tym systemie, czyli na owej makiecie stacji Wysoka – jak ją nazwaliśmy.

Niestety warunki te nie są uniwersalne. Dla każdej stacji, dla każdego układu torowego będą się one różniły, a co za tym idzie trzeba będzie inaczej je zapisać w programie. Dlatego tak ważne jest ich poznanie i zrozumienie. Bez tego nie będzie możliwe stworzenie odpowiedniego oprogramowania. W tym przypadku sprawę bardzo ułatwił Leszek opisując wszystkie sytuacje ruchowe na stacji Wysoka i niejako podając mi te warunki „na tacy”. To było impulsem, aby stworzyć tę serię artykułów oraz ogromną pomocą, bez której pewnie nawet bym się za to nie zabrał. Pragnę zatem podziękować Ci Leszku za tę pomoc.

Na koniec jeszcze poproszę wszystkich odbiorców moich artykułów o przesyłanie na naszą PMM-ową skrzynkę mailową sygnałów zwrotnych z informacjami dotyczącymi ewentualnych niejasności, problemów do rozwiązania lub też o… pochwalenie się swoimi wynikami w pracach nad urealnieniem systemów sterowania swoich makiet.

Bardzo dziękuję wszystkim czytelnikom za wytrwałość i życzę wielu wspaniałych sukcesów w dziedzinie sterowania ruchem na miniaturowej kolei. Pliki wszystkich elementów systemu pobierzesz klikając w wysoka_pulpit.

Udostępnij

Warsztat

Klaudiusz Dawid

  • O nas

    Witajcie na naszej stronie. To miejsce, w którym dzielimy się z modelarzami kolejowymi naszym czasem, wiedzą i emocjami. Modelarstwo to nie tylko budowa makiet czy taboru. To także pasjonujące spotkania, warsztaty oraz inne wydarzenia w kraju i zagranicą, a co za tym idzie, ciekawe miejsca, makiety, ludzie. Znajdziecie tu opisy naszych makiet, modeli oraz relacje z modelarskich wyjazdów bliższych i dalszych.
  • Zobacz nasze filmy na youtube

  • Polub nas na facebooku

    Facebook Pagelike Widget
  • Najnowsze artykuły

    • Intermodellbau 2025 Dortmund
    • Festiwal Kultury Modelarskiej – Olsztyn 5-6 kwietnia 2025
    • Modeltrein Expo On traXS 2025 – Utrecht
    • Kozy 2025 – Prezentacja Modułowej Makiety Kolejowej
    • 12. Mittenwalder Modellbahntage 2025
  • Nasze najbliższe wydarzenia

    Wystawa makiet Kolejowych w Redzie

    Pokaz Makiety Modułowej w Lipuszu

    hobbymesse Lipsk

    Modellbahnausstellung OMC Gera



  • INFORMACJE PRAWNE

    Wszystkie publikacje na tej stronie są własnością autorów i nie można wykorzystywać ich bez zgody. Kopiowanie, powielanie i wykorzystywanie publikacji oraz fotografii bez zgody autorów jest zabronione.


© pmmh0.pl 2024 - Grupa Modelarska

Kontynuując przeglądanie tej witryny, wyrażasz zgodę na korzystanie przez nas z plików cookie.