-
Notifications
You must be signed in to change notification settings - Fork 3
/
processing_program.pde
292 lines (248 loc) · 14.4 KB
/
processing_program.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/* Copyright 2014 Gokulakrishna KS <[email protected]>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* EXPERIMENTAL STRESS ANALYSIS
This program was developed for an academic project for Experimental stress analysis using Strain gauges, Arduino Uno and with Data logging. Please refer to the arduino_program in the same repository on how the Arduino program works.
The program "handshakes" with the Arduino this way. Arduino sends A continously until it gets a response from this program. When Arduino gets a response from this program, Arduino sends over data in this format: vref<comma>gaugeoutput1<comma>gaugeoutput2<comma>gaugeoutput3<carriagereturn> and Processing reads it into a string until the carriage return ("\n"). Then it splits the string at comma ',' and stores individual values in float array for further computations. Once the scientific computations are complete, the program writes the results to a timestamped log file in comma separated value format .csv file.
Terminology used in this program:
1) First letter of variable name is in lowercase, second word in variable name has first letter capitalised. Underscore symbol and numbers in identifier is avoided in the entire program.
2) It is known that an array's first element is element[0], but for better readability, In an array, 1st item of consideration is stored in 2nd element of arrays which is element[1].
Therefore strain[1] means first strain, not the second. strain[0] is set to have 0 and is ignored in calculations.
Data log filename : "Log dd\mm\yyyy : hh:00 - (hh+1):00.csv" in the same directory of Processing.
Example : "Log 14\03\2014 : 16:00 - 17.00.csv".
The file has individual rows timestamped at the first entry. The first row of the file has column headings.
If filename doesn't exist, file is created. Else, it is opened and appended. Since Processing has no "true" append mode for files, it has to be opened, written and closed every iteration. This data .csv log file can then be opened in a program like Live-graph (www.live-graph.org) for plotting real time dynamic graph between various variables from data file, or it can be opened in Scientific computational softwares or Spreadsheet applications in Office suites like LibreOffice Calc or Gnumeric for post-processing.
The circuit diagram and also the documentation on engineering topics and explanation on selection of formulae and expressions will be added to the repository at a later date.
If you are new to Processing IDE, setup() executes once, draw() executes itself continuously until the stop button is pressedm SerialEvent() executes when some data is available at the serial port.
*/
import processing.serial.*;
import java.io.BufferedWriter;
import java.io.FileWriter;
Serial myPort;
boolean firstContact = false;
int count=1;
int milliTimer=0;
float secondsTimer=0;
void setup() {
myPort = new Serial(this, Serial.list()[0], 115200);
myPort.bufferUntil('\n'); // List all serial ports by println(Serial.list()) if port is not detected.
// println(Serial.list());// delay(1000); //to make timer in seconds start from 1. That is, millis()/1000 is to be more than 1, So deliberate delay can be been added.
}
void draw() {
milliTimer=millis();
secondsTimer=milliTimer/1000.00; //Program timer to be used in timestamps for data entry in logs.
}
void serialEvent(Serial myPort) {
int inByte=myPort.read();
if(firstContact ==false) //Initialize first contact with Arduino
{
if (inByte == 'A')
{
myPort.clear();
firstContact=true;
myPort.write('A'); //Ask Arduino for data
}
}
else
{
// read the serial buffer:
String myString = myPort.readStringUntil('\n');
myString = trim(myString);
// split the string at the commas
// and convert the sections into integers:
//First value sent in is Vref for any future use with it.
float sensors[] = float(split(myString, ',')); //Split string at comma and save to float array
float[] threeStrain={0,0,0,0,0}; //extra space for any future use, three strain means strain as measured in 3 directions by each of the Strain gauge in 0,60,120 configuration
double[] twoStrain={0,0,0,0,0}; //two strain means reduced strain values in 2 Principal axes
float offset=0; //Change during experiment
print( "\t" + " Next iteration " + "\n");
for (int sensorNum = 1; sensorNum < sensors.length; sensorNum++) {
print("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t"); //for debugging purpose.
} println();
float[] vRatio={0,0,0,0,0}; //Voltage ratio of (Voltage strained - Voltage unstrained) divided by bridge excitation voltage.
double[] stress={0,0,0,0,0}; //2 Principal stresses, plus extra space for future use, double for higher precision
double vonMisesStress;
float n,d; // n - numerator, d - denominator : For readability of formula.
float leadResistance=1; //change during operation by measurement, in ohms
float gageResistance=120; //Strain gauge resistance in ohms
float gageFactor=2; //For strain gauge, from manufacturer's datasheet - 2 with less than 1% variation.
//CALCULATE THREE PRINCIPAL STRAINS
for(int y=1;y<sensors.length;y++)
{
vRatio[y]=(sensors[y] - offset)/10000; //Output minus offset whole divided by supply, bridge excitation voltage is 10V or 10000 mV.
n=4*vRatio[y]*(1+leadResistance/gageResistance);
d=(gageFactor*(1+2*vRatio[y]));
threeStrain[y]=n/d;
print("Directional Strain " + y +" = " + threeStrain[y] + "\t");
}
println();
//CALCULATE STRAIN IN TWO PRINCIPAL AXES
for(int z=1;z<3;z++)
{
twoStrain[z]= (threeStrain[1]+threeStrain[2]+threeStrain[3])/3;
double constantTerm=2.0/3.0;
double sqRoot=java.lang.Math.sqrt(constantTerm);
double a=threeStrain[1]-threeStrain[2];
a=a*a;
double b=threeStrain[2]-threeStrain[3];
b=b*b;
double c=threeStrain[3]-threeStrain[1];
c=c*c;
double total=a+b+c;
//If else - is used here because sqrt() function can't take a negative number as an argument.
if(total<0)
{total=java.lang.Math.sqrt(-total);}
else
{ total=java.lang.Math.sqrt(total);}
sqRoot=sqRoot*total;
if(z==1)
{
twoStrain[z]=twoStrain[z]+sqRoot; //Add to get Principal strain in P direction
}
else
{
twoStrain[z]=twoStrain[z]-sqRoot; //Subtract to get Principal strain in Q direction
}
print("Principal Strain " + z + " = " + twoStrain[z] + "\t");
println();
}
//CALCULATE STRESS IN TWO PRINCIPAL AXES
double youngsModulus;
youngsModulus=java.lang.Math.pow(10.0,9.0);
youngsModulus=70.00*youngsModulus; // Young's modulus of Aluminium = 70 * 10^9 Pascals
double term1; //First term of the product in equation
float poissonRatio=0.33; //Poisson ratio of Aluminium = 0.33
double muSquared=poissonRatio*poissonRatio; //Poisson ratio is called mu, so - muSquared
term1=youngsModulus/(1-muSquared);
stress[1]=term1*(twoStrain[1]+(poissonRatio*twoStrain[2]));
stress[2]=term1*(twoStrain[2]+(poissonRatio*twoStrain[1]));
print("Principal Stress 1 =" + stress[1] + "\n");
print("Principal Stress 2 =" + stress[2] + "\n");
vonMisesStress=(stress[1]*stress[1])-(stress[1]*stress[2])+(stress[2]*stress[2]);
if(vonMisesStress<1)
{
vonMisesStress=vonMisesStress*(-1);
}
vonMisesStress=java.lang.Math.sqrt(vonMisesStress); // square root of (double vonMisesStress);
print("vonMises Stress = " + vonMisesStress + "\t");
println();
//TO MEASURE ANGLES (how much straingauge grid 1 (strain gauge at 0 degrees)is away from one Principal axis, in degrees)
float strainSum;
strainSum=threeStrain[2]+threeStrain[3];
strainSum=strainSum/2;
String angle=" ";
int check=1; //To know if first two if blocks are executed or not.
String direction; //Save Clockwise or anticlockwise. clockwise if (negative result) and anticlockwise if (positive result)
if((threeStrain[1]==strainSum) && (threeStrain[2]<threeStrain[1]))
{
//println("Above value is theta P in MINUS forty five degrees i.e in clockwise direction");
angle="Principal axis P is 45 degrees clockwise from grid 1; Principal axis Q is 90 degrees from axis P";
println(angle);
check=check-1;
}
else if((threeStrain[1]==strainSum) && (threeStrain[2]>threeStrain[1]))
{
// println("Above value is theta P with PLUS forty five degrees, i.e in anticlockwise direction");
angle="Principal axis P is 45 degrees anticlockwise from grid 1; Principal axis Q is 90 degrees from axis P ";
check=check-1;
// println(angle);
}
float angleFromGrid1=0;
if(check>0)
{
n=(sqrt(3.0)) * (threeStrain[2] - threeStrain[3]);
d=(2.0*threeStrain[1]) - threeStrain[2] - threeStrain[3];
n=atan(n/d); //Output is in radions... and reusing same float n
n=degrees(n); //in degress.
angleFromGrid1=0.5*n;
//print("Angle of a Principal axis from Grid 1 = " + angleFromGrid1 + "Refer output log file for further info" + "\n");
if(angleFromGrid1>0)
{
direction=" Anti-Clockwise";
}
else
{
direction=" Clockwise";
angleFromGrid1=angleFromGrid1*(-1); //to remove negative sign, since "Clockwise" implies negative.
}
if(threeStrain[1]>strainSum)
{ //"anglefromgrid1 is theta P");
angle="Principal P is " + angleFromGrid1 + " degrees" + direction + " from grid 1 ; Principal Axis Q is 90 degrees from Axis P";
// println(angle);
}
else if(threeStrain[1]<strainSum)
{
//"anglefromgrid1 is theta Q");
angle="Principal axis Q is " + angleFromGrid1 + " degres" + direction +" from grid 1; Principal Axis P is 90 degrees from Axis Q ";
//println(angle);
}
else
{
if(((sensors[1]==0) && (sensors[2]==0)) && (sensors[3]==0))
{
angle="System under no load. No input from Strain gauges";
}
else
{
// println("all three strains are same : indeterminate equal biaxial strains");
angle="Indeterminate angle because individual 3 direction strains are same : i.e Equal biaxial strain ";
//println(angle);
}
}
}
print("More info on the angle above : "+ angle + "\t");
println();
//CALCULATE SHEAR STRAIN AND SHEAR STRESS
double shearStrain=0;
double shearStress=0;
shearStrain=twoStrain[1]-twoStrain[2];
shearStress=(youngsModulus*shearStrain)/(2*(1+poissonRatio));
print("Shear Strain = " + shearStrain + " Shear stress = "+ shearStress + "\n");
double yieldStrength;
yieldStrength=241*pow(10,6); //in Pascals, for Aluminium 6061 T6 alloy.
String vonMisesCriterion=" ";
if (vonMisesStress<yieldStrength)
{ vonMisesCriterion=" Safe"; }
else //Will not happen in actual experimental stress analysis with safeloads, unless you do destructive testing to find when material yields
{ vonMisesCriterion="Failure";}
print("vonMises Criterion check : " + vonMisesCriterion + "\n");
//WRITE TO FILE
// For filename with format : day\month\year:hour (in 24 hour format) , nf function returns a number in string format.
String timestamp = "Log : " + nf(day(),2) + "\\" + nf(month(),2) + "\\" + year() + " : " + nf(hour(),2) + ":00"+ " - "+nf(hour()+1,2) + ":00 ";
// First column for datalog is to be system time at which the recording was made.
String timestamp2= nf(hour(),2)+" : "+ nf(minute(),2) + " : " + nf(second(),2);
double mpa=java.lang.Math.pow(10,6); //to get output in mega pascals.
try
{
FileWriter output = new FileWriter((timestamp + ".csv"),true); //Boolean true will append the new data, if file exists, else creates a new file and starts appending.
print("Writing to file..." + "\n");
if(count==1) //For first time alone - the table HEADER column
{
//Heading row
output.write("System Time" + "," + "Running time" + "," + "Gauge0 (mV)" + "," + "Gauge60 (mV)" + "," + "Gauge120 (mV)" + "," + "Strain in Principal axis P " +"," + "Strain in Principal axis Q" + "," + "Shear strain" + "," + " Stress in Principal Axis P (Pa) " + "," + " Stress in Principal Axis Q (Pa) " + "," + "Shear stress (Pa) " + "," + " Von mises stress (Pa) " + "," + "Principal Stress in Axis P (MPa) " + "," + "Principal Stress in Axis Q (MPa) " + "," +"Shear stress (MPa)" + "," + " Von Mises Stress (MPa) " + "," + " Angle of Strain gage grid 1 to Principal axes "+","+ "Von-Mises Criterion Failure mode (if VonMisesStress is less than Yield strength - Safe) " + "\n");
output.flush(); //Flush in
count=count+1; // update to ignore this block for consequent entries
}
//Write data starting from 2nd row (under heading row)
output.write(timestamp2 + "," + secondsTimer + "," + sensors[1]+"," + sensors[2]+ "," + sensors[3] + "," + twoStrain[1] + "," + twoStrain[2] + "," +shearStrain+ "," + stress[1] + "," + stress[2] + "," +shearStress + "," + vonMisesStress + "," + stress[1]/mpa + "," + stress[2]/mpa + "," + shearStress/mpa + ","+ vonMisesStress/mpa + ",");
output.write(angle + "," + vonMisesCriterion + "\n");
output.flush(); //Flush in
output.close(); //Close
delay(50); //to set number of entries per second in data log, imposing delay/ Setting 50ms delay restricts to 11 or 12 entries per second in data log.
myPort.write('A');
}
catch(IOException e)
{
println("Exception encountered. Perhaps file may not be exist or it's open but in read mode. Or I/O error. EXIT");
e.printStackTrace(); //StackTrace
}
}
}