PlantBot – The Plant Watering Robot

PlantBot – because watering plants is boring.

Laser Cutter Plans:

Here is a preview of what the plans look like:
laser_plans

For laser cutting, click here to download an SVG file of the plans

Code:

#include <math.h>
#include <Servo.h>

Servo arm;
Servo shoulder;
Servo pull;


//servo angle limits (abs degrees)
#define S_MIN -60
#define S_MAX 60

#define A_MAX 170
#define A_MIN 0

#define P_OPEN -40
#define P_CLOSED 67

//xy_points of robot arm when over a plant box section
int xy_points[16][2] = { {1,3}, {5,1}, {0,-12}, {0,-16},
                         {0,-3},{1,-5},{3,-10}, {3,-14},
                         {2,-3}, {3,-5}, {5,-9}, {6,-13} }; 

void setup()
{
  Serial.begin(9600);
  arm.attach(9); 
  shoulder.attach(5);
  pull.attach(2);
}

float calc_shoulder_angle(int x, int y){  //forward kinematics for shoulder
  static int neg_flag = 0;
  
  if(y < 0) {
    neg_flag = 1;
    y = abs(y);
  }
  
  static float shoulder_angle, yx_div, q_ang;
  yx_div = (float)y/x;
  
  q_ang = acos( (x*x + y*y +49.91) / (24*sqrt(x*x + y*y)) );
 
  shoulder_angle = atan(yx_div) -q_ang ;
  
  if(neg_flag == 0) {
    shoulder_angle = ( shoulder_angle + q_ang ) + abs(q_ang); 
  }
  
  shoulder_angle = shoulder_angle*(57296/1000);

  if(neg_flag){
    shoulder_angle = shoulder_angle - 90;
    shoulder_angle = shoulder_angle + (2*q_ang*(57296/1000));
    neg_flag = 0;
  }
  
  return shoulder_angle;
  
}

float calc_arm_angle(int x, int y){  //forward kinematics for arm
  static float arm_angle;

  arm_angle = acos( (x*x + y*y -238.09) / (232.8) );
  arm_angle = arm_angle*(57296/1000);
  
  return arm_angle;
}

void set_angles(int x, int y){     //set angles of shoulder and arm servos

  static int a_ang,s_ang;
  
   s_ang = (int)calc_shoulder_angle(x,y);
  a_ang = (int)calc_arm_angle(x,y);
 

  arm.write(180 - a_ang);  //invert arm angle to robot arm bends the other way

  shoulder.write( abs_to_servo(s_ang) );
  
  
}

int abs_to_servo (int abs_ang){ // converts from absolute angles (unit circle) to servo angles
  static int servo_ang;
  servo_ang = 90 + abs_ang;
  return servo_ang;
}

void pull_lever(void){          //pull the spray bottle lever
  pull.write( abs_to_servo(-40) );
  delay(1000);
  pull.write( abs_to_servo(67));
}

void loop() 
{ 

  //goes to each planter box aquare and pulls lever
  
  for(int i=0; i<12; i++){
      set_angles(xy_points[i][0], xy_points[i][1]);
      pull_lever();
      delay(1500);
    }

  

  
} 

The calc_shoulder_angle function is dodgy – Instead of fixing it I entered in x y points with two potentiomenters to find out which ones line up over the planter box squares. Right now it doesn’t go to x-y points as expected. This will get fixed eventually.

Pictures:

IMG_20151130_155519[1]

IMG_20151130_155541[1]

IMG_20151130_155425[1]

IMG_20151130_155526[1]

Whats Next:

Arduino was used for fast prototyping, PlantBot V2 will have a custom pcb and be solar powered, possibly without a battery – just using capacitors. Need to do some experimentation to see if this is even possible. Will make a custom pcb with a uC that has a very low current power saving mode:)

%d bloggers like this: