Monday, June 02, 2025

Introduction to the blog

Introduction


This blog describes ongoing progress in the development of a G gauge / 15mm scale / 1:20.32 / Fn3 scale Garden Railway from its inception to the present day.    

NEW (April 2025)
Extracts from a Southwold session - Part 1
 
Extracts from a Southwold session - Part 2
 


When I became interested in building my own garden railway I spent a considerable amount of time (and money) on books, videos, DVDs and scouring the internet for information, ideas and inspiration. When I eventually started construction, I used some of the ideas I had discovered, but also experimented with my own approaches. This blog outlines how I have gone about constructing my own garden railway. My aim is to provide the sort of information I was looking for when I was getting started, and also to share what I've learned (or 'borrowed' from others). I've tried to include a few 'How I ........' postings interspersed with occasional 'Progress Reports'. I do not profess to be any kind of expert - what I offer here is an opportunity for you to metaphorically look over my shoulder to see how I have gone (and am going) about this fascinating hobby.

As this is a blog, the various posts are presented in reverse chronological order (ie the most recent first). To see a categorised list of contents, go to the Blog Contents Page.


If you are thinking about building your own garden railway, then why not join the 16mm Association or the G Scale Society - you'll get plenty more advice and opportunities to visit other peoples' garden railways
. Alternatively, browse through the G Scale Central website - there's plenty more guidance here and an opportunity to sound out the views of others through the G Scale Central discussion forum or the GardenRails.org forum


The Blog


The advantages of blogging are that it is immediate and uncomplicated when creating and uploading information. The other, of course, is that with Blogger it is free. The major disadvantage is that I have minimal control over how the postings are presented. The blogging system adds the most recent information to the start of the blog, hence the postings appear in reverse chronological order (most recent first, oldest last). Whilst there is a list of postings on the right-hand side, it's not particularly easy to see what is there. This introduction is an attempt to provide you with a contents list of the postings organised into categories so, hopefully, you see if what you are looking for is presented in this blog. To ensure that it always appears at the start of the blog, I update its content and set its presentation date into the future each time I add a new posting.

Powered by WebRing.

An Arduino radio control system for garden railway locos

 After experimenting with Arduino Bluetooth control systems (eg see Arduino-based Bluetooth control for model trains - Part 1) and finding that I disliked having to look at my phone screen whenever I wanted to control the loco, I decided to explore using Arduino as the basis for a 2.4GHz radio control system.

I'll say from the start, that it isn't perfect. It works OK for about 90% of the time, but occasionally it seems to have a mind of its own. I haven't yet figured-out why. I have enquired on a couple of Arduino forums, but nothing useful has been suggested. However, I find this system is still preferable to trying to view what is on my phone screen whilst out in the garden when the sun is shining.

 I am no expert with Arduino; I have just acquired sufficient information to solve each problem as it arises. However, you might find this is helpful if you are also a novice, as I will not try to blind you with technical knowledge - because I don't have any.

 

The receiver

Firstly, I acquired the equipment needed for the receiver: an Arduino Nano, an NRF24L01 radio module and an L298n motor driver. These can readily be bought online for modest sums (c £17.50GBP at the time of writing - or cheaper (c£4.50GBP) if bought directly from China via AliExpress).

Basically, all I had to do then was connect the components together. Note: I used an adapter board with the NRF24 module as this provides the required voltage without the need for an additional voltage regulator.

For testing, I used DuPont jumper cables, but once I had tested everything, I soldered the connections.

 The connections to the Arduino Nano were:

Nano pin

Connected to

Comments

D2

Forward facing LED (+ve)

via a 100 ohm resistor

D3

ENA pin on L298N

D3 provides PWM output

D4

IN1 pin on L298N

When high loco moves forward (IN2 Low)

D5

IN2 pin on L298N

When high, loco moves in reverse (IN1 Low)

D6

Rear facing LED (+ve)

Via a 100R resistor

D7

CE pin on NRF24


D10

CSN pin on NRF24


D11

MOSI pin on NRF24


D12

MISO pin on NRF24


D13

SCK pin on NRF24

This pin must be used exclusively for SCK

 The next step was to program the Arduino Nano to respond to the signals it received from the NRF24 receiver.

To do this, the Arduino IDE software needed to be downloaded from the Arduino website ( https://www.arduino.cc/en/software/ ) and installed on my laptop computer.

Once installed, the code needed to be entered. If you are following in my footsteps, you can either copy and paste it into the editor or download the sketch from Dropbox ( https://www.dropbox.com/sh/jlqvtb89xs4keve/AACxO5eDeAnR7q__DERQwq-qa?dl=0 ).

/* Basic receiver code without sound
* Adapted from the code provided by Electronoobs - http://www.electronoobs.com/eng_arduino_tut25.php
 */


#include <SPI.h> // This library is included as part of IDE
#include <nRF24L01.h>  //The nrf24 libraries must be installed for the code to work - available from https://www.arduinolibraries.info/libraries/rf24
#include <RF24.h>

const uint64_t pipeIn = 0xE8E8F0F0E1LL;     //This 'pipe' code must be the same as in the transmitter sketch
RF24 radio(7, 10);  //CSN and CE pins

// The size of this struct should not exceed 32 bytes which is why the byte variable is used for each channel
struct Received_data {
 byte ch1; //Throttle data from Tx
 byte ch2; //Not used this time but defined in case you want to add additional features (eg sound triggers, user-controlled lights etc)
 byte ch3;
 byte ch4;
};

Received_data received_data;

int ch1_value = 127; //127 is the mid-point value for the potentiometer output
int ch2_value = 255;
int ch3_value = 255;
int ch4_value = 255;
int ch1_oldval = 127;


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

// Variables //
int val = 0; // speed

void reset_the_Data()
{
 // 'safe' values to use when NO radio input is detected
 received_data.ch1 = ch1_oldval;      //Throttle (channel 1) - keeps the speed constant if the signal is lost (change this to 0 if you want the loco to stop if the signal is lost
 received_data.ch2 = 127; //Resets Ch2 to its mid setting
 received_data.ch3 = 255; // Resets Ch3 to High
 received_data.ch4 = 255; // Resets Ch4 to High
}



/**************************************************/

void setup()
{
 //Reset the received values when first turned on
 reset_the_Data();

 // Initializing Serial
 Serial.begin(9600);

 //Begin and radio configuration
 radio.begin();
 radio.setAutoAck(false);
 radio.setDataRate(RF24_250KBPS);  
 radio.openReadingPipe(1,pipeIn);
 
 //We start the radio comunication
 radio.startListening();

 // Initialising Motor-Driver outputs
 pinMode(motorSpeedPin, OUTPUT);
 pinMode(IN1, OUTPUT);
 pinMode(IN2, OUTPUT);
 analogWrite(motorSpeedPin, 0);

 // Initialising LED pins as outputs
 pinMode(fwdLED, OUTPUT);
 pinMode(revLED, OUTPUT);
 digitalWrite(fwdLED, HIGH); //Turns on the forward facing LED - confirming the loco is switched on
}

/**************************************************/

unsigned long lastRecvTime = 0;

//Here we define the function that will read the data
void receive_the_data()
{
 while ( radio.available() ) {
 radio.read(&received_data, sizeof(Received_data)); //Here we receive the data
 lastRecvTime = millis(); //When the data was received
}
}

/**************************************************/

void loop()
{
 //Receive the radio data
 receive_the_data();

//////////This will reset the data if signal is lost for 2 sec.
/////////////////////////////////////////////////////////////////////////
 unsigned long now = millis(); //Time now
 if ( now - lastRecvTime > 2000 ) { //Checks now time with when the data was last received - if greater than 2 secs assume signal is lost
   // If signal lost
   reset_the_Data();
   //Use the values set above
 }
 ch1_oldval = ch1_value;
 ch1_value = received_data.ch1; //Assign the values received to the relevant variables
 ch2_value = received_data.ch2;
 ch3_value = received_data.ch3;
 ch4_value = received_data.ch4;

 
    // Direction and Stop
    if (ch1_value > 140) { // Go forward if throttle is greater than 140
     digitalWrite(IN1, HIGH); //Tells the motor control board to go forward
     digitalWrite(IN2, LOW);
     digitalWrite(fwdLED, HIGH); //Turns on the forward facing LED
     digitalWrite(revLED, LOW); //Turns off the reverse facing LED
     val = map (ch1_value, 141, 255, 0, 255); //Maps the received throttle output from 141-255 to 0 to 255
    }
     else if (ch1_value < 121) { // Go in reverse if throttle setting is less than 121
       digitalWrite(IN1, LOW);
       digitalWrite(IN2, HIGH); //Tells the motor controller to go in reverse
       digitalWrite(fwdLED, LOW);
       digitalWrite(revLED, HIGH);
       val = map (ch1_value,0, 120, 255, 0); //Maps the throttle output from 0-121 to 255 to 0
       }
       else { // Stop if the throttle control on the Tx is between 122 and 139 (ie in the centre)NOTE A broad range is used to take account of variations in the tolerances of potentiometers used
         digitalWrite(IN1, LOW);
         digitalWrite(IN2, LOW);
         digitalWrite(fwdLED, LOW); //Delete these two lines of code if you want the LED to remain on when the loco is stationary
         digitalWrite(revLED, LOW); // ditto
       }
       
      analogWrite(motorSpeedPin, val); // Throttle
      
}//Loop end

The code then needs to be uploaded to the Arduino Nano.

If you are not familiar with this process, then here's a quick guide.

 Step 1 - The sketch for the receiver has been downloaded and opened in Arduino IDE.

 

Step 2 - Connect the Arduino Nano to your computer – any USB to mini USB connector cable can be used. You may already have one available from another device, or they can be readily and cheaply purchased from eBay.

Step 3 - Before uploading the sketch, the Arduino IDE application needs to configured to communicate with the Nano. In the Tools menu click on Arduino Nano from the drop-down field beside Board:

 


Step 4 -  If, like me, you bought your Nano from eBay, you will need to tell IDE to use the Old Bootloader. In the Tools menu, select Atmega328P (Old Bootloader) from the drop-down list beside Processor:

Step 5 - Before uploading to your Nano, check the syntax of the code is OK by clicking on the tick button. If no errors are detected, then click the Upload (arrow) button. If there are errors, try downloading the code again and re-opening it in IDE or check the erroneous bit of code highlighted by the error checker.

 

Step 6 – A couple of ‘libraries’ of commands will need to be added to the basic Arduino program to enable the Nano to communicate with the NRF24 board (nRF24L01.h and RF24.h). Adding libraries is dead easy. Go to the relevant website (https://www.arduinolibraries.info/libraries/rf24 ) and download the libraries as a .ZIP file (this contains both libraries).


 

Step 7 – Once these have been saved to your computer hard drive, they are installed in IDE by going to the Sketch menu, clicking on Include library and then on Add .ZIP library. Navigate to where you saved the libraries and they will then be unzipped and installed in IDE.


 The Transmitter

With the receiver constructed and programmed, I now turned my attention to the transmitter. While running RC Trains a few years ago, I developed knowledge and skills to construct Deltang transmitters and so it was a simple process to transfer this knowledge to constructing one for Arduino components.

 The components needed for the transmitter were:

  • Arduino Nano 
  • NRF24 
  • NRF24 adapter
  • Three push buttons (momentary)
  • Illuminated push-push on/off switch
  • SPDT toggle switch
  • 10k linear potentiometer
  •  PP3 battery snap connector
  • PP3 battery
  • Small instrument case with PP3 battery compartment

 The first job was to connect together the components.

The adapter for the NRF24 wasn't essential, but I decided to use one as it obviates the need for the voltage regulator. I also, eventually, swapped the NRF24 with external antenna, for the standard model as I found the one with the antenna drained the PP3 battery within an hour. The range from the standard NRF24 module was perfectly adequate in my garden.


 The other components were acquired from Rapid Electronics.

The case (a KE32 Enclosure with Battery Compartment, Grey, 110 x 66 x 27mm) was bought from Eltop Electronics

You could connect several push buttons or switches to the Nano, in the end I just opted for one push button and one two way switch.

The connections to the Nano were:

Nano pin

Connected to

Comments

D2

SPDT switch centre pin (other two pins of switch connected to ground and 5v output from Nano

Enables the D2 to be switched high(5v) or Low (0v)

D3

Push button 1

Other pin of button connected to 0v

D4

Push button 2

Other pin of button connected to 0v

D5

Push button 3

Other pin of button connected to 0v

D6

Not used

Could be used for additional switches or buttons

D7

Not used

Could be used for additional switches or buttons

D8

Not used

Could be used for additional switches or buttons

D9

CE pin on NRF24


D10

CSN pin on NRF24


D11

MOSI pin on NRF24


D12

MISO pin on NRF24


D13

SCK pin on NRF24

This pin must be used exclusively for SCK

A0

To centre pin of 10k pot


A1

To centre pin of two-way switch


A2 – A7

Not used

Could be connected to other potentiometers for live steam loco control

3v3

To +ve leg of LED in illuminated on/off switch via 30R resistor


5v

To one of the outside pins on the potentiometer

The other outside pin of the pot connected to 0v (ie ground)


Initially, the connections were made with Du Pont connectors but once it had been tested, the connections were soldered.

The Nano was connected to my laptop as above and programmed with the following code:

/* Transmitter code - adapted from that provided on the Electronoobs website
   http://www.electronoobs.com/eng_arduino_tut25.php
*/

#include <SPI.h>
#include <nRF24L01.h> //The nrf24 library must be installed first - avaiable from https://www.arduinolibraries.info/libraries/rf24
#include <RF24.h>

const uint64_t my_radio_pipe = 0xE8E8F0F0E1LL; //This code should be the same for the receiver

RF24 radio(9, 10);  //CE and CSN pins on the Nano

// The size of this struct should not exceed 32 bytes which is why we are defining each variable as a byte.
struct Data_to_be_sent {
  byte ch1; //Throttle channel
  byte ch2; //Switch direction 1
  byte ch3; //Switch direction 2
  byte ch4; //Button 1
  byte ch5; //Button 2
  byte ch6; //Button 3
};



//Create a variable with the structure above and name it sent_data
Data_to_be_sent sent_data;


void setup()
{
  radio.begin(); //These statements set up the NRF24 as a transmitter to enabe it to send data
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(my_radio_pipe);

  //Default channel values
  sent_data.ch1 = 127; //The mid position for the speed controller (0 = Low, 255=High)
  sent_data.ch2 = 255; //Sets each channel initially to HIGH (Could use 'HIGH' instead of '255')
  sent_data.ch3 = 255; 
  sent_data.ch4 = 255;
  sent_data.ch5 = 255;
  sent_data.ch6 = 255;

}

/**************************************************/


void loop()
{
  sent_data.ch1 = map( analogRead(A0), 0, 1024, 0, 255); //Reads the potentiometer value and and then maps the reading of 0 to 1024 to 0 to 255
  sent_data.ch2 = digitalRead(2); //Reads the input from the SPDT switch's pin 1
  sent_data.ch3 = digitalRead(3); //Reads the input from the SPDT switch's pin 2
  sent_data.ch4 = digitalRead(4); //Reads the input the push button connected to pin 4
  sent_data.ch5 = digitalRead(5); //Reads the input on pin 5
  sent_data.ch6 = digitalRead(6); //Reads the input on pin 6


  radio.write(&sent_data, sizeof(Data_to_be_sent)); // Sends the values to the receiver
}

Once the code had been checked with the receiver, the case was drilled to take the switches, push buttons and potentiometer and the components and battery carefully (!) placed inside.

An overlay was printed on to self-adhesive vinyl and stuck to the outside of the case. BTW, I also coat the vinyl with clear sticky-backed plastic to protect the printing.

Adding sound to the receiver

I like my locos to make noises - preferably sounds related to the type of loco. Before doing anything else, I tracked down what I felt were appropriate sounds. After drawing a blank with YouTube videos, I eventually came across a set of sound files for an old Famulus RS1430 tractor on the SoundSnap website. I felt they were well worth the $15USD required to download five files.  

NOTE: Soundsnap now seems to have changed its pricing to subscription only. It would appear you now have to buy a month's subscription for $29USD.

After being downloaded, the files were edited using Audacity (a free sound editing program). In addition, I found the sound of an air horn on YouTube and incorporated that into some of the files until I ended up with the following set of files:

  • 001 - Silence (1 min)

  • 002 - Silence plus horn sound (3 seconds)

  • 003 - engine start-up to idle (4 seconds)

  • 004 - idle (15 secs)

  • 005 - idle plus horn (4 seconds)

  • 006 - slow run (15 secs)

  • 007 - slow run plus horn (4 secs)

  • 008 - medium run (15 secs)

  • 009 - medium run plus horn (4 secs)

  • 010 – fast run (15 secs)

  • 011 – fast run plus horn (4 secs)

  • 012 - shut down (5 secs)

 I then purchased a DF Mini Player module from eBay (for £3.49GBP) and uploaded the files to a mini SD card. Note: It's important that the files are uploaded in the order as shown above otherwise the Nano won't be able to play the requisite track when needed.

 The DF Mini Player was connected into the receiver circuitry thus:


Nano pin

Connected to

Comments

D2

Forward facing LED (+ve)

via a 100 ohm resistor

D3

ENA pin on L298N

D3 provides PWM output

D4

IN1 pin on L298N

When high loco moves forward (IN2 Low)

D5

IN2 pin on L298N

When high, loco moves in reverse (IN1 Low)

D6

Rear facing LED (+ve)

Via a 100R resistor

D7

CE pin on NRF24


D8

Rx input pin on DF mini player

Via 1k resistor to help protect the mini player

D9

Tx output pin on DF mini player


D10

CSN pin on NRF24


D11

MOSI pin on NRF24


D12

MISO pin on NRF24


D13

SCK pin on NRF24

This pin must be used exclusively for SCK

A0 – A7

Not used

Could be used as output triggers for soundcards etc

 ...... and the following code was uploaded to the Nano.

/* Receiver code for PLR rc system with sound synchronisation
 * Adapted from code provided on Electronoobs website - http://www.electronoobs.com/eng_arduino_tut25.php
*/


#include <SPI.h> //This library is normally included as part of the IDE download
#include <nRF24L01.h> //This library can be downloaded from https://github.com/maniacbug/RF24
#include <RF24.h> //This library can be downloaded from https://www.arduinolibraries.info/libraries/rf24
#include <SoftwareSerial.h> //This library is normally included as part of the IDE download
#include <DFPlayerMini_Fast.h> //This library can be downloaded from https://github.com/PowerBroker2/DFPlayerMini_Fast

// SOFTWARE SERIAL
SoftwareSerial mySerial(8, 9); // RX and TX pins for SD player
DFPlayerMini_Fast myMP3; // Initialises SD Player

const uint64_t pipeIn = 0xE8E8F0F0E1LL;     //This code must be the same as the transmitter code
RF24 radio(7, 10);  //CSN and CE pins

// This struct should not exceed 32 bytes in total
//The number of channels can be increased or reduced dependent on the number of controls on your transmitter
struct Received_data {
  byte ch1; // Throttle channel (connected to potentiometer)
  byte ch2; //Switch (forward direction)
  byte ch3; //Switch (reverse direction)
  byte ch4; //Button (Red)
  byte ch5; //Button (F1)
  byte ch6; //Button (F2)
};

Received_data received_data;

int ch1_value = 127; //defines the variables as integers and sets their initial values
int ch1_oldval = 127;
int ch2_value = 255;
int ch3_value = 255;
int ch4_value = 255;
int ch5_value = 255;
int ch6_value = 255;

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

// Variables //
int val = 0; // speed 
int Track = 1; // which track is playing - sets this initially to track 1 (silence)
int slowVal = 70; // idle speed max - change to suit your loco
int medVal = 120; // slow speed max - change to suit your loco
int fastVal = 180; // med speed max - change to suit your loco

void reset_the_Data() 
{
  // 'safe' values to use when NO radio input is detected
  received_data.ch1 = ch1_oldval; // Resets the throttle to its old value (ie for cruise control if the signal is lost - put 0 if you want the loco to stopon the loss of rc signal
  received_data.ch2 = 255; // Sets the inputs from the buttons and switch to HIGH
  received_data.ch3 = 255;
  received_data.ch4 = 255;
  received_data.ch5 = 255;
  received_data.ch6 = 255;
}



/**************************************************/

void setup()
{
  //Reset the received values (as above)
  reset_the_Data();

  // Initializing Serial
  Serial.begin(9600);
  mySerial.begin(9600);
  myMP3.begin(mySerial); //Initialises MP3 player

  myMP3.volume(30); //Sets the volume of the MP3 output
  myMP3.loop(1); //Starts the MP3 player by looping track 1 (silence)

  //Begin and radio configuration
  radio.begin();
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);  
  radio.openReadingPipe(1,pipeIn); //Sets up the NRF24 as a receiver
  
  //We start the radio comunication
  radio.startListening();

  // 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);

}

/**************************************************/

unsigned long lastRecvTime = 0;

//The function which reads the data from the Tx
void receive_the_data()
{
  while ( radio.available() ) {
  radio.read(&received_data, sizeof(Received_data)); //Here we receive the data
  lastRecvTime = millis(); //Records the time when the data were received
}
}

/**************************************************/

void loop()
{
  //Receive the radio data
  receive_the_data();

//////////Resets the data if signal is lost for 2 sec.
/////////////////////////////////////////////////////////////////////////
  unsigned long now = millis();
  if ( now - lastRecvTime > 2000 ) { // Compares time now with time when the data were last received
    // signal lost?
    reset_the_Data();
  } 
  
  ch1_oldval = ch1_value;
  ch1_value = received_data.ch1;
  ch2_value = received_data.ch2;
  ch3_value = received_data.ch3;
  ch4_value = received_data.ch4;
  ch5_value = received_data.ch5;
  
     // Direction and Stop
     if (ch1_value > 140) { // Forward if the speed knob turned to right (127 is central position value)
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(fwdLED, HIGH);
      digitalWrite(revLED, LOW);
      val = map (ch1_value, 141, 255, 0, 255); //Maps the throttle value of 141 - 255 to 0 to 255
     }
      else if (ch1_value < 121) { // Reverse if the speed knob is turned anticlockwise from the central position (127)
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(fwdLED, LOW);
        digitalWrite(revLED, HIGH);
        val = map (ch1_value,0, 120, 255, 0); // Maps the throttle output from 0 to 120 on to 255 to 0 (ie when knob is at zero position (full left) speed in reverse is full
        }
        else { // Stops the loco if the speed knob is in central position (ie between 122 and 139)
          digitalWrite(IN1, LOW);
          digitalWrite(IN2, LOW);
          digitalWrite(fwdLED, LOW);
          digitalWrite(revLED, LOW);
        }
        
       analogWrite(motorSpeedPin, val); // Gives the motor driver module the required speed setting
       
  //Playing the SD card tracks
  
//There are twelve tracks on the SD card
//001 - Silence (1 min)
//002 - Silence plus horn sound (4 seconds)
//003 - engine start-up to idle (3 seconds)
//004 - idle (15 secs)
//005 - idle plus horn (4 seconds)
//006 - slow run (15 secs)
//007 - slow run plus horn (4 secs)
//008 - med run (15 secs)
//009 - med run plus horn (4 secs)
//010 - fast run (15 secs)
//011 - fast run plus horn (4 secs)
//012 - shut down (5 secs)
     
       if(ch2_value==LOW && Track==1){//Has engine start button been pressed on Tx and is there no sound?
        myMP3.play(3); //If so, play engine start-up
        delay(4000); //If your engine start-up track is not 4 secs you will need to change this delay (1000 = 1 sec)
        myMP3.loop(4); //Now play the engine idle sound
        Track = 4;
       }
      if(ch3_value==LOW && Track==4){ //Has engine stop button been pressed on Tx and is the idling track playing?
        myMP3.play(12); //If so, play engine shut-down track
        delay(5000); //If your engine shut down track is not 5 secs long you will need to change this delay (1000 = 1 sec)
        myMP3.loop(1); //Now play silence track
        Track = 1;
       }
     
       if(Track==4 && val>slowVal){ //Move from idling to slow run sound
        myMP3.loop(6);
        Track = 6;
       }
       if(Track==6 && val<slowVal){ //Move from slow run to idle sound
        myMP3.loop(4);
        Track = 4;
       }
       if(Track==6 && val>medVal){ // Move from slow run to med run sound
        myMP3.loop(8);
        Track=8;
       }
       if(Track==8 && val<medVal){ //Move from med run to slow run sound
        myMP3.loop(6);
        Track=6;
       }
        if(Track==8 && val>fastVal){ // Move from med run to fast run sound
        myMP3.loop(10);
        Track=10;
       }
       if(Track==10 && val<fastVal){ //Move from fast run to med run
        myMP3.loop(8);
        Track=8;
       }
        if(ch4_value==0 && (Track==1 || Track==4 || Track==6 || Track==8 || Track==10)) { // Has horn button been pressed?
         myMP3.play(Track + 1);  //Play relevant horn track
         delay(2000);
         myMP3.loop(Track);        
       }

}//Loop end

You can see that the horn sounds whenever Channel 4 is sent low (ie when the button is pressed on the transmitter connected to Pin4 on the Nano) by moving to the next engine sound plus horn track and back again. The sound of the engine increases in speed in three steps as the voltage to the motor increases. The code can be tweaked if you want to increase the number of speed steps or include additional effects such as gear change sounds.

Basically, that's all there is to it. As long as you have the confidence to have a go, I can't see any reason why you couldn't follow in my footsteps and make a similar RC control system for around £30GBP or even less if you source your components directly from China via AliExpress.