diff --git a/.github/workflows/readme-consistency-check.yml b/.github/workflows/readme-consistency-check.yml new file mode 100644 index 0000000..5d43e00 --- /dev/null +++ b/.github/workflows/readme-consistency-check.yml @@ -0,0 +1,81 @@ +name: README Translation Consistency Check + +on: + pull_request: + paths: + - 'README.md' + - 'README.en.md' + push: + branches: + - main + paths: + - 'README.md' + - 'README.en.md' + +jobs: + check-readme-sync: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Check if both READMEs were updated + id: check_files + run: | + # Get list of changed files + if [ "${{ github.event_name }}" == "pull_request" ]; then + CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD) + else + CHANGED_FILES=$(git diff --name-only HEAD^ HEAD) + fi + + echo "Changed files:" + echo "$CHANGED_FILES" + + README_MD_CHANGED=false + README_EN_CHANGED=false + + if echo "$CHANGED_FILES" | grep -q "^README\.md$"; then + README_MD_CHANGED=true + fi + + if echo "$CHANGED_FILES" | grep -q "^README\.en\.md$"; then + README_EN_CHANGED=true + fi + + echo "readme_md_changed=$README_MD_CHANGED" >> $GITHUB_OUTPUT + echo "readme_en_changed=$README_EN_CHANGED" >> $GITHUB_OUTPUT + + # Check if only one was changed + if [ "$README_MD_CHANGED" = true ] && [ "$README_EN_CHANGED" = false ]; then + echo "warning=Only README.md was updated. Please also update README.en.md" >> $GITHUB_OUTPUT + exit 0 + elif [ "$README_MD_CHANGED" = false ] && [ "$README_EN_CHANGED" = true ]; then + echo "warning=Only README.en.md was updated. Please also update README.md" >> $GITHUB_OUTPUT + exit 0 + else + echo "warning=" >> $GITHUB_OUTPUT + fi + + - name: Comment on PR if only one README changed + if: github.event_name == 'pull_request' && steps.check_files.outputs.warning != '' + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '⚠️ **README Translation Warning**\n\n${{ steps.check_files.outputs.warning }}\n\nPlease ensure both language versions are kept in sync.' + }) + + - name: Create annotation + if: steps.check_files.outputs.warning != '' + run: | + echo "::warning::${{ steps.check_files.outputs.warning }}" diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..a44c9b2 --- /dev/null +++ b/README.en.md @@ -0,0 +1,194 @@ +**[🇩🇪 Deutsche Version](README.md)** | **🇬🇧 English version** + +# raspi-can-rocrail-server +Scripts for easily setting up a Raspberry Pi with a CAN interface and Rocrail + +On this page, I describe how a freshly installed Raspberry Pi can be equipped with Rocrail and, by using a CAN HAT, also becomes a CAN interface for Rocrail. + +## Initial situation +The Raspberry Pi has been freshly installed using Raspberry Pi OS in 64-bit, Lite configuration. + +As a CAN HAT, I am using a "Waveshare 2-Channel Isolated CAN Expansion HAT for Raspberry Pi, Dual Chips Solution" (2-CH CAN HAT). The HAT can be mounted right at the beginning. + +## Update, please! +- After the fresh installation, the Raspberry Pi should be brought up to date with sudo apt update && sudo apt upgrade. +- If you like, you can then flash the EEPROM to the latest version with sudo rpi-update. +- Afterwards, reboot the Raspberry Pi with sudo reboot. + +## My setup +I come from a time when the Märklin 6021 control unit was "the hot stuff". I am still perfectly happy with it. However, as someone who has been working in IT for more than three decades, I have repeatedly asked myself how something like an "electronic signal box" could be realized. The various Control Stations or other great products from competitors were priced beyond the hobby budget, so in the next step I opted for a Mobile Station 2 with track box 61116. That made things a bit more modern. + +The rather cumbersome task—compared to the "old digital days"—of searching for the turnouts to switch on the MS2 revived the idea of an "electronic signal box" again, especially after I found out that Märklin apparently uses a CAN bus. + +### Excursion: the CAN bus +The term is probably familiar to anyone who has dealt more closely with automotive technology. This bus system is well known for being installed in virtually every car and truck, where it connects control units, sensors, and actuators (i.e., devices where something actually happens). + +Unlike a computer network ("LAN"), packets are not sent directly from one point to another. Instead, each message is—simplified—prefixed with a type identifier ("left turn signal", "right turn signal", "message from the speed sensor", "message from the catalytic converter") and then put on the bus. + +All devices are connected to the bus and listen to everything, filtering out the information relevant to them. If the information concerns them, they briefly send an acknowledgment on the bus, and the sender then knows that someone was able to use the message. + +The CAN bus normally consists of two wires and, as a third reference potential, ground (GND). + +The two wires carry a differential signal, which makes the system very robust overall. + +Roughly speaking, you can imagine the differential signal as a square wave and its mirrored counterpart with opposite polarity, something like this: + + + |------| |------| |-----| |-----| +-----| |----| |------------------| |-------| |--------------- +======================(imaginary mirror)===================================== +-----| |----| |------------------| |-------| |--------------- + |------| |------| |-----| |-----| + + + +So if an error occurs on the upper wire (high signal), it can be detected by comparing it with the lower wire (low signal). + +The key to robustness, however, is that the imaginary mirror is not at "0 volts" but slightly above it, namely at +2.5 volts. + +With this offset, a digital "1" on the high wire then means a voltage of +3.5V and a digital "0" means +2.5V. + +On the low wire, the digital "1" is then also at +2.5V and the digital "0" at +1.5V. + +This offset has several advantages: +- If you test a CAN bus, neither of the two wires should be at 0 volts. If they are, something is wrong—usually the bus line is broken. +- If you detect a value >+2.5V on the wire, it is definitely the high wire. +- If you detect a value between +1.5V and +2.5V on the wire, it is the low wire. +- High and low wires must not be swapped in the CAN system. Otherwise, the comparator components in the CAN bus elements will no longer recognize a valid signal. + +Due to this technology and the usually twisted wires, the CAN bus is robust against interfering signals such as mobile phones or strong electric motors. + +The CAN bus achieves quite high speeds in the automotive sector (1 Mbit per second). In the Märklin system, however, only a quarter of the speed is used. + +The "MBUS" therefore runs at 250 kbit/s. This is important later for configuring the Raspberry Pi. + +## THE CAN HAT +I deliberately chose a somewhat more expensive but galvanically isolated CAN HAT. Why? + +The Raspberry Pi with the CAN HAT does not necessarily have to be plugged into the same power outlet as the model railway transformer. In theory, different potentials and thus "leakage currents" could occur, which could damage either the model railway control or the computer. + +The isolation is usually achieved by optocouplers. These are small packages where connections on one side go to an LED. Depending on "0" or "1", the LED turns on or off. + +On the other side of the package, a light-sensitive element is built in. It "sees" when the diode is on and then outputs a "1" to the computer. Otherwise a "0". + +The CAN HAT is integrated into the Raspberry Pi system like a serial interface or a network interface, for example. + +I would also like to mention the term "termination". For the bus to run stably (and for the various voltages to be generated cleanly), termination resistors are provided at the bus ends. Usually, these are already set correctly in the delivery state. + +In addition, some CAN HATs have jumpers for different operating voltages. Note that the Raspberry Pi usually operates at 3.3V on the GPIO pins. + +## Preparing the Raspberry Pi for the CAN HAT + +### Settings in the configuration menu + +By calling raspi-config, you enter the Raspberry Pi's configuration program. + +There, the following should be changed: +- (if needed) System Options -> Hostname: the device name of the Raspberry Pi. If you operate several in your network, they must all have different names. +- Interface Options -> SPI: enable. The "Serial Peripheral Interface" forms the communication interface between the Raspberry Pi and the CAN HAT. Data is transmitted via these lines. +- Advanced Options -> WLAN Power Save: disable. Especially if you later want to send or receive commands or states via WLAN, you should disable power saving mode. Otherwise, the Raspberry Pi might miss one or another message. + +Afterwards, please reboot the Raspberry Pi once. After that, you can also reach the device under the new hostname. + +### The script for automatic system configuration +Technically, the Device-Tree Overlay must now be adjusted on the Raspberry Pi and kernel modules must be loaded. + +For many people, this is "magic". That's why I had a script created for this using AI-assisted Coding. + +AI-assisted Coding describes the activity in which you "tell" (prompt) an AI what it should do. A pretty cool technique. If you know how something works and what should happen afterwards, you can tell the AI and it will then create the "program" for it. In the past, this was a lot of typing work and debugging...... + +In short, the following steps happen in the script: +- The Raspberry Pi is told at which connections and at what speed it should communicate with the CAN HAT on the hardware side. +- Then the Raspberry Pi kernel is told how to communicate with the HAT on the software side +- then the CAN bus is replicated on the Raspberry Pi system side so that it behaves like a network interface. +- in the last step, the "can-utils" software package is installed. This allows us to read and write on the CAN bus via the command line. + +To ensure nothing is broken if you run the script multiple times, it checks at each step whether the change has not already been made (idempotence). + +#### Calling the script for automatic system configuration + +The script setup-can.sh can be found here on Github. + +To make it executable ("startable"), the execute bit must be set: + +chmod +x setup-can.sh + +Then the script must be started with root privileges ("admin rights"): + +sudo ./setup-can.sh + +#### Health Check + +The script can-health-check.sh then checks the various parameters of the CAN bus. + +Again: make it executable: + +chmod +x can-health-check.sh + +Then the script must be started with root privileges ("admin rights"): + +sudo ./can-health-check.sh + +With CAN HATs that have multiple buses, it can also happen that the bus names are swapped (can0 / can1). Therefore, feel free to try the health check with the options can0 and can1 as well. + +In my case, a track box is connected. It sends—even in stop mode!—individual CAN frames. This then looks like this: + + + can1 0030532D [0] + can1 00314F73 [8] 47 47 34 08 01 44 00 10 + can1 0030532D [0] + can1 00314F73 [8] 47 47 34 08 01 44 00 10 + can1 0030532D [0] + can1 00314F73 [8] 47 47 34 08 01 44 00 10 + can1 0030532D [0] + can1 00314F73 [8] 47 47 34 08 01 44 00 10 + can1 0030532D [0] + can1 00314F73 [8] 47 47 34 08 01 44 00 10 + can1 0008532D [6] 00 00 40 06 02 CA + + +If these frames are displayed, you have the hardest part behind you. + +--- + +## Installing Rocrail + +The software can be downloaded at https://www.rocrail.online/rocrail-snapshot/index.php. + +Since we are using the 64-bit version of PiOS, we also need to download the 64-bit version ("ARM64") of Rocrail for Raspberry Pi. +The filename is usually: Rocrail-PiOS11-ARM64.zip + +With this command, the current package is downloaded and extracted to the subdirectory "Rocrail": + +wget https://www.rocrail.online/rocrail-snapshot/Rocrail-PiOS11-ARM64.zip +unzip Rocrail-PiOS11-ARM64.zip -d Rocrail +cd Rocrail + + +With a bold ./startrocrail.sh, Rocrail should start on the Raspberry Pi. +You can now start Rocview on another computer on the WLAN and connect to Rocrail by specifying the hostname of the Raspberry Pi ("Connect to"). + +--- + +**Rocrail is open source! And open source should also "be worth something" to you!** +- [x] Do you like Rocrail/Rocview? +- [x] Several people have sacrificed their free time to program the software! +- [x] The software is being further developed. People continue to sacrifice their time. **FOR YOU!** +- [x] Be fair! Support the programmers and purchase a [Support Key!](https://wiki.rocrail.net/doku.php?id=supportkey-en#commercial_support_key) +- [x] In return, you can use the Pro version of Rocrail with the Support Key. You can also find the advantages on the page. + +--- + +## Where is the journey going next? + +I will not explain the configuration of Rocrail here. Others can do that better. But: The "electronic signal box" is now possible. And much, much more! +I am very interested in two things: + +- **Block operation** with Rocrail: I want to use light barriers to detect when a train enters or leaves a certain area. This allows automatic operation. For this, I want to connect IR light barriers to an ESP32, which sends status messages to the Rocrail control center via the UDP protocol over WLAN. And perhaps the reverse way also works and you can send commands to the ESP32. This could make it quite easy to control light signals, for example. +- **Development of a DCC decoder**: If the path to the ESP32 is unreliable, an ESP32 can also be programmed as a DCC decoder. This could digitize things like light signals, (house) lighting, functional models, or a turntable. You can get old turntables for under 100 euros. New ones cost many times more—not to mention transfer tables. + +More on this when there are concrete plans. + + +Best regards, +Thilo diff --git a/README.md b/README.md index 435d2df..69048b7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**🇩🇪 Deutsche Version** | **[🇬🇧 English version](README.en.md)** + # raspi-can-rocrail-server Skripte zum leichten Aufsetzen eines Raspi mit CAN-Interface und Rocrail @@ -56,12 +58,12 @@ Dieser Versatz hat mehrere Vorteile: Durch diese Technik und die üblicherweise miteinander verdrillten Leitungen ist der CAN-Bus robust gegen einstrahlende Signale wie Mobilfunk oder auch starke Elektromotoren. -Der CAN-Bus erreicht im Automotive-Bereich recht hohe Geschwindigkeiten (1 MBit pro Sekunden). Im Märklin-System wird allerdings nur ein viertel der Geschwindigkeit verwendet. +Der CAN-Bus erreicht im Automotive-Bereich recht hohe Geschwindigkeiten (1 MBit pro Sekunden). Im Märklin-System wird allerdings nur ein Viertel der Geschwindigkeit verwendet. Der "MBUS" läuft also mit 250kBit/s. Das ist hinterher wichtig für die Parametrierung des Raspberry. ## DAS CAN-Hat -Ich habe mich bewußt zu einem etwas teureren, dafür aber galvanisch isoliertem CAN-Hat entschieden. Warum? +Ich habe mich bewusst zu einem etwas teureren, dafür aber galvanisch isoliertem CAN-Hat entschieden. Warum? Der Raspberry samt CAN-Hat muss ja nicht unbedingt an der gleichen Steckdose hängen wie der Trafo der Modellbahn. Theoretisch könnten also andere Potentiale und damit "Kriechströme" auftreten, die entweder die Modellbahnsteuerung oder den Computer beschädigen. @@ -79,21 +81,21 @@ Außerdem haben manche CAN-Hats Jumper für verschiedene Betriebsspannungen. Bea ### Einstellungen im Konfigurationsmenü -Durch aufrufen von raspi-config gelangt man in das Konfigurationsprogramm des Raspberry. +Durch Aufrufen von raspi-config gelangt man in das Konfigurationsprogramm des Raspberry. Dort wird geändert: - (bei Bedarf) System Options -> Hostname: der Gerätename des Raspberry. Betreibt man mehrere in seinem Netzwerk, müssen alle unterschiedliche Namen haben. - Interface Options -> SPI: einschalten. Das "Serial Peripheral Interface" bildet die Kommunikationsschnittstelle zwischen Raspberry und dem CAN-Hat. Über diese Leitungen weden die Daten übertragen. - Advanced Options -> WLAN Power Save: ausschalten. Gerade wenn man später über WLAN Kommandos oder Zustände senden oder empfangen will, sollte man den Stromsparmodus ausschalten. Sonst könnte der Raspberry die ein oder andere Nachricht verpassen. -Anschließend bitte den Raspberry einmal booten. Danach kann man das Gerät auch unter dem neuen Hostnamen erreichen. +Anschließend bitte den Raspberry einmal neu booten. Danach kann man das Gerät auch unter dem neuen Hostnamen erreichen. ### Das Skript für die automatische Systemkonfiguration Technisch müssen nun auf dem Raspberry das Device-Tree Overlay angepasst werden und Kernelmodule geladen werden. -Für viele Leute ist das "Magie". Deshalb habe ich per Vibe Coding dafür ein Skript erstellen lassen. +Für viele Leute ist das "Magie". Deshalb habe ich per AI-assisted Coding dafür ein Skript erstellen lassen. -Vibe Coding beschreibt die Tätigkeit, bei der man einer KI "sagt" (prompted), was sie machen soll. Eine recht coole Technik. Wenn man weiß, wie etwas funktioniert und was hinterher passieren soll, kann man das der KI mitteilen und die erstellt dann das "Programm" dazu. Früher war das sehr viel Tipparbeit und Fehlersucherei...... +AI-assisted Coding beschreibt die Tätigkeit, bei der man einer KI "sagt" (prompted), was sie machen soll. Eine recht coole Technik. Wenn man weiß, wie etwas funktioniert und was hinterher passieren soll, kann man das der KI mitteilen und die erstellt dann das "Programm" dazu. Früher war das sehr viel Tipparbeit und Fehlersucherei...... In Kurzform passieren in dem folgenden Skript diese Schritte: - Dem Raspberry wird gesagt, an welchen Anschlüssen er mit welcher Geschwindigkeit mit dem CAN-Hat hardwareseitig reden muss. @@ -103,17 +105,17 @@ In Kurzform passieren in dem folgenden Skript diese Schritte: Damit nichts zerstört wird, wenn man das Skript mehrfach ausführt, prüft es bei jedem Schritt ob die Änderung nicht schon durchgeführt wurde (Idempotenz). -#### Aufruf des Skriptes für die automatisch Systemkonfiguration +#### Aufruf des Skriptes für die automatische Systemkonfiguration Das Skript setup-can.sh findet ihr hier im Github. Um es ausführbar ("startbar") zu machen, muss das Execute-Bit gesetzt werden: -chmod +x setup_can.sh +chmod +x setup-can.sh Anschließend muss das Skript mit Root-Rechten ("Admin-Rechten") gestartet werden: -sudo ./setup_can_marklin.sh +sudo ./setup-can.sh #### Health-Check @@ -121,7 +123,7 @@ Das Skript can-health-check.sh überprüft anschließend die versch Auch hier wieder: ausführbar machen: -chmod +x setup_can.sh +chmod +x can-health-check.sh Anschließend muss das Skript mit Root-Rechten ("Admin-Rechten") gestartet werden: @@ -145,7 +147,7 @@ In meinem Fall hängt eine Gleisbox dran. Die sendet -auch im Stop-Betrieb!- ein can1 0008532D [6] 00 00 40 06 02 CA -Wenn diese Frames angezeigt werden, habt ihr das schwerste hinter euch. +Wenn diese Frames angezeigt werden, habt ihr das Schwerste hinter euch. --- @@ -156,15 +158,15 @@ Die Software kann unter https://www.rocrail.online/rocrail-snapshot/index.php he Da wir die 64bit-Version von PiOS nutzen, müssen wir auch die 64bit-Version ("ARM64") von Rocrail für Raspberry Pi herunterladen. Üblicherweise lautet der Dateiname: Rocrail-PiOS11-ARM64.zip -Mit diesem Befehl wird das aktuelle Paket heruntergeladen und in das Unteverzeichnis "Rocrail" entpackt: +Mit diesem Befehl wird das aktuelle Paket heruntergeladen und in das Unterverzeichnis "Rocrail" entpackt: wget https://www.rocrail.online/rocrail-snapshot/Rocrail-PiOS11-ARM64.zip unzip Rocrail-PiOS11-ARM64.zip -d Rocrail cd Rocrail -Mit einem beherzten ./startrocrail.sh solltet Rocrail auf dem Raspberry starten. -Ihr könnt nun Rocview auf einem weiteren Rechner im WLAN starten und euch mit unter Angabe des Hostnamens des Raspberry mit Rocrail verbinden ("Connect to"). +Mit einem beherzten ./startrocrail.sh sollte Rocrail auf dem Raspberry starten. +Ihr könnt nun Rocview auf einem weiteren Rechner im WLAN starten und euch unter Angabe des Hostnamens des Raspberry mit Rocrail verbinden ("Connect to"). ---