Project tutorial
Arduino IoT Train

Arduino IoT Train © GPL3+

An IoT controlled LEGO Tram that can move forward and backwards, and also has individually controllable LED channels.

  • 1 comment
  • 13 respects

Components and supplies

Apps and online services

About this project

When I was a child, I used to love LEGO trains. I used to build my own and control them with LEGO's Power Functions. However, as I grew older, I wanted to control my trains with my own circuitry. I started working on a prototype for a wirelessly controlled train that could be controlled through Bluetooth LE. However, after I completed the prototype, I tested it out and saw it was not working reliably through BLE. Later, I started working with the Arduino IoT Cloud and thought, "why can't I use this to control a train." I immediately revised my prototype to be controlled using Arduino's IoT Cloud. When I tested it out, it worked flawlessly. The IoT Cloud also let me add LED Channels into the train and control them via switches rather than numbers. (BLE does not have any boolean switches)


  • with the breadboard, you will need to remove the ground and power rails on either side of the breadboard by cutting through the adhesive layer on the bottom and sliding them off of the center breadboard (Image Below)
  • In the actual project, I used breadboard jumper wires like the ones in the picture below to achieve a compact fit, but you can use normal jumper wires to wire the circuit like the ones I will use to demonstrate the wiring
  • If the 9V battery clips you are using do not have breadboard headers (like mine), you may need to solder some headers or jumper wires like the ones above to achieve a secure fit.

Building Sequence:

1. Attach an L293D motor driver on one end of the breadboard and connect the GND pins on either side to each other using jumper wires (attach L293D pins 4 and 5 together and pins 12 and 13 together)

2. OPTIONAL STEP: attach headers to your breadboard for a clean look and easy to wire the LEDs to the breadboard since wiring can get tough later in the project. You do not need these headers though; you can simply put wires where the headers are and connect LEDs to those wires later. (Picture on step 3)

3. Attach a 1k ohm resistor to the breadboard where the LED's ground wires (or headers) will be attached

4. Attach the Nano 33 IoT Board to the breadboard (it will be a congested fit). make sure the micro USB is facing outwards since it won't be programmable otherwise (Picture on step 5)

5. Attach wires to the GND pin and digital pins 2, 3, 5, and 6 (LEDs require PWM pins for brightness modulation). Connect these wires to the breadboard row where the header pins are and the GND wire to the 1k ohm resistor. Each LED is on a separate channel that can be controlled individually. For the purpose of this project, however, everything is controlled by the same IoT Variable

6. (Wires that connect to LEDs are removed only for instructional purposes. You do not need to remove them on this step) Attach wires to digital Pins 10, 11, and 12. Connect digital pins 10 and 11 to pins 2 and 7 on the L293D motor driver (the side that has a crevice on the top is pins 1-8). Attach digital pin 12 to pin 1 on the L293D. This will control the speed of the motor. Then, attach pin 16 on the L293D to the 3.3V pin on the Nano 33 IoT and GND pins to the 2nd GND on the Nano 33 IoT (having the two pins together like instructed on the first step makes the process of grounding much easier. Batteries will also be connected, which can be tough when there are two GND pins it needs to connect to)

7. Next, attach battery clips in the following positions: one battery clip must connect to pin 8 on the L293D for power and pin 3 or 4 on the L293D for grounding. The other battery clip must connect to VIN (Voltage In) pin on Nano 33 IoT and GND pin on Nano 33 IoT.


9. Attach your motor to pins 3 and 6 on the L293D (tweezers show the pins)

10. Connect a cable to your Nano 33 IoT and create a Thing with the following variables and classes:

Class Variable

  • bool direction
  • CloudDimmedLight led
  • int speed
  • int speedControl
  • bool speedReset

11. Set up your Nano 33 IoT as your board for this project and enter your network credentials in the field below it

12. Open your Thing's sketch in the Sketch tab and copy the code featured below (Comments are featured in the code to explain how it functions). Then, upload it to your Nano 33 IoT

13. Go to the dashboard tab in IoT Cloud and create a dashboard. Next, create widgets (the things in the picture below that control the variables) and link them to each variable. You do not need to have the same widgets as mine, but I think this is the easiest and most straightforward design. Reload the page, and you should have a working motor and LEDs If you do not, try re-linking to each variable

Here is a list of how to link to each variable

  • INTERIOR LIGHT Widget ==> led
  • SPEED Widget ==> speed
  • SPEED CONTROL Widget==> speedControl
  • STOP Widget ==> speedReset
  • DIRECTION Widget ==> direction

Congratulations, you have completed this project! You can now remove the cable connecting your computer to the board, and plug the batteries into the clips. The Nano 33 IoT should now work wirelessly by connecting to your internet and communicating with your PC. If you have any questions, problems, or advice, please comment below and I will get back to you as soon as possible.

A demonstration of this project is below.

Thanks for reading!


This is the Code that needs to be uploaded to the Nano 33 IoT for the train to function. You can modify it if you want to add anything extra, but you will need to change the controlled things inside the Arduino IoT Cloud
  Controlled Variables through Arduino IoT Cloud

  bool speedReset;
  bool direction;
  int speed;
  int speedControl;
  CloudDimmedLight led;

#include "thingProperties.h"

//Set LED Channels and variables for control
int ledC1 = 2;
int ledC2 = 3;
int ledC3 = 4;
int ledC4 = 5;
int DUTY = 0;
bool ledSwitch = true;

//Set Speed Control Pins
int SC_A = 12;
int SC_B = 8;

//Set Motor Pins
int MF_A = 10;
int MB_A = 11;

int MF_B = 6;
int MB_B = 7;

//Set values for speed control
int MDUTY = -255;
int MDUTY_N = 0;
int Motor_Speed;

void setup() {
  // Initialize serial monitor:
  Serial.println("Serial Monitor Initialized");
  pinMode(ledC1, OUTPUT);
  pinMode(ledC2, OUTPUT);
  pinMode(ledC3, OUTPUT);
  pinMode(ledC4, OUTPUT);
  pinMode(SC_A, OUTPUT);
  pinMode(SC_B, OUTPUT);
  pinMode(MF_A, OUTPUT);
  pinMode(MF_B, OUTPUT);
  pinMode(MB_A, OUTPUT);
  pinMode(MB_B, OUTPUT);

  // Defined in thingProperties.h

  // Connect to Arduino IoT Cloud
    Serial.println("Failed to Connect to wifi or UBLOX not initialized");
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the ledDUTYer number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4

void loop() 

void onSpeedControlChange() 
  Motor_Speed = speedControl;
  MDUTY = Motor_Speed;
  if(MDUTY > 0)
    speed = MDUTY;
    direction = true;
    //Set the speed of the motors
    analogWrite(SC_A, MDUTY);
    analogWrite(SC_B, MDUTY);
    //Power Motors to turn forward
    digitalWrite(MF_A, HIGH);
    digitalWrite(MF_B, HIGH);
    digitalWrite(MB_A, LOW);
    digitalWrite(MB_B, LOW);
  if(MDUTY < 0)
    //Set MDUTY_N as the absolute value of MDUTY for speed
    MDUTY_N = abs(MDUTY);
    speed = MDUTY_N;
    direction = false;
    //Set the speed of the motors
    analogWrite(SC_A, MDUTY_N);
    analogWrite(SC_B, MDUTY_N);
    //Power Motors to turn backward
    digitalWrite(MF_A, LOW);
    digitalWrite(MF_B, LOW);
    digitalWrite(MB_A, HIGH);
    digitalWrite(MB_B, HIGH);
  if(MDUTY == 0)
    speed = MDUTY;
    //Set the speed of the motors to 0
    analogWrite(SC_A, MDUTY);
    analogWrite(SC_B, MDUTY);
    //Turn off Motors
    digitalWrite(MF_A, LOW);
    digitalWrite(MF_B, LOW);
    digitalWrite(MB_A, LOW);
    digitalWrite(MB_B, LOW);

void onSpeedResetChange() 
  if(speedReset == true)
    speedControl = 0;
    speed = 0;
    //Set the speed of the motors to 0
    analogWrite(SC_A, MDUTY);
    analogWrite(SC_B, MDUTY);
    //Turn off Motors
    digitalWrite(MF_A, LOW);
    digitalWrite(MF_B, LOW);
    digitalWrite(MB_A, LOW);
    digitalWrite(MB_B, LOW);

void onLedChange() 
  if(led.getSwitch() == ledSwitch)
    DUTY = led.getBrightness() * 2.5;
    analogWrite(ledC1, DUTY);
    analogWrite(ledC2, DUTY);
    analogWrite(ledC3, DUTY);
    analogWrite(ledC4, DUTY);
    digitalWrite(ledC1, HIGH);
    digitalWrite(ledC2, HIGH);
    digitalWrite(ledC3, HIGH);
    digitalWrite(ledC4, HIGH);
    DUTY = 0;
    analogWrite(ledC1, DUTY);
    analogWrite(ledC2, DUTY);
    analogWrite(ledC3, DUTY);
    analogWrite(ledC4, DUTY);
    digitalWrite(ledC1, LOW);
    digitalWrite(ledC2, LOW);
    digitalWrite(ledC3, LOW);
    digitalWrite(ledC4, LOW);


Circuit Diagram using Altium CircuitMaker (since I don't have fritzing)
Arduino iot train schematic qdyp1wwjmd


Similar projects you might like

Boat with Arduino Nano 33 IoT on Arduino Cloud

Project tutorial by SandroMesquita and eliezerne

  • 6 respects

IoT Node with STM32F4 Discovery, MKR1000 and Azure IoT Hub

Project tutorial by vincent wong

  • 6 respects

IoT Blink - Getting started with IoT

Project showcase by AppShed Support

  • 1 comment
  • 26 respects

IoT Using ESP8266-01 and Arduino

Project tutorial by Ahmed Ibrahim Ahmed

  • 69 respects

IoT Cloud Enabled Alarm Clock

Project showcase by MoritzDornseifer

  • 17 respects
Add projectSign up / Login