The goal of the project is interesting for me also because I have a FB page/group dedicated to science, so I have only a few things that I would like to add to what has already been written.
The first one is "geometric".
Your text says that the diameter of the tube "should be two to three times larger than the diameter of the lead ball": even if in the "Challenges" section you pointed that out, I would rule out that a tube 3 times larger would work. Even a tube 2 times larger than the ball would not guarantee a trajectory sufficient to let the sensors detect the passage, so I would opt for a smaller diameter, I would say 1.5 not much more.
The other consideration concerns the "drag".
I know you said the tube should be quite larger than the ball, but the air displaced by the ball as it falls could negatively affect the measurements, so if you wanted to shorten the diameter to get around the "geometric" problem, to reduce this "drag" effect it would be appropriate to add a series of small holes on the side of the tube to allow the air to pass through and thus try to balance the pressure above and below the ball and that will reduce the drag.
I suggest you to add this to the experiment description.
The third is just a confirmation request, since it was not specified in the text: the tube must be plastic, to avoid any current induction, which results in the ball slowing down.
Finally, the code.
I would just like to give you some ideas on how to improve the code and make it "closer" to what a student might want to get from an experiment.
Your loop code is the following;
void loop()
{
while (timeA == 0 && timeB == 0 && timeC == 0);
delay(800);
Serial.println(timeA);
Serial.println(timeB);
Serial.println(timeC);
timeA = 0;
timeB = 0;
timeC = 0;
}
I'm not sure that it is right, or, at least, I don't know what is the goal (e.g. the output).
That code means the while() statement exists on any of the variables to be non-zero, but this happens after the ball crosses the first sensor, resulting in an output with just one value, and so on for the second and third sensor (with timings relative to the previous sensor instead of the first one, which is instead the one used for the calculations).
For the experiment purpose, I think it'd be better to wait for the three values to be filled up, then the code could make all the required calculations, and then report the data and results: the t1 and t2 timings and the configuration values d1 and d2 while debugging, and the wanted result, "g". After debugging, the only output could be the "g", so if the code automatically resets to let it be ready for another run, one could collect a dozen of tests, and see if and how the "g" value changes (the code could even collect all the values and show the average!).