Thimble Learning Platform
Back to full view

Robotics Kit 2

Introduction

This is the second in a series of a WiFi Controlled Robot projects. In this kit you'll be putting together a controller to drive your previous kit remotely.

Objectives

  • Assemble a controller
  • Learn out control schemes
  • Have fun!
  • I've Never Used an Arduino

    Then this is a great place to start! If you're already familiar with setting up the Arduino and the IDE, you can skip to the next section.

    Terms 

    When we talk about Arduino, the Arduino IDE, and coding, there are a lot of words being thrown around. This section will clear all of those up and get you ready to start building!

    Arduino 

    The Arduino is a electronics prototyping platform. That means it's a flexible platform for building, testing, and, of course, prototyping electronics. That could be simple LEDs that light up at night, or advanced robots. When we talk about the Arduino we are talking about the physical board itself. The one that comes in this kit is red, but they come in many different shapes and colors. The Arduino brand and original board were created by arduino.cc and you can read more about the details of its history here.

    Arduino IDE 

    The Arduino IDE, or Integrated Development Environment, is not hardware, but a piece of software. If you wanted to write an essay, you might use Microsoft Word or Google Docs. If you wanted to edit pictures, you'd probably use Photoshop or Paint.net. If you want to program code for the Arduino, you'd use the Arduino IDE. Its a computer program (tool) that let's you develop and test out code. Once written, the code can be upload to the physical Arduino where it will stay until you upload new code.

    Download

    Since it is a program, you'll need to install it.

    For Windows computers use this link Windows Installer

    For Mac computers use this link Mac Installer

    After following each link, press the Just Download button to begin downloading the Arduino IDE. The Mac version has a few more steps and we have a video just for that.

    Mac Installation
    For Mac users

    Installation

    Open the executeable file you downloaded. You'll see a screen asking you to agree to their license. You can press I Agree.

    LicenseLicense

    Next up are the installation options. The Install USB Drivers lets the Arduino board communicate with the IDE. We definitely want this. The Associate .ino files makes any Arduino file on your computer open up to the Arduino IDE. Very helpful, so we'll keep that too. Press Next >.

    OptionsOptions

    Now you are being asked where you'd like the Arduino IDE program installed. I don't mind it in the standard Program Files so I just press Install. You can change where it will be installed, just remember what you chose. I recommend not changing it.

    FolderFolder

    Now the IDE is installing.

    InstallingInstalling

    Once completed proceed to the next section.

    CompletedCompleted

    Arduino IDE 101

    Open up the Arduino IDE for the first time. So, let's figure out what's what.

    Arduino IDEArduino IDE

    There is a mostly empty space in the middle that has this text:

    Download file Copy to clipboard
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void setup() {
      // put your setup code here, to run once:
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    

    This is a simple Arduino Sketch. A Sketch is code you write that will later be uploaded to the Arduino board.

    There are few steps to go from code written in a sketch to code that runs on the Arduino board. Those are Verify > Compile > Upload.

    All of these you can get to by going under Sketch on the top bar of the program. Or using the Checkmark and Arrow icons right below that. The Checkmark verifies your code will compile, and the arrow button uploads the code to the Arduino.

    Sketch
    Icons

    Verify - looks at your code and makes sure it can actually run. It checks that there are no errors or things out of place. If your code will work, it goes to the Compile stage.

    Compile - The code you've written is great for human. It is readable and hopefully understandable. But this isn't great for a machine ie the Arduino. The Compile stage takes your written code and translates into something that the Arduino can understand and run, called machine code. It saves that compiled file and tried to Upload it to the board.

    Upload - This takes the compiled files and tries to send it to a plugged in Arduino. The IDE doesn't know where you've plugged in your Arduino or what kind it is. You have to tell it. I'll show you how to set that up in the next section.

    Arduino Board Setup

    For this section, make sure your Arduino Board that came with your kit is plugged in. Use the included micro USB cable to plug your Arduino into any free USB port on you computer.

    Navigate to the Tools section at the top of the Arduino IDE.

    You'll be greeted with a scary drop down. To setup your Arduino to accept uploads, do the following: Go to Board: and make sure Arduino/Genuino Uno is selected.

    BoardBoard

    Next is the Port. For Mac users refer to the video for these instructions. With your Arduino plugged in, you'll see some options. Mine says COM 15. This is the channel that the IDE will use to communicate with your Arduino. If you have a lot of COM # devices and don't know which is your Arduino, unplug your Arduino and take note of that numbers are there. Then plug it back in. Whichever is the new one in the list is your Arduino. Select that port.

    PortPort

    With the board and port selected and ready to go, let's upload our first sketch.

    Sketches

    We are going to upload a simple sketch to make an LED on the board blink. Head to File > Examples > Basics > Blink . You should see this sketch.

    Download file Copy to clipboard
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    /*
      Blink
    
      Turns an LED on for one second, then off for one second, repeatedly.
    
      Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
      it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
      the correct LED pin independent of which board is used.
      If you want to know what pin the on-board LED is connected to on your Arduino
      model, check the Technical Specs of your board at:
      https://www.arduino.cc/en/Main/Products
    
      modified 8 May 2014
      by Scott Fitzgerald
      modified 2 Sep 2016
      by Arturo Guadalupi
      modified 8 Sep 2016
      by Colby Newman
    
      This example code is in the public domain.
    
      http://www.arduino.cc/en/Tutorial/Blink
    */
    
    // the setup function runs once when you press reset or power the board
    void setup() {
      // initialize digital pin LED_BUILTIN as an output.
      pinMode(LED_BUILTIN, OUTPUT);
    }
    
    // the loop function runs over and over again forever
    void loop() {
      digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
      delay(1000);                       // wait for a second
      digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
      delay(1000);                       // wait for a second
    }
    

    Don't worry about the coding for now. Let's upload this sketch. You can press the Arrow icon, go to Sketch then Upload, or you can use the shortcut Ctrl+U in order to upload the code. Your sketch will auto-verify, compile, then upload to your Arduino board.

    Upload the SketchUpload the Sketch

    You will see the message Done uploading and your board should now have a blinking light.

    Uploading Sketches and Code From Thimble 

    We provide example code for all our projects. To use those you'll need to copy them from our website. Then, go into the Arduino IDE, File > New. It's best to then delete all the code already there in the sketch before you paste our code in, as that will avoid any errors from copying over the old code.

    Serial Plotter

    You'll be asked to use the Serial Plotter on some projects. This reads any information coming from the Arduino and displays it on a graph. It can only be accessed after you've uploaded your code. It is in the Tools menu. Once opened, make sure the Baud rate is set to 9600.

    Where to find the Serial Plotter
    Baud rate

    Troubleshooting 

    The most common issues are solved by double checking your Board and Port settings.

    Libraries

    What are Libraries? 

    Libraries are a collection of code that has already been written. We use them when we want to add functionality without have to write everything from scratch.

    Some the projects in this set need libraries so this section will show you how to install those.

    Libraries to be downloaded 

    This kit only uses the libraries you've already installed with other kits. Have fun!

    What Should I Have Received?

    List of Parts 

    This is a list of all the parts you should have received in your Robotics Kit 2 box.

    Parts

    All Parts x Qty
    Top Controller Plate x 1
    Bottom Controller Plate x 1
    Vertical Spacing Plates x 2
    Thumb Joysticks x 2
    Base shield x 1
    9 Volt Barrel Connector x 1
    Cables x 2
    Bag of Hardware x 1

    Additional parts

    You should also have received a sheet of stickers and a postcard with instructions.

    Robotics Kit 2 - Hardware

    Start 

    CompletedCompleted

    This is what the completed controller looks like. It uses WiFi to relay the joystick readings over to Robotics Kit 1. It also has two 1x1 mounting points. We will be using them for shoulder buttons.

    Modules 

    Gather the following parts to complete this project.

    Parts

    All Parts x Qty
    Top Controller Plate x 1
    Bottom Controller Plate x 1
    Vertical Spacing Plates x 2
    Thumb Joysticks x 2
    Base shield x 1
    9 Volt Barrel Connector x 1
    Cables x 2
    Bag of Hardware x 1

    Mounting the Arduino 

    The Arduino and black base shield must be separate for this step. Grab the Bottom Controller Plate, Arduino, three M3 10mm screws, and three M3 hex nuts. The Bottom Controller Plate should be facing up so you can see the L and R engravings. Place the Arduino on top of the Bottom Controller Plate so the mounting holes line up. Place a screw through one of the 3 mounting holes. Flip the Bottom Controller Plate and Arduino over and hand tighten a hex nut. Repeat for the remaining mounting holes. The top right hole makes the screw go in diagonal. This is normal.

    Separate the Arduino and Shield
    All the parts you'll need
    Make sure these letter are correct
    Take the Arduino
    These points...
    ...should fit in these holes
    Place Arduino on top
    I'm starting with this hole
    Take a screw
    Place into mounting hole
    Flip over
    Take a nut
    Hand tighten
    This one is good
    Flip back over
    Repeat with these holes
    All done
    Diagonal is normal

    Reattach the Base Shield 

    With the Arduino in place, reinsert the base shield into the Arduino. Line up the pins on the Shield with the headers in the Arduino and press down.

    Arduino and Shield
    Take the Shield
    Line up with Arduino headers
    Insert
    Just double check
    That the pins are seated

    Attaching the Buttons 

    Grab the two Vertical Spacing Plates, two button modules, four M2 10mm screw, and four M2 hex nuts. Place a button on top of a Vertical Spacing Plate so that the mounting holes in the plate line up with the hole in the module. It does not matter what orientation the plate and board are in. Place an M2 screw through the module then through the plate. Hand tighten an M2 hex nut to the screw. Repeat for the other mounting hole. Repeat these steps for the remaining Vertical Spacing Plate and module.

    All the parts
    Parts for just one
    Take button
    Line up with mounting holes
    Take a screw
    Insert in either hole
    Insert in either hole
    Flip over
    Take nut
    Attach to screw
    Hand tighten
    Flip over
    Repeat with other screw
    Repeat with other button

    Mounting the Standoffs 

    Grab the two 20mm standoffs and two M3 hex nuts. Place one standoff through one of the holes found in the hand grips on the Bottom Controller Plate.The standoff should be coming out of the side of plate with the engravings. Flip the Bottom Controller Plate over and attach a M3 hex nut to the threads of the standoff. Repeat for the remaining mounting hole and standoff.

    All the parts
    We are taking these two standoffs
    Placing them here
    Take one
    Place into L side
    Place into L side
    Flip over
    Take a nut
    Attach to standoff
    Hand tighten
    Flush with the controller
    Flip to front
    Repeat with remaining standoff

    Attaching the Vertical Plates 

    Grab the two Vertical Spacing Plates with buttons in them as well as two M3 10mm screws, and two M3 hex nuts. We will be inserting the Vertical Spacing Plates into the slots at the top of the Bottom Controller Plate. This time the orientation matters. We want the socket on the bottom with the button module facing out or towards the top. Place a hex nut in the t-slot near socket inside a Vertical Spacing Plate. The will be snug. Place the Vertical Spacing Plate into the Bottom Controller Plate. From the bottom of the Bottom Controller Plate insert a screw. It should line up with the hex nut in the t-slot. Tighten the screw but not too tight. Repeat this for the remaining side.

    All the parts
    These sockets
    Facing down or away
    Take a button
    Place into cutouts
    Place into cutouts
    The plate is sticking through
    Take a nut
    Place inside T-Slot
    Take a screw
    Place through bottom plate to T-Slot
    Hand tighten
    Flush with bottom
    Repeat with remaining button
    Repeat with remaining button

    Mount the Joysticks 

    Setting aside what we just made. Grab the two joystick modules, the Top Controller Plate, six M2 10mm screws, and six M2 hex nuts. Place a joystick module in two one of the two cutoffs for it. Do this from the bottom through the plate. Add one M2 screw from the top down. Flip over the plate and hand tighten the nut. Repeat this for the remaining two screw holes. Then repeat for the remaining joystick module and other cutout.

    All the parts
    Grab top plate
    Lift
    Place joystick from under
    Hold in place
    Place a screw
    Flip and attach a nut
    Repeat with all screws
    Repeat with remaining joystick
    You might have to move the joystick to place the screws

    Attaching the Top Controller Plate 

    Grab the Top Controller Plate, four M3 10mm screws, and two hex nuts. Place it on top of the standoffs and Vertical Spacing Plates. Place two screws into the standoffs and tighten. Slide a hex nut into a Vertical Spacing Plate's t-slot. Then add a screw and tighten. Repeat with the remaining Vertical Spacing Plate.

    All the parts
    Take top plate
    Place over bottom
    These screws
    Into the standoffs
    Don't tighten all the way
    You can still see the threads
    These screws
    Into the T-Slots
    See earlier instructions for how
    Now you can tighten these
    Check out that taper

    Wiring Up the Joysticks 

    Grab two cables. Place one end into the left joystick socket and the other side into A0. Take the remaining cable and place it into the right joystick socket and the other side into A2. The joysticks must be spaced out like this because they use two analog channels per joystick. Putting them into A0 and A1 would cause overlap and some directions wouldn't work.

    All the parts
    Left joystick into A0
    Right joystick into A2
    Use the cables
    Make the connections

    Add the WiFi Module 

    Grab the WiFi module, a cable, and a piece of tape to secure it. We are using the tape instead of screws because with the positioning of the WiFi module using screws would dig into your hand when holding the controller. Tape the WiFi module to the Bottom Controller Plate under the right joystick. Using the cable, place one end into the WiFi module socket and the other into D8.

    Adding the WiFi Module
    The module
    Will go here
    Just like this taped down
    Taking a cable now
    We will plug into D8
    Cable in the module
    Cable in the Shield

    A Battery For Later 

    We'll be using a 9-volt battery to power the controller wirelessly. Plug the cable into the battery then attach a piece of tape to the battery. Tape it down like the WiFi module but under the left joystick.

    Parts for this section
    The battery
    Will go here
    Taped onto the bottom plate
    All ready to go

    Next Section 

    With the controller assembled let's move on to the next section where we calibrate the joysticks.

    Calibrate the Joysticks

    Start 

    Why We Need to Calibrate the Joysticks 

    Each joystick uses two analog channels. One for the x-axis and one for the y-axis. The values on each channel change according to the joystick's position is a similar way to the potentiometer. As you twist the potentiometer you are changing it's resistance and therefore changing the voltage reading that goes to the Arduino.

    The joystick also has a button feature. Normally another feature like this would need another channel but using some clever engineering we don't. The potentiometer goes from 0 to 1023. Each joystick channel only goes from about 200-800. When the button is pressed it overwrites the value on the x-axis to 1023. Knowing this, whenever we see 1023 on the x-axis channel of the joystick, we know that can only come from the button being pressed. We sacrifice some resolution in the positioning for the button feature.

    We need to calibrate the joysticks because each one is going to have a different maximum and minimum value in that 200-800 range.

    Upload

    Upload the following code. The left joystick is in A0 and the right joystick is in A2.

    Download file Copy to clipboard
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    /*
        ________    _           __    __
       /_  __/ /_  (_)___ ___  / /_  / /__
        / / / __ \/ / __ `__ \/ __ \/ / _ \
       / / / / / / / / / / / / /_/ / /  __/
      /_/ /_/ /_/_/_/ /_/ /_/_.___/_/\___/
          ____        __          __  _              __ __ _ __     ___
         / __ \____  / /_  ____  / /_(_)_________   / //_/(_) /_   |__ \
        / /_/ / __ \/ __ \/ __ \/ __/ / ___/ ___/  / ,<  / / __/   __/ /
       / _, _/ /_/ / /_/ / /_/ / /_/ / /__(__  )  / /| |/ / /_    / __/
      /_/ |_|\____/_.___/\____/\__/_/\___/____/  /_/ |_/_/\__/   /____/
    */
    
    //Change this to "right" when ready
    String joystick = "left";
    
    //Holds raw measurements
    int xVal;
    int yVal;
    
    //Holds xAxis measurements
    int xMax;
    int xMin;
    
    //Holds yAxis measurements
    int yMax;
    int yMin;
    
    //Trigger for x or y measuring
    bool measuringX = true;
    
    void setup()
    {
      //Start Serial communcation to computer
      Serial.begin(9600);
    }
    
    void loop()
    {
      //If we are calibrating the left joystick
      if (joystick == "left") {
        //Use A0 and A1 for readings
        yVal = analogRead(A0);
        xVal = analogRead(A1);
        //If we are calibrating the right joystick
      } else {
        //Use A2 and A3 for readings
        yVal = analogRead(A2);
        xVal = analogRead(A3);
      }
    
      //If you are pressing the button for the first time
      if (yVal > 1020 && measuringX) {
        //Display current status
        Serial.println("___________________");
        Serial.println("Changeing to Y AXIS");
        Serial.println("___________________");
        Serial.println("Please stop pressing the Joystick");
        //Resets yVal. If this was not done it would be 1023
        yVal = 500;
        // Give user time to respond
        delay(2000);
        //Set this to change axis
        measuringX = false;
        //If you are pressing the button for the second time
      } else if (yVal > 1020) {
        //Print out all results
        printResults();
        //Purposefully get stuck in endless loop to stop measuring
        while (1);
      }
    
      //Checks to see which axis you want to measure
      if (measuringX) {
        //If the xVal is bigger than xMax
        if (xVal > xMax || xMax == 0) {
          //Make it the new Max
          xMax = xVal;
        }
        // If the xVal is smaller than xMin
        if (xVal < xMin || xMin == 0) {
          //Make it the new Min
          xMin = xVal;
        }
    
        //Print out current results
        Serial.print("The MAX X and MIN X are:");
        Serial.print(xMax);
        Serial.print(",");
        Serial.println(xMin);
        Serial.println(" ");
        delay(200);
    
      } else {
        //If the yVal is bigger than yMax
        if (yVal > yMax || yMax == 0) {
          //Make it the new Max
          yMax = yVal;
        }
        // If the yVal is smaller than yMin
        if (yVal < yMin || yMin == 0) {
          //Make it the new Min
          yMin = yVal;
        }
    
        //Print out current results
        Serial.print("The MAX Y and MIN Y are:");
        Serial.print(yMax);
        Serial.print(",");
        Serial.println(yMin);
        Serial.println(" ");
        delay(200);
    
      }
    }
    
    void printResults() {
    
      Serial.println("**********************************");
      Serial.println("Calibration Results for " + joystick + " Joystick");
      Serial.println("**********************************");
      Serial.print("The MAX X and MIN X are:");
      Serial.print(xMax);
      Serial.print(",");
      Serial.println(xMin);
      Serial.println(" ");
    
      Serial.print("The MAX Y and MIN Y are:");
      Serial.print(yMax);
      Serial.print(",");
      Serial.println(yMin);
      Serial.println(" ");
    
      Serial.print("**********************************");
    }
    
    

    How to Calibrate the Joysticks 

    How to Calibrate the Joysticks

    Open up the Serial Monitor. For each axis we will be rotating the joystick 2-3 times. This makes sure we hit the maximum and minimum values. Click the joystick and wait about 4 seconds then repeat. Click again and the Serial Monitor will print out the calibration results. Write this down somewhere. A post-it, text document, or screenshot. We are going to need these numbers. You're not done yet! change the joystick variable from left to right and repeat the whole process.

    Starting with the Left joystick
    Rotate the joystick
    Rotate the joystick
    Rotate the joystick
    Click joystick
    Rotate the joystick
    Rotate the joystick
    Rotate the joystick
    Click joystick
    Changing code for Right joystick
    Rotate the joystick
    Rotate the joystick
    Rotate the joystick
    Click joystick
    Rotate the joystick
    Rotate the joystick
    Rotate the joystick
    Click joystick

    Next Section 

    With both joysticks calibrated and values written down let's jump to the next section.

    Robotics Kit 2 - Software - Robot

    Start 

    Setting Up the Robot 

    You can use any iteration of the final RS1 project. If it has the LEDs or buzzer on it the robot will drive but those extra features won't work ... yet.

    Upload

    Upload the following code. Put your calibration values in below before uploading the code.

    Download file Copy to clipboard
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    /*
      ________    _           __    __
      /_  __/ /_  (_)___ ___  / /_  / /__
      / / / __ \/ / __ `__ \/ __ \/ / _ \
      / / / / / / / / / / / / /_/ / /  __/
      /_/ /_/ /_/_/_/ /_/ /_/_.___/_/\___/
        ____        __          __  _              __ __ _ __     ___
       / __ \____  / /_  ____  / /_(_)_________   / //_/(_) /_   |__ \
      / /_/ / __ \/ __ \/ __ \/ __/ / ___/ ___/  / ,<  / / __/   __/ /
      / _, _/ /_/ / /_/ / /_/ / /_/ / /__(__  )  / /| |/ / /_    / __/
      /_/ |_|\____/_.___/\____/\__/_/\___/____/  /_/ |_/_/\__/   /____/
    */
    
    //All the libraries used
    #include <WiFiEsp.h>
    #include <WiFiEspUdp.h>
    #include "SoftwareSerial.h"
    #include "Grove_I2C_Motor_Driver.h"
    
    // default I2C address is 0x0f
    #define I2C_ADDRESS 0x0f
    
    //Motor names
    #define LEFTMOTOR MOTOR2
    #define RIGHTMOTOR MOTOR1
    
    //Joystick Limits
    int leftUp  = 253;
    int leftDown = 769;
    int rightUp = 775;
    int rightDown = 247;
    
    //Create Serial communication Object
    SoftwareSerial Serial1(8, 9); // RX, TX
    
    WiFiEspUDP Udp;
    
    IPAddress apIP = IPAddress(192, 168, 111, 111);
    IPAddress stationIP = IPAddress(192, 168, 111, 112);
    IPAddress broadcastIP = IPAddress(0, 0, 0, 0);
    
    //Wifi settings
    char ssid[] = "My WiFi Robot";    // the name of your access point
    char pass[] = "password";        // the password for your access point
    int status = WL_IDLE_STATUS;     // the Wifi radio's status
    
    //Ports to be used
    unsigned int listeningPort = 10002;  // local port to listen on
    unsigned int sendingPort = 10003;  // local port to sent on
    
    
    //Message Variables
    #define arrayLength 6
    char data[arrayLength + 1];
    String dataAsString;
    
    // Vaiables
    int leftData = 0;
    int rightData = 0;
    
    //Motor Variables
    int leftSpeed = 0;
    int rightSpeed = 0;
    
    void setup()
    {
      // Start Serial Communication with computer and WiFi module
      Serial.begin(9600);
      // initialize serial for ESP module
      Serial1.begin(9600);
      // initialize ESP module
      WiFi.init(&Serial1);
      WiFi.configAP(apIP);
    
      // start motor driver
      Motor.begin(I2C_ADDRESS);
      // correct pwm cycles
      Motor.frequence(F_490Hz);
    
      // Print out debugging messages
      Serial.print("Attempting to start AP ");
      Serial.println(ssid);
    
      // start access point
      status =  WiFi.beginAP(ssid, 10, pass, ENC_TYPE_WPA2_PSK);
    
    
      // Set up UDP listener on port
      Udp.begin(listeningPort);
    
      // Print out which port
      Serial.print(F("Listening on port "));
      Serial.println(listeningPort);
    
    }
    
    void loop()
    {
    
      //Check for incoming packets
      int packetSize = Udp.parsePacket();
    
      // If there are packets
      if (packetSize) {
        //memset(data, 0, sizeof data);
        //Print out update
        //Serial.println("Packets Received");
        // read the packet into packetBufffer
        int len = Udp.read(data, 6);
        if (len > 0) {
          data[len] = 0;
        }
        //Send received data to function
        dataTranslate(data);
    
        //Map values to speeds
        leftSpeed = map(leftData, leftDown, leftUp, -100, 100);
        rightSpeed = map(rightData, rightDown, rightUp, -100, 100);
      }
    
      //Check to see if joystick is in deadzone
      if (leftSpeed < 10 && leftSpeed > -10) {
        //Stop motor
        Motor.stop(LEFTMOTOR);
      } else {
        //Set motor to mapped speed
        Motor.speed(LEFTMOTOR, leftSpeed);
      }
    
      //Check to see if joystick is in deadzone
      if (rightSpeed < 10 && rightSpeed > -10) {
        //Stop motor
        Motor.stop(RIGHTMOTOR);
      } else {
        //Set motor to mapped speed
        Motor.speed(RIGHTMOTOR, rightSpeed);
      }
    
      //Print out all values
      Serial.println(String(leftSpeed) + "," + String(rightSpeed));
    }
    
    //Function that takes raw string and chops it into values
    void dataTranslate(char recData[]) {
      // Set passed array into a temp variable
      dataAsString = recData;
      // Write a section of the array to a value based on location
      leftData = dataAsString.substring(0, 3).toInt();
      rightData = dataAsString.substring(3, 6).toInt();
    }
    
    
    

    Observe

    The network name of My Wifi Robot should appear as a network on your computer or phone. There is no need to connect to it this time. If you see the network you can move on to the next step.

    Robotics Kit 2 - Software - Controller

    Start 

    Controller in action

    Controller Framework 

    We'll be using the UDP messaging system from the Weather Station Series to send the joystick positions to the robot. The robot will then translate those into a direction and power for the motors. For a more in depth explanation head over to this section.

    Adding the WiFi Module 

    Take a free WiFi module and cable. Roll up a piece of tape to create double sided tape. Place one side of the tape on the bottom plate of the controller. Take the WiFi module and place it on top of the tape. Take a cable and connect one end to the WiFi module socket and the other to D8.

    Upload

    Upload the following code.

    Download file Copy to clipboard
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    /*
      ________    _           __    __
      /_  __/ /_  (_)___ ___  / /_  / /__
      / / / __ \/ / __ `__ \/ __ \/ / _ \
      / / / / / / / / / / / / /_/ / /  __/
      /_/ /_/ /_/_/_/ /_/ /_/_.___/_/\___/
        ____        __          __  _              __ __ _ __     ___
       / __ \____  / /_  ____  / /_(_)_________   / //_/(_) /_   |__ \
      / /_/ / __ \/ __ \/ __ \/ __/ / ___/ ___/  / ,<  / / __/   __/ /
      / _, _/ /_/ / /_/ / /_/ / /_/ / /__(__  )  / /| |/ / /_    / __/
      /_/ |_|\____/_.___/\____/\__/_/\___/____/  /_/ |_/_/\__/   /____/
    */
    
    //All the libraries used
    #include <WiFiEsp.h>
    #include <WiFiEspUdp.h>
    #include "SoftwareSerial.h"
    
    //Create Serial communication Object
    SoftwareSerial Serial1(8, 9); // RX, TX
    
    WiFiEspUDP Udp;
    
    IPAddress apIP = IPAddress(192, 168, 111, 111);
    IPAddress stationIP = IPAddress(192, 168, 111, 112);
    IPAddress broadcastIP = IPAddress(0, 0, 0, 0);
    
    //Wifi settings
    char ssid[] = "My WiFi Robot";    // the name of your access point
    char pass[] = "password";        // the password for your access point
    int status = WL_IDLE_STATUS;     // the Wifi radio's status
    
    //Ports to be used
    unsigned int listeningPort = 10003;  // local port to listen on
    unsigned int sendingPort = 10002;  // local port to sent on
    
    //Message Variables
    #define arrayLength 6
    char data[arrayLength + 1];
    String dataAsString;
    
    // Vaiables
    int leftData;
    int rightData;
    
    void setup()
    {
      // Start Serial Communication with computer and WiFi module
      Serial.begin(9600);
      // initialize serial for ESP module
      Serial1.begin(9600);
      // initialize ESP module
      WiFi.init(&Serial1);
      WiFi.config(stationIP);
    
      // Connect to robot
      status = WiFi.begin(ssid, pass);
    
      // Set up UDP listener on port
      Udp.begin(listeningPort);
    
      // Print out which port
      Serial.print(F("Listening on port "));
      Serial.println(listeningPort);
    }
    
    void loop() {
        //Read the Joystick values
      leftData = analogRead(A0);
      rightData = analogRead(A2);
    
        //Concatanate all the vlaues into one string
      dataAsString = String(leftData) + String(rightData);
    
        //Convert String to char array
      dataAsString.toCharArray(data, arrayLength + 1);
    
      //Print out all values
      Serial.println(data);
    
      //Begin UDP sending
      Udp.beginPacket(apIP, sendingPort);
      //Send the data
      Udp.write(data);
      //Send ending packets
      Udp.endPacket();
    
      //Battery saving delay
      delay(10);
    }
    
    

    Observe

    Make sure RS1 is powered and open up the Serial Monitor. You should see the Controller attempting to connect to the network created by RS1. After connected it will start sending the joystick position. Move the left joystick to control the left wheel and the right joystick to control the right wheel.

    Modify

    Change the robot's motor speed to go faster or slower and take a look at the following section for upgrades!

    Robot Driving Styles

    Start 

    Nonholonomic vs Holonomic 

    Holomonic Drive

    When it comes to movement there are two main differences. One is a system of movement where we can go in whatever direction we want. This would be an example of a Holonomic system. The other system is one where we cannot move however we want. This is called a Nonholonomic system. This is the type of system in which a car fits. To parallel park we cannot just slide into the spot. We must take many steps to achieve the result that a slide would get us. As we can see in the video above, the forklift is fitted with special wheels that allow it move in a Holonomic system. It can move forward, backwards, side to side, as well as turning.

    Quick terms

    Some words we need to know are defined in the part.

    Vector - A Vector is a direction and magnitude. Going 50 miles per house is just a magnitude but going 50 miles per hour heading west is a vector. The magnitude can be any unit of speed. Such as miles per hour or meters per second. A direction can be a compass heading or degrees.

    Nonholonomic Example 

    Let's look at how a car moves. The tires use friction to move the car. The tires can only produced motion in the way they are pointed. You use the pedals to apply a magnitude of speed and the steering wheel to apply a direction. These two values come together to create a vector. You can see the vector as a red arrow in the picture below.

    Classic TiresClassic Tires

    Tank or Differential Drive

    Tank drive keeps the wheel locked into one position. All the direction part of the vector comes from a difference in magnitude of the two sides. This is best illustrated in the picture below. One side is going forward and the other backward. This creates a stationary turn. Check out vectors below.

    Tank TreadsTank Treads

    Holonomic Examples 

    Here are two examples of Holonomic driving systems.

    Omni-wheels

    Omni-wheelsOmni-wheels

    Omni-wheels are wheels that In the picture below check out the individual vectors on the left and the sum total on the right.have rollers along the circumference. They rotate like normal tires but due to the rollers, you can move side to side. They are usually found at 90 or 120 degree differences to each other. Unlike a car that would have all the tires facing the same direction. By combining the vectors of multiple wheels you can achieve a Holomonic drive system. In the picture below check out the individual vectors on the left and the sum total on the right.

    Omni-wheel VectorsOmni-wheel Vectors

    Mecanum Wheels

    Mecanum WheelsMecanum Wheels

    Mecanum wheels are mounted similar to normal tires and have rollers like omni-wheels. However, their rollers are positioned at 45 degree angle to how like rotate. This allows them to create the same vectors as omni-wheels but in a simpler layout. In the picture below check out the individual vectors on the left and the sum total on the right.

    Mecanum Wheel VectorsMecanum Wheel Vectors

    Adding Additional Controls

    Start 

    Buttons in Effect

    In this section we will use the two buttons on the Controller to control individual LEDs on the robot. You'll see the frame work needs to add other inputs and outputs.

    Connecting the Buttons 

    Take a cable. Unwrap it and place one end into the left button on the Controller. The other end of the cable should go into D6. Take another cable. Unwrap it and place one end into the right button on the controller. The other end should go into D5.

    Parts for this section
    These sockets
    D5 for Left
    D6 for Right
    Take the cables
    Make the connections
    A little messy but looking good

    Upload

    Upload the following code.

    Download file Copy to clipboard
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    /*
      ________    _           __    __
      /_  __/ /_  (_)___ ___  / /_  / /__
      / / / __ \/ / __ `__ \/ __ \/ / _ \
      / / / / / / / / / / / / /_/ / /  __/
      /_/ /_/ /_/_/_/ /_/ /_/_.___/_/\___/
        ____        __          __  _              __ __ _ __     ___
       / __ \____  / /_  ____  / /_(_)_________   / //_/(_) /_   |__ \
      / /_/ / __ \/ __ \/ __ \/ __/ / ___/ ___/  / ,<  / / __/   __/ /
      / _, _/ /_/ / /_/ / /_/ / /_/ / /__(__  )  / /| |/ / /_    / __/
      /_/ |_|\____/_.___/\____/\__/_/\___/____/  /_/ |_/_/\__/   /____/
    */
    
    //All the libraries used
    #include <WiFiEsp.h>
    #include <WiFiEspUdp.h>
    #include "SoftwareSerial.h"
    
    //Button sockets
    #define leftSocket 5
    #define rightSocket 6
    //Create Serial communication Object
    SoftwareSerial Serial1(8, 9); // RX, TX
    
    
    WiFiEspUDP Udp;
    
    IPAddress apIP = IPAddress(192, 168, 111, 111);
    IPAddress stationIP = IPAddress(192, 168, 111, 112);
    IPAddress broadcastIP = IPAddress(0, 0, 0, 0);
    
    //Wifi settings
    char ssid[] = "My Wifi Robot";    // the name of your access point
    char pass[] = "password";        // the password for your access point
    int status = WL_IDLE_STATUS;     // the Wifi radio's status
    
    //Ports to be used
    unsigned int listeningPort = 10003;  // local port to listen on
    unsigned int sendingPort = 10002;  // local port to sent on
    
    //Message Variables
    #define arrayLength 8
    char data[arrayLength + 1];
    String dataAsString;
    
    // Vaiables
    int leftData;
    int rightData;
    int leftButton;
    int rightButton;
    
    void setup()
    {
      // Start Serial Communication with computer and WiFi module
      Serial.begin(9600);
      // initialize serial for ESP module
      Serial1.begin(9600);
      // initialize ESP module
      WiFi.init(&Serial1);
      WiFi.config(stationIP);
    
      // Connect to robot
      status = WiFi.begin(ssid, pass);
    
      // Set up UDP listener on port
      Udp.begin(listeningPort);
    
      // Print out which port
      Serial.print(F("Listening on port "));
      Serial.println(listeningPort);
    }
    
    void loop() {
      //Read the Joystick values
      leftData = analogRead(A0);
      rightData = analogRead(A2);
    
      //Read button values
      leftButton = digitalRead(leftSocket);
      rightButton = digitalRead(rightSocket);
    
      //Concatanate all the vlaues into one string
      dataAsString = String(leftData) + String(rightData) + String(leftButton)+ String(rightButton);
    
      //Convert String to char array
      dataAsString.toCharArray(data, arrayLength + 1);
    
      //Print out all values
      Serial.println(data);
    
      //Begin UDP sending
      Udp.beginPacket(apIP, sendingPort);
      //Send the data
      Udp.write(data);
      //Send ending packets
      Udp.endPacket();
    
      //Battery saving delay
      delay(10);
    }
    
    

    Observe

    Taking a quick look at the code you can see that we added two more placed to the data[] array. One for each button. We are adding those values to the string that we send the robot.

    Adding the LEDs 

    We'll need two Chainable LEDs as well as two more cables. Plug one cable into D6 on the Robot and the other side into the IN socket on one of the Chainable LEDs. Take another cable and plug that into the OUT side of the same LED. The other side of cable should go into the IN side of the remaining and unconnected LED. You can now take some tape and tape them down to the Robot chassis.

    Following the instruction from RS1
    Starting at D8
    IN to one LED
    OUT of same LED
    IN to other LED

    Upload

    Upload the following code.

    Download file Copy to clipboard
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    /*
      ________    _           __    __
      /_  __/ /_  (_)___ ___  / /_  / /__
      / / / __ \/ / __ `__ \/ __ \/ / _ \
      / / / / / / / / / / / / /_/ / /  __/
      /_/ /_/ /_/_/_/ /_/ /_/_.___/_/\___/
        ____        __          __  _              __ __ _ __     ___
       / __ \____  / /_  ____  / /_(_)_________   / //_/(_) /_   |__ \
      / /_/ / __ \/ __ \/ __ \/ __/ / ___/ ___/  / ,<  / / __/   __/ /
      / _, _/ /_/ / /_/ / /_/ / /_/ / /__(__  )  / /| |/ / /_    / __/
      /_/ |_|\____/_.___/\____/\__/_/\___/____/  /_/ |_/_/\__/   /____/
    */
    
    //All the libraries used
    #include <WiFiEsp.h>
    #include <WiFiEspUdp.h>
    #include "SoftwareSerial.h"
    #include "Grove_I2C_Motor_Driver.h"
    #include <ChainableLED.h>
    
    //Create Chainable LED object
    ChainableLED leds(6, 7, 2);
    
    // default I2C address is 0x0f
    #define I2C_ADDRESS 0x0f
    
    //Motor names
    #define LEFTMOTOR MOTOR2
    #define RIGHTMOTOR MOTOR1
    
    //Joystick Limits
    int leftUp  = 253;
    int leftDown = 769;
    int rightUp = 775;
    int rightDown = 247;
    
    //Button Variables
    int leftButton = 0;
    int rightButton = 0;
    
    //Create Serial communication Object
    SoftwareSerial Serial1(8, 9); // RX, TX
    
    WiFiEspUDP Udp;
    
    IPAddress apIP = IPAddress(192, 168, 111, 111);
    IPAddress stationIP = IPAddress(192, 168, 111, 112);
    IPAddress broadcastIP = IPAddress(0, 0, 0, 0);
    
    //Wifi settings
    char ssid[] = "My Wifi Robot";    // the name of your access point
    char pass[] = "password";        // the password for your access point
    int status = WL_IDLE_STATUS;     // the Wifi radio's status
    
    //Ports to be used
    unsigned int listeningPort = 10002;  // local port to listen on
    unsigned int sendingPort = 10003;  // local port to sent on
    
    
    //Message Variables
    #define arrayLength 8
    char data[arrayLength + 1];
    String dataAsString;
    
    // Vaiables
    int leftData = 0;
    int rightData = 0;
    
    //Motor Variables
    int leftSpeed = 0;
    int rightSpeed = 0;
    
    void setup()
    {
      // Start Serial Communication with computer and WiFi module
      Serial.begin(9600);
      // initialize serial for ESP module
      Serial1.begin(9600);
      // initialize ESP module
      WiFi.init(&Serial1);
      WiFi.configAP(apIP);
    
      // start motor driver
      Motor.begin(I2C_ADDRESS);
      // correct pwm cycles
      Motor.frequence(F_490Hz);
    
      // Print out debugging messages
      Serial.print("Attempting to start AP ");
      Serial.println(ssid);
    
      // start access point
      status =  WiFi.beginAP(ssid, 10, pass, ENC_TYPE_WPA2_PSK);
    
    
      // Set up UDP listener on port
      Udp.begin(listeningPort);
    
      // Print out which port
      Serial.print(F("Listening on port "));
      Serial.println(listeningPort);
    
      //Initalize the LEDs
      leds.init();
    
      //Turn both off
      leds.setColorRGB(0, 0, 0, 0);
      leds.setColorRGB(1, 0, 0, 0);
    
    }
    
    void loop()
    {
    
      //Check for incoming packets
      int packetSize = Udp.parsePacket();
    
      // If there are packets
      if (packetSize) {
        //memset(data, 0, sizeof data);
        //Print out update
        //Serial.println("Packets Received");
        // read the packet into packetBufffer
        int len = Udp.read(data, arrayLength);
        if (len > 0) {
          data[len] = 0;
        }
        //Send received data to function
        dataTranslate(data);
    
        //Map values to speeds
        leftSpeed = map(leftData, leftDown, leftUp, -100, 100);
        rightSpeed = map(rightData, rightDown, rightUp, -100, 100);
      }
    
      //Check left button values
      if (leftButton) {
        //Set Left LED to green
        leds.setColorRGB(0, 0, 255, 0);
      } else {
        //Set LED off
        leds.setColorRGB(0, 0, 0, 0);
      }
    
      //Check left button values
      if (rightButton) {
        //Set Right LED to green
        leds.setColorRGB(1, 0, 255, 0);
      } else {
        //Set LED off
        leds.setColorRGB(1, 0, 0, 0);
      }
    
      //Check to see if joystick is in deadzone
      if (leftSpeed < 10 && leftSpeed > -10) {
        //Stop motor
        Motor.stop(LEFTMOTOR);
      } else {
        //Set motor to mapped speed
        Motor.speed(LEFTMOTOR, leftSpeed);
      }
    
      //Check to see if joystick is in deadzone
      if (rightSpeed < 10 && rightSpeed > -10) {
        //Stop motor
        Motor.stop(RIGHTMOTOR);
      } else {
        //Set motor to mapped speed
        Motor.speed(RIGHTMOTOR, rightSpeed);
      }
    
      //Print out all values
      Serial.println(String(leftSpeed) + "," + String(rightSpeed) + "," + String(leftButton) + "," + String(rightButton));
    }
    
    //Function that takes raw string and chops it into values
    void dataTranslate(char recData[]) {
      //Set passed array into a temp variable
      dataAsString = recData;
      //Write a section of the array to a value based on location
      leftData = dataAsString.substring(0, 3).toInt();
      rightData = dataAsString.substring(3, 6).toInt();
      leftButton = dataAsString.substring(6, 7).toInt();
      rightButton = dataAsString.substring(7, 8).toInt();
    }
    
    
    

    Observe

    We added variables to store the new information that we are sending. You can find that towards the top of the code. In the dataTranslate function we added two new lines that read the values of the buttons from the string sent over to the Robot.

    In the main loop of the code is where we set the LEDs color based on those translated button values.

    Going Further 

    We could have added a dial or any other sensor to the controller. For simple switches we only see one more byte in the data[] array. For an analog value we would need 4 bytes.

    On the receiving side, it's important to keep track of which values are where in the string.