Introduction: Arduino Powered Autonomous Vehicle

A few months back I started playing around with Arduino micro controllers as a learning exercise (and for fun); this project is the culmination of that. The goal of the project was to create a vehicle that can autonomously navigate through a series of waypoints (GPS coordinates) while avoiding any obstacles it encounters along the way.

The project uses an assortment of electronic sensors and components, and pulled together the knowledge I had learned and synthesized from many sources along the way.

In the attached video you can see a short clip of the car on its way, in this run it navigated through five GPS waypoints on a course on my neighborhood streets totaling about 300 meters.

Step 1: Component List & Project Cost

The main components were the following:

    • A basic radio controlled (RC) vehicle. Can be a basic one like I used which are available in the $15 range. If you want to spend a bit more, get one with proportional steering and four wheel drive. The one I used was similar to this one from Amazon.com (though it came from Wal-Mart and at a lower price at the time).
    • An Arduino Uno micro controller. Amazon.com $24
    • A motor shield to control the two electric motors and allow for a separate motor power supply. Adafruit Motor Shield v2 $19.95.
    • A GPS for navigation. Adafruit Ultimate GPS Shield $49.95 (or breakout for $39.95)
    • A magnetometer for compass navigation. Adafruit HMC5883 Magnetometer $9.95
    • An HC-SR04 ultrasonic distance sensor for object avoidance. Amazon.com $6.00
    • An LCD display to display vehicle status and information. Yourduino.com $5.75 (I later upgraded to a 4-line LCD for about $12)
    • An infrared sensor & remote. Optional, added some convenience but not required for the project. I already had these components from a previous kit from Yourduino.com
    • And of course an Arduino sketch (a C++ program) to control everything (code attached in this Instructable)

    Additionally, the project used the following smaller components and accessories:

    • A thin wood board as a mounting platform; acrylic or other would have worked (and probably looked better!), but this is what I was able to find at local hobby shops
    • Breadboard(s) for making connections. I used a long narrow breadboard for the main connections, and a very small breadboard (that originally came with a proto-shield) so that I could mount the magnetometer as far from the other electronics as possible
    • Jumper wires
    • Surgu for mounting the ultrasonic sensor. Amazon.com $12

    The following tools were used:

    • Soldering iron & solder
    • Drill

    The rough project cost is around $120 - 150 depending on what components you may already have.

    A note on project cost: other than the mounting board, almost all of the other components are re-usable; either things you already have that you can use for this project, or things that we can eventually disassemble from this project and re-use elsewhere.

    Step 2: Vehicle Chassis and Mounting Platform

    I had seen posts on the internet about hacking inexpensive radio controlled (RC) cars and directly connecting an Arduino to the existing circuit board. I happened to have such a car around that my 3 year old no longer played with; it was a $15 Wal-Mart RC car.

    Unfortunately, my early soldering skills left a lot to be desired and I burned through a couple the delicate surface mount components, so I ended up with a partially functioning vehicle.

    Plan B: I ripped out the car's entire control board and purchased an Adafruit Motor Shield (v2). Problem solved. Now I had full control over the vehicle's motors...though they were pretty basic.

    The car was controlled by two DC motors: one controlled the drive, and using the pulse wave modulation (PWM) of the motor controller I was able to control the speed across a range of speeds; the other controlled the steering. This inexpensive RC car did not have proportional steering; the left and right wheels are joined, and there is a spring in the middle that holds the wheels in neutral (center) position when the DC motor is not engaged. When the motor is engaged, it goes to a full/hard turn left or right. That allowed me to turn the vehicle, but provides limitations later when I want more sophisticated navigation. For a future enhancement I will try to replace the DC motor with a servo for full proportional steering control.

    I used a thin board as a mounting surface on which I attached the breadboards, Arduino, LCD, etc. I placed the battery supplies beneath the board and passed the cables through holes I drilled.

    In the first photo above, you see (1) the LCD, (2) the main breadboard, (3) the small breadboard for the magnetometer, (4) the Arduino (you are seeing the GPS Shield as you look down), and (5) the magnetometer sitting up high on its pole mounted perch.

    Step 3: Program Logic

    The Arduino is controlled through a C++ program ("sketch"). The main action happens in the Arduino sketch loop() function which runs repeatedly. The basic program control logic is:

    1. Check to see if the kill switch was pressed (if enable in the configuration).
    2. Process any new GPS information and update the course and distance to the target. Move on to the next waypoint if we have reached the current destination.
    3. Read compass to get current bearing and decide the desired direction to turn the car
    4. Move the vehicle and check for any obstacles we need to avoid.
    5. Update LCD display

    The code to handle each of these is in separate functions.

    Fully documented source code is attached.

    Step 4: LCD Display

    The LCD provides invaluable insight what the vehicle is doing, critical for debugging and tuning the code. It also looks cool!

    While running, the main screen shows the following information:

    Row 1:

    1. tH = Target Heading, the course to the current waypoint;

    2. cH = Current Heading, the direction the vehicle is actually facing

    Row 2:

    3. Err = Error (in degrees) between the target heading and compass heading; this is a signed value indicating which direction (left or right) the vehicle needs to turn to intercept the target heading;

    4. Dist = Distance (meters) to the current waypoint; you will notice the small inline bar graph showing the remaining distance to this waypoint.

    Row 3:

    5. Snr = Sonar distance, i.e. the distance to any objects in front of the vehicle. Also has an line bar graph from 0 to the maximum detectable distance;

    6. Spd = Speed of vehicle (0-255)

    Row 4:

    7. Mem = Memory (in bytes) of free memory; the Arduino Uno only has 2k so I had to watch this closely;

    8. WPT n OF x; shows where the vehicle is in the list of waypoints.

    Step 5: Object Avoidance

    To drive autonomously, the vehicle needs to be able to check for and avoid obstacles it encounters as it drives. I handle this with a "ping" ultrasonic sensor and some computer logic.

    The sensor is a basic ultrasonic sensor. I combined that with the Arduino NewPing library, which is a big improvement over the original Ping library (among other things, it only requires a single shared pin for both send & receive).

    The sensor is pretty basic, and has a very narrow field of view. For this project, I am only using a single sensor with a fixed position (not a sweeping "radar" type implementation).

    I mounted the sensor to the front bumper of the vehicle with some Surgu. This was my first time using the product, and it works very well. I only used a single 3.5g packet, and that was sufficient for this purpose.

    The sensor has a tendency to return the occasional odd or random value...not sure why. In his excellent series of articles, Miguel Grinberg offers a simple solution: use a moving average. I adopted his MovingAverage class to the project with good results.

    The checkSonar() routine continually takes new measurements, adding each new measurement to the moving average; the average is then used for program logic.

    If an object is detected, the following logic is applied:

    • Slow down
    • If the vehicle is going straight (not turning), turn in the direction closest to our waypoint (technically, closest to the course to our waypoint).
    • If the vehicle is already turning, then turn in the opposite direction to try to avoid the object.
    • If we get within a definable distance (TOO_CLOSE) of the object, stop, backup, and try again.

    Once we have a clear path ahead, normal navigation resumes.

    Step 6: Waypoint Management

    In order to navigate a course, we need a way to manage the various waypoints. I started by creating a simple WaypointClass that holds a longitude and latitude value. I then created an array of WaypointClass members to hold the waypoints, and a currentWaypoint variable to keep track of the current waypoint.

    We continually check the distance to the current waypoint; if the distance falls within a configurable tolerance (say 5 meters), we say that the current waypoint has been reached and advance to the next waypoint in the array.

    A waypoint with 0 / 0 values signifies the end of the program.

    Step 7: GPS Navigation

    We use the GPS to answer the basic question "Where are we right now?" Since we the waypoints are known constants, with the current local information we can then calculate the distance and course to the current waypoint.

    I used the excellent Adafruit Ultimate GPS Shield for the GPS. I was very impressed with this unit. My workshop is in the house in an upstairs bedroom where I didn't expect to receive a GPS signal at all. To my surprise, I could get a good quality fix with 8 - 10 satellites! The acquisition time was amazingly fast...a few seconds, and much faster than my expensive TomTom car based GPS. Note: since the GPS shield was on the top of my vehicle, I saved money by not purchasing the separate antenna assembly and instead just used the built-in antenna...it worked great.

    I used the Adafruit GPS library, mainly because of the good sample code that allowed the GPS reading to occur in an interrupt routine; that really freed up the rest of my code so that timing was no longer a concern.

    I borrowed code from the TinyGPS library to create functions to calculate distance-to-waypoint and course-to-waypoint.

    Step 8: Compass Navigation

    The GPS works great for providing accurate location data, but the scale on which this project operates is too small for it to provide accurate heading information (the car can perform a 360 degree turn within a radius of about 6 feet, which is smaller than the typical accuracy of the GPS).

    I utilized a digital magnetometer (which I refer to in the code as the "compass" through technically it isn't a compass). The "compass" provides a super fast readout of the vehicles current heading.

    With our current location from the GPS and our current heading from the compass, we calculate the course to our destination and which way to turn (left/right) to intercept the target course.

    Note that due to limitations in the steering ability of this inexpensive RC car, there was no proportional steering and no way to use more sophisticated PID logic. Instead, I did a poor man's approach: I set a configurable "heading tolerance" of +/- 10 degrees. Meaning if our desired heading was 180 degrees, any course from 170 to 190 was acceptable to the program (note: I played with this and tuned it...about 8 degrees seemed to work best). This prevented constant steering corrections in the short term. In the long term, the problem was self-correcting: the "course to waypoint" is not static, it is constantly recalculated, so if our actual heading is off from the target heading, as we continue moving forward a new target heading is calculated and will eventually fall outside of the steering tolerance, resulting in a turn towards the target path.

    The magnetometer is very sensitive to electrical interference, so originally I mounted the compass on a mini-breadboard as far from the DC motors as possible to avoid the main culprits of interference. Unfortunately, there was still too much interference, leading to inaccurate and random compass readings. I ended up having to mount the magnetometer on a pole sitting about 10" above the car; that seemed to work well.

    Step 9: Motor & Speed Control

    The vehicle's speed is controlled through pulse wave modulation (PWM) provided by the Adafruit Motor Shield. Basically it allows us to apply partial power to the DC motor (i.e. run at 25%, 50%, 75%, 100%, etc). For practical purposes, the motor needs around 20% power just to have enough torque to overcome resistance and get rolling; and too fast of speeds made the vehicle too difficult to control. We defined a series of speeds as #define statements in the program, like SPEED_SLOW, SPEED_FAST, SPEED_NORMAL, SPEED_TURN, etc.

    The program logic sets the speed based on the following logic:

    • If the vehicle going straight (not turning), and no objects are detected, go fast
    • If the vehicle is going straight and detects an object, slow down
    • If the vehicle is turning (to avoid and object or just for intercept a navigation heading), slow down to the "turn speed"

    The steering mechanism has a spring that holds the steering in the center position when power is not applied to the steering motor; this limits the steering to either a hard-left or hard-right; proportional steering is not possible.

    In the photo above, you can see (1) the rear wheel drive motor and (2) the front wheel steering motor.

    Step 10: Infrared Sensor and Remote

    I added an infrared (IR) sensor (with corresponding handheld remote) to provide some convenient functionality :

    • Kill switch. It is convenient to have a "kill switch" feature to stop the vehicle if it is behaving poorly.
    • Controlled start. When you power up the Arduino, the vehicle may start moving before you are ready. The IR remote allows a way to add a "push button to start" functionality for a controlled start.

    The IR sensor is only marginally effective as a kill switch; it is easily hindered by direct sunlight and has a limited range.

    The remote control was nice for debugging the unit; I ultimately removed it in the final version to save memory, as the Arduino sketch was getting tight on the Arduino Uno's very tight 2K of SRAM space available for variables, data and the stack.

    Step 11: Potential Future Enhancements

    I have a list of potential enhancements that would be nice:

    • Better RC car as the chassis. My son has this car (Amazon.com $40), and it is pretty awesome...4 wheel drive, works great on grass, rocks, dirt, etc. No proportional steering though.
    • Add proportional steering...either get an RC car with this, or hack or upgrade an existing car. A servo may be one solution.
    • Add a SD card for logging the GPS track. This would require upgrading to an Arduino Mega, as the SD card requires about 700 bytes of RAM which I don't have available on the Uno.
    • Add a better remote/kill switch.
    • Add a camera for still photos or video. A first person view video would be entertaining, and helpful for debugging.
    • Add a radio to send live telemetry data so I can track progress and information in real time. A two way radio might also allow for remote upload of waypoints instead of having to recompile the Arduino sketch each time.

    Step 12: Final Thoughts

    This was a fun project. I learned a ton, and about a wide range of topics. I also benefited from a lot of information and resources that others have shared on the internet. The full program code is documented and attached, I hope you find it helpful.

    Comments

    author
    DarrellL11 made it! (author)2017-01-12

    I used a RockCrawler 3X, 4WD car, replaced its DCMotor gear reduction steering with a stepper motor, custom 3D printed a steering arm, and used AccelStepper library and coding, using MoveTo commands for steering. As you can see from the photos, my version is very tidy.

    AO6A1528.jpegAO6A1542.jpegAO6A1606.jpegAO6A1613.jpegAO6A1751.jpegAO6A1752.jpegAO6A1753.jpegAO6A1754.jpeg
    author
    guilherminhu (author)DarrellL112017-08-15

    Really Great work !!

    Can you please share more details about your work? Like the diagram and the final code.....

    Do you have an instructable for it?

    author
    figaro96 (author)DarrellL112017-03-16

    hey, can you please share the code you used to control the stepper motor for steering the car. I'm having trouble using the Motor which came with my rock crawler!

    author
    DarrellL11 (author)figaro962017-03-17

    Sure.

    Around line 28, include the AccelStepper library.

    #include // include for stepper motor turning

    Lines 50-65 replace the dcmotor references with stepper references,like so:
    // Setup motor controllers for both drive and steering (turn).
    Adafruit_StepperMotor *turnMotor = AFMS.getStepper(200, 1); // I used a NEMA 17 stepper from my 3D printer, which is 200 steps/revolution
    Adafruit_DCMotor *driveMotor = AFMS.getMotor(3);
    #define TURN_LEFT -10
    #define TURN_RIGHT 10
    #define TURN_STRAIGHT 0
    // you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
    // wrappers for the turn motor!
    void forwardstep1() {
    turnMotor->onestep(FORWARD, DOUBLE);
    }
    void backwardstep1() {
    turnMotor->onestep(BACKWARD, DOUBLE);
    }
    // Now we'll wrap the turn stepper in an AccelStepper object
    AccelStepper stepper1(forwardstep1, backwardstep1);

    Around line 217, replace the remarked turnmotor reference with stepper initialization commands

    // turnMotor->setSpeed(255); // full turn; only option with current RC car chassis
    stepper1.setMaxSpeed(100.0);
    stepper1.setAcceleration(100.0);
    stepper1.moveTo(0);

    The meat of the turning routines is in the move and avoid section. This is what mine looks like.

    void moveAndAvoid(void)
    {

    if (sonarDistance >= SAFE_DISTANCE) // no close objects in front of car
    {
    if (turnDirection == straight)
    speed = FAST_SPEED;
    else
    speed = TURN_SPEED;
    driveMotor->setSpeed(speed);
    driveMotor->run(FORWARD);
    // turnMotor->run(turnDirection);
    stepper1.moveTo(turnDirection);
    return;
    }

    if (sonarDistance > TURN_DISTANCE && sonarDistance < SAFE_DISTANCE) // not yet time to turn, but slow down
    {
    if (turnDirection == straight)
    speed = NORMAL_SPEED;
    else
    {
    speed = TURN_SPEED;
    stepper1.moveTo(turnDirection);
    // turnMotor->run(turnDirection); // alraedy turning to navigate
    }
    driveMotor->setSpeed(speed);
    driveMotor->run(FORWARD);
    return;
    }

    if (sonarDistance < TURN_DISTANCE && sonarDistance > STOP_DISTANCE) // getting close, time to turn to avoid object
    {
    speed = SLOW_SPEED;
    driveMotor->setSpeed(speed); // slow down
    driveMotor->run(FORWARD);
    switch (turnDirection)
    {
    case straight: // going straight currently, so start new turn
    {
    if (headingError <= 0)
    turnDirection = left;
    else
    turnDirection = right;
    stepper1.moveTo(turnDirection);
    // turnMotor->run(turnDirection); // turn in the new direction
    break;
    }
    case left: // if already turning left, try right
    {
    stepper1.moveTo(TURN_RIGHT);
    // turnMotor->run(TURN_RIGHT);
    break;
    }
    case right: // if already turning right, try left
    {
    stepper1.moveTo(TURN_LEFT);
    // turnMotor->run(TURN_LEFT);
    break;
    }
    } // end SWITCH

    return;
    }


    if (sonarDistance < STOP_DISTANCE) // too close, stop and back up
    {
    driveMotor->run(RELEASE); // stop
    stepper1.moveTo(TURN_STRAIGHT);
    // turnMotor->run(RELEASE); // straighten up
    turnDirection = straight;
    driveMotor->setSpeed(NORMAL_SPEED); // go back at higher speet
    driveMotor->run(BACKWARD);
    while (sonarDistance < TURN_DISTANCE) // backup until we get safe clearance
    {
    if(GPS.parse(GPS.lastNMEA()) )
    processGPS();
    currentHeading = readCompass(); // get our current heading
    calcDesiredTurn(); // calculate how we would optimatally turn, without regard to obstacles
    checkSonar();
    updateDisplay();
    delay(100);
    } // while (sonarDistance < TURN_DISTANCE)
    driveMotor->run(RELEASE); // stop backing up
    return;
    } // end of IF TOO CLOSE

    } // moveAndAvoid()

    I hope this helps. I can send my entire .ino file to you, or perhaps figure out a way to post it here, if you think that would help.

    author
    figaro96 (author)DarrellL112017-04-10

    hey thanks again for the code! I'm facing an issue with the power source. Can you explain how you kept the rc car powered on once you uploaded the code. I'm using a 9v battery but it doesn't seem to power the car for more than a minute.

    author
    DarrellL11 (author)figaro962017-04-13

    I use a 1200 mah, 7.4 V lithium ion battery to power both the Arduino and the Rockcrawler motors and servo. 9V batteries don't have enough current to run the motors. See attached photo.

    IMG_4300.JPG
    author
    figaro96 (author)DarrellL112017-04-26

    Hi, I followed what you did but now the car gives me trouble with it's movement. It just keeps going backward in a circle and then the display on the LCD freezes. I think everything is properly connected. Do you know of any reason why this might be happening?

    author
    DarrellL11 (author)figaro962017-04-26

    Check if the drive motor reverses direction when your IR detector senses an object in front of your car . The IR echo value displayed on the LCD should drop from a high number like 90 to a low number like 6 or 3, and the tires should reverse direction.

    Also check if the number at the end of the first line of the LCD display is 0, 10, or -10 as you rotate the car around a circle. It should read 0 when you're pointed at your destination, -10 for a left turn, and 10 for a right turn.

    author
    annas.fresti (author)2017-08-09

    interesting project, superb, sorry nubie here, but there is no schematic diagram so i cant try this project, anyone have it? It would
    be helpful. Please send it to sayahabibi@gmail.com

    author
    DhairyaN1 (author)2017-08-02

    How do u control it? without IR and remote

    author
    Filbert93 (author)2015-03-25

    Hi , can anyone send me a schematic circuit for this project? It would be helpful and I really need it. Please send it to filbert_z@yahoo.com .. Thanks for the help !

    author

    I am also interested to receive the schematic. pf_link@hotmail.com

    Prior to purchase the components, I would like to see the connections et accuracy limitations.

    author
    krunals8 (author)2017-06-16

    Really Great work !! It will really nice of you if you can provide wiring diagram

    author
    VaddepallyB1 (author)2017-06-07

    can you please provide us schematic circuit diagram

    Thank you

    author
    VikyV (author)2017-04-16

    where can i able to find math.h library file for this poject. please help me out

    replay ASAP

    author
    DarrellL11 (author)2017-03-17
    //Following is the .ino file for my Rockcrawler project with stepper //motor steering. Copy and paste, then save the code below this.
    //___________________________________________________
    //
    // Autonomous RC Car
    //
    //
    // ARDUINO (UNO) SETUP:
    // =======================
    // Ping sensor = 5V, GRND, D11 (for both trigger & echo)
    // LCD Display = I2C : SCL (A5) & SDA (A4)
    // Adafruit GPS = D7 & D8 (GPS Shield, but pins used internally)
    // IR Receiver = D5
    // Adafruit Magnetometer Adafruit_HMC5883 = I2C : SCL (A5) & SDA (A4)
    // SD Card (D10, D11, D12, D13)
    //


    #include // used by: motor driver
    #include // motor driver
    #include // motor driver
    #include // Ping sonar
    #include // LCD library
    #include // part of mag sensor
    #include // mag sensor
    #include // custom class to manaage GPS waypoints
    #include // GPS
    #include // used by: GPS
    #include // used by: GPS
    #include // simple moving average class; for Sonar functionality
    #include // include for stepper motor turning
    //#include // PString class, for "message" variable; LCD display


    // Select optional features
    // COMMENT OUT IF NOT DESIRED, don't just change to "NO"
    #define USE_GRAPHING YES // comment out to skip graphing functions in LCD display
    #define USE_LCD_BACKLIGHT YES // use backlight on LCD; commenting out may help in direct sunlight
    #define DEBUG YES // debug mode; uses Serial Port, displays diagnostic information, etc.
    //#define USE_IR YES // comment out to skip using the IR sensor/remote
    //#define NO_GPS_WAIT YES // define this for debugging to skip waiting for GPS fix


    // Setup magnemeter (compass); uses I2C
    Adafruit_HMC5883_Unified compass = Adafruit_HMC5883_Unified(12345);
    sensors_event_t compass_event;


    // Create the motor shield object with the default I2C address
    Adafruit_MotorShield AFMS = Adafruit_MotorShield();


    // Setup motor controllers for both drive and steering (turn).
    Adafruit_StepperMotor *turnMotor = AFMS.getStepper(200, 1); // I used a NEMA 17 stepper from my 3D printer, which is 200 steps/revolution
    Adafruit_DCMotor *driveMotor = AFMS.getMotor(3);
    #define TURN_LEFT -10
    #define TURN_RIGHT 10
    #define TURN_STRAIGHT 0
    // you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
    // wrappers for the turn motor!
    void forwardstep1() {
    turnMotor->onestep(FORWARD, DOUBLE);
    }
    void backwardstep1() {
    turnMotor->onestep(BACKWARD, DOUBLE);
    }
    // Now we'll wrap the turn stepper in an AccelStepper object
    AccelStepper stepper1(forwardstep1, backwardstep1);

    // LCD Display
    LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3,POSITIVE); // Set the LCD I2C address and size (4x20) //changed address from 0x3F
    #define LEFT_ARROW 0x7F
    #define RIGHT_ARROW 0x7E
    #define DEGREE_SYMBOL 0xDF
    //char lcd_buffer[20];
    //PString message(lcd_buffer, sizeof(lcd_buffer)); // holds message we display on line 4 of LCD


    // Ultrasonic ping sensor
    #define TRIGGER_PIN 11
    #define ECHO_PIN 11
    #define MAX_DISTANCE_CM 250 // Maximum distance we want to ping for (in CENTIMETERS). Maximum sensor distance is rated at 400-500cm.
    #define MAX_DISTANCE_IN (MAX_DISTANCE_CM / 2.5) // same distance, in inches
    int sonarDistance;
    NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE_CM); // NewPing setup of pins and maximum distance.
    MovingAverage sonarAverage(MAX_DISTANCE_IN); // moving average of last n pings, initialize at MAX_DISTANCE_IN


    // Compass navigation
    int targetHeading; // where we want to go to reach current waypoint
    int currentHeading; // where we are actually facing now
    int headingError; // signed (+/-) difference between targetHeading and currentHeading
    #define HEADING_TOLERANCE 5 // tolerance +/- (in degrees) within which we don't attempt to turn to intercept targetHeading


    // GPS Navigation
    #define GPSECHO false // set to TRUE for GPS debugging if needed
    //#define GPSECHO true // set to TRUE for GPS debugging if needed
    SoftwareSerial mySerial(8, 7); // digital pins 7 & 8
    Adafruit_GPS GPS(&mySerial);
    boolean usingInterrupt = false;
    float currentLat,
    currentLong,
    targetLat,
    targetLong;
    int distanceToTarget, // current distance to target (current waypoint)
    originalDistanceToTarget; // distance to original waypoing when we started navigating to it


    // Waypoints
    #define WAYPOINT_DIST_TOLERANE 5 // tolerance in meters to waypoint; once within this tolerance, will advance to the next waypoint
    #define NUMBER_WAYPOINTS 5 // enter the numebr of way points here (will run from 0 to (n-1))
    int waypointNumber = -1; // current waypoint number; will run from 0 to (NUMBER_WAYPOINTS -1); start at -1 and gets initialized during setup()
    //waypointClass waypointList[NUMBER_WAYPOINTS] = {waypointClass(30.508302, -97.832624), waypointClass(30.508085, -97.832494), waypointClass(30.507715, -97.832357), waypointClass(30.508422, -97.832760), waypointClass(30.508518,-97.832665) };
    waypointClass waypointList[NUMBER_WAYPOINTS] = {waypointClass(-122.15187, 38.04881), waypointClass(-122.15105, 38.04988), waypointClass(-122.15105, 38.04988), waypointClass(-122.15077, 38.05016), waypointClass(-122.15118, 38.04997) }; //

    // Steering/turning
    enum directions {left = TURN_LEFT, right = TURN_RIGHT, straight = TURN_STRAIGHT} ;
    directions turnDirection = straight;


    // Object avoidance distances (in inches)
    #define SAFE_DISTANCE 70
    #define TURN_DISTANCE 40
    #define STOP_DISTANCE 12


    // Speeds (range: 0 - 255)
    #define FAST_SPEED 150
    #define NORMAL_SPEED 125
    #define TURN_SPEED 100
    #define SLOW_SPEED 75
    int speed = NORMAL_SPEED;

    // IR Receiver
    #ifdef USE_IR
    #include "IRremote.h" // IR remote
    #define IR_PIN 5
    IRrecv IR_receiver(IR_PIN); // create instance of 'irrecv'
    decode_results IR_results; // create instance of 'decode_results'
    #endif


    // IR result codes
    #define IR_CODE_FORWARD 0x511DBB
    #define IR_CODE_LEFT 0x52A3D41F
    #define IR_CODE_OK 0xD7E84B1B
    #define IR_CODE_RIGHT 0x20FE4DBB
    #define IR_CODE_REVERSE 0xA3C8EDDB
    #define IR_CODE_1 0xC101E57B
    #define IR_CODE_2 0x97483BFB
    #define IR_CODE_3 0xF0C41643
    #define IR_CODE_4 0x9716BE3F
    #define IR_CODE_5 0x3D9AE3F7
    #define IR_CODE_6 0x6182021B
    #define IR_CODE_7 0x8C22657B
    #define IR_CODE_8 0x488F3CBB
    #define IR_CODE_9 0x449E79F
    #define IR_CODE_STAR 0x32C6FDF7
    #define IR_CODE_0 0x1BC0157B
    #define IR_CODE_HASHTAG 0x3EC3FC1B


    //
    // Interrupt is called once a millisecond, looks for any new GPS data, and stores it
    SIGNAL(TIMER0_COMPA_vect)
    {
    GPS.read();
    }


    //
    // turn interrupt on and off
    void useInterrupt(boolean v)
    {
    if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
    } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
    }
    }

    void setup()
    {

    // turn on serial monitor
    Serial.begin(115200); // we need this speed for the GPS


    //
    // Start LCD display
    lcd.begin(20, 4); // start the LCD...new version doesn't require size startup parameters
    #ifdef USE_LCD_BACKLIGHT
    lcd.backlight();
    #else
    lcd.noBacklight();
    #endif
    lcd.clear();
    #ifdef USE_GRAPHING
    createLCDChars(); // initialize LCD with graphing characters
    #endif


    //
    // Start motor drives
    AFMS.begin(); // create with the default frequency 1.6KHz

    // Set the speed to start, from 0 (off) to 255 (max speed)
    driveMotor->setSpeed(NORMAL_SPEED);
    // turnMotor->setSpeed(255); // full turn; only option with current RC car chassis
    stepper1.setMaxSpeed(100.0);
    stepper1.setAcceleration(100.0);
    stepper1.moveTo(0);

    //
    // start Mag / Compass
    if(!compass.begin())
    {
    #ifdef DEBUG
    Serial.println(F("COMPASS ERROR"));
    #endif
    lcd.print(F("COMPASS ERROR"));
    loopForever(); // loop forever, can't operate without compass
    }


    //
    // start GPS and set desired configuration
    GPS.begin(9600); // 9600 NMEA default speed
    GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // turns on RMC and GGA (fix data)
    GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
    GPS.sendCommand(PGCMD_NOANTENNA); // turn off antenna status info
    useInterrupt(true); // use interrupt to constantly pull data from GPS
    delay(1000);

    //
    // Wait for GPS to get signal
    #ifndef NO_GPS_WAIT
    lcd.setCursor(0, 0);
    lcd.print(F("Autonomous R/C car"));
    lcd.setCursor(0, 1);
    lcd.print(F("Built by Darrell Lee"));
    unsigned long startTime = millis();
    while (!GPS.fix) // wait for fix, updating display with each new NMEA sentence received
    {
    lcd.setCursor(0, 2);
    lcd.print(F("Waiting for GPS: "));
    lcd.print((int) (millis() - startTime) / 1000); // show how long we have waited
    if (GPS.newNMEAreceived())
    GPS.parse(GPS.lastNMEA());
    } // while (!GPS.fix)
    //delay(1000);
    #endif


    //
    // Start the IR receiver
    #ifdef USE_IR
    IR_receiver.enableIRIn(); // Start the receiver
    // Wait for operator to press key to start moving
    lcd.setCursor(0, 3);
    lcd.print(F("Press key to start"));
    while(!IR_receiver.decode(&IR_results)) ; // wait for key press
    IR_receiver.resume(); // get ready for any additional input
    #else
    // if not waiting for user input to start driving, at least give a countdown so they are ready...
    lcd.clear();
    lcd.print(F("GPS Acquired"));
    lcd.setCursor(0, 1);
    lcd.print(F("Starting in..."));
    lcd.setCursor(0, 2);
    for (int i = 10; i > 0; i--)
    {
    lcd.print(i);
    lcd.print(F(" "));
    if (GPS.newNMEAreceived())
    GPS.parse(GPS.lastNMEA());
    delay(500);
    }
    #endif


    //
    // get initial waypoint; also sets the distanceToTarget and courseToTarget varilables
    nextWaypoint();

    } // setup()


    void loop()
    {

    // check for manual kill switch pressed
    #ifdef USE_IR
    checkKillSwitch();
    #endif

    // Process GPS
    if (GPS.newNMEAreceived()) // check for updated GPS information
    {
    if(GPS.parse(GPS.lastNMEA()) ) // if we successfully parse it, update our data fields
    processGPS();
    }

    // navigate
    currentHeading = readCompass(); // get our current heading
    calcDesiredTurn(); // calculate how we would optimatally turn, without regard to obstacles

    // distance in front of us, move, and avoid obstacles as necessary
    checkSonar();
    moveAndAvoid();
    stepper1.run();
    // update display and serial monitor
    updateDisplay();

    } // loop()


    //
    // Called after new GPS data is received; updates our position and course/distance to waypoint
    void processGPS(void)
    {
    currentLat = convertDegMinToDecDeg(GPS.latitude);
    currentLong = convertDegMinToDecDeg(GPS.longitude);

    if (GPS.lat == 'S') // make them signed
    currentLat = -currentLat;
    if (GPS.lon = 'W')
    currentLong = -currentLong;

    // update the course and distance to waypoint based on our new position
    distanceToWaypoint();
    courseToWaypoint();

    } // processGPS(void)


    void checkSonar(void)
    {
    int dist;

    dist = sonar.ping_in(); // get distqnce in inches from the sensor
    if (dist == 0) // if too far to measure, return max distance;
    dist = MAX_DISTANCE_IN;
    sonarDistance = sonarAverage.add(dist); // add the new value into moving average, use resulting average
    } // checkSonar()


    int readCompass(void)
    {
    compass.getEvent(&compass_event);
    float heading = atan2(compass_event.magnetic.y, compass_event.magnetic.x);

    // Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
    // Find yours here: http://www.magnetic-declination.com/
    // Cedar Park, TX: Magnetic declination: 4° 11' EAST (POSITIVE); 1 degreee = 0.0174532925 radians
    //Vallejo, CA Mag decl 13° 39' = 13.65 * .0174532925

    #define DEC_ANGLE 0.2382
    // #define DEC_ANGLE 0.069
    heading += DEC_ANGLE;

    // Correct for when signs are reversed.
    if(heading < 0)
    heading += 2*PI;

    // Check for wrap due to addition of declination.
    if(heading > 2*PI)
    heading -= 2*PI;

    // Convert radians to degrees for readability.
    float headingDegrees = heading * 180/M_PI;

    return ((int)headingDegrees);
    } // readCompass()

    void calcDesiredTurn(void)
    {
    // calculate where we need to turn to head to destination
    headingError = targetHeading - currentHeading;

    // adjust for compass wrap
    if (headingError < -180)
    headingError += 360;
    if (headingError > 180)
    headingError -= 360;

    // calculate which way to turn to intercept the targetHeading
    if (abs(headingError) <= HEADING_TOLERANCE) // if within tolerance, don't turn
    turnDirection = straight;
    else if (headingError < 0)
    turnDirection = left;
    else if (headingError > 0)
    turnDirection = right;
    else
    turnDirection = straight;

    } // calcDesiredTurn()


    void moveAndAvoid(void)
    {

    if (sonarDistance >= SAFE_DISTANCE) // no close objects in front of car
    {
    if (turnDirection == straight)
    speed = FAST_SPEED;
    else
    speed = TURN_SPEED;
    driveMotor->setSpeed(speed);
    driveMotor->run(FORWARD);
    // turnMotor->run(turnDirection);
    stepper1.moveTo(turnDirection);
    return;
    }

    if (sonarDistance > TURN_DISTANCE && sonarDistance < SAFE_DISTANCE) // not yet time to turn, but slow down
    {
    if (turnDirection == straight)
    speed = NORMAL_SPEED;
    else
    {
    speed = TURN_SPEED;
    stepper1.moveTo(turnDirection);
    // turnMotor->run(turnDirection); // alraedy turning to navigate
    }
    driveMotor->setSpeed(speed);
    driveMotor->run(FORWARD);
    return;
    }

    if (sonarDistance < TURN_DISTANCE && sonarDistance > STOP_DISTANCE) // getting close, time to turn to avoid object
    {
    speed = SLOW_SPEED;
    driveMotor->setSpeed(speed); // slow down
    driveMotor->run(FORWARD);
    switch (turnDirection)
    {
    case straight: // going straight currently, so start new turn
    {
    if (headingError <= 0)
    turnDirection = left;
    else
    turnDirection = right;
    stepper1.moveTo(turnDirection);
    // turnMotor->run(turnDirection); // turn in the new direction
    break;
    }
    case left: // if already turning left, try right
    {
    stepper1.moveTo(TURN_RIGHT);
    // turnMotor->run(TURN_RIGHT);
    break;
    }
    case right: // if already turning right, try left
    {
    stepper1.moveTo(TURN_LEFT);
    // turnMotor->run(TURN_LEFT);
    break;
    }
    } // end SWITCH

    return;
    }


    if (sonarDistance < STOP_DISTANCE) // too close, stop and back up
    {
    driveMotor->run(RELEASE); // stop
    stepper1.moveTo(TURN_STRAIGHT);
    // turnMotor->run(RELEASE); // straighten up
    turnDirection = straight;
    driveMotor->setSpeed(NORMAL_SPEED); // go back at higher speet
    driveMotor->run(BACKWARD);
    while (sonarDistance < TURN_DISTANCE) // backup until we get safe clearance
    {
    if(GPS.parse(GPS.lastNMEA()) )
    processGPS();
    currentHeading = readCompass(); // get our current heading
    calcDesiredTurn(); // calculate how we would optimatally turn, without regard to obstacles
    checkSonar();
    updateDisplay();
    delay(100);
    } // while (sonarDistance < TURN_DISTANCE)
    driveMotor->run(RELEASE); // stop backing up
    return;
    } // end of IF TOO CLOSE

    } // moveAndAvoid()



    void nextWaypoint(void)
    {
    waypointNumber++;
    targetLat = waypointList[waypointNumber].getLat();
    targetLong = waypointList[waypointNumber].getLong();

    if ((targetLat == 0 && targetLong == 0) || waypointNumber >= NUMBER_WAYPOINTS) // last waypoint reached?
    {
    driveMotor->run(RELEASE); // make sure we stop
    stepper1.moveTo(TURN_STRAIGHT);
    // turnMotor->run(RELEASE);
    lcd.clear();
    lcd.println(F("* LAST WAYPOINT *"));
    loopForever();
    }

    processGPS();
    distanceToTarget = originalDistanceToTarget = distanceToWaypoint();
    courseToWaypoint();

    } // nextWaypoint()


    // returns distance in meters between two positions, both specified
    // as signed decimal-degrees latitude and longitude. Uses great-circle
    // distance computation for hypothetical sphere of radius 6372795 meters.
    // Because Earth is no exact sphere, rounding errors may be up to 0.5%.
    // copied from TinyGPS library
    int distanceToWaypoint()
    {

    float delta = radians(currentLong - targetLong);
    float sdlong = sin(delta);
    float cdlong = cos(delta);
    float lat1 = radians(currentLat);
    float lat2 = radians(targetLat);
    float slat1 = sin(lat1);
    float clat1 = cos(lat1);
    float slat2 = sin(lat2);
    float clat2 = cos(lat2);
    delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
    delta = sq(delta);
    delta += sq(clat2 * sdlong);
    delta = sqrt(delta);
    float denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
    delta = atan2(delta, denom);
    distanceToTarget = delta * 6372795;

    // check to see if we have reached the current waypoint
    if (distanceToTarget <= WAYPOINT_DIST_TOLERANE)
    nextWaypoint();

    return distanceToTarget;
    } // distanceToWaypoint()


    // returns course in degrees (North=0, West=270) from position 1 to position 2,
    // both specified as signed decimal-degrees latitude and longitude.
    // Because Earth is no exact sphere, calculated course may be off by a tiny fraction.
    // copied from TinyGPS library
    int courseToWaypoint()
    {
    float dlon = radians(targetLong-currentLong);
    float cLat = radians(currentLat);
    float tLat = radians(targetLat);
    float a1 = sin(dlon) * cos(tLat);
    float a2 = sin(cLat) * cos(tLat) * cos(dlon);
    a2 = cos(cLat) * sin(tLat) - a2;
    a2 = atan2(a1, a2);
    if (a2 < 0.0)
    {
    a2 += TWO_PI;
    }
    targetHeading = degrees(a2);
    return targetHeading;
    } // courseToWaypoint()

    // converts lat/long from Adafruit degree-minute format to decimal-degrees; requires library
    double convertDegMinToDecDeg (float degMin)
    {
    double min = 0.0;
    double decDeg = 0.0;

    //get the minutes, fmod() requires double
    min = fmod((double)degMin, 100.0);

    //rebuild coordinates in decimal degrees
    degMin = (int) ( degMin / 100 );
    decDeg = degMin + ( min / 60 );

    return decDeg;
    }

    //
    // Uses 4 line LCD display to show the following information:
    // LINE 1: Target Heading; Current Heading;
    // LINE 2: Heading Error; Distance to Waypoint;
    // LINE 3: Sonar Distance; Speed;
    // LINE 4: Memory Availalble; Waypoint X of Y;
    void updateDisplay(void)
    {

    static unsigned long lastUpdate = millis(); // for controlling frequency of LCD updates
    unsigned long currentTime;

    // check time since last update
    currentTime = millis();
    if (lastUpdate > currentTime) // check for time wrap around
    lastUpdate = currentTime;

    if (currentTime >= lastUpdate + 500 ) // limit refresh rate
    {
    lastUpdate = currentTime;

    // line 1
    lcd.clear();
    lcd.print(F("tH= "));
    lcd.print(targetHeading, DEC);
    lcd.write(DEGREE_SYMBOL);
    lcd.print(F(" cH= "));
    lcd.print(currentHeading, DEC);
    lcd.write(DEGREE_SYMBOL);
    lcd.print(turnDirection);
    // line 2
    lcd.setCursor(0, 1);
    lcd.print(F("Err "));
    if (headingError < 0)
    lcd.write(LEFT_ARROW);
    lcd.print(abs(headingError), DEC);
    if (headingError > 0)
    lcd.write(RIGHT_ARROW);
    lcd.print(F(" Dist "));
    lcd.print(distanceToTarget, DEC);
    lcd.print(F("m "));
    #ifdef USE_GRAPHING
    lcd.write(map(distanceToTarget, 0, originalDistanceToTarget, 0, 7)); // show tiny bar graph of distance remaining
    #endif

    // line 3
    lcd.setCursor(0, 2);
    lcd.print(F("Snr "));
    lcd.print(sonarDistance, DEC);
    #ifdef USE_GRAPHING
    lcd.write(map(sonarDistance, 0, MAX_DISTANCE_IN, 0, 7));
    #endif
    lcd.print(F(" Spd "));
    lcd.print(speed, DEC);
    #ifdef USE_GRAPHING
    lcd.write(map(speed, 0, 255, 0, 7));
    #endif

    // line 4
    lcd.setCursor(0, 3);
    lcd.print(F("Mem "));
    lcd.print(freeRam(), DEC);
    lcd.print(F(" WPT "));
    lcd.print(waypointNumber + 1, DEC);
    lcd.print(F(" OF "));
    lcd.print(NUMBER_WAYPOINTS - 1, DEC);


    #ifdef DEBUG
    //Serial.print("GPS Fix:");
    //Serial.println((int)GPS.fix);
    Serial.print(F("LAT = "));
    Serial.print(currentLat);
    Serial.print(F(" LON = "));
    Serial.println(currentLong);
    //Serial.print("Waypint LAT =");
    //Serial.print(waypointList[waypointNumber].getLat());
    //Serial.print(F(" Long = "));
    //Serial.print(waypointList[waypointNumber].getLong());
    Serial.print(F(" Dist "));
    Serial.print(distanceToWaypoint());
    Serial.print(F("Original Dist "));
    Serial.println(originalDistanceToTarget);
    Serial.print(F("Compass Heading "));
    Serial.println(currentHeading);
    Serial.print(F("GPS Heading "));
    Serial.println(GPS.angle);

    //Serial.println(GPS.lastNMEA());

    //Serial.print(F("Sonar = "));
    //Serial.print(sonarDistance, DEC);
    //Serial.print(F(" Spd = "));
    //Serial.println(speed, DEC);
    //Serial.print(F(" Target = "));
    //Serial.print(targetHeading, DEC);
    //Serial.print(F(" Current = "));
    //Serial.print(currentHeading, DEC);
    //Serial.print(F(" Error = "));
    //Serial.println(headingError, DEC);
    //Serial.print(F("Free Memory: "));
    //Serial.println(freeRam(), DEC);
    #endif

    } // if (currentTime >= lastUpdate + 500 )

    } // updateDisplay()

    //
    // Display free memory available
    //#ifdef DEBUG
    int freeRam () // display free memory (SRAM)
    {
    extern int __heap_start, *__brkval;
    int v;
    return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
    } // freeRam()
    //#endif


    // end of program routine, loops forever
    void loopForever(void)
    {
    while (1)
    ;
    }


    //
    // Graphing (mini-inline bar graph for LCD display)
    #ifdef USE_GRAPHING
    void createLCDChars(void)
    {
    int lvl = 0;
    byte arry[8];
    for (int a = 7; a >= 0; a--)
    {
    for (int b = 0; b <= 7; b++)
    {
    if (b >= lvl)
    arry[b] = B11111; // solid
    else
    //arry[b] = B00000; // blank row
    arry[b] = B10001; // hollow but with sides
    }
    lcd.createChar(a, arry);
    lvl++;
    }
    } // createLCDChars(void)
    #endif


    //
    // Implement an IR "kill switch" if selected in configuration options
    #ifdef USE_IR
    void checkKillSwitch(void)
    {
    if(IR_receiver.decode(&IR_results)) // check for manual "kill switch"
    {
    stepper1.moveTo(TURN_STRAIGHT);
    // turnMotor->run(RELEASE);
    driveMotor->run(RELEASE);

    lcd.clear();
    lcd.print(F("Press to resume"));
    delay(1000);

    IR_receiver.resume();
    while(!IR_receiver.decode(&IR_results)) ; // wait for key press
    IR_receiver.resume(); // get ready for any additional input
    }
    } // checkKillSwitch()
    #endif


    author
    BrianT200 (author)2017-01-27

    ​Awesome Tutorial. I really like how you incorporated many aspects such as GPS Nav, motor control, and object avoidance. I'm in the middle of putting a truck together; I think i'm going to attempt to use a few IR sensors to help with multiple angles, instead of relying on one ultrasonic sensor. Nice Job!

    author
    wajidmasood (author)2017-01-24

    can you share links of all libraries that you have used in your program

    author
    RobertoC174 (author)2017-01-24

    Congratulations for this project.

    Good evening, is it possible to have the circuit design, because it seems unclear how to connect wires without it.

    Thank you very much.

    author
    thecrazyinnovators (author)2017-01-17

    in the lcd display will the location be displayed via the name or in latitude n longitude?

    author

    The lcd does not display your location. It shows direction and distance to your target waypoint.

    author
    NishanthM3 (author)2016-12-20

    can u send the main abstract of this project

    author
    ali3_2001 (author)2016-08-21

    Hi,

    targetHeading = degrees(a2);
    above assignment gives the following error:

    "error: lvalue required as left operand of assignment."

    I have seen seen the source at https://github.com/mikalhart/TinyGPS/blob/master/TinyGPS.cpp
    there this assignment hasn't been made.

    CPARKTX since you have used this assignment in your project could you please explain the error?

    author
    ShehwarK (author)ali3_20012016-10-12

    Hi.
    Can u send the code of this project to me ?

    author
    ali3_2001 (author)ShehwarK2016-12-13

    what is your application

    author
    ali3_2001 (author)ShehwarK2016-11-15

    hi shehwark

    author
    rudiracer (author)2016-11-24

    I have some problems with my GPS. It is disturbing my steering servo because it gives some voltage peaks. Is there someone who can help me with this?

    author
    7991VJ (author)2016-11-10

    how to fix this error

    C:\Users\VJ\AppData\Local\Temp\arduino_modified_sketch_559611\sketch_nov10a.ino:17:66: fatal error: Adafruit_MotorShield.h: No such file or directory

    #include // motor driver

    ^

    compilation terminated.

    exit status 1
    Error compiling for board Arduino/Genuino Uno

    author
    HeadlessHamster (author)7991VJ2016-11-20

    Have you installed the adafruit motorshield library (correctly)?

    author
    nidane (author)2016-10-17

    Hi,

    I use a different type of GPS and compass and also L293D Motor shield.

    Can you help me in how to modify the code RC_Car_Test_2014_07_20_001.

    author
    ali3_2001 (author)nidane2016-11-15

    Which GPS are you using?

    author
    nidane (author)ali3_20012016-11-16

    Hi again,

    I use Skylab SKM53 GPS.

    author
    7991VJ (author)2016-11-09

    CAN YOU GIVE A CIRCUIT DESIGN

    author
    cityflex (author)2016-04-05

    I downloaded you're waypoint.h file. Since it isn't a library I can't
    upload it to arduino. Neither can I find a library that may have this
    waypoint.h. Help with this please

    author
    salmansahilkhan (author)cityflex2016-10-06

    Hello dear cityflex
    Dear I am one of the B'S telecommunications student I want to do final year project kindly send me the proposal ,abstract and report of this project .

    And how much it will cost to make it.


    Kindly reply me on zarifullah1993@gmail.com

    author
    ali3_2001 (author)cityflex2016-08-21

    Create a folder name wapointClass in Arduino Library folder

    open wapointClass file in wordpad

    SAVE AS with the name "wapointClass.h" in the arduino library directory folder name wapointClass that you initially created.

    author
    AbdullahK24 (author)2016-09-30

    when you shot videos do it in landscape and not portrait

    author
    mharker1 (author)2016-08-29

    when you shot videos do it in landscape and not portrait

    author
    AdityaG66 (author)2016-07-28

    Hey CPARKTX! I am trying to make a wifi enabled gps tracker robot. Can you please forward me your final code for this one? It will be a great help, Thanks!

    gaag454545@gmail.com

    author
    RichardW170 (author)2016-05-09

    Very interesting project. Thanks for the details

    I am thinking about applying major parts of this to help a friend who is blind to get around.

    author
    arif mulla (author)2015-05-24

    with your program i m getting this error plz help me out i m trying to buid same project as yours but getting error

    error is ->RC_Car_Test_2014_07_20_001.ino:17:66: fatal error: Adafruit_MotorShield.h: No such file or directory

    compilation terminated.

    Error compiling

    i dont know anything about programming

    author
    Kenji UlisesF (author)arif mulla2016-04-11

    change the name of that data, an connect the arduino again

    author
    CPARKTX (author)arif mulla2015-05-25

    You haven't installed (or properly installed) the Adafruit motor shield driver.

    author
    kesha9 (author)2016-02-22

    Hey any chance you could share the schematics?

    Thank you.

    author
    RushinK (author)2016-02-03

    can u pls help me??

    author
    RushinK (author)2016-02-03

    i want the full circuit diagram for the connections.

    can u pls provide the information ?

    author
    RushinK (author)2016-02-03

    i want the full circuit diagram for the connections.

    can u pls provide the information ?

    author
    RushinK (author)2016-02-03

    i want the full circuit diagram for the connections.

    can u pls provide the information ?

    author
    RushinK (author)2016-02-03

    i want the full circuit diagram for the connections.

    can u pls provide the information ?

    author
    rsikandar (author)2016-01-10

    nice work! can you please provide diagram and pinout's of equipment how to soldering compass and gps and other things together?