How to Build a Robot- Robot Assembly

November 12, 2016 | Author: Adalberto Sharpley | Category: N/A
Share Embed Donate


Short Description

Let’s look at how to build robot, first I gathered all the pieces and just kind of loosely placed them on the chas...

Description

How to Build a Robot: Robot Assembly How to Build Robot Let’s look at how to build robot, first I gathered all the pieces and just kind of loosely placed them on the chassis to get a rough idea of how they would fit. I placed the four AA batteries in the middle because they are the heaviest element, we want the heaviest thing over the center of gravity, and thus the robot will be stable and not want to tip over. Learn powerful info on how to build robot. The receiver for the IR remote has also been connected. There are 3 wires that need to be connected, PWR, which is connected to 5V on the Arduino, GND which is connected to GND on the Arduino, and IN, which is connected to port 11 on the Arduino.

We won’t need too much of the breadboard just enough to hold the ultrasonic sensor so we can later put the 9 V battery on top of it. The breadboard that I ordered came with some sticky tape

on the back the which is actually quite strong and holds very well even against wood, which is not usually a very good material for adhering to with tape. Peel the paper off to reveal the sticky part.

Then place the breadboard as close to the front of the robot as you can.

This is the box of Velcro that I use. This Velcro is nice because it comes in a long strip and you actually get quite a lot for the money compared with buying little packages. You can cut this Velcro with a pair of scissors, or a sharp utility knife.

The backside of the Arduino Uno has all the solder connections exposed it’s possible that some of these can get shorted if you laid it on top of something that was metal, its mostly plastic on top of our gearbox, but just to be sure I took the small piece of foam that came with the Arduino and mounted it on top of the foam with some little screws, but you can use just about anything else like tape or some hot melt glue if you don’t have screws. I then put the Arduino with the motor shield attached on top of the motor gearbox and fastened this down with some Velcro. Here is a view from the back of the robot you can see the small strip of Velcro and foam that the Arduino and motor shield are mounted to.

I went ahead and placed the ultrasonic sensor on the breadboard even though we haven’t yet got to programming it. We just need to get a sense of how much space it takes up, we want to leave the first two or three rows of the breadboard accessible after the ultrasonic sensor for wires to plug-in to, there is a total of 3 wires that will need to be connected to the ultrasonic sensor when we get to it. I made sure to cut the wires connected to the motor a little bit long so that I can trim them here. I cut them close so there’s not a lot of slack wire laying around.

Here you see the motor wires are connected, it matters which wire you hook up to to the individual A and B terminals on the motor shield (because of motor direction), but we can also tweak this later in software so I didn’t worry about it too much now.

I also used Velcro to attach the battery holder for the four AA batteries. I put on a piece of Velcro which was a little too wide then used a hobby knife to trim it. Velcro is particularly useful here because when we want to remove the battery pack we can just remove it and not have to worry about scraping off tape or glue.

I also attached the 9V battery and connector using some Velcro, there was just enough room left on the breadboard to be able to get the 3 wires that we will need to hook up the ultrasonic sensor.

Lastly we need to figure out a way to attach the infrared receiver, there was not a real obvious way to do this so I end up using a small piece of Velcro and just attaching it to the back one of the plastic connectors on the motor shield.

Also for the infrared receiver, the part that does the receiving is only on one side of the device, but if the robot is making a turn, this could end up putting the backside of the receiver towards us and it would not receive the signal from the remote. To fix this I took the receiver and bent it so that the portion that actually receives the IR signal is pointed up. Since I’ll mostly be standing when I’m controlling the robot and I’m pointing the remote downward, this turned out to work quite well, and had a surprisingly good range as long as you don’t go behind an object which would block the infrared signal.

Lastly I took the wires and bent them around in a manner so they wouldn’t get hung up on the tracks or snagged on something else. In this picture, everything is connected except the ultrasonic sensor.

With the robot assembled, we are ready to write a bit more sophisticated code to actually be able to control the robot using the remote. We will get it working with the remote, then add the ultrasonic sensor as an enhancement. First lets write a short program just to establish communication with the robot. This program will start one track in motion when a button on the remote is pressed.

#include

// variables for IR remote int RECV_PIN = 4; IRrecv irrecv(RECV_PIN); decode_results results; // hex code assigned to a button

const long prev_button = 0xFD20DF; void setup() { Serial.begin(9600); irrecv.enableIRIn(); // Start the receiver //motor setup pinMode(12, OUTPUT); //Initiates Motor Channel A pin pinMode(9, OUTPUT); //Initiates Brake Channel A pin } void loop() { if (irrecv.decode(&results)) {

// results is an instance of a

decode_results class, decode() returns an int //Serial.println(results.value, HEX); if(results.value == prev_button) { //Serial.println("in loop"); // move motor forward digitalWrite(12, HIGH); // Establishes forward direction of Channel A digitalWrite(9, LOW);

// Disengage the Brake for Channel A

analogWrite(3, 255);

// Spins the motor on Channel

delay(2000); } irrecv.resume(); // Receive the next value } }

Pressing the previous button on the remote, should start the left track in motion.

Not much of that code should seem new. The code for infrared remote is very similar to what we have already seen, only here we check if it matches the hex code for the prev_button, and if it does than we start the motor on channel A, which is the left track. Its good to start with a program like this that is as short and simple as possible, yet connects all the individual components together. This program pretty much covers every element that we will need to program our robot for moving about. Lets move on to writing a more sophisticated program, and then we’ll discuss some of the code in greater detail. How to Build Robot – Writing a Program to Control a two tracked robot There are a few different ways we can write a program to control a two tracked robot. The way that I ended up doing it was to write a robot class, this class will keep track of the state tracky is in. There are several different ways that we could implement the capability to turn, one way would be simply to stop one of the tracks and keep the other one going, or you could change the speed of one track which would also cause the robot to turn, but I also wanted the robot to be able to spin in place, that is if we send the command to turn left while tracky is not moving the robot should spin in place. I think things are a little bit simpler overall if we implement turns not by changing the speed of the track, but by changing the direction of the track, for example to turn left we would have the left track move backwards in the right track move forwards this would be spinning left. This also means that we only need to worry about two speeds, zero, and MAX_SPEED. We can come back later and try to make a more sophisticated turning mechanism. Here is the code that provides for controlling the Robot using 5 buttons. ( forward, backward, stop, turn left, turn right ).

// adds second motor and 2 button control #include // pin assignments const int RECV_PIN = 4; const int directionPinA = 12; const int directionPinB = 13; const int motorPinA = 3; const int motorPinB = 11;

const int brakePinA = 9; const int brakePinB = 8; // hex code assigned to a button press const long forward_button = 0xFD807F;

// uses 'VOL+' button

const long stop_button = 0xFDA05F;

// uses 'Play' button

const long reverse_button = 0xFD906F;

// uses 'VOL-' button

const long left_button = 0xFD20DF;

// uses 'prev' button

const long right_button = 0xFD609F;

// uses 'next' button

const long repeat = 0xFFFFFFFF; // global vars const int AFORWARD = LOW; const int BFORWARD = HIGH; IRrecv irrecv(RECV_PIN); decode_results results; long current_command = 0; long previous_command = 0; // speed is used globally for motion and steering const int MAX_SPEED = 255; // use speed 255 // main class to represent our robot class Robot { private: int _lts; // left track speed int _rts; // right track speed int _ltd; // left track direction int _rtd; // right track direction void drive(int lts, int rts, int ltd, int rtd); public: Robot(int lts, int rts, int ltd, int rtd); void Stop(); // engage both brakes

void DriveForward(); // both forward void DriveBackward(); // both backward void TurnLeft(); // opposite directions void TurnRight(); // opposite directions }; // create a new robot Robot tracky(0, 0, AFORWARD, BFORWARD); // our robot is named tracky void setup() { Serial.begin(9600); irrecv.enableIRIn(); // Start the receiver // setup channels A pinMode(motorPinA, OUTPUT); //Initiates Motor Channel A pin pinMode(brakePinA, OUTPUT); //Initiates Brake Channel A pin // setup Channel B pinMode(motorPinB, OUTPUT); //Initiates Motor Channel B pin pinMode(brakePinB, OUTPUT);

//Initiates Brake Channel B pin

digitalWrite(brakePinA, LOW);

// disengage the Brake for channel A

digitalWrite(brakePinB, LOW);

// disengage the brake for channel B

} void loop() { if (irrecv.decode(&results)) {

// results is an instance of a

decode_results class, decode() returns an int Serial.println(results.value, HEX); if( results.value == repeat ) { current_command = previous_command;

} else { current_command = results.value; previous_command = current_command; } // channel A is the left motor as viewed from a "driver" viewpoint" // channel B is the right motor as viewed from a "driver" viewpoint" switch (current_command) { //Serial.println("in switch statement"); case forward_button: tracky.DriveForward(); break; case stop_button: tracky.Stop(); break; case reverse_button: tracky.DriveBackward(); break; case left_button: tracky.TurnLeft(); break; case right_button: tracky.TurnRight(); break; } irrecv.resume(); // Receive the next value } } Robot::Robot(int lts, int rts, int ltd, int rtd)

{ _lts = lts; _rts = rts; _ltd = ltd; _rtd = rtd; } void Robot::drive(int lts, int rts, int ltd, int rtd) { //Serial.println(lts); digitalWrite(directionPinA, ltd); // Establishes direction of Channel A analogWrite(motorPinA, lts);

// Spins the motor on Channel A

//Serial.println(rts); digitalWrite(directionPinB, rtd); // Establishes direction of Channel B analogWrite(motorPinB, rts); full speed } void Robot::Stop() { //Serial.println("Stop"); _lts = 0; _rts = 0; drive(_lts, _rts, _ltd, _rtd); } void Robot::DriveForward() { //Serial.println("Forward"); _lts = MAX_SPEED; _rts = MAX_SPEED; _ltd = AFORWARD;

// Spins the motor on Channel B at

_rtd = BFORWARD; drive(_lts, _rts, _ltd, _rtd); } void Robot::DriveBackward() { //Serial.println("Backwards"); _lts = MAX_SPEED; _rts = MAX_SPEED; _ltd = !AFORWARD; _rtd = !BFORWARD; drive(_lts, _rts, _ltd, _rtd); } void Robot::TurnLeft() { //Serial.println("Turn Left"); Serial.println(_lts); Serial.println(_rts); // the robot does not have to be moving to turn, we will spin in place drive(MAX_SPEED, MAX_SPEED, !AFORWARD, BFORWARD); // drive the left track in the opposite direction delay(500); drive(_lts, _rts, _ltd, _rtd); // resume whatever we were doing when this function was called } void Robot::TurnRight() { //Serial.println("Turn Right"); // the robot does not have to be moving to turn, we will spin in place drive(MAX_SPEED, MAX_SPEED, AFORWARD, !BFORWARD); // drive the left track in the opposite direction

delay(500); drive(_lts, _rts, _ltd, _rtd); // resume whatever we were doing when this function was called }

Lets take a closer look at this program. The only library that we need to include is the remote control library like we did in the IR remote section.

#include

How to Build Robot if you’re new to Programming… If you’re new to programming one thing you’ll hear about before long is being advised against using global variables, this is usually good advice and by using a class here were actually avoiding the use of a lot of global variables and the problems that can come with them, ( i.e. making variables like _lts global instead of a being a member of a class) that said there are still very good uses for global variables. Things like port assignments and hex codes that are associated with a remote control button should be declared as global variables as they won’t change throughout execution of the program, note the hex codes that we use are not int, but rather long, storing these codes actually requires a data type that is larger than a normal integer type. We assign variables to all the needed Arduino ports, and then the hex codes that represent remote control button presses.

// pin assignments const int RECV_PIN = 4; const int directionPinA = 12; const int directionPinB = 13; const int motorPinA = 3; const int motorPinB = 11;

const int brakePinA = 9; const int brakePinB = 8; // hex code assigned to a button press const long forward_button = 0xFF629D;

// uses 'VOL+' button

const long stop_button = 0xFF02FD;

// uses 'Play' button

const long reverse_button = 0xFFA857;

// uses 'Vol-' button

const long left_button = 0xFF22DD;

// uses 'prev' button

const long right_button = 0xFFC23D;

// uses 'next' button

const long repeat = 0xFFFFFFFF; You’ll notice most of the code that handles the infrared remote portion of the program is identical to what we did earlier, just pasted in here. There’s also a global variable to hold MAX_SPEED which is set to 255, I’m using the highest gear ratio, and with this robot’s overall speed is not very fast. So I have MAX_SPEED set to be 255, and then provide the ability to turn simply by changing direction of the tracks.

const int MAX_SPEED = 255; // use speed 255 Remember back we were hooking up the wires to the motors and I said that how you hook up the wires was important, but we can tweak it in software? That’s being done here with the variables AFORWARD and BFORWARD. If one of your tracks is spinning in the wrong direction, you only need to change the value saved for AFORWARD or BFORWARD.

const int AFORWARD = LOW; const int BFORWARD = HIGH; I decided not to use the brakes with this program, I think it keeps things simpler. In the the setup() function we will disengage the brakes as soon as the program starts, then we’ll just use the speed to control when the robot stops by setting it to zero.

digitalWrite(brakePinA, LOW);

// disengage the Brake for channel A

digitalWrite(brakePinB, LOW);

// disengage the brake for channel B

} Also in the setup() function, we need to set up all of our various pins as inputs or outputs, enable the infrared remote, and setup the Serial Monitor.

Serial.begin(9600); irrecv.enableIRIn(); // Start the receiver // setup channels A pinMode(motorPinA, OUTPUT); //Initiates Motor Channel A pin pinMode(brakePinA, OUTPUT); //Initiates Brake Channel A pin // setup Channel B pinMode(motorPinB, OUTPUT); //Initiates Motor Channel B pin There are five public functions stop(), driveForward(), driveBackward(), turnLeft(), and turnRight(). These are the primary functions that we will call from the main loop, to control the robot.

public: Robot(int lts, int rts, int ltd, int rtd); void Stop(); // engage both brakes void DriveForward(); // both forward void DriveBackward(); // both backward void TurnLeft(); // opposite directions void TurnRight(); // opposite directions

The robot has four private variables which represent the left track speed, right track speed, left track direction, right track direction and one private function drive(). It is these four variables that

maintain the Robots ‘state’. Since they are private, you can only use them from within functions that belong to the Robot class (e.g. Robot::DriveForward() ).

private: int _lts; // left track speed int _rts; // right track speed int _ltd; // left track direction int _rtd; // right track direction void drive(int lts, int rts, int ltd, int rtd);

drive() is a low-level function that is called by the other public functions. It actually sets the track directions, and commands the motors to turn. The other public function is the constructor, which initializes the four private variables. We create a new robot object just before calling the setup() function, initializing both speeds to zero, this is done so tracky doesn’t take off as soon as we power him up.

// create a new robot Robot tracky(0, 0, AFORWARD, BFORWARD); // our robot is named tracky In the loop function we are reusing some of the code from the IR remote section. There are a couple new variables however, current command and previous command, these are used because our remote puts out a repeat code of FFFFFF instead of actually repeating the hex code for the button we pressed. What we need to do is save the current command to the previous command variable every time a button is pressed. Then we need to check if the repeat code is given, and if so, use the previous command.

void loop() { if (irrecv.decode(&results)) {

// results is an instance of a

decode_results class, decode() returns an int Serial.println(results.value, HEX);

if( results.value == repeat ) { current_command = previous_command; } else { current_command = results.value; previous_command = current_command; } After setting the value for current command correctly we have a switch statement that checks which button has been pressed, and then calls the function that corresponds to that button.

switch (current_command) { //Serial.println("in switch statement"); case forward_button: tracky.DriveForward(); break; case stop_button: tracky.Stop(); break; case reverse_button: tracky.DriveBackward(); break; case left_button: tracky.TurnLeft(); break; case right_button: tracky.TurnRight(); break; }

View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF