A resposta de Curt Sampson fornece várias considerações de bom design, além da sugestão bastante razoável de que você execute alguns experimentos para caracterizar seus LDRs e seus posicionamentos.
Observe que, se você quiser saber qual sensor tem a leitura mais alta, um loop simples de encontrar valor máximo fará isso, sem nenhuma classificação:
int maxR = leitura [1], maxS = 1; for (byte i = 2; i < = nSensores; ++ i) {if (leitura [i] > maxR) {maxR = leitura [i]; maxS = i; }} // Agora sabemos que o sensor maxS tem leitura máxima, maxR
O código acima segue o esquema de numeração 1–6 dado na pergunta e assume que leitura [i]
significa a leitura do sensor i
.
O código abaixo, no entanto, numera os sensores e suas leituras de 0 a 5 em vez de 1 a 6, para permitir condições mais simples em loops for
. Do ponto de vista da programação, faz sentido chamar o primeiro sensor de 0 se seus dados estiverem armazenados na célula 0.
Encontrando a direção x, y da luz
As suposições por trás do código a seguir são que leituras mais altas indicam mais luz e que, se necessário, alguma calibração da iluminação de fundo foi feita e que a iluminação de fundo já foi subtraída dos dados de leituras. Também assumimos que as leituras máximas são menores que (2¹⁵) / N, onde N é o número de sensores.
O objetivo do código a seguir é definir duas variáveis, x
e y
, que representam a localização relativa de uma fonte de luz. Por exemplo, se x
e y
forem ambos positivos, a luz estará acima e à direita do LDR superior direito. Se x
for negativo e y
for próximo a zero, a luz estará à esquerda do LDR central esquerdo. Se conhecer os sinais de x
e y
for adequado para o seu propósito, então não há necessidade de fazer mais cálculos aritméticos do que o mostrado. Por outro lado, se você quiser calcular algum tipo de ângulo, pode usar atan2 (y, x)
para calcular a direção da luz, em radianos.
leitura interna [nSensores]; const int xdir [] = {-1, 1, -1, 1, -1, 1}; // pesos do sensor de direção xconst int ydir [] = {1, 1, 0, 0, -1, -1}; // pesos do sensor de direção yint x = 0, y = 0; para (byte i = 0; i < nSensors; ++ i) {x + = xdir [i] * leitura [i]; y + = ydir [i] * reading [i];}
Edit 1: Rastreando o tempo em que uma luz está acesa
Os problemas com a temporização da luz incluem em quais níveis começar ou parar a temporização; resolução necessária (milissegundos? minutos?); intervalo necessário (por exemplo, o que aconteceu há um minuto é relevante); e quando redefinir os dados de tempo acumulados. Pode ser mais simples rastrear os tempos de ativação de todos os sensores ao mesmo tempo e, em seguida, selecionar um dos tempos ou combinar alguns. Você quer o maior tempo, o tempo mais recente, o tempo grande mais recente ou o tempo correspondente à maior luz?
Por exemplo, o código abaixo rastreia os níveis de luz que permanecem altos o suficiente para serem registrados em médias suavizadas, acima de algum limite. Em intervalos, as indicações atuais são giradas em mapas de bits que rastreiam os últimos 16 níveis on-off para cada LDR, e as contagens do número de ons são atualizadas também.
// Initialization .. .uint16_t expAvg [nSensors] = {0}; // Médias exponenciais ao longo do tempo
uint16_t bitMaps [nSensors] = {0}; // Rastreia os últimos 16 níveis de ativação / desativação de cada sensor, byte onCounts [nSensors] = {0}; // Número de vezes que o sensor avg > thresholdunsigned long prevMilli = millis (); const int markInterval = 50; // intervalo de ms para registrar os níveis de luzconst int onThreshold = 547 * 16; // Algum limiar luminoso // Em cada passagem de loop () ... for (byte i = 0; i < nSensors; ++ i) expAvg [i] = leitura [i] + 15 * expAvg [ Eu]; // média exponencial com peso 1:16 // Em loop (), em intervalos ... if (millis () - prevMilli > = markInterval) {prevMilli = millis (); para (byte i = 0; i < nSensors; ++ i) {onCounts [i] + = (expAvg [i] > onThreshold) - (! (bitMaps [i] & 0x8000)); bitMaps [i] = (bitMaps [i] <<1) | (expAvg [i] > onThreshold); }}