Make sensor adapt to new light but trigger larger differences

Sorry, complete programming beginner here.
I am controlling model train signals and I have put a light sensor as a detector to see if a train is there. What I want is that the detector detects a train, but not light changes like a cloud going in front of the window. So it has to adapt to the current light.

It should also trigger when a train passes in front.

Here is a pic how much the sensor changes when a train passes in front.

I have a quite good attempt at it with this:

void checkbaliseindicators() {
  if ((millis() - sig13baltimer) >= sig13baldeltatimer) {
    sig13baltimer = millis();
    sig13balval = analogRead(A0);
    if (sig13balval - sig13balpreval >= sig13balthreshold) {
      sig13baltri = 1;
    }
    else if (sig13balval - sig13balpreval <= sig13balthresholdnegative) {
      sig13baltri = 1;
    }
    else {
      sig13baltri = 0;
    }
    sig13balpreval = analogRead(A0);
  }
}

So it waits a time, checks the level and compares it to the previous level.
If the difference is high, it triggers, if low it sees it as the new value.

It still sometimes gives wrong triggers. Any tips on how to make it more average. Maybe some keywords that I can search?

Any pattern of visible light changes you write code for will be fooled easily. If not by clouds passing in front of the sun, then switching room lights on or off or something similar. There probably won't be anything unique enough about the train's shadow.

Don't use a simple visible light sensor to detect the train. Maybe use a modulated IR source and detector. This will not be fooled by any ambient light conditions. Or a magnet attached to the train and a reed switch.

Align a IR light barrier at an angle of 45° to the track and use digital inputs.

I would approach this differently:
I would count photosensor "high" using millis() and stick results in a small array.
When the sensor is "low" search the array, [0] to [n] and if a value is already there within a ceiling-floor, you have an index to return. If not there (longer or shorter outside the ceiling-floor, stick that value into the array and ++ valid elements. The array must be sorted before use.

The model should train quickly and you can then hardcode or at least seed the array at startup with good numbers, Of course, this metric is train velocity dependent. You could go for the BIG time and work out an algorithm whereby the intervals are based in ratios, more universal. Think how Morse Code is decoded with dits/dahs to represent the alphabet.

You could also use a range sensor like an ultasonic range sensor or Time of Flight light sensor. Both are relatively inexpensive and could easily be hidden below the tracks, assuming nothing else passes over them. The TOF sensors also only require a very tiny hole to "see" through, so they would be hidden even easier.

Hall-effect is another possibility as is the old Reed switch. By arranging multiple sensors under the track, a Hall sensor matrix could detect and distinguish different cars: "n" sensors could decode 2^n states and magnets are cheap and can be purchased with adheasive to tape to the lower parts of the cars.

Thanks for the replies. I have no plans on changing the sensor, sorry. Should maybe have mentioned it in the OP. It is not a safety important sensor, I just control the signals with it by turning the signal red for a certain amount of time, nothing too fancy.
Though in hindsight I would have used one of your other sensor suggestions, like the hall sensor or IR barrier since it doesn't include modifying the trains.

@mrburnette
Thanks for the idea with the array. That might be a better way of solving it compared to what I have now. Thanks for the help.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.