Many Springs

First pick a number of moving masses:

num = 7

Next decide to use fixed or periodic boundary conditions, i.e. whether masses 1 and N are attached to fixed walls, or to each other.
Evaluate one of the following two lines:

(*fixed wall*)
 m[i_,j_] = If[i==j,2.0,If[(i==j+1)||(i==j-1),-1.0,0]];
Do[(ϕ[j,0,t_] := 0; ϕ[j,num+1,t_]:=0;),{j,num}];
(mm = Table[ m[i,j],{i,1,num},{j,1,num}])//MatrixForm

(* periodic *)
m[i_,j_] = If[i==j,2.0,If[(i==j+1)||(i==j-1)||(i==num&&j==1)||(i==1&&j==num),-1.0,0]];
Do[(ϕ[j,0,t_] :=Evaluate[ ϕ[j,num,t]]; ϕ[j,num+1,t_]:=Evaluate[ϕ[j,1,t]];),{j,num}];
(mm = Table[ m[i,j],{i,1,num},{j,1,num}])//MatrixForm

For full generality, we leave a hook where we can put in damping if we want it.
Then define lists of variables and the equations they obey.

γ= 0.0;
vars = Table[x[i,t],{i,1,num}];
(eq =Table[D[x[i,t],{t,2}]== -Sum[m[i,j] x[j,t],{j,1,num}]-γ D[x[i,t],t],{i,1,num}])//MatrixForm

A list of boundary conditions saying that everyone starts at rest:

bcRest=Table[((D[x[i,t],{t,1}])/.t->0)== 0,{i,num}]

For starting shapes, we’ll pick eigenvectors

(eig=Eigenvectors[mm])//Transpose//MatrixForm

Here is the first pass a drawing function, with straight line springs

state3Dpassone[t_] := Graphics3D[{
{Red,Dashing[{.005,.003}],Line[Table[{j,0,xx[j,t]},{j,0,num+1}]]},
{Green,Thick,Table[Line[{{i,0,-1},{i,0,1}}],{i,num}]},
{GrayLevel[.25],Specularity[LightBlue,10],Table[Sphere[{i,0,xx[i,t]},0.2],{i,num}]}
},
Boxed->False,PlotRange->{{0,num+1},{-1,1},{-1,1}},ViewPoint->{0,2,1},ImageSize->800]

And here is pass two, with curly springs drawn as a parametric plot, expressed in terms of three perpendicular basis vectors {e1,e2,e3}.

spring[v1_,v2_]:=Module[{q,e1,e2,e3,n=10,z={0,0,1}},(q=v2-v1;e1=q/Norm[q];q=z-(e1.z)e1;e2 = q/Norm[q];e3=Cross[e1,e2];{ParametricPlot3D[v1+s(v2-v1)+.1Tanh[s(s-1)2 π n]*( Cos[2π n s]e2+Sin[2π n s]e3),{s,0,1},PlotStyle->{Red,Thick}][[1]]})]

state3D[t_] := Graphics3D[{
{Green,Thick,Table[Line[{{i,0,-1},{i,0,1}}],{i,num}]},
{GrayLevel[.25],Specularity[LightBlue,10],Table[Sphere[pt[i,t],0.2],{i,num}]},
Table[spring[pt[i,t],pt[i+1,t]],{i,0,num}]
},
Boxed->False,PlotRange->{{0,num+1},{-1,1},{-1,1}},ViewPoint->{0,2,1},ImageSize->800]

For each mode, find the period and the numerical solution, choosing to run for some multiple (say 3) of the longest period.

periodT = (2π/Sqrt[Abs[#]]& /@ Eigenvalues[mm]);
q=Sort[periodT];
maxT = q[[num]];
maxT = If[maxT<100,maxT,q[[num-1]]];
Do[(bceig = Table[ x[i,0]== 1.5eig[[mode,i]],{i,1,num}];
solneig=NDSolve[Join[eq,bcRest,bceig],vars,{t,0,3 maxT}][[1]];
Do[ϕ[mode,i,t_]= Re[x[i,t]/.solneig],{i,num}];),{mode,num}];

Choose a mode to animate

mode=3;
Do[pt[i,t_]={i,0,ϕ[mode,i,t]},{i,0,num+1}];
Animate[state3D[t],{t,0,maxT}]

And here we create a list of 30 frames and dump them out as an animated GIF.

T=periodT[[mode]];
frames=Table[state3D[t],{t,0,T,T/29.999}];
Export["springs7pbc.gif",frames]