David Pyrak Self-Balancing Seesaw

Log

Code

Design Description

A seesaw with an accelerometer in the center to detect if it is balanced. Servos tighten rubberbands till the board is level.

 

 

Components

Accelerometer(ADXL335)/Two Standard Servo Motors(HS-5485HB)/Arduino Uno/Seesaw Components/Rubberbands

 

Video - The project balances slowly so the video is 2 x faster then the original.

 

 

Log

4/15/11

Built Seesaw from 1/4" plywood

4/18/11

Wired Accelerometer

Test basic accelerometer program

Test one servo motor control with accelerometer

Test two servo motors with accelerometer

Modified seesaw for servo mounting

Added mounts to servos for weights

Mounted servos with weights on seesaw

4/19/11

Coded and tested for seesaw balanced by weights

Weights do not work - thinking of new way to balance seesaw

4/21/11

Modified Seesaw to replace weights with Rubberbands

Coded and tested for seesaw balanced by rubberbands - Need different servos

4/28/11

Replaced Servos with higher torque servos

4/29/11

Changed code - Works

Project is Finished

 

Code

toycode2.pde

#include <Servo.h>

 

//create two servos

Servo myservo1; 

Servo myservo2;               

 

int pos1 = 2000;    // variable to store the servo1 position set to neutral postion

int pos2 = 1000;    // variable to store the servo2 postion set to neutral postion

int count = 0;    //variable to store state for move servo1/servo2 and counts time level

int num = 0;    //variable to store state for move/wait

int cnt = 0;    //variable to count time level

int cnt2 = 0;    //variable to count time not level

 

const int groundpin = 18;             // analog input pin 4 -- ground

const int powerpin = 19;              // analog input pin 5 -- voltage

const int xpin = A3;                  // x-axis of the accelerometer

 

void setup()

{

   myservo1.attach(9); // attaches the servo1 on pin 9 to the servo object

   myservo2.attach(10); //attaches the servo2 on pin 10

  // initialize the serial communications:

  Serial.begin(9600);

  // Power and ground the necessary pins. Providing power to both

  // the analog and digital pins allow me to just use the breakout

  // board and not have to use the normal 5V and GND pins

  pinMode(groundpin, OUTPUT);

  pinMode(powerpin, OUTPUT);

  digitalWrite(groundpin, LOW);

  digitalWrite(powerpin, HIGH);

}

 

void loop()

{

  //sets servos to initial once

  if(count == 0)

  {

     myservo1.writeMicroseconds(pos1);

     delay(15);

     myservo2.writeMicroseconds(pos2);

     delay(15);

     count = 1;

  }

 

  //checks if left side is down (/) sets servo2 to full tension

  if(analogRead(xpin) < 495 && num == 0 && count == 1)

  {

    if(pos1 != 2000)    //sets servo1 to neutral position

    {

     pos1 = 2000;

     myservo1.writeMicroseconds(pos1);

     delay(20);

    }

    if(pos2 != 2000)    //sets servo2 to full tension position

    {

     pos2 = 2000;

     myservo2.writeMicroseconds(pos2);

     delay(20);

    }

    count = 2;    //sets state to only allow servo 2 movement

  }

 

  //Right side angled down (\) sets servo1 to full tension

  if(analogRead(xpin) > 505 && num == 0 && count == 1)

  {

    if(pos1 != 1000)    //sets servo1 to full tension position

    {

     pos1 = 1000;

     myservo1.writeMicroseconds(pos1);

     delay(20);

    }

    if(pos2 != 1000)    //sets servo2 to neutral position

    {

     pos2 = 1000;

     myservo2.writeMicroseconds(pos2);

     delay(20);

    }

    count = 3;    //sets state to only allow servo1 movement

  }

 

  //slowly decreases tension in servo2 till level

   if(analogRead(xpin) > 505 && count == 2 && num == 0)

  {

     pos2 -= 5;

     myservo2.writeMicroseconds(pos2);

     delay(20);

  }

 

  //increases tension in servo2 if it drops below level

   if(analogRead(xpin) < 495 && count == 2 && num == 0)

  {

     pos2 += 1;

     myservo2.writeMicroseconds(pos2);

     delay(20);

  }

 

  //slowly decreases tension in servo1 till level

  if(analogRead(xpin) < 495 && count == 3 && num == 0)

  {

     pos1 += 5;

     myservo1.writeMicroseconds(pos1);

     delay(20);

  }

 

  //increases tension in servo1 if it drops below level

  if(analogRead(xpin) > 505 && count == 3 && num == 0)

  {

     pos1 -= 1;

     myservo1.writeMicroseconds(pos1);

     delay(20);

  }

 

  //if between 495 and 505 count +1

  if(analogRead(xpin) >= 495 && analogRead(xpin) <= 505 && num == 0)

  {

    cnt += 1;

  }

 

  //if not level count +1 & if servo not level 4 times restarts both counts

  if((analogRead(xpin) < 495 || analogRead(xpin) > 505) && num == 0)

  {

    cnt2 += 1;

    if(cnt2 == 4)

    {

      cnt = 0;

      cnt2 = 0;

    }

  }

 

  //if seesaw is level 5 times without restarting then servos detach

  if(analogRead(xpin) >= 495 && analogRead(xpin) <= 505 && num == 0 && cnt == 5)

  {

     myservo1.detach();

     myservo2.detach();

     num = 1;    //sets state so servo movement code doesnt run

     cnt2 = 0;

     delay(200);

  }

 

  //counts if seesaw is level, if level 10 times then reset counts

  if(analogRead(xpin) >= 495 && analogRead(xpin) <= 505 && num == 1)

  {

     cnt2 += 1;

     if(cnt2 >= 10)

     {

       count = 4;

       cnt2 = 0;

     }

  }

 

  //counts if seesaw if not level, if not level 20 times then attachs servos and restarts to servo movement states

  if((analogRead(xpin) < 495 || analogRead(xpin) > 505) && num ==1)

  {

    count += 1;

    if(count >= 24)

    {

     myservo1.attach(9);

     myservo2.attach(10);

     num = 0;

     cnt = 0;

     cnt2 = 0;

     count = 1;

     delay(100);

    }

  }

}