Monday, 23 September 2013

Updating the Code and a progress video

A number of major changes have been made in the code. These have been necessary in order to fix the issue of interference. Shielded cable did nothing, neither did wire management so with the code updates, routines have been altered to fix interference.

The first fix was quite simple. Since the relays were the source of interference, when one axis moved, its caused false signals to be fed to the other photo interrupter. As a result the movement of one axis, would slightly change the coordinate of the other axis. Thus the update routine was given the command to not update whilst the other axis was running.

The second fix was more complex. I myself did not write this part but got help from others at the workshop. After probing the photo interrupter signal on an oscilloscope, we were able to see the signal wave and see how often it peaked abruptly. This was approximately 30 milliseconds, hence a debounce routine was run every 30 milliseconds in order to essentially reverse whatever abrupt false signal was read.

The code below reflects these changes which occurred in the first tab of my major code. There were other very tiny changes for example in the values of the servo for the up and down routines but I won't include these.

Finally the long awaited video can be seen below. From it the difference from V1 to V2 is clear, particularly that this one actually works. Still there is much to fix and add. I'm thinking about a PCB to counter messy circuit boards and interference, buttons to make for a less repetitive and more efficient design, and a new mechanism for the Z axis that drops straight down rather than side on.





Wednesday, 21 August 2013

Mounting the Circuit Board and Cable Management

With construction finished, the electronic components now. It was made based on the same design of the MDF aluminum frame having 6 holes on top for hexstands to be screwed into. This way the circuit board could be mounted using the hexstands and taken off easily if issues with programming, wiring etc happened in future. This mount is shown below:
Once this was mounted, all wires had to be simply plugged into the circuit. However, I already had concerns that interference in the wires primarily motor wires, relays and the photo interrupter cables would be an issue. Thus, I took care in separately the paths of wires making them neat to minimise noise, physical cable tangle, and simply for aesthetics. This was primarily done using duct tape and some flexible plastic tube for the X axis. For the thick shielded cable, small cable clamp like things were stuck to the slide of the legs simply by using the sticky side which came with it. Images of this and the system put together are below:
















Next, the arduino code will be looked at and a number of changes will be introduced to improve efficiency and function in particular to the new design.

Building and attaching the base and its frame

The frame to house the wooden base is displayed below. It was made using 4 pieces of 25x25x1.4mm angle aluminum. These were screwed together to form a rectangular frame. 2 pieces of 3mm flat aluminium where used to form a centre support beam. These were screwed and positioned to sit level with the sides of the angle aluminum. The reason for this centre brace was that MDF board was the material which was going to be used. I was aware that this was common to bend in the centre thus, the support was added to ensure a flat board. 
The board was 9mm MDF cut to fit to the frame using a jigsaw. After the board got in the way of the screw which secured the frame to the legs, I had to cut a small square piece off each corner of the MDF board using the jigsaw. This gave room to screw and unscrew the nuts and bolts so the frame could be easily detached from the legs for storage later.

Attaching the legs and final eletronics

With the axis's finished, I began to contemplate where the "fridges" would be picked up from. At the start, the idea was to like version 1, have the legs and structure screwed to a wooden base. This wooden base would be the floor of the warehouse on which the system would operate. Under this vision I began making the legs.

The legs were 30x30x3mm angle aluminum to make for very strong legs. These were cut to approximately 32mm using a hack saw. They were then all filed to be level and then screwed to the frame of the X-axis. However after all of this, the distance from the servo to the floor was much to high. Thus the original concept of a wooden base which the legs would rest on would not work. 

Instead, another design had to be made. I decided rather than have the legs rest on a base, that the legs would simply rest on the floor. The base for the system to would be housed in an aluminium frame which could be screwed to the legs. This way the distance from the servo to the base could be set at a reasonable height and changed if need be.

I would make this frame later and for now simply finished mounting the photo interrupter for the X motor. This was done just like the Y Motor but proved a lot easier since it was not a moving component. 

Finishing the X-axis and beginning on electronics

The first addition was making a mounting bracket for the idle wheel. This was made similarly to the Y axis but was altered slightly to all exist on one bracket which could be screwed onto the extendable side. After this the belt was added, and just like the Y was tensioned, the whole X structure now screwed together. After testing that the Y structure's running by hand an issue was found. One runner of the 4 was elevated slightly due to it being slightly too far out. As a result it ran along the top of the flat aluminium rather than beside it. This could cause issues in operation or locks in the motor so I quickly fixed this. To do this involved taking the bracket and wheel off and remaking it completely, this time slightly less out, and with the runner slightly lower. After this rework, the Y axis ran smoothly as required so well it ran when tilted under the force of gravity.

Next, a small bracket was made and screwed to the Y axis structure. It was positioned directly in line with the motor, the piece which would connect the belt to the Y structure. This consisted simply of 2 pieces of angle and a piece of flat aluminum for the belt to rest on. Another piece of 3mm flat was then screwed on top to lock the belt. However upon doing this, another issue arose. As previously predicted the motor and idle wheel brackets were slightly too long causing the belt to not sit flat. In operation, this would cause the belt to lock when it got close to the idle wheel or motor. Hence, both brackets were raised and then screwed in again which solved the issue. This finalised the building of the primary X-axis structure.

With the structural completion of the axis's, electronics started to be added. The simplest of this included another limit switch to reset the position of the X-axis when the centre of the Y-axis structure activated the switch. The harder piece was the photo interrupter. At first this was attached just like on version, simply soldered straight onto shielded cable. However the shielded cable was not very flexible and as a result it interfered with the movement of the X-axis and eventually caused the photo interrupter to break. Thus a new photo interrupter was used however this time it was attached tot he cable differently. Firstly, the photo interrupter was fed through a small piece of experimenters board. It was soldered to this and then trimmed very short. Next the wire was then soldered to the back of the experimenters board in a vertical position as shown in the image below. This made it so the wire would not touch the X-axis structure at all. To hold all this in place and ensure a break would not occur again, hot glue was used to act as a sealant for the solder and wire. This was then cut to size using a band saw and a hand held drill was used to drilled holes to fit M3 screws. These allowed it to be screwed into the Y structure and stay in a static position at which it could accurately need the encoder wheel for the Y. This process was quite extensive and brought many issues however I am confident it will not do so with the X axis photo interrupter. This is because the X unlike the Y structure does not have to move. I also now had the experience and resulting new way to connect the shielded cable.

Building the X-axis

I will not go too deep into the build process of the X-axis as it was essentially a repeat of the Y except on a larger scale. Particular care had to be taken to get the dimensions correct. Some changes included using a wider 20mm flat aluminium as a guider for the Y axis. The sides themselves also use a 25mm by 20mm as the running surface for the runners of the Y-axis. The sides parallel to the Y-axis use wider 35mm by 20mm angle. These were all bolted together using M3 screws consisting of 2 major parts like the Y-axis. This is a solid part and an attachment for tensioning the belt.

In addition to this, a bracket was made which was screwed to the side of the angle. Like the Y-axis, this is attached to a bracket which houses the motor keeping it stiff and sturdy. There is a chance looking at it now that this bracket will have to be raised when the belt is connected to the Y structure but this will come later if needed.

The final change was also that a limit switch was attached to the Y axis. This will serve to allow the axis position to reset to 0 position when the runner hits the switch.

Finishing building the Y-Axis

Thanks to a friend of mine, I was able to get the M2.5 screws required to fix the motor. Thus, I made a small bracket which held the motor. This was then fixed to the Y-axis using some counter sunk screws such to not block the motor position. Once this was done, tensioning the belt was then possible. The extendable portion of the Y was simply held tight whilst a hole on each side was drilled. This was then screwed so if ever the belt wasn't fully tensioned, another hole could be drilled to adjust. 

The second part that was completed was the attachment of the ball bearing runner wheels. Like the Z runners, these proved to be an issue as both sides had to be kept level, particularly as the gap from both sides was quite far. The runners like the Z were bolted using 8M screws and nuts. On the motor side this was bolted to a separate bracket however on the extension side, it could be simply bolted to the side. One other issue was that the brackets had to be dissembled to allow me to drill the holes accurately with the vertical drill. Finally, one thing I noticed was the nuts loosened up over time with the friction of the runners. Hence, thread locking glue (loctite) was let to seep through the thread. Now the runners are secure on both the Z and Y. The image below shows the progress so far.


Wednesday, 10 July 2013

Version 2: Planning and Building the Y-Axis

When designing the reworked version of my gantry warehouse system I decided that starting from the Y-axis was the best idea since the design of the rest of the robot which depend on how the Y-axis turned out. As a staple building material, I used mostly angled aluminium and some flat aluminium. Its light, strong, easy to work with and machine, and it can be bought in a number of pre-made dimensions at any bunnings warehouse. Aside from this, a range of M3 screws and nuts were the other staple supply i used in this.

The first stage was simply going down to bunnings warehouse and looking around for what dimensions were available whilst also looking into possible options for a roller design to replace the rod design for the X and Y movement. I then managed to get hold of a company which were giving away off cuts of aluminium from which I managed to get the bulk of my materials. However, the use of slider door rollers was out of the question due to the incredibly high prices.

In the end I chose to use, 20x20x1.5mm angle, 35x25x1.5mm angle and 12x3mm flat. From this I produced a rough sketch of the design shown below.



Upon making this sketch, I then had to build it beginning with the movable component of the Y-axis. This was essentially a tiny car upside down, its wheels running across a length of 12x3mm flat bolted to 20x20 angle. This would replace the rod mechanism and whilst it is much more complex and in need of accurate measurement, it produces little friction and will not bend, a problem with the old design. The car like mover was made of two pieces of 20x20 bolted together. These where drilled with the vertical mill then drilled by hand. The opposite sides of the car where drilled on the vertical mill 80mm in diameter to allow an M8 screw to pass through for each wheel and nut. The alternative used rather than door rollers, was ball bearing wheels. These are stronger, cheaper, easy to bolt, with the only downside being their heavy weight. On the bottom of this contraption, another piece of 20x20 was bolted as a mount for the servo. The servo was then positioned in a hole made by the nibbler tool and then bolted in place. 

Next, the structure for the runners and motor was made. The motor was cable tied to a piece of 35x20x1.5mm angle. A hole was nibbled out for the encoder wheel and gear to fit through. The two long pieces of 20x20x1.5mm and 12x3mm were bolted together, spaced to allow just enough room for the car to hang and run freely without any resistance. M3 screws were used primarily however at one point I ran out and had to switch to M4 screws. 

The issue of tension in the last design was due to the lego having a set distance, however, with aluminium I could custom fit. To ensure the axis was always in tight tension, I did not seal up the other side of the Y axis. It was left free for a movable end to be screwed in. This way, the opposite end could be stretched out to a comfortable tension and then bolted in if ever maintenance was needed rather than cutting a whole new piece of aluminium. This also allows the timing belt to be taken off easily whenever needed. This extendable end was made from 2 lengths of 20x20x1.5mm angle. These were faced opposite to eachother and drilled through to fit an M6 screw. This holds the idle wheel which the timing belt goes around. As spacers nuts and washers were used in between. Finally, the two pieces of 20x20x1.5mm were held together by another piece of 20x20x1.5mm by M3 screws.

Another issue with the last design was the timing belt not catching the gear hub of the motor. This was due to the 3D print not coming out accurate enough. After a lot of testing and reprinting, a very close fit has been produced so that the teeth catch with no problem. On top of this, a new encoder wheel has been made. This was laser cut, the new wheel with 20 slots. This will provide extremely high resolution for the new vesion. 

At this point, the mechanics of the Y-axis are done aside from some final touches that need to be made. For one, the motor is held by cable ties. This is not strong enough and the motor has movement. The reason screws into a mount were not used because the size needed was M2.5, a difficult size to find. However, once I find it I will be able to make a mount, bolt it in properly, then add the screws to hold it in tensiono. Right now it is slack  as I do not know how much tension it can hold as the motor is moving. After this is done, the limit switches need to be mounted and the photo interrupter has to be mounted. After this the process can be repeated on a larger scale for the X-axis.

Saturday, 29 June 2013

Automated Gantry Version 1.0 is complete

I am now deeming this stage that I'm at Automated Gantry Version 1.0. It can now carry out a storage and retrieval function and has all components connected and functioning. In saying this, everything is still too inaccurate for an inventory system so a the moment the storage and retrieval works off an input coordinate, not an item number input. This requires will require more consistency, which cannot be achieved by lego. In addition to that, the teethed pulley hub which was 3D printed was not printed accurately enough to get maximum grip to the timing belt. Thus to get the right tension to make it work, I had to make the x axis longer  using lots of tape to hold it in place. I was in a rush because I had to get the prototype submitted the next day for school.

Flaws exist but nonetheless the robot does function decently where it is at now. A video of this is below consisting of scenarios each at a different angle of the store function being run (to coordinate 15,5), a home function being run (so the robot has to move back to the start position, otherwise it'll just go down and pick up straight away which is no fun), and then the get function (back to coordinate 15,5).

Images of the physical changes and current state are below (The little blue thing is a blue lego brick with a piece of thin steel double sided taped to it. This is meant to represent the fridge).




Aside from the physical updates the code has also changed. On top of a few small value tweaks, a store and get function have been added. These right now run off a coordinate following the function. Eg store 18 3. The other change is that now upon start up, the robot will run routines servo up and home so that it will automatically reset its position to 0,0.

The new code is below:

Whilst blogging this, I have only been producing documentation for my IPT project. The user manual for this version as well as a few diagrams are below:

USER MANUAL:
Manual Control: This is done by use of a number of in-built commands stored in an array. When these commands are entered into the serial input, they will execute a routine which is assigned to that command and perform an action. These are in the table below (“ “) means a value must be written).

Command
Routine
Function
xf
XForward()
Move X-axis forward
xs
XStop()
Stop X-axis movement
xr
XReverse()
Move X-axis backwards
yf
YForward()
Move Y-axis forward
ys
YStop()
Stop Y-axis movement
yr
YReverse()
Move Y-axis backwards
se
ShowEncoders()
Print the current coordinates (in the form “x” “y”)
re
ResetEncoders()
Reset the coordinate value to 0,0
xy “ “ “ “
PickUp()
Move to the written x (input value in first “ “) and y coordinate (input value in second “ “)
IMPORTANT: Only values between 0 and 20 for x axis. Only values between 0 and 10 for y axis.
servo “ “
DriveServo()
Move servo to position “ “. This lowers and raises the electromagnet (The Z-Axis)
IMPORTANT: Only values between 60 (highest point) and 230 (lowest point) should be inputted.
solon
SolenoidOn()
Turn electromagnet on.
soloff
SolenoidOff()
Turn electromagnet off.
home
Home()
Move x and y axis back to starting position (0,0)

Automated Control:
Storing:
To store an item, you must tell the robot through the serial monitor input that you have an item in the docking bay which must be stored. To do this we enter the command Store. This tells the robot that it is going to the docking bay, and storing an item in an available space.
However, in accordance to the old layout of storage, each row will be dedicated to a certain model of fridge or freezer. Thus, you must also tell the robot, what row and column the fridge is being stored. This can be done by adding a space and then inputting an x y coordinate after.
The final resulting input line could for example be:
Store  15 6
Once this is typed into the input, press enter on the keyboard or click send to initiate the command. From here, the robot will complete the storing process.
Retrieving:
The retrieving process is conducted almost exactly the same as the storing process. Instead of the store command being typed into the serial input, type Get. This will tell the system it must retrieve an item and bring it back to the docking bay. However, you also need to input which model you wish to retrieve. To do this after a space, type the x y coordinate of the item you wish to retrieve.
The final resulting input line could for example be:
Get 15 6

Once it is typed, press enter or click send to start the retrieval. From here the robot will do everything else. 

CONTEXT DIAGRAM:
BLOCK DIAGRAM:
MASTER CIRCUIT:

The robot still hasn't got all the functionality I wanted so this Sunday I will begin the making of version 2.0. This will most probably have the exact same hardware and circuitry (possibly a few modifications) but will most significantly have a new structure built out of aluminium with the perfect tension for the timing belts and an inventory function which works off an item's stored location not a coordinate. 

Tuesday, 18 June 2013

Cleaning up the Wires, Reworking Pulleys and Adding the Z Axis

One major problem that was actually signalling the end to the project as a whole was the pulley material. I was originally using rubber bands but they were so elastic that it resulted in a very inaccurate system. So inaccurate that there was no way it could store and retrieve items. However, after searching I managed to find a timing belt kit which worked perfectly. With this, the system drives to any point with ease and consistency. However, in using this, I had to 3D print two new wheel hubs and cable tie the timing belt to the X and Y axises.

The other thing affecting the consistency was the guiding rails. These were originally out of coat hanger but have now been replaced with hollow brass rods. These are a closer fit to the lego holes and hence give a good guide. It did have a bit of friction at the ends which was an issue but the timing belt solution overcame it.

Still, there wasn't enough resolution with my old 2 tab encoder wheels. So I have made 2 new encoder wheels with 8 tabs. This will provide much greater resolution for the coordinates but is yet to be attached. These are below:

I also finally cleaned up the wires on the robot. Originally there were wires everywhere and they'd get caught when it ran. However, they now have been trimmed, fed through containment units and guiders to the wires can now move the whole length of the X and Y without getting tangled or caught.

The Z axis is now fully functioning. It is run by a mini servo which is connected a long lego piece with cable ties and string to the servo arm. This is then attached to another long lego piece making it retract and extend. From Testing I have got a range of position 60-230 for this servo so that it doesn't lock on the Y-axis or go out of its range.

The circuit board has also been attached to the base using hex stands. This way the board can be easily screwed off at any time.

The code has also been changed now neater (separated into tabs) and more efficient in its function. This is below:

Automated Gantry: This contains all the integers (data type for number storage) to tell the program which pins to reference on the eleven for each variable. It also outlines whether each variable is an INPUT or OUTPUT.  It also contains general routines such as that to print out the location of the gantry, to move back to (0,0).
#include <Wire.h>
#include <Servo.h>

int Xdir=6;          // drive pin to X direction relay
int Ydir=4;          // drive pin to Y direction relay
int Xenable=5;       // drive pin to X enable relay
int Yenable=10;      // drive pin to Y enable relay
int Xpulse=3;              // input from X encoder
int Ypulse=2;              // input from Y encoder
int Solenoid = 9;
boolean Xdirection=false;  // true if motor forward / false if reverse
boolean Ydirection=false;  // true if motor forward / false if reverse

Servo Lift;
int Xposition=0;           // encoder count for X
int Yposition=0;           // encoder count for Y
boolean Xtravel = false;
boolean Ytravel = false;
int OldXstate, OldYstate;  // input state of encoder pins (HIGH,LOW)

String inputString = "";
boolean stringComplete=false;
String cmd = "";
int arg [4] = {0,0,0,0};
int ArgIndex;

void setup()
{
  Serial.begin(9600);
  Serial.setTimeout(2);
  inputString.reserve(200);
 
  Serial.println(" Automated Gantry Warehouse");
  pinMode(Xdir, OUTPUT);
  pinMode(Ydir, OUTPUT);
  pinMode(Xenable, OUTPUT);
  pinMode(Yenable, OUTPUT);
  pinMode(Solenoid,OUTPUT);
  pinMode(Xpulse,INPUT);
  pinMode(Ypulse,INPUT);
  digitalWrite(Solenoid,LOW);
  Lift.attach(7);
  Lift.write(128);
  OldXstate = digitalRead(Xpulse);    // get state of encoder inputs
  OldYstate = digitalRead(Ypulse);    // ...
}

void loop(){
 // serialEvent();
  if (stringComplete){
  HandleCommand();
  inputString="";
  stringComplete=false;
  } 
}

void Home(){
  MoveTo(0,0);
}
 
void MoveTo(int x, int y){
//  if ((x < 0) || (y < 0) || (x > 40) || (y > 40)){
//      Serial.println("XY commands out of bounds");
//      return;
//  }
   
  Serial.println(y);
  if (x !=Xposition){
      if (x > Xposition) XForward();
      if (x < Xposition) XReverse();
  }
  while (Xposition !=x){
      CheckEncoders();
  }
  XStop();
  ShowEncoders();
  delay (1000);
//  ShowEncoders();
//  delay (2000);
  if (y != Yposition){
      if (y > Yposition) YForward();
      if (y < Yposition) YReverse();
  }
  ShowEncoders();
  while (y !=Yposition){
      CheckEncoders();
  }
  YStop();
  ShowEncoders();
}

void PickUp(){
  MoveTo(arg[0], arg[1]);
}  

Commands: This is the code for manual control of the robot. By inputting a command from the code in the serial monitor, it will reference the array of commands, and run the routine set to that command; movement of the x, movement of the y, on and off of electromagnet, driving the servo, going to a certain coordinate, resetting and reading the encoders to see the coordinate.
void HandleCommand(){
  ParseInput();
  if (cmd == "xf") XForward();
  if (cmd == "xs") XStop();
  if (cmd == "xr") XReverse();
  if (cmd == "yf") YForward();
  if (cmd == "ys") YStop();
  if (cmd == "yr") YReverse();
  if (cmd == "se") ShowEncoders();
  if (cmd == "xy") PickUp();
  if (cmd == "re") ResetEncoders();
  if (cmd == "servo") DriveServo();
  if (cmd == "solon") SolenoidOn();
  if (cmd == "soloff") SolenoidOff();
  if (cmd == "home") Home();
}

// from the serial input separate all arguments
void ParseInput(){
  Serial.println(inputString);
  int space, slash;
  for(int x = 0; x < 4; x++){              // flush the last args
    arg[x] = 0;
  }
  ArgIndex = 0;                                      // reset number of args to zero
  space=inputString.indexOf(' ');
  slash = inputString.indexOf('\n');
  inputString = inputString.substring(0,slash);
  cmd = inputString.substring(0,space);
  inputString = inputString.substring(space+1,slash);
  while (inputString.indexOf(' ') > 0){
     space = inputString.indexOf(' ');
     arg[ArgIndex] = inputString.substring(0,space).toInt();
     inputString = inputString.substring(space+1,inputString.length());
     ArgIndex++;  
  }
  arg[ArgIndex] = inputString.toInt();
}

void serialEvent(){
//  Serial.println("l");
  while(Serial.available()){
//    Serial.println("d");
   char inChar=(char)Serial.read();
   inputString += inChar;
//   Serial.println(inputString);
   if(inChar=='\n'){
       stringComplete=true;
//       Serial.println("complete");
   }
  }
}

Encoders: This contains the code for reading the photo interrupters and then updating the coordinates in accordance. This essentially runs the function of the location system of the robot knows where it is. On top of this it contains the routines for resetting the coordinates back to (0,0) and printing out the current position.
The arduino reads the photo interrupter which depending on the starting position of the encoder wheel attached to the motor (gap or filled) will read the starting position HIGH or LOW. It will then continue to read the photo interrupter until it detects a change. Once this change is detected it must update the position of the axis. To determine whether to decrement or increment the value, it will check the variable Xdirection (in Boolean is false). It equals Xdirection (false) then the value of the X coordinate will increase by 1. Otherwise if it does not equal Xdirection, it will decrease by 1. It will then update the OldXstate so it knows where it is now. This process continuously repeats at an extremely fast rate for the X axis and Y axis to keep an update of the location of the gantry.
void CheckEncoders(){
  int X,Y;
  X = digitalRead(Xpulse);
  Y = digitalRead(Ypulse);
//  Serial.print(Xposition);
//  Serial.print("  ");
//  Serial.println(Yposition);
  delay(200);
  if (OldXstate == LOW){
      if(X ==HIGH){
          if (Xdirection) Xposition++;
          if (!Xdirection) Xposition--;
          OldXstate = X;
          goto  CheckY;
      }
    }
  if (OldXstate == HIGH){
      if (X == LOW){
          if (Xdirection) Xposition++;
          if (!Xdirection) Xposition--;
          OldXstate = LOW;
      }
  }
  CheckY:
   if (OldYstate == LOW){
      if(Y ==HIGH){
          if (Ydirection) Yposition++;
          if (!Ydirection) Yposition--;
          OldYstate = Y;
 //         Serial.println(Yposition);
          return;
      }
    }
  if (OldYstate == HIGH){
      if (Y == LOW){
          if (Ydirection) Yposition++;
          if (!Ydirection) Yposition--;
          OldYstate = LOW;
  //        Serial.println(Yposition);
      }
  }
}

// used in serial to show encoder counts
void ShowEncoders(){
    Serial.print("X= ");
    Serial.print(Xposition);
    Serial.print( " Y= ");
    Serial.println(Yposition);
}

void PrintPosition(){
  Serial.print(Xposition);
  Serial.print("  ");
  Serial.println(Yposition);
}

void ResetEncoders(){
  Xposition = 0;
  Yposition = 0;
  Serial.println("Encoders reset");
}

Motor Control: This contains the routines for the driving of the x-axis and y-axis motors. This includes forward movement, reverse movement, stopping of the motors. These are referenced in an array and are initiated by the commands outlined in the “commands” tab. When the motor is set at HIGH, it moves in a forward direction. When LOW, it moves in reverse. When the enable is LOW, the motor is off. When the enable is HIGH, the motor is on.
void SetXForward(){
 digitalWrite(Xdir,HIGH);
 Xdirection= true;
}

void SetXReverse(){
 digitalWrite(Xdir,LOW);
 Xdirection = false;
}

void XForward(){
  Xdirection=true;
  digitalWrite(Xenable,LOW);
  delay(30);
  digitalWrite(Xdir,HIGH);
  digitalWrite(Xenable,HIGH);
}

void YForward(){
  Ydirection=true;
  digitalWrite(Yenable,LOW);
  delay(30);
  digitalWrite(Ydir,HIGH);
  digitalWrite(Yenable,HIGH);
}

void XReverse(){
  Xdirection=false;
  digitalWrite(Xenable,LOW);
  delay(30);
  digitalWrite(Xdir,LOW);
  digitalWrite(Xenable,HIGH);
}

void YReverse(){
  Ydirection=false;
  digitalWrite(Yenable,LOW);
  delay(30); 
  digitalWrite(Ydir,LOW);
  digitalWrite(Yenable,HIGH);
}

void XStop(){
  digitalWrite(Xenable,LOW);
  digitalWrite(Xdir,LOW);
  Xtravel = false;
}

void YStop(){
  digitalWrite(Yenable,LOW);
  digitalWrite(Ydir,LOW);
  Ytravel = false;
}

void Test(){
  XForward();
  delay(1250);
  XStop();
  delay(1000);
  XReverse();
  delay(1250);
  XStop();
  delay(1000);

  YForward();
  delay(500);
  YStop();
  delay(1000);
  YReverse();
  delay(500);
  YStop();
  delay(1000);
}

Servo: This contains the routine for driving the servo to a specific angle. By doing so, it will lower a string with the electromagnet attached to it. This will bring it low enough to pick up an item. This code can function manually from the serial monitor. When the command for the servo is called, and followed by a value, the servo will drive to that angle.
void DriveServo(){
  Lift.write(arg[0]);
}

Solenoid: This contains the code for the on and off routines of the electromagnet. When it is written HIGH, it is on. When it is written LOW, it is off.

void SolenoidOn(){
  digitalWrite(Solenoid,HIGH);
}
void SolenoidOff(){
   digitalWrite(Solenoid,LOW);
}

In this code new commands for manual control have also been added. They are now:
Command
Routine
Function
xf
XForward()
Move X-axis forward
xs
XStop()
Stop X-axis movement
xr
XReverse()
Move X-axis backwards
yf
YForward()
Move Y-axis forward
ys
YStop()
Stop Y-axis movement
yr
YReverse()
Move Y-axis backwards
se
ShowEncoders()
Print the current coordinates (in the form “x” “y”)
re
ResetEncoders()
Reset the coordinate value to 0,0
xy “ “ “ “
PickUp()
Move to the written x (input value in first “ “) and y coordinate (input value in second “ “)
servo “ “
DriveServo()
Move servo to position “ “. This lowers and raises the electromagnet (The Z-Axis)
IMPORTANT: Only values between 60 (highest point) and 230 (lowest point) should be inputted.
solon
SolenoidOn()
Turn electromagnet on.
soloff
SolenoidOff()
Turn electromagnet off.
home
Home()
Move x and y axis back to starting position.

All that is left now is the code for the item inventory, putting on a new electromagnet (as my other one broke), adding from limit switches and drilling some new holes to connect the robot to the base (it was slightly out of alignment before). The new electromagnet, resistors (10K) for the limit circuit circuit, and limit switches are below:

This should be done on wednesday and I'll upload a video sometime after.