Vol12: Mechanical design & machine design

The Farmbot


This week we learned about mechanical design and making machines on our own.

Requirements

Group Assignment "Mechanical & Machine Design"
  1. Design a machine that includes mechanism + actuation + automation + application
  2. Actuate and automate your machine
  3. Build the mechanical parts and operate it manually
  4. Document the group project

Individual Assignment
  1. Document your individual contribution

Softwares 💻

  1. Fusion 360
  2. PrusaSlicer
  3. Arduino IDE

Group Assignment

In this week we're BUILDING A MACHINE TOGETHER! We first met two times to decide what we want to do and found multiple ideas, I want to make a foam wire cutter, Amr wanted to make an Air Hockey machine, and Doaa wanted to make a light printing machine. Then out of the blue Saeed showed us the Farmbot and we all agreed to make a Farmbot.

Final

Farmbot is a CNC machine that can plant seeds and water them. It can monitor different plants in one big pot. It's opensource so it's very customizable it has an application and lots of other features. If you've noticed from my photoes we have here in our lab a beautiful garden and we want to tend to our plants and make sure they are watered and taken care of. So we thought it would be a great idea to make a Farmbot!


Team division!

We divided the work between us and I was responsible for the Z-axis and the wiring. We agreed first on what we want the machine to do and that how it'll function and the dimension of each axis then who will handle each axis and I chose to take the Z-axis as a challengle because I wanted to make changeable head one for the soil moisture sensor and one for the water pump.

Here's the draft we made with.

Final

Individual Assignment

Z-Axis Design, Fabrication, & Implementation

In the beginning, I was so hyped about the idea of kinematic coupling and I wanted to integerate it in our machine and I did extensice research on it and found this guide here. But I found no steel balls in any online store so I set my mind on using different approach. And I started my design process!

  • Step 1

    I Created a sketch of axis which will be held on the x-axis.

    Then I extruded with the "thickness" parameter and created the top and bottom which are secured with a t-slot

  • Step 2

    I imported a stepper motor, 8mm lead screw & nut, 5mm linear bearing, and 8mm coupler in my sketch and arranged them. I projected the stepper motor's screw holes and drew a circle bigger than the shaft on the top face and extruded them

  • Step 3

    Then I wanted to make the gantry which I dedcied to make it 3d printed. I started with making a sketch at the top view of the linear bearings & lead screw nut. Then once done I extruded the part with out. after this I created a grove for the nut and holes for screwing the nut securely by using the same cut but using the extrude cut.I drew two circles that will extrude cut and this is useful to the tool changer part. Then I added a small hand-like pieces in the design to support the head.

    I didn't find the limit switch we're going to use on grabcad so I drafted this one and I added a wood part so it can make the limit switch easy to trigger.

  • Step 4

    Time for the head changer design, I want to make something that can be easy to assemble with a zip tie and easy to remove because i didn't have the time to come up with anything creative because of Maker Faire Cairo!

    I designed this pieces that will be 3d printed and will have holes for zipties with which the different heads are secured. the piece has a

  • Step 5

    Then I created the head by importing the soil sensor and water pump from grabcad. I made wood pieces with the same holes as the tool holder and projected the holes for securing the components on these pieces And I designed some foot caps for the linear rod to be secured in the axis. Then VOILA

Special Thanks!

This goes to Doaa who when I told her I'm overwhelmed about the head design she took the time when she was traveling back home to sketch some ideas and send them to me!


Fabrication & Assembly

I used the 3d printer to print the gantry and the head. I used the PrusaSlicer to slice the files and I printed them on the Prusa i3 MK3S+ with PLA filament.I made several tested that's why the gantry that worked gread after testing is red my second version because the first version the linear bearing grabcad model was not the same size so I resized it and printed it again.

I used the laser cutter to cut the axis and gantry.


Wiring

I made the wiring schematic on Fritzing. We used a water pump though -the 12v one". We used NEMA17 stepper motor and A4988 Stepper drivers and breakout board. A stepper motor is a brushless DC motor which position can be precisely controlled. It is based on magnetic fields. It can be controlled with a driver that helps control the direction of movement and the number of steps. Here's a useful guide by How to Mechatronics

Fritzing

Axis Code

One of my challenges this week was not only coming up with an idea for a changeable head but also time since we were getting ready for maker faire. Amr and Doaa helped me a lot in the coding. Amr was the first to finish the coding after finishing the design and assembly of his Y-axid and since he could travel to the lab everyday we would join online meetings to test his code. He shared his code with me, I changed bit of the code to suit my z axis and send over the serial my first command "ZH" which Z for the axis identity and H for homing action. Check out Amr's documentationto know more.

Here's a very dramatic expression to the code working this was done while Amr was joining us online. Thanks AMR!!!

Doaa helped a lot here as well. So would come and test the code when I was at my day job as a fab lab specialist and once I finish at 6pm I would join her. She also tested the pump and the soil moisture sensor. I only integerated the code and added the pump and sensor to the code and made sure everything works.Check out her documentation for more The code is provided below

Final Code


#include SoftwareSerial.h>
const byte rxPin = 2;
const byte txPin = 3;
SoftwareSerial mySerial(rxPin, txPin);

//Stepper motor
int ZdirectionPin = 8;  //purple
int ZstepsPin = 9;      //yrllow
//Steps variables
int microStepping = 1;
int betweenStepsDelay = 1000;  // in Microseconds
int steps_fullRevolution = 200;
int gearBeltPitch = 8;  // in mm
//int numteeth = 20; // pulley teeth number
//Distances
unsigned long wantedDistance;
unsigned long wantedSteps;
//Serial Command variables
//int baudrateSerial = 115200;
char myaxis;
char axis = 'Z';
char mydirection;
char home = 'H';
char forward = 'F';
char Reverse = 'R';
int mydistance;
String mycommand;
//End stop sensor
int sensor = 11;
int sensorval;
int homingOffset = 2;  // in mm
//pump and moisture sensor
int enablepump = 7;
int dir1 = 10;
int dir2 = 12;
int Soil = A4;
char pump = 'P';
char Moist = 'M';

int pumpoffset = 1;   // in mm
int moistoffset = 1;  // in mm

int moistvalue;
int sum = 0;

int readingdelay = 200;



void forwards() {
  digitalWrite(ZdirectionPin, 0);  //SAME DIRECTION
}
void backwards() {
  digitalWrite(ZdirectionPin, 1);  //SAME DIRECTION
}

void enableTX() {
  pinMode(txPin, OUTPUT);
  digitalWrite(txPin, HIGH);
}

void disableTX() {
  pinMode(txPin, INPUT);
}

void setup() {
  Serial.begin(9600);
  mySerial.begin(600);
  pinMode(ZdirectionPin, OUTPUT);
  pinMode(ZstepsPin, OUTPUT);
  pinMode(sensor, INPUT);
  pinMode(Soil, INPUT);
  pinMode(enablepump, OUTPUT);
  pinMode(dir1, OUTPUT);
  pinMode(dir2, OUTPUT);

  //Homing Z axis

  Serial.println("HOMING !!!");
  backwards();  //towards the limit switch downwards
  while (digitalRead(sensor)) {
    //Serial.println("s");
    digitalWrite(ZstepsPin, 1);
    delayMicroseconds(betweenStepsDelay);
    digitalWrite(ZstepsPin, 0);
    delayMicroseconds(betweenStepsDelay);
  }
  wantedSteps = (steps_fullRevolution * microStepping * homingOffset) / (gearBeltPitch);
  for (int steps = 0; steps <= wantedSteps; steps++) {
    //Serial.println("E");
    forwards();
    digitalWrite(ZstepsPin, 1);
    delayMicroseconds(betweenStepsDelay);
    digitalWrite(ZstepsPin, 0);
    delayMicroseconds(betweenStepsDelay);
  }
  enableTX();
  delayMicroseconds(100);
  mySerial.println("ZHD");
  mySerial.flush();
  disableTX();
}

void loop() {
  if (mySerial.available()) {
    mycommand = mySerial.readStringUntil('\n');
    mycommand.trim();
    Serial.println(mycommand);
    myaxis = mycommand.charAt(0);
    mydirection = mycommand.charAt(1);
    mydistance = mycommand.substring(2).toInt();
    if (myaxis == axis) {
      if (mydirection == home) {
        Serial.println("HOMINGGGGGGGGGGGGGGGGGGGGGGGGGG !!!");
        backwards();
        while (digitalRead(sensor)) {
          //Serial.println("s");
          digitalWrite(ZstepsPin, 1);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, 0);
          delayMicroseconds(betweenStepsDelay);
        }
        wantedSteps = (steps_fullRevolution * microStepping * homingOffset) / (gearBeltPitch);
        for (int steps = 0; steps <= wantedSteps; steps++) {
          //Serial.println("E");
          forwards();
          digitalWrite(ZstepsPin, 1);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, 0);
          delayMicroseconds(betweenStepsDelay);
        }
        enableTX();
        delayMicroseconds(100);
        mySerial.println("ZHD");
        mySerial.flush();
        disableTX();


      } else if (mydirection == forward) {
        Serial.print("Moving forwards:   ");
        Serial.println(mycommand.substring(2).toInt());  //prints the distance
        /*enableTX();
        delayMicroseconds(100);
        mySerial.print("Z Moving forwards:   ");
        mySerial.println(mycommand.substring(2).toInt());
        mySerial.flush();
        disableTX();*/

        wantedDistance = mydistance;
        wantedSteps = (steps_fullRevolution * microStepping * wantedDistance) / (gearBeltPitch);
        for (int mystep = 0; mystep <= wantedSteps; mystep++) {
          forwards();
          digitalWrite(ZstepsPin, HIGH);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, LOW);
          delayMicroseconds(betweenStepsDelay);
        }

      } else if (mydirection == Reverse) {
        Serial.print("Moving backwards:   ");
        Serial.println(mycommand.substring(2).toInt());
        /*
        enableTX();
        delayMicroseconds(100);
        mySerial.print("Z Moving backwards:   ");
        mySerial.println(mycommand.substring(2).toInt());
        mySerial.flush();
        mySerial.flush();
        disableTX();*/
        wantedDistance = mydistance;
        wantedSteps = (steps_fullRevolution * microStepping * wantedDistance) / (gearBeltPitch);
        for (int mystep = 0; mystep <= wantedSteps; mystep++) {
          backwards();
          digitalWrite(ZstepsPin, HIGH);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, LOW);
          delayMicroseconds(betweenStepsDelay);
        }

      } else if (mydirection == pump) {
        Serial.println("HOMINGGGGGGGGGGGGGGGGGGGGGGGGGG !!!");
        backwards();
        while (digitalRead(sensor)) {
          //Serial.println("s");
          digitalWrite(ZstepsPin, 1);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, 0);
          delayMicroseconds(betweenStepsDelay);
        }
        wantedSteps = (steps_fullRevolution * microStepping * homingOffset) / (gearBeltPitch);
        for (int steps = 0; steps <= wantedSteps; steps++) {
          //Serial.println("E");
          forwards();
          digitalWrite(ZstepsPin, 1);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, 0);
          delayMicroseconds(betweenStepsDelay);
        }

        delay(1000);
        Serial.println("Operate Pump!");
        digitalWrite(enablepump, HIGH);
        //digitalWrite(dir1, HIGH);
        //digitalWrite(dir2, LOW);
        delay(1500);
        Serial.println("Operate Pump!");
        digitalWrite(enablepump, LOW);
        //digitalWrite(dir1, LOW);
        //digitalWrite(dir2, LOW);

        Serial.print("Moving backwards to lift pump:   ");
        wantedDistance = pumpoffset;
        wantedSteps = (steps_fullRevolution * microStepping * wantedDistance) / (gearBeltPitch);
        for (int mystep = 0; mystep <= wantedSteps; mystep++) {
          forwards();
          digitalWrite(ZstepsPin, HIGH);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, LOW);
          delayMicroseconds(betweenStepsDelay);
        }

      } else if (mydirection == Moist) {
        Serial.println("HOMINGGGGGGGGGGGGGGGGGGGGGGGGGG !!!");
        backwards();
        while (digitalRead(sensor)) {
          //Serial.println("s");
          digitalWrite(ZstepsPin, 1);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, 0);
          delayMicroseconds(betweenStepsDelay);
        }
        wantedSteps = (steps_fullRevolution * microStepping * homingOffset) / (gearBeltPitch);
        for (int steps = 0; steps <= wantedSteps; steps++) {
          //Serial.println("E");
          forwards();
          digitalWrite(ZstepsPin, 1);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, 0);
          delayMicroseconds(betweenStepsDelay);
        }


        Serial.println("Measure moist!");
        sum = 0;
        for (int r = 0; r <= 10; r++) {
          moistvalue = analogRead(Soil);
          moistvalue = map(moistvalue, 1023, 400, 0, 100);
          sum = sum + moistvalue;
          delay(readingdelay);
        }
        int average = sum / 10;
        Serial.println(average);
        enableTX();
        delayMicroseconds(100);
        mySerial.println(average);
        mySerial.flush();
        disableTX();
        wantedDistance = moistoffset;
        wantedSteps = (steps_fullRevolution * microStepping * wantedDistance) / (gearBeltPitch);

        for (int mystep = 0; mystep <= wantedSteps; mystep++) {
          forwards();
          digitalWrite(ZstepsPin, HIGH);
          delayMicroseconds(betweenStepsDelay);
          digitalWrite(ZstepsPin, LOW);
          delayMicroseconds(betweenStepsDelay);
        }
      }
    }
  }
}

Homing

Here's a video of us after we assmbled our parts together and made our firsssst homing to all the axes


Check out our working machine on our Group Assignment page



Files

  • Arduino Z axis final code
  • Z-axis final f3z
  • fritizing Wiring