Update 11/24/13

I have been able to get the motor working with the valve, as well as mechanically stabilize the motor so it does not turn itself rather than turning the valve.

I have run into several issues with the code/hardware. The main issue is the tradeoff between resolution and speed. In order to have a resolution conducive to application, the speed drops to below 20 rpm, this however is more than likely too slow for any application. The second issue is the initial force required to open the valve causes calculation issues in the code. The code does not have the ability to determine the actual position of the motor, it can only tell the motor to move a set number of ticks and can record that, if there is too much resistance and the motor cannot turn, the recorded number is off and the motor will over or under close. I attempted to solve this by introducing a stopping mechanism at the beginning that would complete a circuit and make the program break if the motor returned to the “almost close” position (did not want full closure as it required too much force to open). However this exposed a new problem, the amount of time it took to read the data from a second (or the same) arduino into the system greatly dropped the resolution again.

This program that runs the interface between MATLAB and the arduino seems to have some faults along communication. It seems to work well for simple tasks (inputs and outputs) but sending a waveform through a motor that is so time sensitive seems to cause problems.

The code I have now that works to some degree is below. It introduces a break in the motor code if the position becomes less than 0 ( to prevent over closure) It also has the speed greatly lowered (to help with resolution). This speed as well with the constants set at the beginning will change calibration in the future with the flow meter. (For some reason if I change the speed it changes the maximum position)

Note: I introduced a second arduino into the system prior using “b = arduino”COM 4”; and using the b variable to control it. This is not included in this code as it caused issues

\code
%% Inhalation Profile to Motor Movement
% Last Updated 11/22/2013
%% code overview
%input from excel spreadsheet
%-> profile (flow rate) as a matrix
%-> time (corrosponding to profile) as a matrix
% the input will be translated to motor position vs. time
% which will involve changing the scale to fit the motor callibrations
% the motor will follow the calibrated matrix and perform the profile

%% Inhalation Profile Data Bank
%
% Format for importation:
% matrix = xlsread(‘File name’, ‘spreadsheet name’);
% note: Filename must include extension (.xlsx) and make sure to include
% the single quotes
%
% File name: ‘InhalationProfileExcel.xlsx’ MUST BE IN MATLAB FOLDER
%
% Spreadsheet names (First is for time data, second is for flow rate)
% ‘Profile1Time’; ‘Profile1Flow’; This is test data made using a sigmoid derivitive with max flow rate of around 3 L/s
clc;clear all; close all;

%% Connect to Arduino and set motor speed

a=arduino(‘COM3’);

rpmmax = 15; % 150-160 is the max rpm we can get without the motor malfunctioning
mot = 2; % motor is connected to the stepper 2 spot
posmax = 300; % (probably bad) estimation will be callibrated later
flowmax = 1.5; % L/s
convert = posmax/flowmax; % conversion factor to convert flow rate to position

direction = 1; %direction of movement (for position tracker)
a.stepperSpeed(mot,rpmmax) % We want to set the stepper speed to max
pt = 0;%position tracker to make sure that we get back to full close

%% Import Inhalation Profile via Excel Spreadsheet

%max inhalation ~ 280 L/min ~ 5 L/s

%% This Portion will be the only part that will need to be changed to test various profiles (the rest will auto-correct accordingly)
%See Inhalation Profile Data Bank section at begining of code for
% instructions, file names, and descriptions

%time data for inhalation profile
time = xlsread(‘InhalationProfileExcel.xlsx’,’Profile1Time’);% test data = linspace(0,5);
%Flow rate for inhalation profile
profile = xlsread(‘InhalationProfileExcel.xlsx’,’Profile1Flow’);% test data = 200.*(exp(time))./(exp(time) +10).^2 -2 -> sigmoid derivitive with max 3 L/s

%% Make sure that no negatives are present in the flowrate (make sure program doesn’t crash)

for i=1:length(profile)
if profile(i) <0
profile(i) = 0;
end
end

%% plot inhalation profile for referance
figure()
plot(time,profile)
title('Inhalation Profie')
xlabel('Time (s)')
ylabel('Flow Rate (L/s)')

%% Translate to motor position vs. time

motorpos = profile * convert;
movearray = zeros(size(profile)); %create a blank array to store the movements of the motor
movetime = zeros(size(profile)); %create a blank array to store the time relative to motor
track = zeros(size(profile));
moveindex = 1; %array index for the motor movement arrays;

%% translate to num steps vs time.

stepcount = diff(motorpos);

%% Perform Motor Function
tic %tic/toc will be used as it will provide the quickest response possible from the system

while toc=0)); %want the non-zero minimum (so we move foward in the matrix)
%cont. otherwise the minimum would always be the first index
if isempty(minCheck) == true % failsafe since sometimes a very small neg is formed instead of a 0 term for the final index
minCheck = max(check);
end

timeindex = find(check == minCheck); %finds time index that corrolates with the time closest to clock
move = round(abs(stepcount(timeindex-1))); % uses time index to find motor position needed at this time

movearray(moveindex) = move; % store motor position for comparison

%determine direction of motor movement from slope

if stepcount(timeindex-1)> 0
dir = ‘backward’;
d = 1;
else
dir = ‘forward’;
d = -1;
end

%% move stepper motor to correct position
if move > 0

a.stepperStep(2,dir,’interleave’,move);
pt = pt + d*move
if pt <= 0
break
end

track(moveindex) = pt;
moveindex = moveindex + 1;
%pause(.1);
end

end

pt

track(moveindex) = pt;
while pt < 0

a.stepperStep(2,'backward','interleave',1)

pt = pt + 1;
end

a.stepperStep(2,'release');
%plot motor movement for comparison to inhalation profile
figure()

plot(movetime,track)
title('Motor Position vs. Time')
xlabel('Time (s)')
ylabel('Motor Position (relative)')

a.delete
\end code

Major Progress

I now have access to Matlab that is running a support package that allows direct interfacing with the arduino. With this I have developed a Matlab program that takes an inhalation profile from excel (given in matrix form) and outputs motor movement. (Note: ********** means that this is not finalized and needs to be changed before any proper testing can begin, this is mostly due to no-calibration being set/ not having motor currently connected)


%% Inhalation Profile to Motor Movement
% Last Updated 10/7/2013
%% code overview
%input from excel spreadsheet
%-> profile (flow rate) as a matrix
%-> time (corrosponding to profile) as a matrix
% the input will be translated to motor position vs. time
% which will involve changing the scale to fit the motor callibrations
% the motor will follow the calibrated matrix and perform the profile

%% Inhalation Profile Data Bank
%
% Format for importation:
% matrix = xlsread('File name', 'spreadsheet name');
% note: Filename must include extension (.xlsx) and make sure to include
% the single quotes
%
% File name: 'InhalationProfileExcel.xlsx' MUST BE IN MATLAB FOLDER
%
% Spreadsheet names (First is for time data, second is for flow rate)
% 'Profile1Time'; 'Profile1Flow'; This is test data made using a sigmoid derivitive with max flow rate of around 3 L/s

%% Connect to Arduino and set motor speed

%***********a=arduino('COM3');
%a.stepperSpeed(1,50) % We want to set the stepper speed to max

%% Import Inhalation Profile via Excel Spreadsheet
clc;clear all; close all;
%max inhalation ~ 280 L/min ~ 5 L/s

% This Portion will be the only part that will need to be changed to test various profiles (the rest will auto-correct accordingly)
%See Inhalation Profile Data Bank section at begining of code for
% instructions, file names, and descriptions

%time data for inhalation profile
time = xlsread('InhalationProfileExcel.xlsx','Profile1Time');% test data = linspace(0,5);
%Flow rate for inhalation profile
profile = xlsread('InhalationProfileExcel.xlsx','Profile1Flow');% test data = 200.*(exp(time))./(exp(time) +10).^2 -2 -> sigmoid derivitive with max 3 L/s

%% Make sure that no negatives are present in the flowrate (make sure program doesn't crash)

for i=1:length(profile)
if profile(i) <0
profile(i) = 0;
end
end

%% plot inhalation profile for referance
figure()
plot(time,profile)
title('Inhalation Profie')
xlabel('Time (s)')
ylabel('Flow Rate (L/s)')

%% Translate to motor position vs. time

convert = 1; %********************* this will be calculated later
motorpos = profile * convert;
movearray = zeros(size(profile)); %create a blank array to store the movements of the motor
movetime = zeros(size(profile)); %create a blank array to store the time relative to motor
moveindex = 1; %array index for the motor movement arrays;

%% Perform Motor Function
tic %tic/toc will be used as it will provide the quickest response possible from the system

while toc=0)); %want the non-zero minimum (so we move foward in the matrix)
%cont. otherwise the minimum would always be the first index
if isempty(minCheck) == true % failsafe since sometimes a very small neg is formed instead of a 0 term for the final index
minCheck = max(check);
end

timeindex = find(check == minCheck); %finds time index that corrolates with the time closest to clock
move = motorpos(timeindex); % uses time index to find motor position needed at this time
movearray(moveindex) = move; % store motor position for comparison

%determine direction of motor movement from slope
if moveindex == 1
dir = 'forward';
elseif (movearray(moveindex)- movearray(moveindex-1)) 0
dir = 'forward';
end

% Here is where the actual motor functions will go that will turn the motor
% to the position 'move' that was calculated. In theory this position will
% produce the flow rate desired

%********************potential code:
% a.stepperStep(1,dir,'double',move); %not sure whether to use double or
% single

moveindex = moveindex + 1;
end

%plot motor movement for comparison to inhalation profile
figure()
plot(movetime,movearray)
title('Motor Position vs. Time')
xlabel('Time (s)')
ylabel('Motor Position (relative)')

The only remaining work to do with this code is to connect it to the Arduino and motor and include a proper conversion factor for flow rate to motor position (this can be done using a flow meter) – hopefully the conversion is relatively linear. I will probably have to make adjustments to the speed and possibly the stepper movement type – I will need to look more into the motor for this.

The images below show the input function of flow rate (L/s) vs time(s) in relation to the outputted motor position vs running time (s) (the current conversion factor is 1 to make for easy comparison). The distance between steps is likely to change due to the hardware limitations of the motor and the extra processing time required.
FlowRatevsTime

MotorPositionvsTime

The most important thing to see in this code is the section denoted by (%%) – Import Inhalation Profile via Excel Spreadsheet. The following code shows the method by which data is imported from an excel spreadsheet. This will allow us to contain all of the inhalation profiles in a single excel spreadsheet (with the time and flow rate separated on separate sheets). A legend (as see at the beginning of the code) can be provided to make it easier to switch between profiles. This should be the only portion (once the code is fully functional/calibrated) that should be changed for each test.

Next Steps:

Firstly, I will need to connect the arduino and motor to the program (or a separate program to just test motor functionality) and confirm that I can achieve movement given time data.
Secondly, I will need to gather data using a flow meter to get flow rate vs. motor position and find the proper conversion to implement in the program.

I may be able to get the first part done by the end of the (for sure done by next Monday) – I have the GRE this Friday afternoon, so I will be very busy until then with last minute studying.

If any clarification on the code is needed, ask me and I will add additional comments accordingly.
Note: The code contains several fail-safes due to problems that occurred/may occur with negative/zeros. I believe I have addressed all concerns, but there may be more that will arise as testing proceeds.

I made some very basic code today for a sigmoidal function that utilizes the write to text function that is in Matlab.


clc
clear all
close all
x=0:1:10;
a = 1; % sign determines R or L open
c = 5; % determines center
y=100./(1 + exp(-a.*(x-c)));
plot(x,y)
title('Air Speed vs. Time')
ylabel('Air Speed')
derivative = diff(y);
speed = zeros(size(x));

save Speed.txt - ascii y
save time.txt - ascii x

Sigfunc

The results of the text file are as follows (the info in quotations is a direct copy and paste of the text file)
x

-3 7 2
0 -4 10
2 1 11
-5 4 8

y

8 -2 4 7 -1
7 12 -3 6 6
0 -10 -2 3 9

If I can figure out a way to read from a text file, to the arduino, we should have a roundabout way of inputting mathematical data to the arduino. Then we can tweak the code to fit what we need, that should not pose that much of a problem.

Update

I have been gone from lab for a while due to summer school, but have recently been back, thinking about how to get data from sigmodial waves in MATLAB/Octave to the arduino.
It appears as if my last post never made it, I suppose my phone glitched out when posting, so I will summarize. The last time I was in lab I was able to create a basic sigmoidal function for the motor on the Arduino.

void Sigmoidal(){
stepper.move(-pos);
while(1){
if(stepper.distanceToGo() == 0){
delay(50);
stepper.move(-pos);
break;
}
stepper.setSpeed(1000);
stepper.runSpeedToPosition();
}
stepper.move(-pos*2);
while(1){
if(stepper.distanceToGo() == 0){
delay(50);
stepper.move(-pos*2);
break;
}
stepper.setSpeed(5000);
stepper.runSpeedToPosition();
}
stepper.move(-pos);
while(1){
if(stepper.distanceToGo() == 0){
delay(50);
stepper.move(-pos);
break;
}
stepper.setSpeed(1000);
stepper.runSpeedToPosition();
}

stepper.move(pos*4);
while(1){
if(stepper.distanceToGo() == 0){
delay(50);
stepper.move(pos*4);
break;
}
stepper.setSpeed(10000);
stepper.runSpeedToPosition();
}
}

I was also able to create a basic sigmoidal function graph in MATLAB. I used the derivative of the function to give a graph of air speed vs. time. I was unsure of how to relay this information to the arduino, but yesterday I discovered that you can save MATLAB output as a txt file, and from this we should be able to read the data to the arduino. ( I assume octave file outputs will save to TXT as well) I found a tutorial online on reading data from a txt file to the arduino (http://arduinobasics.blogspot.com/2012/05/reading-from-text-file-and-sending-to.html) and will experiment with this the next time I am in lab.

Things are Working! 6/28/13

I was able to get the tube to hold a vacuum with very little leakage. There isn’t enough leakage to cause any trouble anyways. Also I was able to mess around with the motor and code that Gio set up and get that working as well. I changed up the code just a little bit so I had full control of the valve opening and closing. Basically I would press the button once to open the valve, and again to close it. The code is as follows


//declare constants for button
const int buttonPin = 2; // the number of the pushbutton pin

int buttonState = 0; // variable for reading the pushbutton status
int alternate = 1;
void setup(){

pinMode(8, OUTPUT); //DIR
pinMode(9, OUTPUT); //STEP

// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}

void loop() {

buttonState = digitalRead(buttonPin);

int count = 200;
int a = 0;

if (buttonState == HIGH && alternate == 1) {

digitalWrite(8, HIGH); //clockwise (open valve)

//open acceleration
for(a = count; a >= 50; a-=2){

for(int b = 0; b < 200; b++){

digitalWrite(9, HIGH);
delayMicroseconds(a);
digitalWrite(9, LOW);
delayMicroseconds(a);
}

}
alternate = 2;
}

// Waiting for second button press
buttonState = digitalRead(buttonPin);
for(int b = 0; b<1;){
if (buttonState == LOW){
delay(100);
buttonState = digitalRead(buttonPin);
}
if (buttonState == HIGH){
delay(100);
b = 1;
}
}
buttonState = digitalRead(buttonPin);

if (buttonState == HIGH && alternate == 2) {
digitalWrite(8, LOW); //counterclockwise (close valve)

//close deceleration
for(a = 50; a <= count; a+=2){

for(int b = 0; b < 200; b++){

digitalWrite(9, HIGH);
delayMicroseconds(a);
digitalWrite(9, LOW);
delayMicroseconds(a);
}
}
alternate = 1;
}
delay(300);
}

It is almost exactly the same as Gio’s accelerate code, I just made the closing of the valve a separate loop, and added a waiting loop that would wait for a second pressing of the button. The only variable of note that is added is alternate. This variable is 1 when the valve is closed and needs to be opened, and 2 when the valve has been opened and needs to be closed. I don’t know if this is something that would work for our purposes, but we now have it if we do need it.

I am also in the process of downloading “Processing 2” to the lab computer. I do not think I can get anything major done with it today but I will start looking into it.

An idea

I have found out that it is not a good idea to connect metal to pre the way we have been doing. This is because the diameter of the metal fitting increases as we tighten it, and that can cause the hole threaded into the Pvc to crack. When connecting Pvc to metal you want the Pvc threads on the outside since it is the weaker of the two. I took a trip to lowest and found something that may solve our problem. Since we can connect Pvc to Pvc just fine. We can use a Pvc nipple with threads on the outside on both ends as shown below.

image

image

It will not fit perfectly into the metal, however parafilm should help make a seal, once connected to the metal it should remain that way as the threads may become damaged if removes and replaced. This would then be inserted into the Pvc plug, hopefully not causing it to crack since we are using a weaker material that can take some of the load off the plug.

— excuse typos as this is typed from my phone

informational site about connecting pvc to metal http://www.irrigationtutorials.com/faq/connections.htm

6/14/13

I met with Andy and Sarah today in lab.
I have attempted to fix the leak in the pipe plug ( as I just learned they are called) by applying epoxy where it was cracking. However, there is still a chance of there being a recurrance of the same crack, or another one. Because of this I have looked up some pipe fittings, and have found two, one pvc and one metal, that may fit our current set up. The first one, metal pipe plug, is metal and should withstand the force of attaching fittings,if we are able to create threads in it. The second one,PVC pipe plug, is a different type of pvc plug, this one does not have the extruding square peice which has cracked on one of our current plugs, I am thinking that the size of this peice and the seams that it has may create a weak point, but I am not sure. These are the only two options I could find, I am sure there are more, I will update if I have any ideas.

Also, Andy decided that we needed a designated computer for this project, so me and him found two non working desktops, and I took the power source and hard-drive out of one and put it into the other, and connected it up to a screen and such, and we now have a working desktop which I will be installing the arduino software on so it can be used for coding.

–UPDATE–

I was able to install the Arduino software and connect the arduino to it, I uploaded a blank code to the arduino to make sure that it was connected and I received no error messages, so it appears to be in working order.