{"id":722,"date":"2026-10-29T15:00:00","date_gmt":"2026-10-29T06:00:00","guid":{"rendered":"https:\/\/vandermeij.familyds.com\/wordpress\/?page_id=722"},"modified":"2026-11-01T14:04:40","modified_gmt":"2026-11-01T05:04:40","slug":"train-controller-software","status":"publish","type":"page","link":"https:\/\/vandermeij.familyds.com\/wordpress\/?page_id=722","title":{"rendered":"Train Controller: Software"},"content":{"rendered":"<p><a href=\"https:\/\/vandermeij.familyds.com\/wordpress\/?page_id=717\">\u2190 Back to Train Controller<\/a><\/p>\n<p dir=\"ltr\">The controller runs as one Python program on the Raspberry Pi. It uses the pigpio library for accurate hardware PWM and serves its own web dashboard.<\/p>\n<h2 dir=\"ltr\"><strong>What it does<\/strong><\/h2>\n<p dir=\"ltr\">The program runs a loop: the train accelerates, runs at full speed, slows down on approach, stops at the platform, the turnout switches, and the cycle repeats. Speed changes in small steps every 0.05 seconds, so the train accelerates and brakes smoothly.<\/p>\n<p dir=\"ltr\">At a platform the train waits 8 seconds. That is the time the mechanical turnout needs: a one-second pulse, and then seven seconds to finish moving. Then the train accelerates to full speed again.<\/p>\n<h2 dir=\"ltr\"><strong>Recognising each train<\/strong><\/h2>\n<p dir=\"ltr\">A background routine reads the code on the train (a barcode or a QR code; the scanner reads both). Each train has its own maximum full speed and slow speed in a small SQLite database, and these are loaded automatically when the train is identified. That way every train behaves realistically.<\/p>\n<h2 dir=\"ltr\"><strong>Safety<\/strong><\/h2>\n<p dir=\"ltr\">An emergency stop halts the train immediately. A separate shutdown button waits until the train has stopped, tidies up, and then powers off the Raspberry Pi. Both buttons use double-press detection, so an accidental touch does nothing. Overcurrent protection is done in hardware (see the <a href=\"https:\/\/vandermeij.familyds.com\/wordpress\/?page_id=720\">Hardware page<\/a>).<\/p>\n<h2 dir=\"ltr\"><strong>The web dashboard<\/strong><\/h2>\n<p dir=\"ltr\">A dashboard built into the program shows live status and lets me control the speed, trigger the emergency stop, enter a train\u2019s identity and see the current readings. It can be opened in a browser on any device in the home network.<\/p>\n<h2 dir=\"ltr\"><strong>Status<\/strong><\/h2>\n<p dir=\"ltr\">This is a work in progress, developed and tested step by step on the bench. At the moment I am checking the slowest running speed against the motor\u2019s starting threshold on the rebuilt two-board hardware.<\/p>\n<p dir=\"ltr\">\n<p dir=\"ltr\"><a href=\"https:\/\/github.com\/PetervanderMeij\/train-controller\">Source code on GitHub<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u2190 Back to Train Controller The controller runs as one Python program on the Raspberry Pi. It uses the pigpio [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":717,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"wprm-recipe-roundup-name":"","wprm-recipe-roundup-description":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"disabled","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"disabled","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-722","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/vandermeij.familyds.com\/wordpress\/index.php?rest_route=\/wp\/v2\/pages\/722","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vandermeij.familyds.com\/wordpress\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/vandermeij.familyds.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/vandermeij.familyds.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vandermeij.familyds.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=722"}],"version-history":[{"count":6,"href":"https:\/\/vandermeij.familyds.com\/wordpress\/index.php?rest_route=\/wp\/v2\/pages\/722\/revisions"}],"predecessor-version":[{"id":748,"href":"https:\/\/vandermeij.familyds.com\/wordpress\/index.php?rest_route=\/wp\/v2\/pages\/722\/revisions\/748"}],"up":[{"embeddable":true,"href":"https:\/\/vandermeij.familyds.com\/wordpress\/index.php?rest_route=\/wp\/v2\/pages\/717"}],"wp:attachment":[{"href":"https:\/\/vandermeij.familyds.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=722"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}