Detecting the light source location using multiple photoresistors I am not an expert yet, so please forgive any possibly wrong terminology that I may have used.

I am planning to place 6 light sensors in 1 meter (or maybe more) distance from one another, like this (sorry about the bad schematic, I am not an expert, but I hope it makes sense):







simulate this circuit &ndash; Schematic created using CircuitLab

I am going to place them in a relatively dark room. My goal is, when I am pointing a flash light towards them to be able to tell which sensor is measuring the highest values (where the light is coming from), and for how long (in milliseconds).

I know how to do the connections and measure values. My questions are two:


Which is the most efficient way to detect which of the 4 sensors is recording the higher values? I am assuming I have to compare the values that they are recording. However, I think that if in each loop I sort the captured values, the process might become heavy. I guess I could minimise the comparisons, since for example if LDR1's value is higher than LDR2 and LDR3, I can assume that the light source is cannot be pointing towards LDR6 for example. However, I am thinking that maybe there could be an even more efficient way to detect that (not necessarily in software).
Since the room will not be completely dark, the analog pins will record some values even when I am not pointing the flash light towards them. Is there a way to filter that out? I have come across calibration (https://www.arduino.cc/en/tutorial/calibration), but I am not sure whether this is the optimal solution. Please take into account that the light source might not be very strong (but its light will definitely be brighter than the room light).
The answer from Curt Sampson provides several good design considerations, plus the quite-reasonable suggestion that you run some experiments to characterize your LDRs and their placements.

Note that if you want to know which sensor has the highest reading, a simple find-maximum-value loop will do that, without any sorting:

int maxR = reading[1], maxS=1;
for (byte i=2; i &lt;= nSensors; ++i) {
  if (reading[i] &gt; maxR) {
    maxR = reading[i];
    maxS = i;
  }
}
// Now we know sensor maxS has max reading, maxR


The code above follows the 1–6 numbering scheme given in the question, and assumes that reading[i] stands for the reading from sensor i.

Code below, however, numbers the sensors and their readings from 0 to 5 instead of from 1 to 6, to allow simpler conditions in for loops.  From a programming standpoint, it makes sense to call the first sensor 0 if its data is stored in cell 0.



Finding x, y direction of the light

Assumptions behind the following code are that higher readings indicate more light, and that if necessary some background-lighting calibration has been done, and that background lighting has already been subtracted from readings data.  We also assume that maximum readings are less than (2¹⁵)/N, where N is number of sensors.

The point of the following code is to set two variables, x and y, that represent the relative location of a light source.  For example, if x and y are both positive, the light is above and to the right of the top right LDR.  If  x is negative and  y is near zero, the light is to the left of the middle-left LDR.  If knowing the signs of x and y is adequate for your purpose, then there's no need to do more arithmetic than shown.  On the other hand, if you want to compute some sort of angle, you can use atan2(y, x) to compute the direction of the light, in radians.

int reading[nSensors];
const int xdir[] = { -1, 1, -1, 1, -1,  1}; // x-direction sensor weights
const int ydir[] = {  1, 1,  0, 0, -1, -1}; // y-direction sensor weights
int x=0, y=0;
for (byte i=0; i &lt; nSensors; ++i) {
  x += xdir[i] * reading[i];
  y += ydir[i] * reading[i];
}




Edit 1: Tracking the time a light is on

Issues with light-timing include what levels to start or stop timing at; necessary resolution (milliseconds? minutes?); necessary range (eg, is what happened a minute ago relevant); and when to reset accumulated time data.  It may be simplest to track the on times of all the sensors at the same time, then select one of the times or combine some times.  Do you want the largest time, the newest time, the newest large time, or the time corresponding to the largest light?

For example, the code below tracks light levels that remain high long enough to register, in smoothed averages, as above some threshold.  At intervals, current indications are rotated into bit maps that track the last 16 on-off levels for each LDR, and counts of number-of-ons are updated too.

// Initialization ...
uint16_t expAvg[nSensors]={0};  // Exponential averages over time
uint16_t bitMaps[nSensors]={0}; // Track each sensor's last 16 on-off levels
byte onCounts[nSensors]={0};    // Number of recent times sensor avg &gt; threshold
unsigned long prevMilli=millis();
const int markInterval=50;   // ms interval for recording light levels
const int onThreshold=547*16; // Some light-is-on threshold

// In each pass of loop() ...
for (byte i=0; i &lt; nSensors; ++i)
  expAvg[i] = reading[i] + 15*expAvg[i]; // exponential averaging with 1:16 weight

// In loop(), at intervals ...
if (millis()-prevMilli &gt;=  markInterval) {
  prevMilli = millis();
  for (byte i=0; i &lt; nSensors; ++i) {
    onCounts[i] += (expAvg[i] &gt; onThreshold) - (!(bitMaps[i] &amp; 0x8000));
    bitMaps[i] = (bitMaps[i]&lt;&lt;1) | (expAvg[i] &gt; onThreshold);
  }
}