Part 4b - Setting up Schedules
Since starting this worked example, I knew that I would eventually want to setup schedules. From the last part, we saw that the default Load and Empty states aren't really going to work for what we want to do.
Creating the schedules and custom loads for them is actually fairly easy. We're only using a small portion of the schedule functionality, so it's mostly just repetitive work. It's a three-step process. First the custom loads are created. Then schedules are created for each spur, containing an entry for each custom load handled by the spur. Finally the cars are updated with correct RWE and Load settings.
Create Custom Loads
Before we create schedules, we need to create custom loads for our cars. An easy way to do this is from the Cars window, select a group of cars and use the Tools -> Set Cars dialog.
I created the following Custom Loads for each car type in storage:
Location | Car Type | Custom Load |
---|
Storage 4 | TGP23 | Latex, MTY |
Storage 3 | CPG410, CPG308 | Plastics, MTY |
Storage 2 | FB58, FC75 | Lumber, Plywood, MTY |
Storage 1 | BC250, BP250, BS250 | Plywood, MDF, MTY |
Storage 1 | BP260, BS260 | XPS, MTY |
Notes:
- For each car type, I created a custom empty load called MTY. We will need this to get the empties properly routed back to storage.
- For now, the plastics cars just have a single custom load called "Plastics". Eventually I can create different plastics types (HDPE,LDPE, LLDPE, PP, etc.) once I have cars being routed the way I want. The same goes for Latex.
- The bulkhead and centerbeam cars carry dimensional lumber and exterior sheeting plywood.
- The double-door boxcars carry finished plywood and MDF sheets, products which need to be protected from the elements.
- The 60' boxcars carry Extruded Polystyrene sheets (XPS, the rigid foam insulation stuff)
- For the flatcars and boxcars, I randomly selected about half the cars for each custom load (half the FB58 cars are Lumber, half are Plywood, etc).
You can try setting the RWE value at this point, but JMRI may complain that the setting may not work because the selected spur doesn't handle custom loads yet. In that case, we will verify the settings are still correct once we've created the schedules.
Create Schedules
Next, we create schedules for each spur in storage as well as for each spur on the layout. The storage spurs all receive MTY loads and ships the loaded loads. Each spur needs a schedule entry for each car type and load. To add a schedule to a spur, edit the spur track for a location.
Here is the schedule for Storage 1. Note that we're using Match mode for all of the schedules. For each car type that can ship multiple loads, I set the Random value to 50. This means that when JMRI is filling cars using this schedule, there's a 50 percent chance that it will set the car to that load. The Random setting is not strictly necessary at this point, and you can leave it unset for now until you get a better feel for how cars are being selected when trains are built. The Hits field maintains a count of the number of times that specific schedule entry was used to fill a car load.
Here is the schedule for Storage 2. The same notes for Storage 1 apply here.
Here is the schedule for Storage 3. I decided that CP510 cars will only ship flour. The CP410 cars will ship both flour and masaca (milled corn used to make corn tortillas).
Storage 4 is simple, as I only have a single tank car type handling the Latex for now.
On the layout, I only created schedules for selected spurs that I have cars servicing right now. The list of spurs currently active include both lumber spurs, the hoppers for Rudy's Tortillas, hoppers for Alamo Packaging, and Latex tank cars. The boxcars for the warehouse, Rudy's, and Alamo are not handled yet.
For each of the spurs, there is an entry for each car type and load received. Each entry ships the MTY empty load.
For now, both 3520.1 and 3520.2 use the same schedules. Eventually I want to create slightly different schedules so that XPS loads prefer the 3520.1 spot as the primary. The lumber distributor can unload the foam from either spot, but prefers 3520.1 as it's closest to where the foam is stored.
You will notice the wait value is non-zero for the 60' cars in this screenshot. You can leave them all as zero for now. I took this screenshot after doing some other tweaking.
Adjusting the Staging Tracks
We need to make a couple of adjustments to the staging tracks to make sure cars are routed properly from storage to the layout and back. We never want a car to be left at the staging location.
For each staging track, make sure the set outs and pick ups trains are set accordingly. Staging-1 should only handle Westbound movements and staging-2 should only handle Eastbound movements. For each track from the Tools menu, select Track Destinations. Make sure the option to only accept cars with a final destination is checked. Optionally, set the accepted destinations as shown - staging-1 only accepts cars for Zone 'OP' and staging-2 only accepts cars for Storage.
Final Adjustments
Now that we have the custom loads created and schedules setup for each spur, we need to go back and make sure all the cars are set properly. Go back to the Cars window and edit each car (or group of cars) to make sure the RWE and Load settings are correct.
Let's Build Some Trains!
Now that we have created the custom loads, set schedules for all the spurs, and tweaked the staging tracks, we can run some trains. I like to have the Cars window open and sorted by Location while building trains. JMRI updates the car locations and destinations in real-time as the train is built and moved.
After building several trains, we see that everything appears to be working almost as expected. However, I noticed on my builds that no cars were ever being routed to the "yard" tracks as off-spots on the layout. Why is that happening? I had that working on my original example. What's different?
After doing several backups and restores, switching between this example and my original example, I found what appears to the the reason.
For each spur, I had both "Use car type and load" and "Hold cars with custom loads when spurs are full" selected. The second one was causing my issue. If the spur is full, JMRI won't route any cars for that spur onto the layout. If it is deselected, JMRI can move cars towards the spur, holding at the nearest yard (our off-spot tracks in this case). I went back and deselected the second option for each spur. I also deselected the first option, but it doesn't appear to have any effect in this case.
Now we can run some more trains. It's looking better now, as cars are being routed to the West tail track when the spur is full. However, now they get stranded there. They have the correct final destination but the train isn't moving the cars from the tail track to the customer spot. Now what? Since it appears to be something with the train itself, let's have a look at the build options.
I originally had "Send all car pick-ups to terminal" selected, thinking this was correct since all cars should go back to staging and storage. It appears that JMRI considers a move to be a pick up and then a set out. Since cars on the off-spot need to be picked up, but they don't have a final destination that matches the staging track, the train ignores them. Make sure this is deselected for the OP Turn train so that the train can make local pick ups and set outs between the yard track and destination spur. This setting can be left selected for the trains between storage and staging since they are "through trains" between storage and staging.
With that issue fixed, let's build some more trains.
Success!
After building a whole bunch of trains, we see that it's finally doing what we want. Cars are being moved between storage and the layout through staging. No cars are being left in staging at all. Some cars are being left at the off-spot locations when the spur is full, and they are being moved to the spur when space is available. Looking at the Hits fields in the schedules, we see that the moves distribution is roughly evenly distributed between the different loads for each type.
Further Enhancements
At this point, we have all of the desired basic functionality for car movements. From here we can run more trains to get a better picture of how cars are being moved. We can tinker with the schedules and routes to alter the number of cars moved during each session. We can change how long cars are left before being picked up. We can change how often certain loads show up.
Use the random setting for the Storage to Staging route to alter how many cars will come onto the layout each session. The Random value is a percentage that specifies how many cars the train can be reduced. In this case, 50 means up to 50 percent reduction, so my trains may have 3, 4, 5, or 6 cars leaving storage. To allow more than 6 cars occasionally, bump up the Moves values and use in conjunction with the Random value.
Cautions: Ensure your arrival moves is at least as big as your departure moves, the train size is only as big as the smallest Moves value. I recommend only setting the Random value for the entry coming out of storage. If a random value is set anywhere else, you may end up with cars left at Staging. Ensure the Moves value for subsequent routes is at least as big as the last Moves value on the current route. (If this train brings up to 6 cars onto staging, ensure the OP Turn starts with at least 6 cars from staging, etc.)
Use the Wait field in the Schedules to control how many sessions a car remains at an industry before it changes to empty and can be picked up. Each time JMRI builds a train that can service that spur, the Wait count is decremented and when it becomes 0, the car is available for pick up. In this case, I have set the schedule so that 4-bay hoppers require two sessions to unload, and 3-bay hoppers require 1 session to unload.
Another option is to create multiple entries for the same car type and load, but specify different Wait times and set a Random value.
Here we have three different entries for the Latex tank cars. For each car that arrives on the siding, JMRI will try to match against the row containing the current pointer, and will continue to move the pointer to the next one until a match is made. In this case, when the pointer is on the first row, there's a 50 percent chance that the car will wait for 1 session. If no match, the pointer is moved to the second row where there's a 25 percent chance that the car will wait for 2 sessions. If no match, the pointer is moved to the last row where the car will be picked up at the next session.
Conclusion
Thanks for following along with this JMRI learning experience. I hope you find some useful tips from this and other examples. If you haven't considered exploring computer-based operations, I hope this provides some inspiration to jump in and start playing with it.
As I continue building my layout, I'll be playing with this example further. There are new aspects to explore that I haven't discovered yet. In particular, I'd like to explore using a tablet and the built-in web server for electronic switch lists (the Conductor feature of the operation).
As always, comments or suggestions are always welcome!
Craig