@cdswindell I'm very interested in your python code to read and write the commands via the SER2.
Sharing code is always a humbling experience
FYI, the following code was actually generated by the AI assistant in PyCharm! So far we have traveled since I started programming for a living in 1979...
So, with that caveat, here is the code to fire Route 10:
import serial
def write_byte_sequence_to_serial_port(port, baudrate, byte_sequence):
# Open the serial port
with serial.Serial(port, baudrate) as ser:
# Write the byte sequence
ser.write(byte_sequence)
byte_sequence = bytes.fromhex("FED51F")
write_byte_sequence_to_serial_port("/dev/ttyUSB0", 9600, byte_sequence)
So some explanation. This code relies upon the PyThon package PySerial to do the output over the RS232 port of my Pi (which in my case is a USB - RS232 dongle). The helper method write_byte_sequence_to_serial_port
writes a specified byte sequence out to the specified serial port on my Pi.
The line:
byte_sequence = bytes.fromhex("FED51F")
encodes the TMCC 1 command into a byte sequence that is sent to the serial port and read by the LCS SER2 device (and forwarded to my Base 3).
From the Lionel Legacy Command Protocol document, we can understand the 6 character hexadecimal value passed into the Python bytes.fromhex function (and in case others are reading this, a byte is comprised of 8 bits; 4 bits can be expressed by a single Hexadecimal (base 16) digit; 0 - F, so one byte can be expressed as 2 Hex digits; the string of 6 Hex digits above ("FED51F") thus represents the 3 byte TMCC1 command sequence; the route number, 10 in my case is expressed as 5 binary digits (0, 1), or 01010, and, as may make sense below, the first 4 of these 5 bits. 0101, are represented by the hex digit "5" ( 0*16 + 1*8 + 0*4 + 1*2 + 0*1)):
Byte 1: 0xFE - specifies the start of a TMCC1 command (page 3 of the document)
Byte 2: 0xD5 - the first 4 bits (0xD) specify the command is a route fire command; the 2nd 4 bits (0x5) are the 4 most significant bits of the 5 bit encoded route number.
Byte 3: 0x1F - this byte has the last bit of the route number, and a 2 bit command field, and a 5 bit data field (refer to page 4 of the Lionel documentation for an explanation of these bits...)
I hope this helps. The code isn't pretty and as the route number is "hard coded", is minimally reusable. But, when ran from my Pi connected to my LCS SER2, it did fire Route 10
My ultimate goal over the next sever months is to build a python package that:
- exposes command line tools to flip switches, fire routes, and maybe fire accessories
- provides classes that a developer could use to send Legacy commands via serial
- sense button clicks and fire Legacy commands in response
- provide a configuration language to specify the binding of a button press to the command to fire and the required parameters (route number, switch number and through/out, etc)
My goal is to be able to build a physical control panel, such as one I built for a DCC-controlled Z-scale layout I built with discrete hardware during the pandemic. Once I set up the GitHub project, I will post it's link.
-- Dave