Team 26 - Appendix
Bill of Materials:
MATLAB code:
Main code:
clc; clear; format compact; clf; close all;
set(0,'defaultTextInterpreter','latex');
set(0, 'defaultAxesTickLabelInterpreter','latex');
set(0, 'defaultLegendInterpreter','latex');
set(0,'defaultAxesFontSize',18);
set(0, 'DefaultLineLineWidth', 2);
set(groot, 'defaultFigureUnits', 'pixels', 'defaultFigurePosition', [440 278 560 420]);
d = 46.47;
d_dot = 10;
[ta, tb, wa, wb] = mechanism1(d, d_dot);
tb = ta + 75 * pi/180;
wb = wa;
[a, ta, a_dot, wa] = mechanism2(tb, wb);
% Calculating input slider position and velocity
d = linspace(30.25, 111, 100);
pitch = 2; % mm/rev
w_motor = 200 * 2*pi / 60; % rad/s (200 RPM)
d_dot = w_motor * pitch / (2 * pi); % mm/s
tb_bank = zeros(1, length(d));
wb_bank = zeros(1, length(d));
ta_bank = zeros(1, length(d));
wa_bank = zeros(1, length(d));
for i = 1:length(d)
[ta, tb, wa, wb] = mechanism1(d(i), d_dot);
tb = ta + 75 * pi/180;
wb = wa;
[a, ta, a_dot, wa] = mechanism2(tb, wb);
tb_bank(i) = tb;
wb_bank(i) = wb;
ta_bank(i) = ta;
wa_bank(i) = wa;
end
figure
hold on
box on
plot(d - 30, ta_bank, '-r')
plot(d - 30, tb_bank, '-b')
xlabel('Input Slider Actuation, $x$ [mm]')
ylabel('$\theta$ [rad]')
legend('Distal Finger Angle, $\theta_{a}$', 'Proximal Finger Angle, $\theta_{b}$')
legend('location', 'best')
title('Finger Angular Positions vs. Slider Input')
xlim([0, 80])
figure
hold on
box on
plot(d - 30, wa_bank, '-r')
plot(d - 30, wb_bank, '-b')
xlabel('Input Slider Actuation, $x$ [mm]')
ylabel('$\dot{\theta}$ [rad/s]')
legend('Distal Finger Velocity, $\dot{\theta_{a}}$', 'Proximal Finger Velocity, $\dot{\theta_{b}}$')
legend('location', 'best')
title('Finger Angular Velocities vs. Slider Input')
xlim([0, 80])
Function for mechanism #1:
function [ta, tb, wa, wb] = mechanism1(d, d_dot, is_symbolic)
if nargin < 3
is_symbolic = false;
end
if is_symbolic == true
syms a b c d ta tb tc td d_dot wa wb;
% Position
eqn1 = a*cos(ta) + c + b*cos(tb) == 0;
eqn2 = a*sin(ta) - d + b*sin(tb) == 0;
eqns = [eqn1, eqn2];
vars = [ta, tb];
[solv, solu] = solve(eqns, vars);
ta = simplify(solv(2));
tb = simplify(solu(2));
% Velocity
eqn1 = -a*wa*sin(ta) - b*wb*sin(tb) == 0;
eqn2 = a*wa*cos(ta) - d_dot + b*wb*cos(tb) == 0;
eqns = [eqn1, eqn2];
vars = [wa, wb];
[solv, solu] = solve(eqns, vars);
wa = simplify(solv);
wb = simplify(solu);
else
syms ta tb wa wb;
% Position
a = 54.45;
b = 80;
c = 1.72;
eqn1 = a*cos(ta) + c + b*cos(tb) == 0;
eqn2 = a*sin(ta) - d + b*sin(tb) == 0;
eqns = [eqn1, eqn2];
vars = [ta, tb];
[solv, solu] = solve(eqns, vars);
ta_set = eval(solv);
tb_set = eval(solu);
ta = ta_set(2);
tb = tb_set(2);
% Velocity
eqn1 = -a*wa*sin(ta) - b*wb*sin(tb) == 0;
eqn2 = a*wa*cos(ta) - d_dot + b*wb*cos(tb) == 0;
eqns = [eqn1, eqn2];
vars = [wa, wb];
[solv, solu] = solve(eqns, vars);
wa = eval(solv);
wb = eval(solu);
end
end
Function for mechanism #2:
function [a, ta, a_dot, wa] = mechanism2(tb, wb, is_symbolic)
if nargin < 3
is_symbolic = false;
end
if is_symbolic == true
syms a b c d ta tb tc td a_dot wa wb wc wd;
% Position
eqn1 = a*cos(ta) - b*cos(tb) + c*cos(tc) + d*sin(ta) == 0;
eqn2 = a*sin(ta) - b*sin(tb) + c*sin(tc) - d*cos(ta) == 0;
eqns = [eqn1, eqn2];
vars = [a, ta];
[solv, solu] = solve(eqns, vars);
a = simplify(solv(1));
b = simplify(solu(1));
% Velocity
eqn1 = a_dot * cos(ta) - a * wa * sin(ta) + b * wb * sin(tb) + d * wa * cos(ta);
eqn2 = a_dot * sin(ta) + a * wa * cos(ta) - b * wb * cos(tb) + d * wa * sin(ta);
eqns = [eqn1, eqn2];
vars = [a_dot, wa];
[solv, solu] = solve(eqns, vars);
a_dot = simplify(solv);
wa = simplify(solu);
else
syms a ta a_dot wa;
% Position
b = 120;
c = 90;
d = 26.42;
tc = 3*pi/4;
eqn1 = a*cos(ta) - b*cos(tb) + c*cos(tc) + d*sin(ta) == 0;
eqn2 = a*sin(ta) - b*sin(tb) + c*sin(tc) - d*cos(ta) == 0;
eqns = [eqn1, eqn2];
vars = [a, ta];
[solv, solu] = solve(eqns, vars);
a_set = eval(solv);
ta_set = eval(solu);
a = a_set(1);
ta = ta_set(1);
% Velocity
eqn1 = a_dot * cos(ta) - a * wa * sin(ta) + b * wb * sin(tb) + d * wa * cos(ta);
eqn2 = a_dot * sin(ta) + a * wa * cos(ta) - b * wb * cos(tb) + d * wa * sin(ta);
eqns = [eqn1, eqn2];
vars = [a_dot, wa];
[solv, solu] = solve(eqns, vars);
a_dot = eval(solv);
wa = eval(solu);
end
end
Arduino code:
#include <Arduino.h>
#include <Stepper.h>
// Define FSR pin:
#define fsrpin1 A0
#define fsrpin2 A1
#define potpin1 A2
#define potpin2 A3
const int dirPin = 2;
const int stepPin = 3;
int potMax {660};
int potMin {0};
int LEDState=0;
int LEDPinBlue=7;
int LEDPinRed=8;
int buttonPin=12;
int buttonNew;
int buttonOld=1;
int dt=20;
// Define number of steps per revolution:
const int stepsPerRevolution = 200;
// Initialize the stepper library on pins 8 through 11:
Stepper myStepper = Stepper(stepsPerRevolution, 3, 4, 5, 6);
//-------------------------------------------------------------
// Settings
int target_force {12}; // N
float conversion_factor {0.02}; // N/bit(/8)
int prop_gain {1};
float tolerance_window {0.3};
float pot_tol {0.8};
int min_step_size {5};
int max_step_size {200};
int speedMax {250};
bool activeFeedback {0};
signed long currentRotation {0};
bool dir {};
//-------------------------------------------------------------
// Function prototypes
bool setControlMode ();
int adjustSpeed ();
float readForce ();
int calculateStep (float current_force);
int potentiometerControl ();
int adjustDirection ();
void stepMotor (int steps);
//-------------------------------------------------------------
void setup () {
pinMode(LEDPinBlue, OUTPUT);
pinMode(LEDPinRed, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
Serial.begin(9600);
}
void loop () {
// - Check button to determine whether should be using remote control or autonomous
bool activeFeedback {setControlMode()};
// * If closed-loop control should be active
if (activeFeedback == true) {
// - read in force
float current_force {readForce()};
// - use it to determine update in motor step
int step_size {calculateStep(current_force)};
// - execute update
stepMotor(step_size);
// * If remote control should be active
} else {
// - determine direction from user control
signed int direction {adjustDirection()};
// - execute update
stepMotor(direction * 10);
}
delay(10);
}
//-------------------------------------------------------------
void stepMotor(int steps)
{
Serial.println(steps);
if (steps > 0) {
digitalWrite(dirPin, HIGH);
} else if (steps < 0) {
digitalWrite(dirPin, LOW);
}
if (steps != 0) {
for(int x = 0; x < stepsPerRevolution; x++)
{
digitalWrite(stepPin, LOW);
delayMicroseconds(2000);
digitalWrite(stepPin, HIGH);
delayMicroseconds(2000);
}
}
}
int adjustSpeed () {
int potVal = analogRead(potpin2);
int speed = (map(potVal, potMin, potMax, 1, speedMax));
return speed;
}
int adjustDirection () {
int potVal = analogRead(potpin2);
int potMed {((potMin + potMax) / 2)};
Serial.println();
if (potVal > potMed && potVal > (1 + pot_tol) * potMed) {
return 1;
} else if ((potVal < potMed && potVal < (1 - pot_tol) * potMed)) {
return -1;
} else {
return 0;
}
}
bool setControlMode ()
{
buttonNew=digitalRead(buttonPin);
if(buttonOld==0 && buttonNew==1){
if (LEDState==0){
digitalWrite(LEDPinBlue,HIGH);
digitalWrite(LEDPinRed,LOW);
LEDState=1;
}
else{
digitalWrite(LEDPinBlue, LOW);
digitalWrite(LEDPinRed,HIGH);
LEDState=0;
}
}
buttonOld=buttonNew;
delay(dt);
return LEDState;
}
float readForce ()
{
int fsrreading1 = analogRead(fsrpin1);
int fsrreading2 = analogRead(fsrpin2);
float current_force = conversion_factor * ((fsrreading1 + fsrreading2) / 2);
Serial.print("Reading = ");
Serial.println(current_force);
return current_force;
}
int calculateStep (float current_force)
{
int step_size {};
if (((current_force < (1 - tolerance_window) * target_force) && (current_force < target_force)) || ((current_force > (1 + tolerance_window) * target_force) && (current_force > target_force))) {
// step_size = prop_gain * (target_force - current_force);
step_size = prop_gain * ((target_force / conversion_factor) - (current_force / conversion_factor - 0)) * (max_step_size - min_step_size) / (1023 - 0);
}
return step_size;
}
Welcome to the University Wiki Service! Please use your IID (yourEID@eid.utexas.edu) when prompted for your email address during login or click here to enter your EID. If you are experiencing any issues loading content on pages, please try these steps to clear your browser cache.