Auto Sunbath Planter

by toratuy in Circuits > Robots

35 Views, 0 Favorites, 0 Comments

Auto Sunbath Planter

IMG_1722.jpeg

This is a kind of car carrying a flower pot in the brightest direction.

We used laser-cut wood board to make the outside of this machine, and the data of the box is also shared in this document.

Supplies

IMG_1716.jpeg
IMG_1721.jpeg.png

Materials:

Arduino UNO R3 * 1

Continuous servo motor (FS90R) * 2

Servo motor (FS90) * 2

Light sensor (Grove - Light Sensor) * 2

Breadboard * 1

9V battery * 1

Slide switch * 1

Marble * 1

6 cm diameter wheel for continuous servomotors * 2

Flower pot * 1 (We used 9 cm diameter and 5° H plastic pot as in the pictures)

3mm thickness 60 * 30cm plywood


Tools:

laser cutter machine

3D printer (optional)

Glue gun

Arduino Wiring

Copy of Cool Tumelo.png

Wire an arduino like in this figure

Assembling

IMG_1717.jpeg
IMG_1718.jpeg.png
IMG_1719.jpeg.png
IMG_1720.jpeg.png

Printing the exterior using a laser cutter

the printing data is shared in the file

3D print the free wheel

print free wheel using a 3D printer. this data is originated from the website below

https://cults3d.com/en/3d-model/various/marble-caster

Sold slide switch

Sold the slide switch to make a connection as in STEP 1

Assemble the exterior and glue parts

Now it's the time to assemble all the parts. The main part of this machine is like in the 2nd photo. To fix 2 continuous servo motors, use 2 wooden pieces in the laser cutter part.

You will also need tubes to cover the light sensors to detect the light direction.

Code


#include <Servo.h>


Servo servoFront; // set up the servo motor in front
Servo servoRear; // set up the servo motor in rear


Servo servoRight; // set up the right servo motor
Servo servoLeft; // set up the left servo motor


int servoRight_stop = 90; // the value witch the right servo motor stops
int servoLeft_stop = 90; // the value whitch the left servo motor stops


struct Average{ // struct for the function "takeAve"
  float aveFront;
  float aveRear;
};
Average average;


struct GetSensor{ // Struct for the function "getSensor"
  int maxAngle;
  int maxLumo;
};


int sensorFront = A1; // pin for the front sensor
int sensorRear = A0; // pin for the rear sensor
int i; // use for counters


void setup() {
  Serial.begin(9600);
  pinMode(sensorFront, INPUT); // configure the pin for the rear sensor
  pinMode(sensorRear, INPUT); // configure the pin for rear sensor
}


void loop() {
  average = takeAve();
  if((average.aveFront + average.aveRear)/2 < 800){ // if the machine is not in the well-lit area, start process
    attachServo(); // attaching the servo motors
    controlServoLR("stop"); //stop the machine
    GetSensor max_angle_and_lumo = getSensor(); // call "getSensor" to get the best angle and biggest sensor data
    int maxAngle = max_angle_and_lumo.maxAngle; // assign the best angle
    int maxLumo = max_angle_and_lumo.maxLumo; // assign the biggest sensor data
    Serial.println((String)"the max value observed in function getsensor: " + maxLumo); // print the biggest sensor data
    Serial.println((String)"the angle which max value was observed in function getsensor: " + maxAngle); // print the best angle
    move(maxAngle, maxLumo); // call function "move" to move the machine
    detachServo(); // detaching the servo motors
  }
  delay(2000);
}


void attachServo(){ // attaching the servo motors
  servoFront.attach(9);
  servoRear.attach(10);
  servoRight.attach(5);
  servoLeft.attach(6);
}


void detachServo(){ // detaching the servo motors
  servoFront.detach();
  servoRear.detach();
  servoLeft.detach();
  servoRight.detach();
}


Average takeAve(){ // take averages of each sensor
  int iter = 100; // iteration times for the operation to take average values
  float lumoFront; // sensor value for the front sensor
  float lumoRear; // sensor value for the rear sensor


  float listFront[iter]; // list to store "lumoFront"
  float listRear[iter]; // list to store "lumoRear"


  //initialize the lists
  for(i=0;i<iter;i++){
    listFront[i] = 0;
    listRear[i] = 0;
  }


  for(i=0;i<iter;i++){
    // assign the sensor values
    lumoFront = analogRead(sensorFront);
    lumoRear = analogRead(sensorRear);


    // sensor values are devide by iter for the preparation of the caluculation of the averagee value
    listFront[i] = lumoFront/iter;
    listRear[i] = lumoRear/iter;


    delay(10); // wait for 0.01 sec
  }


  //take Average
  float aveFront=0;
  float aveRear=0;
  Average takeAve;


  for(i=0;i<iter;i++){
    // calculate the sums of each list to get average value
    aveFront+=listFront[i];
    aveRear+=listRear[i];
  }


  // assign aveFront and aveRear to the struct (Average) takeAve
  takeAve.aveFront = aveFront;
  takeAve.aveRear = aveRear;
 
  return takeAve;
}


GetSensor getSensor(){
  Serial.println("Get sensor value");
  int pos; // counter for the position of the sensor attached servomotors
  int maxAngle = 0; // the best angle
  int maxLumo = 0; // the biggest lumosity
  int lumoFront; // sensor value for the front sensor
  int lumoRear; // sensor value for the rear


  Average ave = takeAve();
  lumoFront = ave.aveFront;
  lumoRear = ave.aveRear;
  // search the biggest value and the best direction
  if(lumoFront < lumoRear){
    maxAngle = 180;
    maxLumo = lumoRear;
  }else{
    maxAngle = 0;
    maxLumo = lumoFront;
  }


  // assign values to struct GetSensor
  GetSensor max_angle_and_lumo;
  max_angle_and_lumo.maxAngle = maxAngle;
  max_angle_and_lumo.maxLumo = maxLumo;


  return max_angle_and_lumo;
}


void move(int maxAngle, int maxLumo){
  //Rotate the machine
  Serial.println((String)"the max value observed in function getsensor: " + maxLumo);
  Serial.println((String)"the angle which max value was observed in function getsensor: " + maxAngle);
  long threholdRotate = 0.97 * maxLumo;
  // variables to store temporal sensor values
  int tempLumoFront;
  int tempLumoRear;
  // variables to store average sensor values
  int lumoFrontCenter;
  int lumoFrontLeft;
  int lumoFrontRight;
  int lumoRearCenter;
  int pos; // counter for the position of servo motor with sensor
  int rotateTime = 1000;
  int searchAngle = 60; // angle for searching the direction
  Average average;


  // Sensoring the light in front of the machine
  for (pos = 0; pos <= 90; pos++) { // goes from 0 degree to 90 degrees
    servoFront.write(pos); // tell servo to go to position in variable 'pos'
    servoRear.write(pos);
    delay(5); // waits 5 ms for the servo to reach the position
  }


  // rotate the machine
  Serial.println("Rotate the machine");
  // take temporal sensor values to decide which side to rotate
  tempLumoFront = analogRead(sensorFront);
  tempLumoRear = analogRead(sensorRear);
  while(tempLumoFront < tempLumoRear){
    if(90 < maxAngle && maxAngle <= 270){ // if the light source is coming from left side
      Serial.println("Rotate anti clockwise");
      controlServoLR("rotateAntiClock"); // turn left
    }else{ // Otherwise
      Serial.println("Rotate clockwise");
      controlServoLR("rotateClock"); // turn right
    }
    // take temporal sensor values
    tempLumoFront = analogRead(sensorFront);
    tempLumoRear = analogRead(sensorRear);
    delay(100);
  }
  controlServoLR("stop");


  // if the machine is in the enough light source, does not move
  // take average values of the sensors
  average = takeAve();
  lumoFrontCenter = average.aveFront;
  lumoRearCenter = average.aveRear;
  // compare the value in front sensor whie center
  while(true){
    // take the value of the front sensor
    average = takeAve();
    lumoFrontCenter = average.aveFront;
    lumoRearCenter = average.aveRear;
    // take a average of the left front
    for (pos; pos >= 90 - searchAngle; pos--) { // goes from 0 degree to 90 degrees
    servoFront.write(pos); // tell servo to go to position in variable 'pos'
    delay(5); // waits 5 ms for the servo to reach the position
    }
    average = takeAve();
    lumoFrontRight = average.aveFront;
    // take average value for the right front
    for (pos; pos <= 90 + searchAngle; pos++) { // goes from 0 degree to 90 degrees
    servoFront.write(pos); // tell servo to go to position in variable 'pos'
    delay(5); // waits 5 ms for the servo to reach the position
    }
    average = takeAve();
    lumoFrontLeft = average.aveFront;
    // reverse the servomotor
    for (pos; pos >= 90; pos--) { // goes from 0 degree to 90 degrees
    servoFront.write(pos); // tell servo to go to position in variable 'pos'
    delay(5); // waits 5 ms for the servo to reach the position
    }
      if (lumoFrontCenter < lumoRearCenter * 0.7 || lumoFrontLeft < lumoRearCenter * 0.7 || lumoFrontLeft < lumoRearCenter * 0.7){ // when the sensor value of front is the biggest but smaller than the the value of the rear sensor
          if (lumoFrontLeft < lumoFrontRight){ // if the right side is brighter
            controlServoLR("rotateClock"); // rotate clockwise
          }else{ // if the left side is brighter
            controlServoLR("rotateAntiClock"); // rotate anti clockwise
          }
        while(true){ // rotate until the sensor value of the front being twice bigger than the rear one
          // take temporal sensor values
          tempLumoFront = analogRead(sensorFront);
          tempLumoRear = analogRead(sensorRear);
          delay(rotateTime/10);
          if(tempLumoFront > tempLumoRear * 2){
            break;
          }
        }
      }else if(lumoFrontCenter < lumoFrontLeft && lumoFrontRight < lumoFrontLeft){ // the light from rear is small enough, although the sensor value from left side is bigger than center one
        controlServoLR("rotateAntiClock");
        delay(rotateTime);
      }else if(lumoFrontCenter < lumoFrontRight){ // the light from rear is small enough, although the sensor value from right side is bigger than center one
        controlServoLR("rotateClock");
        delay(rotateTime);
      }else{ // when the sensor value of the front sensor is the biggest
        break;
      }
      controlServoLR("stop");
    }
    controlServoLR("stop");
    delay(1000); // wait for 1 sec
    // moving forward up to 3 sec, stop if the machine is going into shade
    int tempSensorValFront = 0; // the temporal sensor value, initialize with 0
    int countShade = 0;
    float thresholdNotMoving = 0.05; // the threshold persentage for the machine stacked somewhere
    int countNotMoving = 0;
    Serial.println("Start moving up to 3 sec");
    // start moving forward
    controlServoLR("forward");
    for(i=0;i<100;i++){ // for loop for 100 times (5 sec)
      tempLumoFront = analogRead(sensorFront); // assign sensor value to tempLumoFront
      tempLumoRear = analogRead(sensorRear);
      if(tempLumoFront < tempSensorValFront * 0.5 || tempLumoFront * 2 < tempLumoRear){   // stop moving if the machine goes to shade
        countShade += 1;
      if (countShade == 1){
        Serial.println("the machines stops due to the decline of light");
        break; // leave the for loop
      }
    }/*else if(tempSensorValFront * (1-thresholdNotMoving) < tempLumoFront && tempLumoFront < tempSensorValFront * (1+thresholdNotMoving)){
      countNotMoving += 1;
      if (countNotMoving == 20){
        Serial.println("the machine seems stacked, move backwords");
        // moving back for 1 sec
        controlServoLR("back"); // get away from stacking
        delay(1000);
        controlServoLR("rotateClock"); // move randomly
        delay(1000);
        break; // leave the loop
      }
    }*/
    tempSensorValFront = tempLumoFront; // assign the front sensor value to the temporal sensor value
    delay(50); // keep going for 0.5 sec
  }
  // stop moving the machine
  controlServoLR("stop");
  // move the machine backwards for 1 sec to get a enough space for the next operation
  controlServoLR("back");
  delay(1000);
  controlServoLR("stop");


  // reverse the sensor
  for (pos = 90; pos >= 0; pos--) { // goes from 90 degrees to 0 degree
    servoFront.write(pos); // move servoRear for the position "pos"
    servoRear.write(pos);
    delay(5); // waits 5 ms for the servo to reach the position
  }
}


void controlServoLR(String control){ // function for control the movig of the machine
  if(control == "forward"){
    servoRight.write(servoRight_stop-15);
    servoLeft.write(servoLeft_stop+10);
  }else if(control == "stop"){
    servoRight.write(servoRight_stop);
    servoLeft.write(servoLeft_stop);
  }else if(control == "back"){
    servoRight.write(servoRight_stop+10);
    servoLeft.write(servoLeft_stop-10);
  }else if(control == "rotateClock"){
    servoRight.write(servoRight_stop+10);
    servoLeft.write(servoLeft_stop+10);
  }else if(control == "rotateAntiClock"){
    servoRight.write(servoRight_stop-10);
    servoLeft.write(servoLeft_stop-10);
  }else{
    Serial.println("type 'forward', 'stop', 'back','rotateClock' or 'rotateAntiClock' please ");
  }
}