Modeling of a shock absorber

From Department of Theoretical and Applied Mechanics
Jump to: navigation, search
Virtual laboratory > Modeling of shock absorber

This demonstration stand shows the work of a shock absorber

A shock absorber (in reality, a shock "damper") is a mechanical or hydraulic device designed to absorb and damp shock impulses. It does this by converting the kinetic energy of the shock into another form of energy (typically heat) which is then dissipated.

Automobile shock absorber

The equations of motion have the form (the velocity vector is directed upwards):

[math] m \ddot{y} = -mg - c \Delta y - F_{com}^{ten} \dot{y}, \\ F_{com} = \frac{\pi^{2} * E *\pi * d_{rod}^{4}}{64 * L^{2}},\\ F_{ten} = \frac{d_{pist}^{2} * \pi * p} {4},\\ [/math]

where [math]E[/math] is the modulus of elasticity (Young's modulus) [math]E= 2.05 \cdot 10^{11}[/math] Pa;

[math]F_{com}[/math] is the force directed opposite to the velocity vector (acts during the compression of a piston);

[math]F_{ten}[/math] is the force directed along the velocity vector (acts on the piston during the tension).

You can drag and drop the yellow square to load the damper.

The time dependence of 'y' coordinate is plotted below:

Download Shock_absorbers.zip.

The program text on JavaScript (developer Bogdanov Dmitriy, the code based on the program byTsvetkov Denis):

File "Spring.js"

  1 window.addEventListener("load", Main_Spring, true);
  2 function Main_Spring() {
  3 
  4     var canvas = spring_canvas;
  5     canvas.onselectstart = function () {return false;};     // disabling canvas selection
  6     var ctx = canvas.getContext("2d");                      // ctx drawing 
  7     var w = canvas.width;                                   // the width of the window in the actual coordinates
  8     var h = canvas.height;                                  // the height of the window in the actual coordinates
  9 
 10     var Pi = Math.PI;    	      	    // the 'Pi' number
 11 	var g = 9.81;
 12     var m0 = 1;    		      	        // the scale of weight
 13     var T0 = 1;    		      	        // the scale of time (period of oscillation the initial system)
 14 
 15     var k0 = 2 * Pi / T0;           	// the scale of frequency
 16     var C0 = 1;          	// the scale of stiffness
 17     var D0 = 0.001;  	      	    // the diameter
 18 	var p0 = 1;					// the pressure
 19 	var E0 = 1e-6;
 20 	var L = 300;
 21     // *** Setting the physical parameters ***
 22 	var E = 2.05e11 * E0;				// the elastic modulus
 23     var m = 3 * m0;                 	// the mass
 24     var C = 15 * C0;                 	// the stiffness
 25     var Dp = 43.1 * D0;                 	// the piston diameter
 26 	var Dsh = 17.3 * D0;					// the rod diameter
 27 	var p = 4 * p0;						// the pressure
 28     slider_m.value = (m / m0).toFixed(1); number_m.value = (m / m0).toFixed(1);
 29     slider_C.value = (C / C0).toFixed(1); number_C.value = (C / C0).toFixed(1);
 30     slider_Dp.value = (Dp / D0).toFixed(1); number_Dp.value = (Dp / D0).toFixed(1);
 31 	slider_Dsh.value = (Dsh / D0).toFixed(1); number_Dsh.value = (Dsh / D0).toFixed(1);
 32     slider_p.value = (p / p0).toFixed(1); number_p.value = (p / p0).toFixed(1);
 33     slider_L.value = (L).toFixed(1); number_L.value = (L).toFixed(1);
 34 
 35     // *** Setting the computing parameters***
 36 
 37     var fps = 100;		      	        // frames per second
 38     var spf = 50;		      	        // steps per frame - the number of integration steps between frames (increases the calculation speed)
 39     var dt  = 0.05 * T0 / fps;    	    // the integration step (the quality of calculation)
 40     var steps = 0;                      // the number of integration steps
 41 
 42     function setM(new_m) {m = new_m * m0;}
 43     function setC(new_C) {C = new_C * C0;}
 44     function setDp(new_Dp) {Dp = new_Dp * D0;}
 45 	function setP(new_p) {p = new_p * p0;}
 46     function setDsh(new_Dsh) {Dsh = new_Dsh * D0;}
 47 	function setL(new_L) {L = new_L;}
 48 
 49     slider_m.oninput = function() {number_m.value = slider_m.value;       setM(slider_m.value);};
 50     number_m.oninput = function() {slider_m.value = number_m.value;       setM(number_m.value);};
 51     slider_C.oninput = function() {number_C.value = slider_C.value;       setC(slider_C.value);};
 52     number_C.oninput = function() {slider_C.value = number_C.value;       setC(number_C.value);};
 53     slider_p.oninput = function() {number_p.value = slider_p.value;       setP(slider_p.value);};
 54     number_p.oninput = function() {slider_p.value = number_p.value;       setP(number_p.value);};
 55 	slider_Dp.oninput = function() {number_Dp.value = slider_Dp.value;       setDp(slider_Dp.value);};
 56     number_Dp.oninput = function() {slider_Dp.value = number_Dp.value;       setDp(number_Dp.value);};
 57     slider_Dsh.oninput = function() {number_Dsh.value = slider_Dsh.value;       setDsh(slider_Dsh.value);};
 58     number_Dsh.oninput = function() {slider_Dsh.value = number_Dsh.value;       setDsh(number_Dsh.value);};
 59 	slider_L.oninput = function() {number_L.value = slider_L.value;       setL(slider_L.value);};
 60     number_L.oninput = function() {slider_L.value = number_L.value;       setL(number_L.value);};
 61 
 62     var count = true;       // calculate the system
 63     var v = 0;				// the body speed
 64 
 65     var rw = canvas.width / 10;    	var rh = canvas.height;
 66     var x0 = canvas.width / 2 - 25;     	var y0 = rh/2-25;
 67 
 68     // the spring settings
 69     var coil = 11;        // the number of coils
 70     var startY = h;       // the spring fixation
 71 
 72     // a fancy yellow square
 73     var rect = {
 74         x: x0,  width: 50,
 75         y: y0,	height: 50,
 76         fill: "rgba(112, 155, 255, 1)"    	// yellow
 77     };
 78 
 79     //  mouse control
 80     var my_;                                    // mouse position buffer (to calculate the initial speed of the ball)
 81     document.onmousedown = function(e) {        // mouse click function 
 82         if (Dp <= Dsh)
 83 		{ 
 84 		alert("The diameter of the piston must be larger than the diameter of the rod");
 85 		slider_Dsh.value = (Dp / D0 - 1).toFixed(1); 
 86 		number_Dsh.value = (Dp / D0 - 1).toFixed(1);
 87 		setDsh(slider_Dsh.value);
 88 		setDsh(number_Dsh.value);
 89 		}
 90 			else {
 91 		var m = mouseCoords(e);                 // getting coordinates of the mouse cursor
 92         var x = rect.x;
 93         var xw = rect.x + rect.width;
 94         var y = rect.y;
 95         var yh = rect.y + rect.height;
 96         if (x <= m.x && xw >= m.x   && y <= m.y && yh >= m.y) {
 97             if (e.which == 1) {                         // left mouse button is pressed
 98                 rect.xPlus = rect.x - m.x;              // cursor displacement with respect to the mass on the X axis
 99                 rect.yPlus = rect.y - m.y;              // cursor displacement with respect to the mass on the Y axis
100                 my_ = m.y;
101                 count = false;
102                 document.onmousemove = mouseMove;       // while the mouse button is pressed the function works
103             }
104         }
105 			}
106     };
107 
108     document.onmouseup = function(e) {          // the working function when you release the mouse button
109         document.onmousemove = null;              // when the key is released displacement function does not work
110         count = true;
111     };
112 
113     function mouseMove(e) {                     // the function works only while holding LMB
114         var m = mouseCoords(e);                 // getting calculated coordinates of the mouse cursor
115         rect.y = m.y + rect.yPlus;
116 //        v = 6.0 * (m.x - mx_) / dt / fps;     // inertia conservation law
117         v = 0;
118         my_ = m.y;
119     }
120 
121     function mouseCoords(e) {                   // the function returns the calculated coordinates of the mouse cursor
122         var m = [];
123         var rect = canvas.getBoundingClientRect();
124         m.x = (e.clientX - rect.left);
125         m.y = (e.clientY - rect.top);
126         return m;
127     }
128 
129     // the graph
130     var vGraph = new New_graph(                  // initialisation of the graph
131         "#vGraph",                              // at html-page #vGraph
132         250,                                    // the number of steps by X axis
133         -1, 1, 0.2);                            // the minimum value of Y axis, the maximum value of Y axis, step along the Y axis
134 
135     function control() {
136         calculate();
137         draw();
138         requestAnimationFrame(control);
139     }
140     control();
141 //    setInterval(control, 1000 / fps);                       // starting system
142 	
143 	
144     function calculate() {
145         if (!count) return;
146         for (var s=1; s<=spf; s++) {
147 			var Fo = Math.pow(Dp/D0, 2) * Pi * p / 4;
148 			var Fs = Math.pow(Pi, 3) * E * Math.pow(Dsh/D0, 4) / (64 * L * L * 100); 
149 			document.getElementById('Fo').innerHTML = '<b>F отб. =</b>'+Fo.toFixed(2)+' H';
150             document.getElementById('Fs').innerHTML = '<b>F сж. =</b>'+Fs.toFixed(2)+' H';
151 			var f;
152 			if (v >= 0){
153 			f = -C * (rect.y - y0) - Fs * D0 * v;
154 			};
155 			if (v < 0){
156 			f = -C * (rect.y - y0) - Fo * D0 * v;	
157 			};
158             v += f / m * dt;
159             rect.y += v * dt;
160             steps++;
161             if (steps % 80 == 0) vGraph.graphIter(steps, -(rect.y-y0)/canvas.height*2);   // streaming the data on the graph
162         }
163 
164     }
165     function draw() {
166        ctx.clearRect(0, 0, w, h);
167 	   ctx.fillStyle = "#4B4747";
168 		ctx.fillRect(rect.x-22 , 480, 100, 20 );
169 		ctx.fillRect(rect.x + 18, rect.y + 40, 14, 900 )
170         ctx.strokeStyle = "#000";
171         ctx.beginPath();
172         for (var i = 0; i <= coil; i++ ) {
173             var x;
174             var y;
175             if (i != coil + 1) {
176                 y = startY + ((rect.y - startY))/coil*i;
177                 x = canvas.width/2 + ((i%2==0)?-1:1)*15 + (rect.x - x0)/coil*i;
178             } else {
179                 y = startY + ((rect.y - startY))/coil*(i+1);
180                 x = canvas.width/2 + ((i%2==0)?1:-1)*15 +  (rect.x - x0)/coil*(i+1);
181             }
182 			if (i==0) x = x0+25;
183             ctx.lineTo(x, y+5);
184         }
185         ctx.stroke();
186         ctx.fillStyle = "#FFFC06";
187         ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
188     }
189 }
190 function New_graph(htmlElement, yArrayLen, minY, maxY, stepY){
191     this.htmlElement = htmlElement;
192     this.yArrayLen = yArrayLen;
193     this.minY = minY;
194     this.maxY = maxY;
195     this.stepY = stepY;
196     this.vArray = [];
197 }
198 New_graph.prototype.graphIter = function(x, y){
199     this.vArray.push([x, y]);                    // adding a value to the end of the array
200     if (this.vArray.length > this.yArrayLen) this.vArray.shift(); // if the array has more 'yArrayLen' values, than remove the first one
201     var htmlElement1 = this.htmlElement;
202     var vArray1 = this.vArray;
203     var minY1 = this.minY;
204     var maxY1 = this.maxY;
205     var stepY1 = this.stepY;
206     $(function() {
207         var options = {
208             yaxis: {
209                 min: minY1,
210                 max: maxY1,
211                 tickSize: stepY1
212             }
213         };
214         $.plot(htmlElement1, [vArray1], options);  // drawing graph at the element "vGraph"
215     });
216 };
217 
218 New_graph.prototype.graph = function(data){
219     this.vArray = data;
220     var htmlElement1 = this.htmlElement;
221     var vArray1 = this.vArray;
222     var minY1 = this.minY;
223     var maxY1 = this.maxY;
224     var stepY1 = this.stepY;
225     $(function() {
226         var options = {
227             yaxis: {
228                 min: minY1,
229                 max: maxY1,
230                 tickSize: stepY1
231             }
232         };
233         $.plot(htmlElement1, [vArray1], options);  // drawing graph at the element "vGraph"
234     });
235 };
236 
237 
238 
239 function New(){}
240 New.prototype.addSlider = function(htmlSliderElement, htmlValueElement, minVal, maxVal, stepVal, startVal, setFunc){
241     $(function() {
242         $( htmlSliderElement ).slider({                               // element "slider_m"
243             value:startVal, min: minVal, max: maxVal, step: stepVal,
244             slide: function( event, ui ) {                      // it works during movement of the slider
245                 $( htmlValueElement ).text( ui.value.toFixed(2) );    // it assigns a value to the text field "value_m"
246                 setFunc(ui.value);
247             }
248         });
249     });
250 };
251 New.prototype.addInputSlider = function(htmlSliderElement, htmlValueElement, minVal, maxVal, stepVal, startVal, setFunc, pressFunc){
252     window[pressFunc] = function(event){
253         var regExpPattern = /[0-9]+[.]?[0-9]+/;
254         var inputVal = document.getElementById(htmlValueElement.substr(1)).value;
255         if (regExpPattern.test(inputVal.toString()) && inputVal != 0){setFunc(inputVal);}
256     };
257 
258     $(function() {
259         $( htmlSliderElement ).slider({
260             value:startVal, min: minVal, max: maxVal, step: stepVal,
261             slide: function( event, ui ) {
262                 $( htmlValueElement ).val( ui.value.toFixed(2) );
263                 setFunc(ui.value);
264             }
265         });
266         $( htmlValueElement ).val($( htmlSliderElement ).slider( "value" ).toFixed(2) );
267     });
268 };

File "index.html"

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <meta charset="UTF-8" />
 5     <title>Амортизатор</title>
 6     <script src="Spring.js"></script>
 7     <script src="jquery.min.js"></script>
 8     <script src="jquery.flot.js"></script>
 9 </head>
10 <body>
11 <table>
12 <tr>
13     <td><canvas id="spring_canvas" width="300" height="500" style="border:1px solid #000000;"></canvas></td>
14     <td><div id="vGraph" style="width:600px; height:300px; clear:both;"></div></td>	
15 </tr>
16 <tr>    
17 	<td><input type="range" id="slider_m" min="0.1" max="10" step=0.1 style="width: 120px;" />
18     M = <input type="number" id="number_m" min="0.1" max="10" step=0.1 style="width: 40px;" /> kg<br>
19     <input type="range" id="slider_C" min="0" max="50" step=0.1 style="width: 120px;" /> 
20     C = <input type="number" id="number_C" min="0" max="50" step=0.1 style="width: 40px;" /> *10^5 N/m<br>
21     <input type="range" id="slider_Dp" min="0" max="100" step=0.1 style="width: 120px;" />
22     dpist = <input type="number" id="number_Dp" min="0" max="100" step=0.1 style="width: 40px;" /> mm<br>
23 	<input type="range" id="slider_Dsh" min="0" max="100" step=0.1 style="width: 120px;" />
24     drod = <input type="number" id="number_Dsh" min="0" max="98" step=0.1 style="width: 40px;" /> mm<br>
25 	<input type="range" id="slider_L" min="50" max="500" step=1 style="width: 120px;" />
26     L = <input type="number" id="number_L" min="50" max="500" step=1 style="width: 40px;" /> mm<br>
27 	<input type="range" id="slider_p" min="0" max="10" step=0.1 style="width: 120px;" />
28     p = <input type="number" id="number_p" min="0" max="10" step=0.1 style="width: 40px;" /> MPa<br><br></td>
29 	<td>
30 	<div id = "Fo"> </div>
31 	<div id = "Fs"> </div>
32 	<div id = "info"> where: m is the mass, C is the coefficient of elasticity <br>dpist is the piston diameter, drod is the rod diameter<br>L is the rod length, p is the pressure in the shock absorber<br>Freb is the force of the tension stroke <br>Fcom is the force of the compression stroke 
33 	</td>
34 	</tr>
35 </body>
36 </html>