I think it's because of this small error that the oscillations increase until both weights eventually fly off the top of the screen. I have simulated some "air resistance" to the velocities, which prevents this "runaway". With this friction, the system should gradually come to rest, but it appears that it will run forever. Possibly there's an error in the code that I have missed. Or maybe this is the best that can be done with this method. (I also wrote a program with only 1 spring using the same method, which seems to work perfectly.)
The time and distance units are arbitrary. Making the accelerations (a1 & a2) smaller simulates a shorter time period for variable t, which may increase the accuracy. The main variables can be adjusted near the top of the listing- weights (mass), spring constants, length of springs, etc
I have left in plenty of REM statements, which should help in following the logic. Delete any that you find too trivial.
Code: Select all
/*
Suggestion ON FORUM: motion of 2 springs piggy-backed.
I don't guarantee the accuracy of this program, although it gives a reaonable demonstation.
Because the actions of the upper & lower springs both depend on each other, it is almost impossible to calculate using this method without calculus. So there is always a small error. The weights m1 and m2 eventually fly off the top of the screen. to preent this I have added a small amount of "air resistance" to contol increasing velocities.
It also plots a graph of the movements while it is running. This can be REMed out if not wanted.
All the constants can be adjusted as desired, to see the effect.
It does not give any spectacular results, but settles down to a steady pattern.
Assumptions:
1. Length of springs is calulated to CENTRE of weights.
2. Springs are always within their range of elasticity.
NOTES:
1. The tensions in both springs are dependent on each other, which is almost impossible to program in small increments. You would get a circular calculation. Therefore this simulation is probably not too accurate, although I think the general idea is correct.
2. The time and distance units are arbitrary. Making the acceleration smaller would simulate a shorter time period for variable t, which should increase the accuracy. The main variables can be adjusted near the top of the listing.
3. I think it's because of this small error that the oscillations increase until both weights eventually fly off the top of the screen. I have simulated some "air resistance" to the velocities, which prevents this "runaway". With this friction, the system should gradually come to rest, but it appears that it will run forever. Or possibly there's an error in the code that I have missed. Or maybe this is the best that can be done with this method. [Programs "Spring-1- ONLY.sb" seems to work perfectly.
VARIABLES: naming system:
Upper spring & weight are #1, bottom are #2.
k is Hooke's Law constant: Force=k*change in length of a spring
all pxx are positions - only used for placing of Sprites, not in calculations
psr1 - relaxed posn of spring 1 (pixels from top of screen)
pb02 - initial hanging posn of ball 2
Lr1 - relaxed length of spring 1
L02 - initial sretched length of spring1 i.e. hanging stationary with weights (balls)
L1, L2 - current length of springs; only used to calc ps1 & 2 and pb1 & 2.
m1, m2 - mass (weight) of balls
ts1, ts2 - tension in springs; ALWAYS a +ve number; direction depends if it's pulling up or
' down on a ball. It must be added or subtracted accordingly. (UP is -ve, ie subtract).
f1, f2 - NET FORCE (sum of all forces) pulling on balls 1 & 2 (including weights); zero when stationary
'limit a1 & a2 to prevent runaway
fh - "human" force pulling on ball 1 to start it off.
*/
OPTION BASE 1
OPTION SPRITE POS CENTRAL
GRAPHICS ! GRAPHICS CLEAR 1,1,1
DRAW SIZE 2
DRAW COLOR 0,0,0
FILL COLOR 1,0,0
'g' =========== INITIAL SETTINGS, CONSTANTS =====================
'. ======== 1 IS TOP, 2 IS BOTTOM ===== '
'HOOKES LAW: F=K*∆D === bigger K is stronger spring ========
'relaxed posn's ie no tension in springs: psr1,2; f1, 2=0, ==================
m1=10 'mass (weight) of balls
m2=10
k1=0.1 'spring constant: tension/stretch (mass/pixels) (Hooke's law: F=k*∆L)
k2=0.1
Lr1=100
Lr2=100 'relaxed length, i.e. lying flat on a table, no forces in effect
fh=10 'human pull applied
speed=.01 'delay for control of display speed.
RANDOMIZE
fh=20 ' "human" pull applied to start it off.
r1=RND(.9)
fh=fh*r1+3 'Random variation in human starting pull. REM out if not wanted.
' dbp DEBUG PAUSE. See DEF at end of listing
'r'
SPRITE "s2" BEGIN 20, Lr2 ' Spring 2
FOR y=1 TO Lr2 STEP 10
DRAW LINE 1, y TO 20, y+5 ' down to right
DRAW LINE 1, y+10 TO 20, y+5 ' up to right.
NEXT y
SPRITE END
SPRITE "s2" AT 500, Lr1+Lr2/2 ! SPRITE "s2" SHOW
'-------------
SPRITE "s1" BEGIN 20, Lr1 ' Spring 1
FOR y=1 TO Lr1 STEP 10
DRAW LINE 1, y TO 20, y+5
DRAW LINE 1, y+10 TO 20, y+5
NEXT y
SPRITE END
SPRITE "s1" AT 500,Lr1/2 ! SPRITE "s1" SHOW
'-------------
SPRITE "m1" BEGIN 60,60 'Mass 1
FILL CIRCLE 30, 30 SIZE 30
SPRITE END
SPRITE "m1" AT 500, Lr1 ! SPRITE "m1" SHOW 'relaxed posn
'--------
SPRITE "m2" BEGIN 60,60 'Mass 2
FILL CIRCLE 30,30 SIZE 30
SPRITE END
SPRITE "m2" AT 500, Lr1+Lr2 ! SPRITE "m2" SHOW 'relaxed posn
201
'' ============== Inital Positions, Relaxed on table =========
' ========== As set above =======
DRAW TEXT "Relaxed " AT 200, Lr1+Lr2
PAUSE 2
202
'g' ======== start with INITAL STRETCH, stationary: L01, L02,ps01, pb01 etc ==========
' =======CALCULATE SPRING 2 FIRST because it affects Spring 1 ==========
ts2=m2 'tension/forces on springs, hanging stationary
f2=m2-ts2 'NET forces=0 on ball: UP = - and DOWN = + (because screen counts top down
'net force on ball=0; DOWN-UP; Tension is always a +ve number
strch2=m2/k2 'adds to Lr2
L02=Lr2+strch2 ' stretch; f= k8d,------- L=L+d ---------
' ======== NOW DO SPRING 1 & THEN PLACE SPRING 2 & m2 SUSPENDED FROM IT =====
102
'g'start with INITIAL STRETCH, stationary: L01, L02,ps01, pb01 etc ==============
ts1=m1+m2 'tension/forces on springs, hanging stationary
f1=m1+ts2-ts1 'net force=0 on ball: UP is - and DOWN is + (because screen counts top down
'net force on balls; =0 when stationary
strch1=(m1+m2)/k1 'stretch of spring; adds to current length
L01=Lr1+strch1 ' f=k*d, so L=L+d ---------
ps01=L01/2 'spring pos'n is CENTRE of spring
ps02=L01+L02/2
pb01=L01
pb02=L01+L02
SPRITE "s1" RESIZE 20, L01 'resize sprites to hanging (with weights), stationary size
‘ RESIZE is a permanent resizing. Don’t use in a loop
SPRITE "s1" AT 500, ps01
SPRITE "s2" RESIZE 20, L02. 'stretch spring to initial length
SPRITE "s2" AT 500, ps02
SPRITE "m1" AT 500, pb01
SPRITE "m2" AT 500, pb02
GRAPHICS CLEAR 1,1,1
DRAW TEXT "Hanging, stationary" AT 200,pb02 ‘ so you can see what’s happening
PAUSE 1 ‘ so you can read it
L1=L01 ! L2=L02 'as well as ts1, ts2 above: use in next section (both f1, f2=0)
203
'c'
' add (human) pull on bottom weight m2 =================
' initial human pull on ball added
' calc new t=1 posns etc from t=0 data
ts2=m2+fh
f2=m2+fh-ts2 ' now includes fh ' THESE ALL NEEDED IN NEXT SECTION
ts1=m1+ts2 ' (or ts1=m1+m2+fh since ts2=m2+fh)
f1=m1+m2+fh-ts1 '(or f1=m1+ts2-ts1)
L2=L02+fh/k2 'new L2, L1 both increased by fh/k. This follows Hookes Law f=k*d, d=f/k
L1=L01+fh/k1
ps1=L1/2 ! ps2=L1+L2/2. 'new positions
pb1=L1 ! pb2=L1+L2
SPRITE "s1" AT 500, ps1 SCALE L1/L01 ‘ scales on screen to current length
SPRITE "s2" AT 500, ps2 SCALE L2/L02 'new L2.
SPRITE "m2" AT 500, pb2
SPRITE "m1" AT 500, pb1
'dbp
GRAPHICS CLEAR 1,1,1
DRAW TEXT "Added pull" AT 200, L1+L2
PAUSE 1 'before starting main
'======================= NOW THE FUN PART - Make it all move ==================
204
'b' now REMOVE human pull fh; calculate a, d, new ts === MAIN PART OF PROGRAM ===
GRAPHICS CLEAR 1,1,1
DRAW TEXT "Pull released; now running" AT 150, L1+L2
PAUSE 1
'start with current values at t=0
' calculate new values at t=1
' fh=0 Just a reminder
f2=m2-ts2 ' ts2 (from above) includes fh, so f2 now does as well.
'These 3 equations are used: (1)a=f/m (2)d=(a*t^2)/2 where initial t=1. (3) v=a*t
'Also Hookes Law f=k*d, [ d=f/k ]
'All positions AND TENSIONS are still unchanged UNTIL m1 STARTS TO MOVE! ' f2 from previous
'NET FORCE on m2 will be UP (-ve) at start (t=0), so it will accelerate up
'Tensions are POSITIVE #s. Direction depends what it's pulling on.
'dbp
FOR t=1 TO 30000 '=================== MAIN LOOP =================
' f2 now begins to accelerate m2 upwards.
a2=f2/m2 ' since ∆t=1 for t=1, eqn (1) above, will be NEG UP
v2=v2+a2 ' since ∆t=1; v2+(eqn 3)
v2=v2*(1-.0001*v2^2) 'a small amount of "air friction" to prevent runaway.
d2=a2/2 ' distance moved d=v*t; time interval ∆t=1. eqn (2)
ts2=ts2+k2*d2
IF ts1<0 THEN ts1=0
L2=L2+d2 ' d2 will be -ve (UP) AT t=1
' ----------------- now d1 ----
f2=m2-ts2 ' new net f2 - reduced by ∆L2. F=K*D; d2 is -ve i,e. UP
f2=f2+k*d2
' ======= NOW DO m1,L1 etc, including effect of m1 ========
f1=m1+ts2-ts1 ' still using old ts2
a1=f1/(m1+ts2)
v1=(v1+a1)
v1=v1*(1-.00005*v1^2) 'a small amount of "air friction" to prevent runaway.
‘ d1=v1/2
d1=a1/2
ts1=ts1+k1*d1
IF ts1<0 THEN ts1=0 ' spring doesn't compress
L1=L1+d1 'at t=1, d1 is -ve
ps1=L1/2
ps2=L1+L2/2 'new curr posns.
pb1=L1
pb2=L1+L2
SPRITE "s1" AT 500, ps1 SCALE L1/L01 'scale sprite for display
SPRITE "s2" AT 500, ps2 SCALE L2/L02
SPRITE "m1" AT 500, pb1
SPRITE "m2" AT 500, pb2
GOSUB prgraph 'draws graph, REM out this line if you dont want it.
'dbp
'PAUSE 1
PAUSE speed 'display speed - set at top of listing.
NEXT t '============ END OF MAIN LOOP ==================
DRAW TEXT "========= DONE =========" AT 100,550
END
'y'===================================================
DEF dbp ! DEBUG PAUSE ! ENDDEF 'very handy for debugging
'-------------------------------------------------
prgraph: 'optional subroutine - for printing graph of motion
'DRAW SIZE 1
IF t/100=INTEG(t/100) THEN DRAW LINE t, 150 TO t, 600
FILL COLOR 0,0,0
FILL CIRCLE t/2,pb1 SIZE 2 'plot graph points
FILL CIRCLE t/2,pb2 SIZE 2
RETURN

