Ball and Beam W/LabVIEW & Arduino

1,724

5

3

Introduction: Ball and Beam W/LabVIEW & Arduino

This was a school project, the assignment was to construct a ball and beam control system.

A ping pong ball sits on top of the beam rolling forwards and backwards according to the pitch of the beam. The pitch is controlled by a servo that is connected to an Arduino. The position of the ball is measured by a distance sensor mounted at the end of the beam.

An PID controller is used to control the position of the ball on the beam.

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Parts

Electronics

  • Distance sensor - SHARP 2Y0A21
  • Parallax Standard Servo (#900-00005)
  • Arduino
  • 5V powersupply

3D printed parts

Infill - 20%
Resolution - 0.15mm
Filament Material - PLA

  • Arm
  • Servo arm
  • Servo holder
  • Endplate with sensor
  • Endplate without sensor
  • Hinge

Mechanicall

  • 6x - M4x5mm
  • 1x - M3x45mm
  • 1x - M3x35mm
  • 1x - M3x10mm
  • 4x - 1,5x5mm wood screw
  • 4x - 3,5x15mm woood screw
  • Aluminum profile angle 520mm 15x15x2mm
  • Flanged bearings - 4mm Radial Ball Bearing 8mm O.D
  • 650x95x30mm wood board
  • 145x30x47mm wood stud
  • Ping pong ball

Step 2: Assembling

The design was 3D modelled with Fusion 360

Step 3: Electrical

You need to use an external 5 volt power supply to supply power the servo and distance sensor.

Step 4: PID Controller

LabVIEW

Using the LINX in LabVIEW to connect to the arduino.

Arduino

Using a modified version of SharpIR.h library, originaly by Dr. Marcal Casas-Cartagena

Step 5: LabVIEW Code

Select the COM port to the arduino and the servo and sensor pin.

Step 6: Arduino Code

// Libraries
#include <SharpIR.h> #include <Servo.h>

// Defines #define PIN_SERVO 3 #define PIN_SENSOR 0 #define PIN_LED 13 #define DEBUG_ACTIVE 1 #define IR_MODEL 1080

// Running average const int numReadings = 3; int readings[numReadings]; // The readings from the analog input int readIndex = 0; // The index of the current reading double total = 0; // The running total int sensorRunningAverage = 0;

// Constants const double Kp = 1; const double Ki = 0.1; const double Kd = 15; const double sampleTime = 100; // ms const double setpoint = 20; // cm const int sensorMax = 57; // cm

// Floating variables double error = 0; double oldError = 0; double diffError = 0; double sumError = 0; unsigned long lastTime = 0; unsigned long standbyTime = 0; unsigned long runningTime = 0; double u = 0; // Output of the PID controller int servoOutput = 0; // Output to the servo double dis = 0;

// Functrions Servo servo; SharpIR SharpIR(sensorRunningAverage, IR_MODEL);

void setup() { servo.attach(PIN_SERVO); pinMode(OUTPUT, PIN_LED);

startup();

for (int thisReading = 0; thisReading < numReadings; thisReading++) { readings[thisReading] = 0; } lastTime = millis();

if (DEBUG_ACTIVE) { Serial.begin(9600); }

}

void loop() { sensorRunningAverage = getSensorRunningAverage(analogRead(PIN_SENSOR)); dis = SharpIR.distance(); // this returns the distance to the object you're measuring

/*How long since we last calculated*/ unsigned long now = millis(); double timeChange = (double)(now - lastTime); lastTime = now;

if (dis >= sensorMax) { error = 0; sumError = 0; diffError = 0;

standbyTime = millis() + 2000; } else if (standbyTime < now) { error = dis - setpoint; sumError += (error * (timeChange / 1000)); diffError = error - oldError; oldError = error; }

if (sampleTime + runningTime < now) { if (!(error <= 1 && error >= -1 && servoOutput == 26 && diffError <=0.5 && diffError >=-0.5)) { //tweaking of the regulator so that it stands still if the ball is within +-1 Cm. u = (Kp * error) + (Ki * sumError) + (Kd * diffError); } servoOutput = constrain(-u + 26, 0, 65); servo.write(servoOutput);

runningTime = millis(); } if (DEBUG_ACTIVE) { printStatus(); } }

void startup() { for (int i = 75; i >= 15; i--) { servo.write(i);

if ((i / 2 & 1) == 0) { ledPinOn(PIN_LED); } else { ledPinOff(PIN_LED); } delay(50); } }

int getSensorRunningAverage(int sensorValue) { total = total - readings[readIndex]; readings[readIndex] = sensorValue; // read from the sensor: total = total + readings[readIndex]; // add the reading to the total: readIndex = readIndex + 1; // advance to the next position in the array: if (readIndex >= numReadings) { // if we're at the end of the array... readIndex = 0; // ...wrap around to the beginning: } float average = total / numReadings; // calculate the average: return average; }

void printStatus() { Serial.print("Distance: "); Serial.print(dis); Serial.print("\t");

Serial.print("Error: "); Serial.print(error); Serial.print("\t");

Serial.print("Sum error: "); Serial.print(sumError); Serial.print("\t");

Serial.print("Diff error: "); Serial.print(diffError); Serial.print("\t");

Serial.print("u(t): "); Serial.print(u); Serial.print("\t");

Serial.print("Output: "); Serial.println(servoOutput); }

void ledPinOn(int led) { digitalWrite(led, HIGH); }

void ledPinOff(int led) { digitalWrite(led, LOW); }

Be the First to Share

    Recommendations

    • Finish It Already Speed Challenge

      Finish It Already Speed Challenge
    • First Time Author Contest

      First Time Author Contest
    • Space Challenge

      Space Challenge

    3 Discussions

    0
    hanseokgyu0726
    hanseokgyu0726

    Question 7 months ago

    Good morning.
    I'm studying by myself. If you open the stl file you uploaded, the modeling size is too big. Can I get it as a step file?
    1
    seamster
    seamster

    1 year ago

    This is interesting. I'm curious about the story behind it, and some info on the intended use of this object: is this part of a larger project, or maybe a school assignment to achieve a specific task . . or?

    0
    askjong
    askjong

    Reply 1 year ago

    This was a school project in control engineering. I will update it with the task and the requirements that were specified, and what problems we got while we worked on it :)