ROBOTIC ARM
I programmed a robotic arm in C++ with a partner to pick up an object and throw it. This was done in the Linux environment connected to a Zedboard in order to control the robotic arm.
​
The following code controls the position and speed of a specified servo on the robotic arm. It should be noted that this is not the code for the robot in the video above, as I no longer have access to that code however it is very similar. The ServoSpeed.cc file was modified in order to control the picking up and throwing movement. The GPIO files are used to configure the Zedboard as it resets its configuration upon each reboot. This code was created in collaboration with Northeastern University's Embedded Design spring 2017 class, and my lab partner.
​
GPIO.h:
#ifndef GPIO_H
#define GPIO_H
class GPIO
{
​
// File descriptor
int fd;
​
public:
/*
*
* Class constructor.
*
* @param number
* Port number for GPIO.
*/
GPIO(int number);
​
/*
*
* Class destructor.
*/
​
~GPIO();
​
/*
*
* Generate a PWM signal, blocking the caller while the signal is being generated.
*
* @param period
* PWM period in microseconds.
*
* @param pulse
* Duration of the pulse in microseconds.
*
* @param num_periods
* Number of periods to generate.
*/
​
void GeneratePWM(int period, int pulse, int num_periods);
void GenerateVariablePWM(int period, int first_pulse, int last_pulse, int num_periods);
​
};
#endif
​​
​
GPIO.cc:
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include "GPIO.h"
GPIO::GPIO(int number)
{
​
// GPIO device files will follow the format
// /sys/class/gpio/gpio<NR>/value
// <NR> has to be replaced with the actual device number passed as an argument to the class constructor.
char device_name[128];
sprintf(device_name, "/sys/class/gpio/gpio%d/value", number);
// Open special device file and store file descriptor in class member.
fd = open(device_name, O_WRONLY);
if (fd < 0)
{
std::cerr << "Cannot open " << device_name <<" - forgot sudo? \n";
exit(1);
}
}
GPIO::~GPIO()
{
// Close open file descriptor
close(fd);
}
void GPIO::GeneratePWM(int period, int pulse, int num_periods)
{
// Generate num_perios of the PWM signal
for (int i = 0; i < num_periods; i++)
{
// Write ASCII character "1" to raise pin to 1, starting the ON cycle, then wait duration of pulse.
write(fd, "1", 1);
usleep(pulse);
// Write ASCII character "0" to lower pin to 0, starting the OFF cycle, then wait the rest of the period time.
write(fd, "0", 1);
usleep(period - pulse);
}
}
​
void GPIO::GenerateVariablePWM(int period, int first_pulse, int last_pulse, int num_periods)
{
int pulse;
int total_angle;
total_angle=last_pulse-first_pulse;
int time=period*num_periods;
for (int i = 0; i < num_periods; i++)
{
pulse=first_pulse+total_angle/num_periods*i;
write(fd, "1", 1); usleep(pulse);
write(fd, "0", 1); usleep(period - pulse);
}
}
​​
​
ServoSpeed.cc
#include "GPIO.h"
#include <iostream>
using namespace std;
int main()
{
cout<<"enter a number between one and five \n enter 1 to move the base \n enter 2 to move the bicep \n enter 3 to move the elbow \n enter 4 to move the wrist \n enter 5 to move the gripper"<<endl;
int servo_number; cin>>servo_number;
if(servo_number<1 || servo_number>5)
{
cout<<"Enter a valid input between 1 and five "<<endl;
cin>>servo_number;
}
​
if(servo_number==1) servo_number=13;
if(servo_number==2) servo_number=10;
if(servo_number==3) servo_number=11;
if(servo_number==4) servo_number=12;
if(servo_number==5) servo_number=0;
​
cout<< "enter the angle in degrees that you would like to move the servo"<<endl;
int angle;
cin>>angle; if(angle<0 || angle>180)
{
cout<<"Enter a valid input between 0 and 180"<<endl; cin>>angle;
}
int servo_angle;
servo_angle=(angle/100+.6)*1000;
GPIO gpio(servo_number);
gpio.GeneratePWM(20000,servo_angle,100);
return 0;
}
​
​​
Makefile:
main: GPIO.o ServoPosition.o
g++ GPIO.o ServoPosition.o -o main
GPIO.o: GPIO.cc GPIO.h
g++ -c GPIO.cc
ServoSpeed.o: ServoSpeed.cc GPIO.h
g++ -c ServoSpeed.cc clean:
rm *.o main
​