Skip to main content

@BillYo414 posted:

Would these events include items outside of the Lionel ecosystem? Like say environmental sounds, scenery animations, or digital information? And as far as digital information, that would be things like moving digital freight around the layout.

Yes, absolutely. For example, if you had a gate man connected to an LCS ASC2, you could trigger him coming out of his little house when the train went over the sensor track. True, you could accomplish the same thing with physical wiring, but there is an elegance to doing so by issuing TMCC commands and even using random numbers to control how long the response action lasted.

Last edited by cdswindell

@cdswindell my layout is based on a steel mill. It's still in the very early stages of development but I often plan later stages for future reference since I find slowly working on an idea helps me get it right the first or second time when I build it.

I've toyed with the idea of a fast clock but many people aren't experts on steel making and running against a rigid clock might end up causing chaos in an ops session. I was thinking an event driven sequence would be better. So a car being spotted under the blast furnace would trigger a timer and the furnace tapping animation sequence (lights, smoke, sound) would occur after a set amount of time.

This is probably worth emailing you about for the finer details at this point but having the ability to use the locomotive/car itself to activate this would save me some wiring and hiding of sensors.

I should probably start learning how to use LCS and Python!

Hey all, thank you for the @mentions 😁, I appreciate it. Yes stalled but not completely dead in the water at the PDI phase. I wanted to skip over Wi-Fi because that introduces a whole new level of hassle to the user not to mention possibilities configuration issues getting in the way. For my game idea I wanted to kind of develop the game as a PDI module to make it as easy to implement as possible for the widest number of people. I did take on a new job in May which have been consuming so much more time besides what my business had originally. But I am absolutely down to contribute anything I can to any project hopefully continue with everything else I was doing too. My availability has been starting to get a little better lately (knock on wood).

Most recently I've also been working with my train club TMB to . For them a large scale map of the layout on the wall with live tracking block occupancy across the layout. Which as of last year is now located in a 6,000 ft basement below a church.

I'm going to have to do some reading to catch up on these last two pages in this thread. But I love any and all projects that give LCS a purpose for existing, besides setup and simple location pinging in the old lcs ipad app. Plus I love to see interaction happening with the layout I think that's where the next era of fun to be had can be found.

Plus I recently learned some fun tricks using python code that could absolutely help me break down the PDI data, struct.pack and struct.unpack. Part of what made things tricky before was working in Arduino code exclusively and facing off with decoding raw binary data via bitmasking was not nearly as fun.

@Ryaninspiron, we may make a good team I like decoding raw binary data via bitmasking !

But seriously, I have code in place that decodes 80 to 90% of the PDI commands in the confidential Lionel PDI/LCS docs. The code is all checked in on GitHub. Just search for the PyLegacy project!

  — Dave

I decided to start maintaining state for the LCS Sensor Track. It plugged into the stack with about 90 minutes of coding, which felt pretty good. I could also manage state for (the) other LCS modules, but I’m not sure I’ll need to. I was already processing state changes signaled by the Base, BPC2, ACS2, and STM2 by translating their updates into Switch, Accessory, and Engine/Train space (e.g., recording an STM2 update as a Switch Thrown update).

It will now be easy to have an engine/train go to slow speed or go to normal speed when it crosses over a Sensor Track programmed to generate that sequence.

  — Dave

Plus I recently learned some fun tricks using python code that could absolutely help me break down the PDI data, struct.pack and struct.unpack. Part of what made things tricky before was working in Arduino code exclusively and facing off with decoding raw binary data via bitmasking was not nearly as fun.

@Ryaninspiron, huh, I was unaware of the struct package! That would be very useful for my code that writes PDI/LCS packets that I send to the base, thanks!

  — Dave

@BillYo414 posted:

@cdswindell my layout is based on a steel mill. It's still in the very early stages of development but I often plan later stages for future reference since I find slowly working on an idea helps me get it right the first or second time when I build it.

I've toyed with the idea of a fast clock but many people aren't experts on steel making and running against a rigid clock might end up causing chaos in an ops session. I was thinking an event driven sequence would be better. So a car being spotted under the blast furnace would trigger a timer and the furnace tapping animation sequence (lights, smoke, sound) would occur after a set amount of time.

This is probably worth emailing you about for the finer details at this point but having the ability to use the locomotive/car itself to activate this would save me some wiring and hiding of sensors.

I should probably start learning how to use LCS and Python!

@BillYo414, happy to have an email conversation. The code in its current form can definitely generate events in response to an engine (or car with an IR transmitter) traveling over a sensor track. The event packet contains the ID of the activated sensor track, the direction of travel, the engine/train ID passing over, and a bunch of what I call simulated state (fuel/water level, odometer, total runtime, etc.)

You could write code that “subscribes” to sensor track events. That code would then receive these updates and could go from there. You can also access current engine speed and direction from other components of my system and/or by subscribing to engine/train events.

I don’t currently have any code to sense engine position (other than the sensor track), so I’m not sure how you would tell when a car was next to/underneath your steel mill stuff. My code gives you fine control over train speed (absolute speed step control), as well as commands to immediately stop engine motion immediately. In fact, I’ve implemented all of the TMCC commands in the public Lionel spec (except those to build/tear down train consists)!

  — Dave  

@cdswindell posted:

@Ryaninspiron, we may make a good team I like decoding raw binary data via bitmasking !

But seriously, I have code in place that decodes 80 to 90% of the PDI commands in the confidential Lionel PDI/LCS docs. The code is all checked in on GitHub. Just search for the PyLegacy project!

  — Dave

Absolutely would be great to join forces, and since you love bitmasking so much you might just love to see the work I've done on reverse engineering the sensor box cars and therefore the ability to create postage stamp size modules to add sensor track capabilities at any number of cars or engines. I've already demonstrated one of these modules in operation on one of my YouTube videos on the subject. But until now I haven't had anybody else to share the load with. I had actually ordered about 20 old school irda transceivers, and use that to capture the data into a bit array that I then saved into Arduino code, and then put matching code to retransmit that bit stream back out on the two in IR LEDs. I also did testing and figured out exactly which wavelength of ir LED you can use off the shelf from Amazon as a sensor card transmitter. I have one other person who tested and deployed my code successfully too. But they did not end up having time to help me make progress with completely cracking the code such as transmitting a-la-carte engine IDs and names. But I do have a demo on youtube from several years ago where I trigger sounds on a line Chief engine using my home made sensor car. https://youtu.be/qgGiVOycX8o?si=cXwrYXJELr2Zrtvv

So yes I agree we could make an amazing team, I'm also an LCS partner too. Honestly that made me nervous about what I was allowed to disclose and it made me hesitant to simply publish my code before.

Of course everything I learned on the sensor car box car was through traditional reverse engineering since none of that documentation was included in the partner program. I also had set up a discord server to host discussions about this sensor car reverse engineering project including links to Amazon for buying all the hardware to test it on your own. https://discord.gg/ptmd79Zd

Last edited by Ryaninspiron
@cdswindell posted:

@BillYo414, happy to have an email conversation. The code in its current form can definitely generate events in response to an engine (or car with an IR transmitter) traveling over a sensor track. The event packet contains the ID of the activated sensor track, the direction of travel, the engine/train ID passing over, and a bunch of what I call simulated state (fuel/water level, odometer, total runtime, etc.)

You could write code that “subscribes” to sensor track events. That code would then receive these updates and could go from there. You can also access current engine speed and direction from other components of my system and/or by subscribing to engine/train events.

I don’t currently have any code to sense engine position (other than the sensor track), so I’m not sure how you would tell when a car was next to/underneath your steel mill stuff. My code gives you fine control over train speed (absolute speed step control), as well as commands to immediately stop engine motion immediately. In fact, I’ve implemented all of the TMCC commands in the public Lionel spec (except those to build/tear down train consists)!

  — Dave  

Wow I was just in the middle of implementing a project that uses industrial communication modules(modbus rtu) RS485 to capture the occupancy of all the blocks on a large scale 6,000 sqft layout and was just envisioning tracking engine IDs along the way by tacking them onto the continuous chain of block occupancy that passes over a sensor track.

This feels a bit like a milestone to me. I now have trains automatically slowing down or speeding up as they pass over a sensor track! They only do this if the sensor track sequence is set to one of the two values where a speed dialogue is given, based on the direction of travel. I have some work to do to make the speed up or slow down, look more realistic by taking the train’s Momentum, setting and current speed into account, but I have all the pieces sitting around to do this (in code, of course).

I’ll post a video to YouTube and include its link in a day or two.

I still haven’t started packaging.

  — Dave

Dave,

Looks like I'm in... with a  little overkill.  I just pulled the trigger on the 8G Pi 5 (bare board).  I have a Samsung M.2 970 Pro that I just took out of the workstation and it's gathering dust so I ordered the Pineboards POE+ (2280 M.2).  Not the cheapest configuration... but hey, it's for the trains.

That will more than do!!! FYI, I just installed the M2 hat that Raspberry Pi itself distributes and it worked perfectly. One thing to watch out for. I had better luck using the “Copy SD card” in the Pi gui to clone my system image onto the M2 drive (requires a VNC connection; everything else I do via ssh).

  — Dave

Just checked in support to ramp speeds up and down, more like the Cab2 and Cab3 throttles do. You can still jump immediately to a desired speed, but the default is to now use a ramp that also takes the engine’s momentum into account.

ill post a video tomorrow. Looks nice when the speed is changed by going over a sensor track!!

  — Dave

Checked in support for a Rotary Encoder. Think of these like digital potentiometers, except they rotate round-and-round, just like the big red throttle knob on the Cab 2.

I've incorporated this support into GpioHandler.gantry_crane and GpioHandler.track_crane to rotate the cab. Of course, with that said, when I unboxed my Lionel Legacy CSX Track Crane car, I found it was missing a gear necessary to rotate the cab! But my code does send the right commands and I can see the gears they did install turn in the correct direction. Sigh

Here's what the code looks like a user would have to write to build a dedicated panel to control a track crane car:

GpioHandler.crane_car(
address=91,
cab_pin1=20,
cab_pin2=21,
adc_channel=0, (1)
boom_pin=16,
bh_pin=25,
sh_pin=26,
boom_led_pin=23, (2)
bh_led_pin=24, (2)
sh_led_pin=22 (2)
)


Where:

  • address: TMCC ID of Crane car
  • cab_pin1, cab_pin2:rotary encoder GPIO pins on the Pi
  • adc_channel: the adc channel to read joystick input for boom, small hook, and big hook motion (1)
  • boom_pin, bh_pin, sh_pin: GPIO pins connected to buttons to select what the joystick controls; the boom, the big hook, and the small hook.
  • boom_led, bh_led, sh_led: GPIO pins to drive status less to show which component the joystick will control; boom, big hook, or small hook.

Notes:

  1. I chose to use a MCP3208 analog to digital converter to take input from the analog joystick potentiometer and convert it to digital, so the Pi can consume it. Various vendors supply "hats" which sit on top of the Pi's 40 pin GPIO header. You can stack hats one on top of another, as I've done in the picture below. It would also be possible to use Rotary Encoders to control boom motion, but a joystick with a simple up/down motion felt more natural. The code supports both the MCP3208 (12 bit) and MCP 3008 (10 bit) a to d converters (thanks to the gpiozero python library). One of these chips can support 8 joysticks (or potentiometers).
  2. Status LEDs are optional. I think it adds a nice touch, though, to show what function the joystick will control

All told, you are looking at less that $100 of parts, and all available from Amazon and one other online vendor. IMG_6552



Attachments

Images (1)
  • IMG_6552: Raspberry Pi 4B with MCP3208 ADC hat
@cdswindell posted:

…use a ramp that also takes the engine’s momentum into account

  — Dave

I was playing with “momentum” in analog controllers over the summer. I found that for it to really look and feel right, you need to be playing calculus games - actively changing the rate of change over time (second derivative? I forget, it’s been an awfully long time…) to ease in and out of acceleration and deceleration. Otherwise it’s just like a sort of delayed speed change effect.  With complete control over the software stack like you are building, I bet you can really do momentum right!

@christie posted:

I was playing with “momentum” in analog controllers over the summer. I found that for it to really look and feel right, you need to be playing calculus games - actively changing the rate of change over time (second derivative? I forget, it’s been an awfully long time…) to ease in and out of acceleration and deceleration. Otherwise it’s just like a sort of delayed speed change effect.  With complete control over the software stack like you are building, I bet you can really do momentum right!

Calculus was an awfully long time ago for me, but you absolutely could build any kind of speed table that you want. I took a look at what the Lionel Cab3 controller does and tried to emulate that. My implementation at this point is all based on linear map, but I guess I was just lazy.

  -- Dave

Added a "decode" command to PyTrain to convert hex codes seen in the LCS Monitor app (or Wireshark Sniffer) to the corresponding TMCC or LCS Command.

For example:

>> decode D1 28 F8 87 CC 8D DF
0xd128f887cc8ddf --> [PDI Tmcc_Rx [ENGINE 67 ENGINE_LABOR 12 (0xf887cc)] (0x28f887cc)]
>> decode 0xF88703
0xf88703 --> [ENGINE 67 REVERSE_DIRECTION (0xf88703)]


-- Dave

Finally added logging to the code. Log messages can go to both a file and the console at the same time. Logging can also capture command echoing, so you can have a complex transcript of all the TMCC commands happening on your layout, be they from a Cab 2, a Cab 3, or from the PyTrain command line. This really lets you see the commands the Cab 2 and Cab 3 generate when you operate a control; you’d be surprised!

  — Dave

I received my Gantry Crane today and ****ed if the components I’ve wired up to control it did just that! I turned the rotary encoder and the crane cab turned. I pushed up and down on the joystick and the magnet raised and lowered. And I pushed left and right on the joystick and the crane moved left and right!!

I have some tweaking to do, as the code that sends the numeric prefix (<Aux 1> [1, 2, 3]) needs to be synchronized so that state isn’t lost when you operate multiple controls at the same time, but it works!

  — Dave

I've switched gears to working on support for making the system easier to use and more bulletproof. This is involved two changes. The first is I've developed some scripts that allow you to run the software when the raspberry pie boots up. This will be important because when powers turned onto the layout, I want the pies that are powering the control panels to just boot up and be working, like an embedded device.

The second change is to use a discovery service to allow the PyTrain server(s) to register their presence on the local network. This will allow the client applications to not need to fool with IP addresses. They will auto-discover The IP address of the server, and just simply connect to it. Since the Base 3 Doesn't echo out very many of the commands it receives in, I still think it will be advantageous to have an LCS Ser2 connected to the server. That said, I'm investigating if it makes sense to have each client send train commands directly to the Base 3 over WiFi. This should help distribute the load.

I'm working now on actually building the first control panel to operate my gantry crane. I'll send pictures along once there's something to show. By the way, all of the code is checked in.

  -- Dave

Add Reply

Post
×
×
×
×
Link copied to your clipboard.
×
×