Wednesday, August 14, 2019

Portable freight management program

 Introduction

Whilst clearing out the cupboard under the stairs, I came across an old laptop bag I had used about twenty years ago. Tucked into one of the pockets was my old and trusty Psion 3a palmtop computer. I took out the leaky AA batteries and inserted a couple of new ones, only to find it worked perfectly.

The backup battery had long-since run out and so there was no evidence of my past life in the computer's memory but I remembered what a joy the Psion had been to use and how it included a reasonably powerful and highly accessible programming language (OPL) for creating your own apps. I decided to investigate whether I could program it with a version of my freight handling program. (see My Freight Handling Computer Program). Well, after dusting off my old OPL programming skills I'm pleased to report I now have a fully functioning portable freight management device which saves me having to fire up the laptop and print out hard copies of goods traffic manifests for each running session.

For those unfamiliar with Psion Series 3 computers, they were clamshell devices developed in the early 1990s with a small LCD screen and a rubberised keyboard. In addition to the programming language; a database, word processor, spreadsheet, calculator, agenda and alarm clock were included as standard. For the time, their onboard memory capacities (eg 128k, 1Mb, 2Mb) were reasonably substantial with expansion slots for memory cards and additional software packs.

My Psion 3a has 1Mb of memory capacity which is more than adequate to run the freight handling program. I also have a couple of 512k memory cards which means I can back-up the database and program - just in case!

The wagons database

I like to keep things simple and so the database for the wagons has only the following fields:
  • Number - The number of the record, rather than the number of the wagon
  • Description - A description of the wagon (max 40 characters)
  • Wagon ID - A unique identifier for the wagon (eg OP8 = Open wagon #8)
  • Type - The type of wagon. This ise used to determine the possible destinations it might have.
  • Location - The present location of the wagon on the railway
Here we can see the entry for Open Wagon No. 9 - which is presently located at Bickerton station (BN)

 And here we have the entry for wagon number 43, a flat wagon with tractor load, presently located at Peckforton Station (PK).

It's very easy to set up a database on the Psion and to search for and amend entries. Accessing and updating database records is also relatively easily accomplished within the programming environment.

The structure of the main program

I decided on three main components for the structure of the main freight handling program; a menu, a procedure for generating the freight traffic and a procedure for managing wagons at each station on my railway.

The Main Menu


The top half of the menu provides access to four utility procedures (see below), while the lower half invites me to create either a Pickup Goods or a Mixed train. Pressing either P or M on the keyboard takes me to the Freight Train Generator procedure.

The Freight Train Generator

This procedure uses a simple set of parameters to decide which wagons need to be moved where on the system.

There are five stations on my railway, plus the Copper Mine, to and from which wagons can be sent. Beeston Market is the main station on the railway - the interchange with the main line railway and hence the rest of the world. All wagons travel to and from this station at some point. Coal wagons are loaded up at Beeston Market before being despatched to any of the four other stations. A livestock market is also located at Beeston Market and so cattle wagons, sheep wagons and any other agricultural-related wagon loads will need to travel to and from the station.

There is a brewery at Beeston Castle station and so wagon loads of barrels, together with malt and hops are sent to this station, while barrels of beer are delivered from Beeston Castle to any other station on the system - all the communities served by the railway have pubs.

At Peckforton, there is a sawmill and also a flour mill.

Local fruit farms use Bulkeley station and so a regular supply of closed vans is needed to transport this cargo at peak periods during the year.

In addition to despatching copper ore and spoil, the Copper Mine needs regular supplies of fuel oil, pit props and explosives.

General merchandise such as building materials, groceries, fuel oil, coal and special deliveries are transported up and down the line.

The freight generation procedure picks wagons at random from the database and then decides where they should be sent, based on the above criteria for goods traffic requirements. Once a possible train has been generated, it is presented:

I can then decide to accept this train or generate an alternative .....

.... until I am happy with what is on offer.

Once accepted I am then taken to the next procedure where the freight movements can be managed station, by station.

The Stations Procedure

Let's assume, the pickup goods will be starting from Beeston Market. Pressing the 'M' key on the menu screen ..

.... allows me to see which wagons will be departing from or arriving at the station via the Pickup Goods train.

This enables me to see which wagons need to be marshalled into the train - in this case, Van 3 and the bolster wagons to be sent to Peckforton, and Open Wagon 3 and cattle wagon 2 to be sent down the line to Beeston Castle.

Once the train has been made up, when it reaches Peckforton, for instance, I can then see what needs to be received and despatched from this station.

Pressing the relevant key on the keyboard allows me to show that any particular wagon has been delivered to the station successfully (signified by the wagon code being replaced with OK).

This updates the database, shifting the relevant wagons to their new location.

On return to Beeston Market, if everything has gone according to plan, all the wagons to and from the station will be shown as delivered and the whole process can start over again.

The Utilities Procedures

The four utilities procedures accessible from the main menu allow for blanket manipulation of the records in the database.

Sort

As the name suggests, this procedure sorts the records in the database into numerical order based on the record number field. As each wagon is moved to a new location, its record is appended to the end of the database and so, after a while, the records become jumbled. This makes it easier to browse through the records in the database app.

Reset

This resets the location of every wagon (apart from those Out of Service), to the main station (Beeston Market). This is useful at the start of the season thus enabling the system to start from scratch.

List

This procedure presents a list of all the wagons on the railway showing their present location.

This is useful at the start of a session to make sure each wagon has been correctly positioned before freight operations commence.

Randomise

This procedure randomises the locations of the wagons, based on the criteria set out above. This procedure will prove useful at the start of a season or on occasions when I fancy a change.

Conclusion

OK - so my Psion computer is not what you'd call 'state of the art', but it is functional and pocket-sized. It does the required job and as the programming language is easily accessible I can modify and extend the program in the future if necessary. For example, I'm thinking of adding a 'Specials' option to the freight train management procedure to generate movements for special trains such as the Market Day Special and a Fruit Pickers Special. For now, however, I am happy with the sort of freight movements which the program throws up and the way if offers me the facility to change things on the fly.

I have noticed that Psion palmtops such as my 3a can be bought on eBay for as little as £20 (20GBP) and so, if you wanted to follow in my footsteps, it is possible. I'd be happy to share the code if only I could discover a way of interfacing my old RS232 lead with my USB equipped laptop. I have tried, but with only limited success.

If I was more experienced with programming apps for phones etc., I might consider writing an Android version, but I struggle to see the screen of my mobile phone when out in the garden and so I'm not convinced it would be any more sophisticated than I have produced on my Psion.


Saturday, July 13, 2019

Bluetooth phone app loco control Part 4 - Adding sound


Contents

 

Preamble

In the previous stages of my investigations into controlling a loco using a Bluetooth phone app you will see that -
  • .....  I started off by using a freebie app and its associated code provided by Steve Massiker at arduinorailwaycontrol.com (see Part 1)
  • .... I then tinkered with the default speed settings to try and improve the way the loco responded at slow speeds (see Part 2)
  • ...... I moved on to explore the potential of a different phone app (RoboRemoFree) as this enabled me to have 255 speed steps rather than the nine speed steps offered by Steve's set-up (see Part 3)
In this part of my investigations, I will describe how I added a set of digitised sound files to be (sort of) synchronised with the speed of the loco.

Introduction

Arduino is an Open Source development, which means the resources are made freely available for anyone to explore and further enhance. As a consequence, over the years, numerous add-ons have been developed which enable the basic micro-controller boards to be extended. In the first parts of my explorations, a motor driver and a Bluetooth transceiver were added. In this section, I have added another module - a small SD card player which can be controlled by the Arduino board.
The DFPlayer Mini not only interfaces with the Arduino, it also includes an audio amplifier enabling it to be connected directly to a speaker to provide up to 2 watts of output. Its small size (20 x 20 x 10mm) makes it ideal for squeezing into the insides of a battery powere loco. I bought mine from a UK supplier for £3.50, but they can be bought directly from China or Hong Kong for less the £1.00.

To control the DFPlayer, I downloaded a library of instructions from the GitHub website and installed them in the Arduino IDE program.

The procedure for installing the library I followed was:
 
  1. Visit the GitHub website and click the Download button
  2. Remember where I saved the downloaded ZIP file
  3. Open the Arduino IDE program
  4. Click the 'Sketch' menu item and select Include Library and then Add ZIP. library
  5. Navigate to where I saved the ZIP file
  6. Open it
  7. The library is now installed. When selecting the Include Library option once more, the new library should appear the the bottom of the list of installed libraries.

Before editing the code, I needed to wire up the Player, motor driver and Bluetooth transceiver to the Nano, so I would know to which pins they were connected.

The wiring

I needed to change the existing  wiring (see Part 3) to add the Player to the Nano. The Player and the Bluetooth transceiver are both serial communication devices and only one serial device can normally be added to the Nano. However, it is possible to add another serial device by using the port used by the Nano to communicate with the computer. In addition, the library which I had just installed required the Player to be connected to pins D8 and D9 and so, the motor driver needed to be connected to another pin which could provide PWM output.

You will notice when comparing this wiring diagram with that used previously, that I made a series of other changes as well.

  • I removed the voltage regulator. The L298N motor driver can supply 5 volts (provided its input does not exceed 12 volts) and so this was tapped to power the Player, the Nano and the HC-06 transceiver.
  • I kept the control pins for the motor driver the same (D5 and D6) but moved the PWM input to pin D3.
  • The serial connections for the DFPlayer were attached to pins D8 and D9.
  • The TX and RX connections for the HC-06 were attached to Pins D1 and D0 via a plug and socket so the transceiver could be disconnected when the Nano was connected to the computer.
  • A 3mm white LED was connected to Pin D12 via a 220ohm resistor for a front light.

The Sound files

I prepared twelve sound files:
  • 001 - Silence (1 min)
  • 002 - Silence plus horn sound (2.5 seconds)
  • 003 - engine start-up to idle (7 seconds)
  • 004 - idle (15 secs)
  • 005 - idle plus horn (2.5 seconds)
  • 006 - slow run (15 secs)
  • 007 - slow run plus horn (2.5 secs)
  • 008 - mid run (15 secs)
  • 009 - mid run plus horn (4 secs)
  • 010 - fast run (15 secs)
  • 011 - fast run plus horn (2.5 secs)
  • 012 - shut down (7 secs)
It's not essential to have the numbers at the start of each file name, but it is essential that the files are saved on the SD card in the correct order. When the Arduino executes the command to play, for example, file 3, it will play the third file stored on the card. Putting the numbers in front of the file names helps ensure they are in the correct order before they are copied and pasted from the computer to the card.

I downloaded several sound clips from the internet until eventually homing in on some clips of an old tractor on the SoundSnap website. Although it cost me $15 to buy five sound clips (only three of which I used), I had been unable to track down anything which gave me the range of sounds I wanted. I figured that there was not a lot of difference between the sounds made by a tractor and a narrow gauge diesel locomotive - though no doubt some purists will disagree!

The clips were edited using Audacity - wonderful free program which enabled me to select and save sections from the downloaded sound files and also superimpose the sound of the horn over the sound of the engine noise, and adjust the volume of the two so one wasn't drowned out by the other.

The edited files were exported as 16-bit WAVs, which means they play immediately they are called up by the Arduino code. On other players with MP3 files, I have found there can be a silent gap of up to a second between tracks or when one track loops around.

For more information on using Audacity to edit sound effect files see - How I edited sound files for my railbus

Unfortunately, as the files I used were edited from paid-for originals, I cannot provide them here so I am afraid you will have to do your own tracking-down of files (or also pay for the ones I used)

The RoboRemo App

As I wanted more than five controls on the screen of the app, I had to abandon the free version of RoboRemo and invest in the paid-for Bluetooth version - at a cost of £2.89.

I set up five buttons and one slider:

The actions for the buttons were (without the quote marks):
  • Reverse - 'r'
  • Forward - 'f'
  • STOP - 'x'
  • Horn - 'h'
  • Engine start/stop - 'e'
The slider was given an id of 's' and the scale (min, max) set from 30 to 255.

The code

As previously, the entire code is shown here first followed by a break-down of each section explaining its function. This should enable you to copy and paste the code into Arduino IDE if you want to follow in my footsteps

 //Train control using RoboRemo  
 //Slider on app has id of 's' and range of 40 to 255  
 //Forward button on app has action 'f'  
 //Reverse button on app has action 'b'  
 //STOP button on app has action 'x'  
 #include <softwareserial .h="">  
 #include <DFPlayerMini_Fast.h>  
 // SOFTWARE SERIAL  
 SoftwareSerial mySerial(10, 11); // RX, TX for SD player  
 DFPlayerMini_Fast myMP3; // Initialising SD Player  
 //Pin connections  
 int motorSpeedPin = 3;  
 #define IN1 6 //motor Fwd   
 #define IN2 5 //motor Reverse  
 #define fwdLED 12 //Front facing LED pin  
 #define revLED 13 //Rear facing LED pin  
 // VARIABLES //  
 int val = 0; //Speed  
 int oldval = 0; //Previous speed  
 int Track = 1; // which track is playing  
 char cmd[100]; //Command from app  
 int cmdIndex;  //Used to index character in the command  
 int loSound = 80; // Speed setting between idle and slow run sounds  
 int midSound = 120; // Speed setting for slow to mid run sounds  
 int hiSound = 170; // Speed setting for mid to high speed run sounds  
 void setup() {  
 // Initializing Serial (Hardware and Software Serial)  
  Serial.begin(9600);  
  mySerial.begin(9600);  
  myMP3.begin(mySerial);  
  myMP3.volume(30); //Volume setting  
  myMP3.loop(1); //Loops first (silent) sound track  
 // Initialising Motor-Driver  
  pinMode(motorSpeedPin, OUTPUT);   
  pinMode(IN1, OUTPUT);   
  pinMode(IN2, OUTPUT);  
  analogWrite(motorSpeedPin, 0);  
 // Initialising LED pins  
  pinMode(fwdLED, OUTPUT);  
  pinMode(revLED, OUTPUT);  
  digitalWrite(fwdLED, HIGH); //Turns on front LED as indicator that loco is switched on  
 }  
 void loop() {  
 // ---- Intrepreting app commands  
  if(Serial.available()) {  
   char c = (char)Serial.read();  
   if(c=='\n') {  
    cmd[cmdIndex] = 0;  
    exeCmd(); // execute the command  
    cmdIndex = 0; // reset the cmdIndex  
   } else {     
    cmd[cmdIndex] = c;  
    if(cmdIndex<99) cmdIndex++;  
   }  
  }   
 }  
 //// FUNCTIONS ////  
 void exeCmd() {  
  if(cmd[0]=='s') {  
   oldval = val;  
   val = 0;  
   for(int i=2; cmd[i]!=0; i++) { // number begins at 2  
    val = val*10 + (cmd[i]-'0'); // if cmd is "speed 100", val will be 100  
    }  
   }  
    if(val<loSound-10) val=0; //Sets speed to zero to stop motor buzz on default PWM setting  
    // Direction and Stop  
    if (cmd[0] =='f') { // (f) Forward  
    digitalWrite(IN1, HIGH);  
    digitalWrite(IN2, LOW);  
    digitalWrite(fwdLED, HIGH);  
    digitalWrite(revLED, LOW);  
    }  
    if (cmd[0] =='b') { // (b) Backward  
     digitalWrite(IN1, LOW);  
     digitalWrite(IN2, HIGH);  
     digitalWrite(fwdLED, LOW);  
     digitalWrite(revLED, HIGH);  
     }  
     if (cmd[0] =='x') { // (x) Stop button  
      digitalWrite(IN1, LOW);  
      digitalWrite(IN2, LOW);  
      digitalWrite(fwdLED, LOW);  
      digitalWrite(revLED, LOW);  
      myMP3.loop(1);  
      Track = 1;  
      val = 0;  
      oldval = 0;  
     }  
     analogWrite(motorSpeedPin, val); // Throttle  
 //Playing the SD card tracks  
 //There are twelve tracks on the SD card  
 //001 - Silence (1 min)  
 //002 - Silence plus horn sound (2 seconds)  
 //003 - engine start-up to idle (15 seconds)  
 //004 - idle (15 secs)  
 //005 - idle plus horn (2.5 seconds)  
 //006 - slow run (15 secs)  
 //007 - slow run plus horn (2.5 secs)  
 //008 - mid run (15 secs)  
 //009 - mid run plus horn (4 secs)  
 //010 - fast run (15 secs)  
 //011 - fast run plus horn (2.5 secs)  
 //010 - shut down (3 secs)  
     if(cmd[0]=='e' && Track==1){  
     myMP3.play(3);  
     delay(10000);   
     myMP3.loop(4);//Play 'engine start-up' and then on to 'idle' (Track 4)  
     Track = 4;  
     cmd[0]='n';  
     }  
     if(cmd[0]=='e' && Track==4){  
     myMP3.play(12);  
     delay(7000);  
     myMP3.loop(1);//Play 'engine shut down' then on to silence (Track 1)  
     Track = 1;  
     cmd[0]='n';  
     }  
     if(cmd[0]=='h' && (Track==1 || Track==4 || Track==6 || Track==8 || Track==10)) {  
      myMP3.play(Track + 1); //Play relevant horn track  
      delay(3000);  
      myMP3.loop(Track);      
     }  
     if(Track==4 && val>loSound){  
     myMP3.loop(6);  
     Track = 6;  
     }  
     if(Track==6 && val<loSound){  
     myMP3.loop(4);  
     Track = 4;  
     }  
     if(Track==6 && val>midSound){  
     myMP3.loop(8);  
     Track=8;  
     }  
     if(Track==8 && val<midSound){  
     myMP3.loop(6);  
     Track=6;  
     }  
     if(Track==8 && val>hiSound){  
     myMP3.loop(10);  
     Track=10;  
     }  
     if(Track==10 && val<hiSound){  
     myMP3.loop(8);  
     Track=8;  
     }  
 }  

NOTE: 

Check that the symbols are showing up correctly in the code - some browsers change them.

For example the last part of the code should look like this

How it works


The first section sets up the serial connection and opens the library for the DFPlayer

 #include <SoftwareSerial.h>  
 #include <DFPlayerMini_Fast.h>  
 // SOFTWARE SERIAL  
 SoftwareSerial mySerial(10, 11); // RX, TX for SD player  
 DFPlayerMini_Fast myMP3; // Initialising SD Player  

The next section sets up the pins for the various devices. Note: Because the Bluetooth transceiver is using the Hardware Serial port, it does not need to be initialised.

 //Pin connections  
 int motorSpeedPin = 3;  
 #define IN1 6 //motor Fwd   
 #define IN2 5 //motor Reverse  
 #define fwdLED 12 //Front facing LED pin  
 #define revLED 13 //Rear facing LED pin  

The next chunk of code sets-up the variables used in the program:

 // VARIABLES //  
 int val = 0; //Speed  
 int oldval = 0; //Previous speed  
 int Track = 1; // which track is playing  
 char cmd[100]; //Command from app  
 int cmdIndex;  //Used to index character in the command  
 int loSound = 80; // Speed setting between idle and slow run sounds  
 int midSound = 120; // Speed setting for slow to mid run sounds  
 int hiSound = 170; // Speed setting for mid to high speed run sounds  

Hopefully the comments (signified with a prefix of //) make them self explanatory.

The setup section of the program is very similar to that used in Part 3, with a couple of slight amendments:

 void setup() {  
 // Initializing Serial (Hardware and Software Serial)  
  Serial.begin(9600);  
  mySerial.begin(9600);  
  myMP3.begin(mySerial);  
  myMP3.volume(30); //Volume setting  
  myMP3.loop(1); //Loops first (silent) sound track  
 // Initialising Motor-Driver  
  pinMode(motorSpeedPin, OUTPUT);   
  pinMode(IN1, OUTPUT);   
  pinMode(IN2, OUTPUT);  
  analogWrite(motorSpeedPin, 0);  
 // Initialising LED pins  
  pinMode(fwdLED, OUTPUT);  
  pinMode(revLED, OUTPUT);  
  digitalWrite(fwdLED, HIGH); //Turns on front LED as indicator that loco is switched on  
 }  

The initialisation of the serial connections is slightly different as the Bluetooth module is connected to the Hardware Serial port and so is initialised with Serial.begin(9600) which sets up the baud rate for the communication. Similarly, the baud rate for the player is also set at 9600.

The final command turns on the front LED. I found this useful when testing the loco, to check that the Arduino board was switched on and functioning as expected.

The main loop is exactly the same as in Part 3. This parses the information sent by the app which arrives as a series of individual characters, and then when the terminal character for each string is receiver ('/n'), puts the characters together as a string.

 void loop() {  
 // ---- Intrepreting app commands  
  if(Serial.available()) {  
   char c = (char)Serial.read();  
   if(c=='\n') {  
    cmd[cmdIndex] = 0;  
    exeCmd(); // execute the command  
    cmdIndex = 0; // reset the cmdIndex  
   } else {     
    cmd[cmdIndex] = c;  
    if(cmdIndex<99) cmdIndex++;  
   }  
  }   
 }  

There is only one function (exeCmd), the first part of which was explained in Part 3.

 //// FUNCTIONS ////  
 void exeCmd() {  
  if(cmd[0]=='s') {  
   oldval = val;  
   val = 0;  
   for(int i=2; cmd[i]!=0; i++) { // number begins at 2  
    val = val*10 + (cmd[i]-'0'); // if cmd is "speed 100", val will be 100  
    }  
   }  
The next statement is new:

    if(val<loSound-10) val=0; //Sets speed to zero to stop motor buzz on default PWM setting  

I find that the motor buzzes because the default PWM setting (490Hz) is quite low. So when stationary, I turn off the motor to stop it from buzzing. I am in the process of playing around with the PWM settings and intend to increase the setting to help prevent excess noise from the motor.

The next section is almost as it was in Part 3.

    // Direction and Stop  
    if (cmd[0] =='f') { // (f) Forward  
    digitalWrite(IN1, HIGH);  
    digitalWrite(IN2, LOW);  
    digitalWrite(fwdLED, HIGH);  
    digitalWrite(revLED, LOW);  
    }  
    if (cmd[0] =='b') { // (b) Backward  
     digitalWrite(IN1, LOW);  
     digitalWrite(IN2, HIGH);  
     digitalWrite(fwdLED, LOW);  
     digitalWrite(revLED, HIGH);  
     }  
     if (cmd[0] =='x') { // (x) Stop button  
      digitalWrite(IN1, LOW);  
      digitalWrite(IN2, LOW);  
      digitalWrite(fwdLED, LOW);  
      digitalWrite(revLED, LOW);  
      myMP3.loop(1);  
      Track = 1;  
      val = 0;  
      oldval = 0;  
     }  
     analogWrite(motorSpeedPin, val); // Throttle  

The main differences are that in each sub section, there are commands to control the forward and reverse LED lights - turning them on (by setting the output to HIGH) or turning them off (by setting the output to LOW).

In addition, at the end of the STOP sub-section, in addition to turning off both LEDs and setting the speed (val) to zero, the player is instructed to play the first track (silence).

The final section of the Function, controls the SD player.The first part of this section controls what happens if the 'e' instruction is received from the Bluetooth app (ie when the Engine Start/Stop button is pressed).

      if(cmd[0]=='e' && Track==1){  
     myMP3.play(3);  
     delay(10000);   
     myMP3.loop(4);//Play 'engine start-up' and then on to 'idle' (Track 4)  
     Track = 4;  
     cmd[0]='n';  
     }  
     if(cmd[0]=='e' && Track==4){  
     myMP3.play(12);  
     delay(7000);  
     myMP3.loop(1);//Play 'engine shut down' then on to silence (Track 1)  
     Track = 1;  
     cmd[0]='n';  
     }  

The first 'if' statement checks whether the player is playing Track 1 (ie silence). If so it will play Track 3 (engine start-up) for seven seconds and then move on play the sound of the engine idling (ie track 4).

The second 'if' statement, checks whether Track 4 is playing (ie the idling sound). If so, it will play the engine shot-down track (Track 12) for seven seconds and then play silence (Track 1).

The next 'if' statement, detects whether the horn button has been pressed on the app. If so, it then checks which track is playing and plays the track following it - for example, if Track 6 (slow run) is playing, it will play track 7 for 3 seconds before returning to play Track 6.


     if(cmd[0]=='h' && (Track==1 || Track==4 || Track==6 || Track==8 || Track==10)) {  
      myMP3.play(Track + 1); //Play relevant horn track  
      delay(3000);  
      myMP3.loop(Track);      
     }  

Finally, the last set of  'if' statements change the track which is playing, dependent on the speed of the motor.


     if(Track==4 && val>loSound){  
     myMP3.loop(6);  
     Track = 6;  
     }  
     if(Track==6 && val<loSound){  
     myMP3.loop(4);  
     Track = 4;  
     }  
     if(Track==6 && val>midSound){  
     myMP3.loop(8);  
     Track=8;  
     }  
     if(Track==8 && val<midSound){  
     myMP3.loop(6);  
     Track=6;  
     }  
     if(Track==8 && val>hiSound){  
     myMP3.loop(10);  
     Track=10;  
     }  
     if(Track==10 && val<hiSound){  
     myMP3.loop(8);  
     Track=8;  
     }  
 }  

As you can see, if one of the trigger values for speed which were set at the beginning of the program is reached, it checks which track is playing and either moves up or down to the next relevant track.


Conclusion

Of source, it is not perfect. In an ideal world, the pitch and speed at which the sound of the engine is played would vary in proportion to the speed of the locomotive. This is not achievable when the sounds are tracks on an SD player. I did try playing a track which accelerated or decelerated the sound as the tracks changed, but this proved impossible to work reliably. Like the horn or the engine start/stop tracks, the Arduino was unable to do something else and, as these tracks were triggered by a speed change, it was unable to detect the new speed until the track finished playing - which either led to some very jerky running or completely confused the system as to which track ought to be playing. If someone with more programming knowledge than me is able to sort out this conundrum I will be very grateful.

In the meantime, I am quite pleased with the outcome. 


It took me several tries until I got the relative speeds of the sounds matched to the speed of the loco without making the jump from one track to the next too noticeable. If I had more time and more patience, I could add several more speed triggers and more tracks to make the increases and decreases in engine sound less noticeable - but I'll leave that to someone else.

Controlling a loco with Arduino and a Bluetooth phone app - Part 3 - Speed control

Contents


Introduction

In Part 1 provided background information on Ardiuno and Bluetooth and used a freebie phone app provided by Steve Massikker at arduinorailwaycontrol.com, installing Arduino components following his recommendations. In Part 2, I modified his coding for the Arduino microcontroller to tailor the speed settings to better suit my needs for more precise slow movement. However, I was finding the nine speed steps inherent in Steve's code to be a bit restrictive and so I did some further research and came across an app which allowed me to create my own controller by placing buttons, sliders and other features on the screen to communicate with a Bluetooth enabled device. More significantly, the code provided on the app's website showed how the output from a slider could be turned into a number from 0 to 255 - potentially offering up to 255 speed steps. This app is called RoboRemo. I downloaded the free version - RoboRemoFree.

The wiring

I used the same wiring as I described in Part 1. But I'll repeat it here to save having to switch between pages.
The voltage regulator was set to 5 volts. I have since discovered that the 5v terminal on the L298N motor driver can be used to provide the Nano with 5v and so the voltage regulator can be dispensed with (See Part 4 - pending)

The Train Control App

Firstly, I design my own app using RoboRemoFree. This used three buttons and a slider.
  • The slider controls speed, with its 'id' set to 's' and its min value set to 40 and max value set to 255.
  • One button instructs the loco to move forward and has an 'action' of 'f'
  • Another button instructs the loco to move in reverse and has an action of 'b'
  • The final button is the emergency stop button and has an action of 'x'

For more information about setting up RoboRemo see their website https://www.roboremo.com/
Their video tutorial on the homepage is very clear and understandable.

Coding for more precise speed settings

The complete code for controlling the loco with Ardiuino is shown below. However, I've also broken the code into chunks and explained how it works in case you want to make some changes to it - otherwise, just copy and paste the complete code into Arduino IDE on your computer and then upload it to your Arduino Nano.

 #include <SoftwareSerial.h>  
 #define bluetooth Serial  
 // SOFTWARE SERIAL  
 SoftwareSerial Bluetooth(12, 13); // RX, TX  
   
 // VARIABLES //9  
 #define L298_IN1 6  
 #define L298_IN2 5  
 int motorSpeedPin = 0; // pin 9 (PWM) to contorl motor speed  
   
 char cmd[100];  
 int cmdIndex;  
 int val;  
   
 void setup() {  
   
  delay(500); // wait for bluetooth module to start  
   
  bluetooth.begin(115200); // Bluetooth default baud is 115200  
  bluetooth.print("$");  
  bluetooth.print("$");  
  bluetooth.print("$");  
  delay(250);  
  bluetooth.println("U,9600,N");  
   
  Serial.begin(9600);  
  bluetooth.begin(9600);  
    
  pinMode(motorSpeedPin, OUTPUT);  
  pinMode(L298_IN1, OUTPUT);  
  pinMode(L298_IN2, OUTPUT);    
  analogWrite(motorSpeedPin, 0);  
  cmdIndex = 0;  
 }  
   
   
 void loop() {  
  if(bluetooth.available()) {  
   char c = (char)bluetooth.read();  
   if(c=='\n') {  
    cmd[cmdIndex] = 0;  
    exeCmd(); // execute the command  
    cmdIndex = 0; // reset the cmdIndex  
   } else {     
    cmd[cmdIndex] = c;  
    if(cmdIndex<99) cmdIndex++;  
   }  
  }   
 }  
   
 void exeCmd() {  
   
    
  if( cmd[0]=='s')  
  {   
     val = 0;  
     for(int i=2; cmd[i]!=0; i++) { // number begins at cmd[6]  
      val = val*10 + (cmd[i]-'0'); // if cmd is "speed 100", val will be 100   
     }  
  }  
    // Direction and Stop  
     if (cmd[0] =='f') { // (f) Forward  
      delay (200);  
      digitalWrite(L298_IN1, HIGH);  
      digitalWrite(L298_IN2, LOW);  
     }  
     if (cmd[0] =='b') { // (r) Reverse  
      delay (200);  
      digitalWrite(L298_IN1, LOW);  
      digitalWrite(L298_IN2, HIGH);  
     }  
     if (cmd[0] =='x') { // (x) Stop button  
      delay (200);  
      digitalWrite(L298_IN1, LOW);  
      digitalWrite(L298_IN2, LOW);       
      val = 0;  
     }   
       
     analogWrite(motorSpeedPin, val);  
    
 }  


How the code works

The first section initialises the serial connection needed for the Bluetooth transceiver (HC-06).

 #include <SoftwareSerial.h>  
 #define bluetooth Serial  
 // SOFTWARE SERIAL  
 SoftwareSerial Bluetooth(12, 13); // RX, TX  

The next section of the code sets up the global variables which will be used in the main part of the program.

 // VARIABLES //9  
 #define L298_IN1 6  
 #define L298_IN2 5  
 int motorSpeedPin = 0; // pin 9 (PWM) to contorl motor speed  
 char cmd[100];  
 int cmdIndex;  
 int val;  

The first three variables identify the pins which will be used to send instructions to the motor driver (L298N). Pin 6 is the connection for the Forward instruction, Pin 5 is the connection for the Reverse instruction and Pin 9 is the pin which controls the speed of the motor.

The two cmd variables are used to interpret the signal from the Bluetooth app. The signal is sent as a series of characters (rather than numbers) and so the first variable (cmd[100]) sets up an array of 100 characters just in case..... while the next variable (cmdIndex) determines the position of the character in the array which is being studied (0 is the position of the first character and 99 the position of the last one). The last variable (val) is the speed instruction sent to the motor (via Pin 9). 

The next section sets-up the program. This section, as with the section above, is only interpreted once when the program starts running on the Nano. The first part sets up the parameters for the Bluetooth module to start communicating

 void setup() {  
  delay(500); // wait for bluetooth module to start  
  bluetooth.begin(115200); // Bluetooth default baud is 115200  
  bluetooth.print("$");  
  bluetooth.print("$");  
  bluetooth.print("$");  
  delay(250);  
  bluetooth.println("U,9600,N");  
  Serial.begin(9600);  
  bluetooth.begin(9600);  

The next part instructs the Nano to set the pins communicating with the motor driver as outputs. The analogWrite command sets the speed of the motor to zero - it's not an essential instruction but better to be safe than sorry! Similarly, the cmdIndex variable is also set to zero - ready to read the first character in the first signal from the Bluetooth transceiver.

 pinMode(motorSpeedPin, OUTPUT);  
  pinMode(L298_IN1, OUTPUT);  
  pinMode(L298_IN2, OUTPUT);    
  analogWrite(motorSpeedPin, 0);  
  cmdIndex = 0;  
 }  

Now comes the interesting bit. This is main part of the program which continuously loops around while the Nano is switched-on.

 void loop() {  
  if(bluetooth.available()) {  
   char c = (char)bluetooth.read();  
   if(c=='\n') {  
    cmd[cmdIndex] = 0;  
    exeCmd(); // execute the command  
    cmdIndex = 0; // reset the cmdIndex  
   } else {     
    cmd[cmdIndex] = c;  
    if(cmdIndex<99) cmdIndex++;  
   }  
  }   
 }  

Firstly it checks to see if anything is being sent from the app. If there is something, it checks to see if the message is complete - every time a button is pressed or the slider is moved, it sends the character determined by the 'action' or the 'id' together with a number showing the position of the slider, followed by the character '\n' to show the message has finished.

The program adds each new character it receives to the cmd[100] array, cmdIndex is incremented by 1 each time (with cmdIndex++). Once the terminator character '\n' is received it calls up the exeCmd sub-routine.

The Execute Command sub-routine (exeCmd) does the hard work of controlling the loco. The sub-routine firstly checks if the message from the app is from the slider by seeing if the first character is 's'. If so, it then turns the string of characters which follow into a number - multiplying what's already stored in variable 'val' by ten as each new number is added. Hence for example, three individual characters  '1', '4' and '3' are turned into one hundred and forty three (143). It's a clever little routine for which I can take no credit - I pinched it from the RoboRemo website!

 void exeCmd() {  
  if( cmd[0]=='s')  
  {   
     val = 0;  
     for(int i=2; cmd[i]!=0; i++) { // number begins at cmd[6]  
      val = val*10 + (cmd[i]-'0'); // if cmd is "speed 100", val will be 100   
     }  
  }  

The next part of the sub-routine sets the value for the output pins determining the direction of the motor to HIGH or LOW, dependent on which direction button has been pressed on the app. If the STOP button is pressed, the direction outputs are both set to LOW, so the motor turns in neither direction.

    // Direction and Stop  
     if (cmd[0] =='f') { // (f) Forward  
      delay (200);  
      digitalWrite(L298_IN1, HIGH);  
      digitalWrite(L298_IN2, LOW);  
     }  
     if (cmd[0] =='b') { // (r) Reverse  
      delay (200);  
      digitalWrite(L298_IN1, LOW);  
      digitalWrite(L298_IN2, HIGH);  
     }  
     if (cmd[0] =='x') { // (x) Stop button  
      delay (200);  
      digitalWrite(L298_IN1, LOW);  
      digitalWrite(L298_IN2, LOW);       
      val = 0;  
     }   

The very last instruction sends the speed setting stored in the variable 'val' to the motor driver.

    analogWrite(motorSpeedPin, val);  
 }  

 Conclusion

So, what impact did this have?


As can be seen, the level of control on the loco is a lot more precise and there are no sharp changes in speed as the slider is moved up and down.

My next experiments will explore adding sound to the loco through the use of a small SD card player module - for more information see Part 4.

Controlling a loco with a Bluetooth phone app and Arduino - Part 2

Introduction

Having tried a simple approach to controlling a loco with a Bluetooth app and Arduino, I felt the need ArduinoRailwayControl.com could be modified. What I needed was more precise control at slower speeds for shunting at the sacrifice of losing more precision when running faster. This involved changing the code uploaded to the Arduino Nano board.
to develop the system further to improve the way the loco responded at slow speeds. As my knowledge and skills do not extend as far as writing my own apps, I decided to explore ways in which the nine step output from the ArduinoRailwayControl free app could be tweaked to provide more precise slow running.

Modifying the code

Fortuitously, Steve Massikker suggests that users might need to tinker with his code to tailor it to the needs of different locos and set-ups. The instructions for translating the signals received from the Bluetooth app have been made conveniently available in an array at the start of theArdiono program (sketch).

byte speedArray [] = {60, 80, 100, 120, 140, 170, 200, 230, 255};
 As can be seen, the speed steps increase by a factor of 20 initially, rising to 30 and finally 35. I felt the starting value of 60 was a little too high for my loco and so, after some experimentation, reduced this to 45. I then, changed the size of the steps to something a more exponential than linear.
byte speedArray [] = {45, 46, 48, 52, 60 , 76, 108, 172, 255};
Whilst this was an acceptable mathematical progression of steps, as you can see, in reality, the increments are quite abrupt at the upper ends of the scale.

So, some sort of compromise was needed.
byte speedArray [] = {45, 50, 60, 75, 95, 120, 150, 185, 225};
This provided a smoother speed progression at the lower end of the spectrum. Interestingly, the more abrupt speed changes are less noticeable at the upper end.


As can be seen, the speed steps now provide more control at lower speeds and are barely noticeable.


My next investigations will be to explore a way in which the output from a Bluetooth app can provide even more precise control. See Bluetooth loco control with a phone app - Part 3



Monday, July 01, 2019

Controlling a loco with a Bluetooth phone app and Arduino - Getting started

Contents


Introduction

Having progressed from analogue track power (see How I did the electrics) to DCC (see Digital developments) and then on to battery power and radio control using Deltang components (see Getting started with Deltang), I felt I had reached my ideal control system. However, technology doesn't stand still and so I became interested in the potential of Bluetooth based control. It seemed to offer a lot of potential and seemed reasonably cost effective. I toyed with the idea of investing in a BlueRail receiver but at nearly £80 per loco, it seemed quite a lot to invest for evaluation purposes. I have dabbled with using Picaxe programmable microprocessors for a couple of projects (see How I control my signals and How I control my points remotely), so when I came across some online articles describing the Bluetooth control of model trains using Arduino components I became interested.

What is Bluetooth?

Bluetooth is a form of low power radio communication which is built in to most modern forms of portable technology devices such as mobile phones, tablet computers and car radios. It enables two way communications between devices so, for example, music files stored on a mobile phone can be played remotely on a car radio and the radio can be used to control the phone.


The two devices need to be 'paired' before communication can take place and the distances over which the communication can take place is limited to around 10 metres though distances of 30 metres have been reported. The system is quite robust and reliable and as its use is widespread, there is a wealth of reasonably priced equipment available and plenty of tried and tested examples of applications of the technology which are freely available online.

What is Arduino?

Arduino is a low cost electronics system which is programmable using open source software. Open source means that it is free to use and can be adapted and extended by anyone with the knowledge and skills to do so.
The core system can be easily expanded through the connection of modules and components which can sense environmental conditions and control the actions of devices such as motors, servos and electrical and electronic gadgets. As Arduino has become very popular among hobbyists, educationalists and developers, so the range of compatible hardware has increased and the prices have fallen.

So what does this mean for model train control?

It means that someone with sufficient know-how can create a control system for model trains to suit their own needs. There is a range of Arduino units available which form the heart or, more  accurately, the brains of the system.  Electronic modules are readily available to connect with the Arduino board to add functionality - for example, motor controllers, radio control transmitters and receivers, sensor units, audio players, amplifiers, servo controllers, etc., etc., etc..

Arduino Nano board
The Arduino unit is connected to a computer for programming and then, once the set of instructions has been downloaded to the Arduino, it is able to carry out a series of functions independently. In terms of Bluetooth, a receiver and a motor controller are connected to an Arduino board, the board is then programmed to enable it to be controlled from a smart phone or tablet computer. Furthermore, in addition to instructions being sent from the phone or tablet to control the speed and direction of the motor, other things can be controlled such as sound cards, lighting and remote couplers. It is even possible to transmit sounds stored on the smart device to the loco. In addition, the loco can communicate information back to the smart device, such as its speed or, in the case of a live steam loco, the boiler pressure and gas setting, provided appropriate sensors have been fitted. Lonesome features such as pointwork, uncouplers, signals, lighting and station announcements could also be put under the control of a Bluetooth equipped smart device. It should even be possible to put an entire layout under computer control. Theoretically, any number of locos or accessories could be controlled from one smart device, though there is a limitation on how many could receive sounds from it.

As will be seen, it is possible to set up a simple Bluetooth system to remotely control one or more locos for under £20 per loco and, if you shop around, for considerably less.


A simple basic system

Fortunately, there are plenty of enthusiasts out there who have recognised the advantages of controlling trains with Bluetooth and have provided information and resources for free or for a modest sum.

Steve Massikker of ArduinoRailwayControl.com has provided simple way for anyone to get started. In addition to providing clear instructions as to the equipment needed, how to wire it up and the code which needs to be downloaded to the Arduino Nano or Uno board, he has also made a simple app available for Android and iPhone devices which can be installed free of charge to enable us to evaluate its potential. In addition he has more sophisticated apps for reasonable prices.

His video clearly and concisely explains the process:

Rather than installing the system to control my loco through the track, I wanted to control a battery powered loco running on my 45mm gauge, 16mm scale garden railway.

How I went about it.

1. I downloaded and installed the Arduino IDE programming software on my laptop computer from https://www.arduino.cc/en/Main/Software

2. I purchased the three bits of equipment needed from eBay, namely:

  • 1 x Arduino Nano board (£3.55)
  • 1 x  HC-06  Bluetooth receiver (£4.90)
  • 1 x L298N motor controller (£5.95)

Total cost £14.40. I could have bought the items more cheaply had I been prepared to wait for them to be delivered from China.


3. In addition, I bought an adjustable step down voltage regulator from eBay to provide the Nano with 5 volts as the loco I will be controlling has a 3S 11.1v li-ion power pack (£2.18). I could have made my own voltage regulator circuit but wanted to keep things simple.
The specification for the Nano indicates that it can handle inputs of up to 12 volts, but sometimes the voltage of the pack exceeds this immediately after recharging and so I prefer to play safe.

3. I downloaded the control code needed from the ArduinoRailwayControl.com website and pasted it into the Arduino IDE program on my laptop.


4. I connected the Arduino Nano to my laptop and uploaded the code to it from Arduino IDE. Note: Because the Nano I bought from eBay was a cheaper clone of the original, I had to download and install a driver from  http://www.wch.cn/downloads/file/5.html before  the IDE program on my laptop would recognise the Nano was connected. It was only a 5 minute job (Use Chrome to access the site to translate it into English).

5. Once the Nano had been programmed and disconnected from the laptop, I connected the  components together, following the guidance on the ArduinoRailwayControl.com website.
Source:arduinorailwaycontrol.com

6. In addition, I wired up the voltage regulator to supply power to the Nano, and wired up a charge socket and on off switch for the loco.

7. I then downloaded and installed the free app on to my tablet computer from the link on the ArduinoRailwayControl website.

Source: arduinorailwaycontrol.com

8. I turned on the loco, including its new control system and then opened up the app on my tablet


9. I paired the loco with the app.

10. I could then control my loco using the app on my tablet.



Conclusions

I found the process to be fairly straightforward, but then I am fairly confident with technology and quite happy to tinker around with electronics and a soldering iron, though it is possible to connect everything together with Dupont female to female and male to female cables.

The only complication was getting the laptop to recognise the Arduino Nano and having to install a driver, but this wouldn't have been necessary if a genuine Arduino Nano had been bought from a reputable supplier.

In terms of performance, a drawback for me in using a phone or a tablet to control my locos is seeing the screen in the sunshine when outside in the garden. When using my Deltang based radio transmitters, I seldom look at them when running my trains. I can feel the speed control knob and the switches and buttons without having to look at them. This means I can focus on watching the loco, particularly when shunting.

Another small drawback for me was the size of the speed increments in the default coding. The speed control has nine 'notches' from zero to full speed. I found the loco increased and decreased speed in discernible steps as the throttle was opened or closed. This was particularly noticeable when the loco was starting off and moving slowly - quite important when shunting. However, by changing the values in the array at the beginning of the Arduino code, it was possible to fine tune the way the loco responds at slower speeds (see Part 2 - Tweaking the speed steps).

Overall, Bluetooth enabled technology does seem to offer a flexible and relatively cheap was of controlling model trains. It certainly seems to be future-proofed as it is likely that apps will be further developed. No doubt, at some point in the not to distant future, Bluetooth will be superseded by something more sophisticated but in the meantime it does appear to offer an interesting and readily extendable method of controlling trains.



Thursday, June 27, 2019

How I created various wagon loads

Contents


Introduction

It's no secret that the mainstay of traffic movements on my railway relates to freight operations (eg see Managing freight on the railway). Over the years, I have steadily increased the number of goods wagons and from time to time described how I have made removable loads for them (eg see How I made some open wagons). However, I have never gathered together all these disparate chunks of information into one place. This post aims to rectify this.

Open wagons

I have constructed open wagons in three different ways; making them from scratch using plasticard, making them from my own resin castings and modifying cheap commercial models. Apart from a couple of my very first plasticard models, I have made all the loads on my open wagons removable so I can run them loaded in one direction and empty when they return.

The majority of my open wagons have coal loads, to reflect the preponderance of this traffic during the period when my railway is set (ie the early 1930s).

Real chunks of coal are used (therapeutically created by bashing normal house coal with a hammer),  glued to rectangles of plywood mounted on strip wood as strengthening battens and to allow the loads to be more readily removed.

I have also created various other loads for open wagons based on the sort of other general merchandise which might have been carried at the time on a light railway serving a rural community. For example, a load of barrels travelling to or from the brewery at Beeston Castle.

The barrels were bought from a trader at the Llanfair Garden Railway Fair, painted and glued to a piece of plywood scribed to represent planking.

Another wagon has been loaded with sawn timber, representing a load which might travel from the sawmill at Peckforton to any other station, but most likely to the main terminus at Beeston Market.

The timber planks are a mix of coffee stirrers, lollypop sticks and offcuts of stripwood. They are tied down with book-binding twine which doesn't tend to fray like other string. This load isn't removable at present, but eventually I will modify it so it can be removed.

Based on an old photo of a wagon on the Welshpool and Llanfair Railway and another taken on the Southwold Railway, one open wagon has a mixed load of packing cases, a gear wheel and a couple of milk churns. The gear wheel could be delivered to the water mill or maybe to the brewery.

The packing cases were made by cladding wooden blocks with coffee stirrer planking, the milk churns were bought at a fair and the gear wheel is plastic bought on eBay and mounted on a cradle made from cut down lolly sticks. This load is removable in its entirety, everything being glued to a plywood base.

One wagon has a load destined for a builders' merchant with a stack of bricks, a pile of cement bags and a heap of sand in one corner. It's assumed that this could travel to or from any station on the line as a building project could happen anywhere and the builders' merchant similarly might be anywhere.

The bricks were bought on eBay though several dolls house suppliers also stock them, the cement bags were moulded in Fimo then painted and covered with tissue paper coated in PVA and painted to represent a tarpaulin. A piece of balsa wood was shaped with a knife and file before being covered in PVA and sprinkled with sand to represent the pile of sand. Everything was then stuck to a piece of plywood so the load could be easily removed.

Two open wagons have tarpaulin covers.


One cover was made from a piece of cotton fabric dyed green and attached with button thread to the wagon. This is not removable which isn't important as anything could be carried by the wagon in either direction. The other was made by draping a couple of layers of paper towel over a wagon protected with cling film, then soaking the towel in diluted PVA. When the PVA had dried, the cover was removed and painted with acrylic paint. As it has hardened to form the shape of the wagon it is removable.

Flat wagons

I have a range of flat wagons derived from various sources. Their loads are designed to reflect the needs of the rural locality served by the railway.

One wagon carries farm machinery.

The machinery is actually a couple of Brittains model ploughs bought on eBay and painted with red oxide primer. Although they are under scale, when clumped together they look suitably workmanlike and agricultural.

Another wagon is loaded with a tractor.

This was originally a resin cast moneybox, again bought on eBay. It is roped down to a couple of stripwood blocks glued to a piece of plywood.

One wagon is loaded with milk churns. This wagon tends to be attached to the first mixed train of the day and also to the afternoon mixed.

Because I needed quite a few and the cost of resin cast 1920s conical milk churns was prohibitive, I made my own using the ends of some cheap plastic party toys (see How I made some milk churns).

The match truck for the mobile crane is loaded with a mixture of  appropriate paraphernalia.

The jacks are white metal castings bought online from Garden Railway Specialists, the timber baulks are pieces of stripwood, the chain was bought from Cornwall Model Boats, the rope is a piece of garden twine and the toolbox was made from a piece of balsa with paperclip wire handles.

The permanent way wagon was similarly loaded with tools and other suitable oddments.

The bits and pieces are all from the Bachmann platelayers' accessory pack, weathered with acrylic paints.


Timber wagons

The sawmill at Peckforton (see How I constructed the sawmill) requires some quite specific traffic. As can be seen above, one of the open wagons carries sawn timber but the sawmill also requires the raw material, transported by various timber wagons.

Half a dozen stake wagons are loaded with plastic logs, glued together with Evostick and draped with chains. The logs can be removed as a unit.

Pit props of various lengths cut from twigs pruned from trees in the nearby wood were loaded on to some of the other timber wagons.


It seems that there was no standard length for a pit prop. Mines required a range of lengths to suit the needs of the tunnels below ground.

A large tree trunk was formed from a card tube, covered in paper towel soaked in PVA scrunched to represent bark. This was wedged into the stakes on the bolster wagons.

Tipplers and hoppers

I have two rakes of tippler wagons used to transport ore and spoil from the copper mine to the exchange siding at Beeston Market. One rake is permanently full and the other is permanently empty. The full rake runs up the line and is then swapped for the empty rake to run back down the line. There is a hidden link between the exchange siding and the copper mine to make the swap.

The tipplers have false floors made from plywood covered with PVA and then sprinkled with crushed sandstone.

There is also a rake of hopper wagons similar to those which ran on the Snailbeach and District Railways. These serve the sand quarry and so have removable loads of sand made in a similar way to the tippler loads.

A rectangle of 3mm plywood was cut to the same dimensions as the inside of the wagon, together with a piece of foam packaging (rescued from a parcel received in the post - I seldom throw anything 'useful' away!). Note: the foam can be 'tidied-up' later.

The foam was then stapled to the ply along three edges

Offcuts of foam were then squeezed into the pocket and the fourth edge stapled.

Battens from ply or balsa were then glued to the inderside of the ply (these varied in depth so the loads for each wagon would be non uniform).....

.... and foam was then given a generous coat of PVA and sprinkled with solver sand (the sand intended for children's play pits), .......

...... before being inserted into the wagon.

Conclusion

To my mind, the wagon loads add to the interest of trains running up and down the line. I really enjoy watching a mixed goods slowly meandering through the undergrowth and the logistical puzzles involved in shunting wagons at each station en route.

I need to make a few more loads of sawn timber for the stake wagons and probably need a few more varied loads for open wagons but, otherwise, I am reaching the stage where goods traffic on the line has reached its optimum level.

Of course, I could always make more loads than wagons - and swap them around a bit for variety. That would mean making some amendments to my home-grown freight management computer program (see My freight management computer program) - but, of course, that would make it better reflect the varied nature of goods traffic on a light railway in the 1930s....... I wonder what they might have to carry if the circus same to town???