How would I connect an torque screwdriver to MATLAB to simultaneously output a graph of Torque vs Time while my other code measures force from a sensor?
2 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
I am working on a research project that uses a MATLAB program that measures force from a donut hole FUTEK sensor in conjunction with implanted screws that go into bones. A screw goes into the hole on the sensor and compresses bone and we measure that force. Here is the sensor specs:
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1636281/image.png)
Essentially, I am attempting to use a digital torque screwdriver (this model: https://imada.com/products/cedar-did-4a-digital-torque-screwdriver/) to incorporate real-time continuous torque measurements and compare these with the force outputs from the written MATLAB program. My current task is centered on trying to incorporate this into the MATLAB program possibly by having it side by side on two different graphs with one being force data and one being torque amount which could then be filtered or even overlaying both sets.
I am pretty new to MATLAB but have some experience and would like some suggestions on how to connect devices to the program and read their output and how I can add to this program to output torque from the screwdriver and compare it to the force. Any help is appreciated!
Here is the code for the project (written before I joined the project) that I am attempting to add to, it includes an app interface :
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
cutoff matlab.ui.control.NumericEditField
FilterCutoffEditFieldLabel matlab.ui.control.Label
order matlab.ui.control.NumericEditField
FilterOrderEditFieldLabel matlab.ui.control.Label
ReadyButton matlab.ui.control.StateButton
persecondLabel matlab.ui.control.Label
DataCollectionRateLabel matlab.ui.control.Label
DataRate matlab.ui.control.NumericEditField
AppliedLoad matlab.ui.control.NumericEditField
AppliedLoadkgEditFieldLabel matlab.ui.control.Label
CalibrationStatusLamp matlab.ui.control.Lamp
CalibrationStatusLampLabel matlab.ui.control.Label
SetupButton matlab.ui.control.Button
FullCalibrationButton matlab.ui.control.Button
QuickCalibrationButton matlab.ui.control.Button
CheckCalibrationButton matlab.ui.control.Button
BoneViscoelasticityDataCollectionLabel matlab.ui.control.Label
Directions matlab.ui.control.Label
txtLabel1 matlab.ui.control.Label
Filename matlab.ui.control.EditField
FilenameEditFieldLabel matlab.ui.control.Label
StopButton matlab.ui.control.StateButton
StartButton matlab.ui.control.Button
TimeLabel matlab.ui.control.Label
ResetButton matlab.ui.control.Button
TurnGague matlab.ui.control.LinearGauge
NumberofTurnsGaugeLabel matlab.ui.control.Label
TurnButton matlab.ui.control.Button
UIAxes matlab.ui.control.UIAxes
end
methods (Access = private)
function results = func(app)
end
end
methods (Access = public)
function results = func2(app)
end
end
% Callbacks that handle component events
methods (Access = private)
% Button pushed function: TurnButton
function TurnButtonPushed(app, event)
app.TurnGague.Value = app.TurnGague.Value + 0.25;
end
% Button pushed function: ResetButton
function ResetButtonPushed(app, event)
app.TurnGague.Value = 0;
app.StopButton.Value = 0;
app.TimeLabel.Text = num2str(0);
app.Directions.Text = 'Program reset. Type new filename for new data collection';
global file;
file = 1;
pause (0.0001);
end
% Button pushed function: StartButton
function StartButtonPushed(app, event)
global filename
global file
global rate
global order
global cutoff
if file == 1
app.Directions.Text = 'Please type new filename for data collection';
end
if rate ~= 0 %prevents from dividing by zero
timeconst = 1 / rate; %seconds between readings
else
timeconst = 0.1; %defaults to 10 times per second
end
stop = app.StopButton.Value;
app.Directions.Text = 'beginning data collection';
pause(1)
global ard;
global calZero;
global calOffset;
[b,a] = butter(order, cutoff);
i = 0; %initialization of counter
t=(tic);
while (stop == 0 && file == 0)
turns = app.TurnGague.Value;
pause(0.00001);
if toc >= (timeconst * i)
tstart=now();
time = toc(t);
app.TimeLabel.Text = num2str(time);
voltage = readVoltage(ard, 'A1');
compression = (voltage - calZero) / calOffset;
app.Directions.Text = strcat(num2str(compression), " Newtons");
pause(0.00001);
if i == 0
data = table(time, voltage, compression, turns);
plotdata = compression;
avg0 = compression;
elseif i == 1
T = table(time, voltage, compression, turns);
data = vertcat(data, T);
plotdata = [plotdata ((compression + avg0) / 2)];
avg1 = compression;
else
T = table(time, voltage, compression, turns);
data = vertcat(data, T);
plotdata = [plotdata ((compression + avg0 + avg1) / 3)];
avg0 = avg1;
avg1 = compression;
end
writetable(data, filename);
plot(app.UIAxes, data.time, plotdata);
i = i + 1;
stop = app.StopButton.Value;
pause(0.001);
end
%app.Directions.Text= strcat(num2str(now()-tstart), " time");
end
filtered = filter(b,a,data.compression);
time = data.time;
turns = data.turns;
T2 = table(time, filtered, turns);
filename2 = strcat(erase(filename, ".xlsx"), "_filtered.xlsx");
writetable(T2, filename2);
if file == 0
app.Directions.Text = 'Data collection ended. Reset to collect new data';
end
end
% Value changed function: Filename
function FilenameValueChanged(app, event)
global filename
filename = app.Filename.Value;
t = datetime('now'); %append with date time to prevent overwriting data
filename = strcat(filename, '_');
filename = strcat(filename, datestr(t, 'mm.dd.yy_HH.MM.SS'));
filename = strcat(filename, '.xlsx'); %makes output an excel spreadsheet file
global file
file = 0;
app.Directions.Text = 'press start when ready';
end
% Button pushed function: SetupButton
function SetupButtonPushed(app, event)
global ard;
if ~isempty(instrfind)
fclose(instrfind);
delete(instrfind);
end
if isempty(ard) == 1
ard = arduino('/dev/cu.usbmodem1301','Mega2560');
end
cfile = fopen('calibData.txt', 'r');
cdata = fscanf(cfile, '%f\n');
fclose('all');
%create global variables with calibration constants
global calZero
calZero = cdata(1);
global calOffset
calOffset = cdata(2);
global rate
rate = app.DataRate.Value;
global order
order = app.order.Value;
global cutoff
cutoff = app.cutoff.Value;
app.Directions.Text = 'Setup Complete. Run calibration check or enter filename to begin data collection.';
end
% Value changed function: DataRate
function DataRateValueChanged(app, event)
global rate
rate = app.DataRate.Value;
end
% Button pushed function: CheckCalibrationButton
function CheckCalibrationButtonPushed(app, event)
app.Directions.Text = 'Please remove all load from sensor and press Ready';
go = 0;
while go == 0
go = app.ReadyButton.Value;
pause(0.01)
end
app.Directions.Text = 'Measuring zero';
pause(1)
global ard
global calZero
global calOffset
%run a loop to measure output with zero load
val = zeros(20,1);
i = 0;
timeconst = 0.1;
tic
while i < 20
if toc > (timeconst * i)
val(i + 1) = readVoltage(ard, 'A1');
i = i + 1;
end
end
checkzero = mode(val);
app.ReadyButton.Value = 0;
app.Directions.Text = 'Please load sensor with tray and 25lb weight and press Ready';
go = 0;
while go == 0
go = app.ReadyButton.Value;
pause(0.01)
end
app.Directions.Text = 'Measuring weight';
pause(1);
%run a loop to measure output with load
val = zeros(20,1);
i = 0;
tic
while i < 20
if toc > (timeconst * i)
val(i + 1) = readVoltage(ard, 'A1');
i = i + 1;
end
end
checkoffset = mode(val);
checkoffset = (checkoffset - checkzero) / 117.4 %load in newtons from tray and weight
checkoffset = abs(checkoffset - calOffset) / calOffset;
checkzero = abs(checkzero - calZero) / calZero %calculate the error
if (checkzero < 0.01) && (checkoffset < 0.01)
calib = 0
elseif checkzero < 0.01
calib = 1;
elseif checkoffset < 0.01
calib = 1;
elseif (checkzero < 0.05) && (checkoffset < 0.05)
calib = 1;
else
calib = 2;
end
switch calib
case 0
txt = strcat('Calibration is good. Checkzero = ', num2str(checkzero));
txt = strcat(txt, ', Checkoffset =', num2str(checkoffset));
app.Directions.Text = txt;
app.CalibrationStatusLamp.Color = 'green';
case 1
txt = strcat('Calibration is slightly off. Quick calibration recommended. Checkzero = ', num2str(checkzero));
txt = strcat(txt, ', Checkoffset =', num2str(checkoffset));
app.Directions.Text = txt;
app.CalibrationStatusLamp.Color = 'yellow';
case 2
txt = strcat('Calibration is off. Quick or full calibration necessary. Checkzero = ', num2str(checkzero));
txt = strcat(txt, ', Checkoffset =', num2str(checkoffset));
app.Directions.Text = txt;
app.CalibrationStatusLamp.Color = 'red';
end
app.ReadyButton.Value = 0;
end
% Button pushed function: QuickCalibrationButton
function QuickCalibrationButtonPushed(app, event)
%copy current calibration values to new file
cfile = fopen('calibData.txt', 'r');
t = datetime('now'); %append with date time to show old calibration
newfile = strcat('calibDataBefore', datestr(t, 'mm.dd.yy_HH.MM.SS'));
newfile = strcat(newfile, '.txt');
cfilenew = fopen(newfile, 'w');
cdata = fscanf(cfile, '%f\n');
fprintf(cfilenew, '%f\n', cdata);
fclose('all');
%measure different loads, starting at zero
app.Directions.Text = 'Please remove all load from sensor for calibration and press Ready';
go = 0;
while go == 0
go = app.ReadyButton.Value;
pause(0.01)
end
app.Directions.Text = 'Calibrating zero';
pause(1)
weights = [0; 54.286; 117.143];
val = zeros(20,1);
i = 0;
timeconst = 0.1;
global ard
tic
while i < 20
if toc > (timeconst * i)
val(i + 1) = readVoltage(ard, 'A1');
i = i + 1;
end
end
zcal = mode(val);
%repeat with small weight
app.ReadyButton.Value = 0;
app.Directions.Text = 'Please load sensor with tray and 10lb weight and press Ready';
go = 0;
while go == 0
go = app.ReadyButton.Value;
pause(0.01)
end
app.Directions.Text = 'Calibrating weight';
pause(1)
val = zeros(20,1);
i = 0;
tic
while i < 20
if toc > (timeconst * i)
val(i + 1) = readVoltage(ard, 'A1');
i = i + 1;
end
end
wcalsmall = mode(val);
%repeat with larger weight
app.ReadyButton.Value = 0;
app.Directions.Text = 'Please load sensor with tray and 25lb weight and press Ready';
go = 0;
while go == 0
go = app.ReadyButton.Value;
pause(0.01)
end
app.Directions.Text = 'Calibrating weight';
pause(1)
val = zeros(20,1);
i = 0;
tic
while i < 20
if toc > (timeconst * i)
val(i + 1) = readVoltage(ard, 'A1');
i = i + 1;
end
end
wcalbig = mode(val);
%calculate calibration constants
global calZero
global calOffset
voltages = [zcal; wcalsmall; wcalbig];
W = [ones(length(weights), 1) weights];
B = W\voltages; %calculates linear regression
calZero = B(1);
calOffset = B(2);
app.CalibrationStatusLamp.Color = 'green';
%overwrite calibration file with new calibration constants
cfile = fopen('calibData.txt', 'w');
fprintf(cfile, '%f\n', B);
fclose('all');
app.ReadyButton.Value = 0;
end
% Value changed function: AppliedLoad
function AppliedLoadValueChanged(app, event)
global load
load = app.AppliedLoad.Value;
end
% Button pushed function: FullCalibrationButton
function FullCalibrationButtonPushed(app, event)
%copy current calibration values to new file
cfile = fopen('calibData.txt', 'r');
t = datetime('now'); %append with date time to show old calibration
newfile = strcat('calibDataBefore', datestr(t, 'mm.dd.yy_HH.MM.SS'));
newfile = strcat(newfile, '.txt');
cfilenew = fopen(newfile, 'w');
cdata = fscanf(cfile, '%f\n');
fprintf(cfilenew, '%f\n', cdata);
fclose('all');
%define weights and calculate all values
weightskg = [0; 10; 25; 50; 75; 100; 125; 150; 175; 200];
weightsN = weightskg * 9.807;
voltages = zeros(10, 1);
i = 1;
global ard
global load
timeconst = 0.1;
while i <= 10
app.ReadyButton.Value = 0;
txt = strcat('Please load sensor with ', num2str(weightskg(i)));
txt = strcat(txt, ' kilograms and enter exact value then press Ready');
app.Directions.Text = txt;
go = 0;
while go == 0
go = app.ReadyButton.Value;
pause(0.01)
end
weightsN(i) = load * 9.807;
val = zeros(20,1);
j = 0;
tic
while j < 20
if toc > (timeconst * i)
val(j + 1) = readVoltage(ard, 'A1');
j = j + 1;
end
end
voltages(i) = mode(val);
i = i + 1;
end
%calculate linear regression and save as global calibration constants
W = [ones(length(weightsN), 1) weightsN];
B = W\voltages; %calculates linear regression
global calZero
global calOffset
calZero = B(1);
calOffset = B(2);
app.CalibrationStatusLamp.Color = 'green';
%overwrite calibration file with new calibration constants
cfile = fopen('calibData.txt', 'w');
fprintf(cfile, '%f\n', B);
fclose('all');
app.ReadyButton.Value = 0;
end
0 comentarios
Respuestas (1)
nathan blanc
el 6 de Mzo. de 2024
The answer to this depends on your hardware for torque measurments. almost any data acquisition hardware can be read using the data acquisition toolbox. Alternativeky, If your measurments can be continously recorded to a file, you can periodically read from the file using matlab.
e.g. the following code will read from the file 'blabla.text' every second and plot the data.
fileID = fopen('blabla.txt','r');
while true
A = fscanf(fileID,'%f');
plot(A);
pause(1)
end
fclose(fileID);
0 comentarios
Ver también
Categorías
Más información sobre MuPAD en Help Center y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!