Pages: 1 2 [3]   Go Down
Author Topic: Fully Autonomous Golf Caddy  (Read 3747 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 9
Real Skills - Security Engineering, CAD Design, Website Design, Graphic Design, Too Many Hobbies - Halloween Prop Building, CNC, Alternative Energy, MTG, Airbrushing, Electronics, All things Tech.,
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I though about doing this a long time ago but you have a very good start. You know there is a lot easier way of doing this. No gps needed. You just want the bag to stay within a certain distance of the golfer while walking, say 4 ft behind you. You just need a small signal transmitter that could be on a key chain, Then something attached to the arduino that looks at the signal strength to determine distance. Then you just need 2 buttons go and stop so when you actually go to the tee it is not trying to follow you there. That way it works anywhere not just on 1 golf course and if you shank a ball your bag isn't 30ft away from you. Just need a way to identify you from your others in your party. Could even use infrared leds to follow.

Maybe this helps
Logged

NJ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
ARDUINO BEEP BEEP
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That actually already exists and it's undesirable because it still requires attention. Senior Design is about pushing the industry, not trying to simply make something cheaper.

Shadow Caddy, Bat Caddy, and Follow-Me Caddy were our literature examples.

this will ideally drive by itself completely. So far it's getting close but it still needs a bit of tuning and optimizing.
Logged

NJ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
ARDUINO BEEP BEEP
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

what you're talking about was designed with active RFIDs, it works pretty well.

Essentially you have a "stop" and "follow" button on a belt clip and it does exactly that.

Not very well priced though, most of the solutions out there cost quite a bit (although somewhat insignificant when compared to the cost of golfing)
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 24
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Are you planning on doing a full write up when the project is done?  A video with working caddy while under GPS Nav would be nice too.  Keep up the good work!!! 8-)
Logged

NJ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
ARDUINO BEEP BEEP
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

yeah, there's going to be a full report and presentation. Not sure if the presentation is going to be video taped but I can put the full report up here when it's done and there are already lots of videos and there will be many more.

check my youtube channel (bleedscarlet) for latest videos, when we come up with good solid tests the videos will get posted here but you can see our progress there.

We are GPS navigating! just not very well nor very fast...
Logged

NJ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
ARDUINO BEEP BEEP
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

with some assistance in the troubleshooting section of the forum we figured out a way to get the accuracy we need. We drop the degrees and just use the minutes and fractional minutes instead :p

since a degree is >42 miles and the golf course is in the middle of a degree we don't need to bother with that complication for now.

In a full scale deployment we would have to put an if statement around the whole thing to add some kind of directional correction if say you needed to move from 74.0001 to 73.9989 or something, but we're not concerning ourselves with that mostly because i'm burning out from staying in the lab until 2AM every night.
Logged

NJ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
ARDUINO BEEP BEEP
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Some asshole decided texting and driving is cool.

We almost got run over.





Needless to say the physical damage isn't too bad, but every component is broken. Our demonstration was supposed to be at 1PM on friday.....this happened at 4PM on thursday...
« Last Edit: December 10, 2010, 04:26:23 am by bleedscarlet » Logged

NJ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
ARDUINO BEEP BEEP
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Here was our last program framework.

Code:
/*******************************************************************
Avinash Arora
Carl Barreau
Stephen Dudek
Asa Roper
Senior Design - Industrial and Systems Engineering - 2010
Motor Controller uses Serial 3
GPS uses Serial 2
Serial 1 cell phone
Compass uses SCL & SLA, SCL=green, SLA=blue
*******************************************************************/


/*******************************************************************
                           Libraries
*******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <String.h>
#include <ctype.h>
#include <math.h>
#include <Wire.h>
/*******************************************************************
                        Initialize Variables
*******************************************************************/
int onModulePin = 2;        // the pin to switch on the module (without press on button)
int timesToSend = 1;        // Numbers of SMS to send
int count = 0;
int compassAddress = 0x32 >> 1;
int heading = 0;
int tilt = 0;
int roll = 0;
int ledPin = 13;
int rxPin = 0;
int txPin = 1;
int byteGPS=-1;
char linea[300] = "";
char comandoGPR[7] = "$GPRMC";
int cont=0;
int bien=0;
int conta=0;
int indices[13];
char CurrentXascii[14];
char CurrentYascii[14];
int CurrentXsingle;
int CurrentYsingle;
float CurrentX;
float CurrentY;
long CurrentX1;
long CurrentY1;
int CurrentX2;
int CurrentY2;
double CurrentXi;
double CurrentYi;
long CurrentXoff;
long CurrentYoff;
double CurrentHeading;
double CurrentHeading0;
byte responseBytes[6];
int GPStimer=0;
double DeltaX=0.000;
double DeltaY=0.000;
int Instance=0;
int InstanceSize=0;
int buttonState=0;
int buttonPin = 22;
int lastButtonState=0;
int buttonPushCounter=0;
float DesiredHeading=0.0;
int CompassComplete=0;
int LeftSpeed=0;
int RightSpeed=0;
int LeftSpeed0=0;
int RightSpeed0=0;
int MoveSwitchPin=34;
int MoveSwitch=0;
int Calibration=0;
int CalibrationCounter=0;
double ParkingLotX[3] = {31.2462,31.2475,31.2523};
double ParkingLotY[3] = {27.6146,27.5992,27.6102};
long OffsetX=0.0000;
long OffsetY=0.0000;
/*******************************************************************
                       Set Engine Speed 1
*******************************************************************/

void setEngineSpeed1(signed char cNewMotorSpeedH)
{
  
    unsigned char cSpeedVal_Motor1 = 0;
    if(cNewMotorSpeedH==0)
    {
      
        Serial3.print(0,BYTE);
        return;
        
    }
    
    cSpeedVal_Motor1 = map(cNewMotorSpeedH,-100,100,1,127);
    Serial3.print(cSpeedVal_Motor1, BYTE);
    
}

/*******************************************************************
                       Set Engine Speed 2
*******************************************************************/

void setEngineSpeed2(signed char cNewMotorSpeed2)
{    
  
    unsigned char cSpeedVal_Motor2 = 0;
    if(cNewMotorSpeed2 == 0)
    {
      
        Serial3.print(0,BYTE);
        return;
        
    }
    
    cSpeedVal_Motor2 = map(cNewMotorSpeed2,-100,100,128,255);
    Serial3.print(cSpeedVal_Motor2, BYTE);
    
}
/*******************************************************************
                   Switch Cell Phone Module On
*******************************************************************/
void switchModule()
{
  
   digitalWrite(onModulePin,HIGH);
   delay(2000);
   digitalWrite(onModulePin,LOW);
   delay(10000);
  
}
/*******************************************************************
                      Read Sensor (Compass)
*******************************************************************/

void readSensor()
{
  
    Wire.beginTransmission(compassAddress);
    Wire.send(0x50);
    Wire.endTransmission();
    delay(2);
    Wire.requestFrom(compassAddress, 6);
    if(6 <= Wire.available())
    
    {
      
        for(int i = 0; i<6; i++)
        
        {
            responseBytes[i] = Wire.receive();
            
        }
        
    }
    
    heading = ((int)responseBytes[0]<<8) | ((int)responseBytes[1]);
    tilt = (((int)responseBytes[2]<<8) | ((int)responseBytes[3]));
    roll = (((int)responseBytes[4]<<8) | ((int)responseBytes[5]));
    CurrentHeading = heading/10;
    
}

/*******************************************************************
                          Read Sensor (GPS)
*******************************************************************/

void readGPS()

{
  
    for(GPStimer=0;GPStimer<250;GPStimer++)
    
    {
      
        byteGPS=Serial2.read();
        if (byteGPS == -1)
        {
          
            delay(10);
            
        }
        
        else
        
        {
          
            linea[conta]=byteGPS;
            conta++;
            if (byteGPS==13)
            {
              
                digitalWrite(ledPin, LOW);
                cont=0;
                bien=0;
                for (int i=1;i<7;i++)
                
                {
                    if (linea[i]==comandoGPR[i-1])
                    {
                      
                        bien++;
                        
                    }
                    
                }
                
                if(bien==6)
                {
                  
                    for (int i=0;i<300;i++)
                    
                    {
                        if (linea[i]==',')
                        
                        {
                            indices[cont]=i;
                            cont++;
                            
                        }
                        
                        if (linea[i]=='*')
                        
                        {
                          
                            indices[12]=i;
                            cont++;
                            
                        }
                    }
//                    Serial.println("");
//                    Serial.println("");

                    Serial.println("---------------");
                    for (int i=0;i<12;i++)
                    
                    {
                        for (int j=indices[i],k=0;j<(indices[i+1]-1);j++,k++)
                        
                        {
                            switch(i)
                            
                            {
                              
                            case 2 :
                                CurrentXascii[k]=linea[j+1];
                             break;
                            case 4 :
                                CurrentYascii[k]=linea[j+1];
                                break;
                                
                            }
                            
                        }
                        
                    }
                    
//                    int xlength=sizeof(CurrentXascii);
//                    int ylength=sizeof(CurrentYascii);
//                    for (int i=0;i<xlength;i++){
//                        CurrentX1[i]=(int)CurrentXascii[i];
//                    }
//                    for (int i=0;i<ylength;i++){
//                        CurrentY[i]=(int)CurrentXascii[i];
//                    }
//                    CurrentX=atof(CurrentXascii)/10000;
//                    CurrentY=-atof(CurrentYascii)/10000;
/*                for (int i=0,k=5;i<5;i++,k--){
                        CurrentX1=CurrentX1+(10^k)*((int)CurrentXascii[i]);
                        Serial.println(CurrentX1);
                    }
                    for (int i=6,k=8;i<13;i++,k--){
                        CurrentX2=CurrentX2+(10^k)*((int)CurrentXascii[i]);
                        Serial.println(CurrentX2);
                    }
                    for (int i=1,k=5;i<6;i++,k--){
                        CurrentY1=CurrentY1+(10^k)*((int)CurrentYascii[i]);
                        Serial.println(CurrentY1);
                    }
                    for (int i=7,k=7;i<13;i++,k--){
                        CurrentY2=CurrentY2+(10^k)*((int)CurrentYascii[i]);
                        Serial.println(CurrentY2);
                    }
                    CurrentXi=CurrentX1+(CurrentX2/10000);
                    CurrentYi=-(CurrentY1+(CurrentY2/10000));
                    CurrentX=CurrentXi;
                    CurrentY=CurrentYi;
                    CurrentX1,CurrentX2,CurrentY1,CurrentY2,CurrentXi,CurrentYi=0;
                    String CurrentXc=CurrentXascii.replace(".",""); */
                    
                    //remove degrees to allow for greater dimensional accuracy
                    for (int i=0,j=9;i<2;i++)
                    {
                      
                        CurrentXascii[i]='0';
                        
                    }
                    
                    for (int i=0;i<3;i++)
                    {
                      
                         CurrentYascii[i]='0';
                        
                    }
                    
                    //clear extraneous digits
                    for (int i=9;i<13;i++)
                    {
                      
                        CurrentXascii[i]='0';
                        
                    }
                    
                    for (int i=10;i<13;i++)
                    {
                      
                         CurrentYascii[i]='0';
                        
                    }
                    
« Last Edit: December 10, 2010, 04:27:44 am by bleedscarlet » Logged

NJ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
ARDUINO BEEP BEEP
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:


//                    CurrentX1=atol(CurrentXascii);
//                    CurrentY1=-atol(CurrentYascii);
//                    CurrentX=floor(CurrentX1/100000)+(CurrentX1%10000)/10000;
//                    CurrentY=floor(CurrentY1/100000)+(CurrentY1%10000)/10000;
//                    CurrentXoff=(atof(CurrentXascii));
//                    CurrentYoff=(atof(CurrentYascii));
                    CurrentX=(atof(CurrentXascii))-0.00324; //+OffsetX;
                    CurrentY=(atof(CurrentYascii))+0.01864; //+OffsetY;                    
                }
                
                conta=0;
                for (int i=0;i<300;i++)
                {
                    linea[i]=' ';                        
                }
                
            }
            
        }
        
    }
    
}

/*******************************************************************
                             Void Setup
*******************************************************************/

void setup()
{
    delay(500);
    
    Wire.begin();
    Wire.send(0x82);
    
    delay(500);
    
    //Telemetry:
    Serial.begin(9600);
    pinMode(13, OUTPUT);
    pinMode(MoveSwitchPin, INPUT);
    digitalWrite(13, HIGH);
    
    //GPS Module:
    Serial2.begin(4800);
    
    for (int i=0;i<300;i++)
    {
      
        linea[i]=' ';
        
    }
    
    //Motor Controller:
    Serial3.begin(9600);
    
    delay(2000);
    
    setEngineSpeed1(0);
    setEngineSpeed2(0);
    Instance=0;
    
    MoveSwitch=digitalRead(MoveSwitchPin);

    //Cell Phone:
    Serial1.begin(19200);               // the GPRS baud rate
//    switchModule();                    // swith the module ON
   for (int i=0;i<2;i++)
   {
       delay(5000);
      
   }
  
      Serial1.println("AT+CMGF=1");         // set the SMS mode to text
      delay(100);
      
}

/*******************************************************************
                            Void Loop
*******************************************************************/

void loop()
{
//    buttonState = digitalRead(buttonPin);
//    if (buttonState != lastButtonState) {
//        if (buttonState == HIGH) {
//            buttonPushCounter++;
//        }
//        lastButtonState = buttonState;
//    }
//    Instance=buttonPushCounter;
    MoveSwitch=digitalRead(MoveSwitchPin);
    if (Calibration==0)
    {
      readGPS();
        if (CalibrationCounter<10)
        {
            delay(10);
            CalibrationCounter++;
            Serial.println("Calibrating...");
        }
        else if (CalibrationCounter>=10)
        {
//            OffsetX=31.2523-CurrentXoff;
//            OffsetY=27.6102-CurrentYoff;
            Calibration=1;
            Serial.println("Calibration Complete.");
        }
        
    }
    
    else if (Calibration==1)
    
    {
      
        if (MoveSwitch == LOW)
        {
            if (Instance<3)
            {
                readSensor();
    //            Serial.print("Heading: ");
    //            Serial.print(CurrentHeading);
    //            Serial.print("\t Tilt: ");
    //            Serial.print(tilt / 10, DEC);
    //            Serial.print("\t Roll: ");
    //            Serial.println(roll / 10, DEC);
                delay(5);
                readGPS();
    //            Serial.print("Current X Value: ");
    //            Serial.print(CurrentX, 10);
    //            Serial.print("\t");                    
    //            Serial.print("Current Y Value: ");
    //            Serial.println(CurrentY, 10);
    //            Serial.println("---------------");
    
/*******************************************************************
                    Figure Out Delta X & Delta Y
*******************************************************************/
    
                DeltaX=ParkingLotX[Instance]-CurrentX;
                DeltaY=ParkingLotY[Instance]-CurrentY;
                
                if((abs(DeltaX)>0.002)||(abs(DeltaY)>0.002))
                {
                  
                    readGPS();
                    
/*******************************************************************
                     Calculate Desired Heading
*******************************************************************/
    
                      if (DeltaX<0) //Must Go South
                      {
                          if (DeltaY>0) // Must Go South East (Reversed from normal quadrant because of hemisphere flip)
                          {
                              DesiredHeading=270+atan(DeltaX/DeltaY)*180/3.14159265;
                          }
                          
                          else if (DeltaY<0) // Must Go South West (Reversed from normal quadrant because of hemisphere flip)
                          {
                              DesiredHeading=90+atan(DeltaX/DeltaY)*180/3.14159265;
                          }
                          
                      }
Logged

NJ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
ARDUINO BEEP BEEP
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
                     
                      else if (DeltaX>0) //Must Go North
                      {
                          if (DeltaY>0) // Must Go North East (Reversed from normal quadrant because of hemisphere flip)
                          {
                              DesiredHeading=270+atan(DeltaX/DeltaY)*180/3.14159265;
                          }
                          
                          else if (DeltaY<0) // Must Go North West (Reversed from normal quadrant because of hemisphere flip)
                          {
                              DesiredHeading=90+atan(DeltaX/DeltaY)*180/3.14159265;
                          }
                          
                      }
                      
    //                if (DeltaY<0)
    //                {
    //                    if (DeltaX>0)
    //                    {
    //                        DesiredHeading=270-atan(DeltaY/DeltaX)*180/3.14159265;
    //                    }
    //                    else if (DeltaX<0)
    //                    {
    //                        DesiredHeading=90+atan(DeltaY/DeltaX)*180/3.14159265;
    //                    }
    //                }
    //                else if (DeltaY>0)
    //                {
    //                    if (DeltaX>0)
    //                    {
    //                        DesiredHeading=270+atan(DeltaY/DeltaX)*180/3.14159265;
    //                    }
    //                    else if (DeltaX<0)
    //                    {
    //                        DesiredHeading=90-atan(DeltaY/DeltaX)*180/3.14159265;
    //                    }
    //                }
    
/*******************************************************************
                   Pull Current Heading & Auto Correct
*******************************************************************/
    
                    readSensor();
                    if (((DesiredHeading-CurrentHeading) < 15)&&((DesiredHeading-CurrentHeading)>6))
                    {
                        LeftSpeed=40;
                        RightSpeed=30;
                    }
                    
                    else if (((DesiredHeading-CurrentHeading) <= 30)&&((DesiredHeading-CurrentHeading)>15))
                    {
                        LeftSpeed=40;
                        RightSpeed=20;
                    }
                    
                    else if (((DesiredHeading-CurrentHeading) <= 60)&&((DesiredHeading-CurrentHeading)>30))
                    {
                        LeftSpeed=40;
                        RightSpeed=10;
                    }
                    
                    else if (((DesiredHeading-CurrentHeading) <= 180)&&((DesiredHeading-CurrentHeading)>60))
                    {
                        LeftSpeed=40;
                        RightSpeed=1;
                    }
                    else if (((DesiredHeading-CurrentHeading) <= 360)&&((DesiredHeading-CurrentHeading)>180))
                    {
                        LeftSpeed=-1;
                        RightSpeed=39;
                    }                
                    else if (((DesiredHeading-CurrentHeading) <= -6)&&((DesiredHeading-CurrentHeading)>-15))
                    {
                        LeftSpeed=30;
                        RightSpeed=39;
                    }
                    
                    else if (((DesiredHeading-CurrentHeading) <= -15)&&((DesiredHeading-CurrentHeading)>-30))
                    {
                        LeftSpeed=20;
                        RightSpeed=39;
                    }
                    
                    else if (((DesiredHeading-CurrentHeading) <= -30)&&((DesiredHeading-CurrentHeading)>-60))
                    {
                        LeftSpeed=10;
                        RightSpeed=39;
                    }
                    
                    else if (((DesiredHeading-CurrentHeading) <= -60)&&((DesiredHeading-CurrentHeading) > -180))
                    {
                        LeftSpeed=-1;
                        RightSpeed=39;
                    }
                    else if (((DesiredHeading-CurrentHeading) <= -180)&&((DesiredHeading-CurrentHeading) >= -360))
                    {
                        LeftSpeed=39;
                        RightSpeed=-1;
                    }
                    
                    else if (((DesiredHeading-CurrentHeading) <= 6)&&((DesiredHeading-CurrentHeading) >= -6))
                    {
                        LeftSpeed=40;
                        RightSpeed=39;
                    }
                    
/*******************************************************************
    Exponential Moving Average Motor Control & Send Motor Speeds
*******************************************************************/
    
                    LeftSpeed0=.9*LeftSpeed+.1*LeftSpeed0;
                    RightSpeed0=.9*RightSpeed+.1*RightSpeed0;
                    setEngineSpeed1(LeftSpeed0);
                    setEngineSpeed2(RightSpeed0);
                    
/*******************************************************************
Serial Prints for data verification (to be removed with final implementation)
*******************************************************************/
    
                    Serial.print("LeftSpeed: ");
                    Serial.print(LeftSpeed0);
                    Serial.print("\t");
                    Serial.print("RightSpeed: ");
                    Serial.print(RightSpeed0);
                    Serial.print("\t");
                    Serial.print("DesiredHeading: ");
                    Serial.print(DesiredHeading);
                    Serial.print("\t");
                    Serial.print("CurrentHeading: ");
                    Serial.print(CurrentHeading);
                    Serial.print("\t");
                    Serial.print("Calibrated? ");
                    Serial.print(Calibration);
                    Serial.print("\t");
                    Serial.print("Offset X: ");
                    Serial.print(OffsetX,6);
                    Serial.print("\t");
                    Serial.print("Offset Y: ");
                    Serial.println(OffsetY,6);
                    Serial.print("CurrentXascii: ");
                    Serial.print(CurrentXascii);
                    Serial.print("\t");
                    Serial.print("CurrentYascii: ");
                    Serial.print(CurrentYascii);
                    Serial.print("\t");
                    Serial.print("CurrentX: ");
                    Serial.print(CurrentX, 4);
                    Serial.print("\t");
                    Serial.print("CurrentY: ");
                    Serial.print(CurrentY, 4);
                    Serial.print("\t");
                    Serial.print("X: ");
                    Serial.print(ParkingLotX[Instance],6);
                    Serial.print("\t");
                    Serial.print("Y: ");
                    Serial.print(ParkingLotY[Instance],6);
                    Serial.print("\t");
                    Serial.print("Instance: ");
                    Serial.println(Instance);
                    
/*******************************************************************
                          End Telemetry
*******************************************************************/
    
                }
                
                else if((abs(DeltaX)<=0.002)&&(abs(DeltaY)<=0.002))
                {
                    Instance++;
                    setEngineSpeed1(0);
                    setEngineSpeed2(0);
                    delay(5000);
                }
            }
            
            else
            
            {
/*******************************************************************
                  Send Text Message Indicating Arrival
*******************************************************************/
             while (count < timesToSend)
             {
    
                 delay(1500);
                 Serial1.print("AT+CMGS=");          // send the SMS the number
                 Serial1.print(0x22,BYTE);             // send the " char
                 Serial1.print("17322337949");         // send the number (change ********* by the actual number)
                 Serial1.println(0x22,BYTE);           // send the " char
                 delay(1500);
                 Serial1.println("Hey, I'm here!");     // the SMS body
                 delay(500);
                 Serial1.println(0x1A,BYTE);             // end of message command 1A (hex)
                 delay(5000);
                 count++;
    
               }
    
            }
    
/*******************************************************************
       Issue full stop for 5 seconds and start next instance
*******************************************************************/
            MoveSwitch=digitalRead(MoveSwitchPin);
        }
        
/*******************************************************************
If initial assistance switch is depressed, ignore sensors & go 100%.
*******************************************************************/
    
        else if(MoveSwitch == HIGH)
        {
          
            setEngineSpeed1(100);
            setEngineSpeed2(97);
            Serial.print("Moving...");
            delay(200);
            MoveSwitch=digitalRead(MoveSwitchPin);
            
        }

    }

      
Logged

Darlington, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 125
Shaamo
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This is such a cool project... I'm very interested in the Norobo implementation as I've been a little lost with it's use since I got hte DroneCell, so a big thankyou from me for posting this up!
Logged

Pages: 1 2 [3]   Go Up
Jump to: